可以将一个免费的 monad 转换为任何其他 monad,但是给定一个 type 的值Free f x
,我想打印整个树,而不是将生成的 AST 的每个节点映射到另一个 monad 中的某个其他节点。
Gabriel Gonzales直接使用该值
showProgram :: (Show a, Show r) => Free (Toy a) r -> String
showProgram (Free (Output a x)) =
"output " ++ show a ++ "\n" ++ showProgram x
showProgram (Free (Bell x)) =
"bell\n" ++ showProgram x
showProgram (Free Done) =
"done\n"
showProgram (Pure r) =
"return " ++ show r ++ "\n"
可以抽象为
showF :: (x -> b) -> ((Free f x -> b) -> f (Free f x) -> b) -> Free f x -> b
showF backLiftValue backLiftF = fix (showFU backLiftValue backLiftF)
where
showFU :: (x -> b) -> ((Free f x -> b) -> f (Free f x) -> b) -> (Free f x -> b) -> Free f x -> b
showFU backLiftValue backLiftF next = go . runIdentity . runFreeT where
go (FreeF c ) = backLiftF next c
go (Pure x) = backLiftValue x
Choice x = Choice x x
如果我们有像(用作仿函数)这样的多态函数,这很容易调用
showChoice :: forall x. (x -> String) -> Choice x -> String
showChoice show (Choice a b) = "Choice (" ++ show a ++ "," ++ show b ++ ")"
但这对于一个简单的操作来说似乎相当复杂......还有哪些其他方法可以从f x -> b
到Free f x -> b
?