当试图找到一个可以逐步执行的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 <*> xfmap基本定义<*>

最佳答案

这样可以吗

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/

10-10 16:30
查看更多