8
可以将免费单片机翻译为任何其他单片机,但给定类型为Free f x
的值时,我想打印整棵树,而不是将生成的AST的每个节点映射到另一单片机中的某个其他节点。打印免费单片机
加布里埃尔冈萨雷斯uses值直接
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
?
啊,这很好!谢谢。现在我发现很明显,人们必须寻找将'f'的代数翻译为'Free f'的代数。 – nicolas
我喜欢你的'iter''。我试图最近找到一些服务于这个普通用途的东西(感觉自己肯定有一个),但某种方式未能击中正确的类型。 – dfeuer
这可能是有价值的基准对'iter'f g =去哪里......。有些测量表明,当至少有两个参数在递归中保持不变时,这往往是好的。 – dfeuer