Учитывая бесплатную DSL-монаду, такую как:
data FooF x = Foo String x
| Bar Int x
deriving (Functor)
type Foo = Free FooF
И случайный интерпретатор для Foo
:
printFoo :: Foo -> IO ()
printFoo (Free (Foo s n)) = print s >> printFoo n
printFoo (Free (Bar i n)) = print i >> printFoo n
Мне кажется, что в каждой итерации printFoo должно быть возможно перевести что-то в другое место, не прибегая к его выполнению вручную:
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
Как это возможно, путем "обертывания" оригинала printFoo
?
Мотивация: я пишу небольшой DSL, который "компилируется" до двоичного формата. Бинарный формат содержит некоторую дополнительную информацию после каждой пользовательской команды. Он должен быть там, но совершенно неуместен в моей работе.