当试图找到一个可以逐步执行的haskell monad /允许线程化时,我发现了免费的monad
data Free f a = Return a | Roll (f (Free f a))
及其monad实例
instance (Functor f) => Monad (Free f) where
return = Return
Return x >>= f = f x
Roll action >>= f = Roll $ fmap (>>= f) action
及其函子实例
instance (Functor f) => Functor (Free f) where
fmap f (Return x) = Return (f x)
fmap f (Roll x) = Roll $ fmap (fmap f) x
我知道每个monad都是
pure = return
和(<*>) = ap
的应用函子。对我而言,应用函子在概念上比monad难。为了更好地了解应用函子,我喜欢使用应用实例而不求助于
ap
。<*>
的第一行很简单:instance (Applicative f) => Applicative (Free f) where
pure = Return
Return f <*> x = fmap f x -- follows immediately from pure f <*> x = f <$> x
--Roll f <*> x = Roll $ (fmap ((fmap f) <*>)) x -- wrong, does not type-check
如何用
Roll f <*> x
和fmap
基本定义<*>
? 最佳答案
这样可以吗
instance (Functor f) => Applicative (Free f) where
pure = Return
Return f <*> as = fmap f as
Roll faf <*> as = Roll (fmap (<*> as) faf)
计划仅对产生功能的树的叶子起作用,因此对于
Return
,我们通过将函数应用于自变量操作产生的所有自变量值来执行操作。对于
Roll
,我们只需要对所有子操作执行我们打算对整体操作执行的操作。至关重要的是,在到达
Return
时,我们已经开始进行操作。我们不会根据我们在树中的位置来更改计划。这就是Applicative
的标志:计算的结构是固定的,因此值取决于值,而动作不取决于值。关于haskell - 免费monad的适用实例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22121960/