Consider the lovely little HoleyMonoid library, which lets you build typed variadic printf-like functions as follows:
{-# LANGUAGE NoMonomorphismRestriction #-}
import Control.Category
import Data.HoleyMonoid
import Prelude hiding ((.), id)
foo =
now "hello "
. later id
. now ", you are "
. later show
. now " years old"
bar = run foo
-- > bar "alice" 42
-- "hello alice, you are 42 years old"
-- > bar 42 "alice"
-- type error
Is there any way to examine a container (a list, an AST, etc.) and build such a function based on its contents?
As a toy example, you can picture something like the following:
import Data.Monoid
adder = go where
go [] = now (Sum 0)
go (x:xs)
| x == 5 = now 100 . go xs
| otherwise = later id . go xs
-- hypothetical usage
--
-- > :t run adder [1, 3, 5]
-- Num a => Sum a -> Sum a -> Sum a
--
-- > getSum $ run adder [1, 3, 5] 0 1
-- 101
adder
fails the occurs check, but you can see what I'm shooting for. The problem seems to be that it's difficult to hold the state of the computation anywhere, as i.e. now 100
and later id
are at different types.