Given a free monad DSL such as:
data FooF x = Foo String x
| Bar Int x
deriving (Functor)
type Foo = Free FooF
And a random interpreter for Foo
:
printFoo :: Foo -> IO ()
printFoo (Free (Foo s n)) = print s >> printFoo n
printFoo (Free (Bar i n)) = print i >> printFoo n
It appears to me that it should be possible to intersperse something into each iteration of printFoo without resorting to doing it manually:
printFoo' :: Foo -> IO ()
printFoo' (Free (Foo s n)) = print s >> print "extra info" >> printFoo' n
printFoo' (Free (Bar i n)) = print i >> print "extra info" >> printFoo' n
Is this somehow possible by 'wrapping' the original printFoo
?
Motivation: I am writing a small DSL that 'compiles' down to a binary format. The binary format contains some extra information after each user command. It has to be there, but is totally irrelevant in my usecase.
The other answers have missed how simple
free
makes this! :) Currently you havewhich gives
That's fine, but
iterM
can do the requisite plumbing for youThen we get
OK great, it's the same as before. But
printFooF
gives us more flexibility to augment the translator along the lines you wantthen we get
Thanks Gabriel Gonzalez for popularizing free monads and Edward Kmett for writing the library! :)