gpt4 book ai didi

haskell - 打印自由单子(monad)

转载 作者:行者123 更新时间:2023-12-04 07:19:50 25 4
gpt4 key购买 nike

可以将自由 monad 转换为任何其他 monad,但给定类型为 Free f x 的值,我想打印整个树,而不是将生成的 AST 的每个节点映射到另一个 monad 中的某个其他节点。

加布里埃尔·冈萨雷斯 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 ?

最佳答案

使用 iter fmap :

{-# LANGUAGE DeriveFunctor #-}

import Control.Monad.Free

data Choice x = Choice x x deriving (Functor)

-- iter :: Functor f => (f a -> a) -> Free f a -> a
-- iter _ (Pure a) = a
-- iter phi (Free m) = phi (iter phi <$> m)

showFreeChoice :: Show a => Free Choice a -> String
showFreeChoice =
iter (\(Choice l r) -> "(Choice " ++ l ++ " " ++ r ++ ")")
. fmap (\a -> "(Pure " ++ show a ++ ")")
fmapFree f a 转换至 Free f b , 和 iter做剩下的。您可以考虑这一点,也许会获得更好的性能:
iter' :: Functor f => (f b -> b) -> (a -> b) -> Free f a -> b
iter' f g = go where
go (Pure a) = g a
go (Free fa) = f (go <$> fa)

关于haskell - 打印自由单子(monad),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34287089/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com