フリーモナドを他のモナドに変換することはできますが、 type の値が与えられた場合、Free f x
生成された AST のすべてのノードを別のモナドの他のノードにマップするのではなく、ツリー全体を出力したいと考えています。
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
?