你可能听说过
Monad 是一类内函子中的幺半群
你已经提到过幺半群只是列表。所以你来了。
稍微扩展一下:
data Free f a = Pure a
| Free (f (Free f a))
这不是一个普通的列表a
,而是一个包含 tail 的列表f
。如果您编写多个嵌套绑定的值结构,您会看到它:
pure x >>= f >>= g >>= h :: Free m a
可能导致
Free $ m1 $ Free $ m2 $ Free $ m3 $ Pure x
where m1, m2, m3 :: a -> m a -- Some underlying functor "constructors"
如果m
在上面的示例中是 sum 类型:
data Sum a = Inl a | Inr a
deriving Functor
那么列表实际上是一棵树,因为在每个构造函数中我们可以向左或向右分支。
你可能听说过
Applicative 是一类内函子中的幺半群
...类别只是不同。在Roman Cheplyaka 的博客文章中有不同的免费应用编码的很好的可视化。
所以免费Applicative
也是一个列表。我把它想象成一个异构的f a
值列表和单个函数:
x :: FreeA f a
x = FreeA g [ s, t, u, v]
where g :: b -> c -> d -> e -> a
s :: f b
t :: f c
u :: f d
v :: f e
在这种情况下,尾巴本身没有包裹在 中f
,而是单独包裹在每个元素中。Applicative
这可能有助于也可能不会帮助理解和之间的区别Monad
。
请注意,这f
不需要与Functor
上面的monadApplicative (FreeA f a)
相反。Free
还有免费的Functor
data Coyoneda f a = Coyoneda :: (b -> a) -> f b -> Coyoneda f a
这使得任何* -> *
类型Functor
。将其与Applicative
上面的免费进行比较。在应用情况下,我们有一个长度为n的f a
值的异构列表和一个组合它们的 n 元函数。Coyoneda 是上述的一元特例。
我们可以结合Coyoneda
并Free
制作Operational
免费的单子。正如其他答案所提到的,这棵树很难想象成树,因为其中涉及到功能。OTOH,您可以将这些延续想象为图片中不同的神奇箭头:)