Arrow
基本上是
单子范畴1的类,其中“单子”不是指
Monoid
,而是Haskell类型的
乘积单子。即具有单位元素
()
和乘法
(,)
。现在,总和类型也组成了一个单子,这就是
ArrowChoice
使用的内容。这两个类在这个意义上是互补的;
ArrowChoice
不应该真正成为
Arrow
的子类。
在单子范畴中,您可以继续拥有单子函子。如何得到这些取决于您使用的类型单子。对于(), (,)
,您将获得:
class ProdMonoidalFtor f where
prodUnit :: () -> f ()
prodZip :: (f a, f b) -> f (a,b)
type (+) = Either
class SumMonoidalFtor f where
sumUnit :: Void -> f Void
sumZip :: f a + f b -> f (a+b)
原来后者基本上是没有用的,因为
Void
是
Hask 的
初始对象,这意味着存在恰好一个
Void -> a
(即对于
所有 类型
a
,都是如此)(这个唯一的函数是
absurd
)。然而,使用带有
+
的
余单函子确实是有意义的。
class SumCoMonoidalFtor f where
sumCounit :: f Void -> Void -- I bet you find this useless too, but it's not totally.
sumCozip :: f (a+b) -> f a + f b
这反过来对于产品类型是没有意义的,因为()
是终端对象。
现在有趣的是,ProdMonoidalFtor
等同于Applicative
:
instance (ProdMonoidalFtor f) => Applicative f where
pure x = fmap (const x) $ prodUnit ()
fs <*> xs = fmap (\(f,x) -> f x) $ prodZip (fs,xs)
那么,人们可能会怀疑Alternative
等同于SumMonoidalFtor
,但实际上不是这样!事实上,它等同于决策函子,这些函子与余单子的关系类似于应用函子与单子的关系。
而Alternative
和MonadPlus
似乎没有太多的数学支持,它们本质上是在“非Kleisliing”ArrowChoice
类时得到的,但使用由ProdMonoidalFtor
产生的Kleisli范畴。这一切都有点可疑。
1这仅考虑first
/left
,second
/right
和***
/+++
。至于剩下的&&&
,|||
和arr
,这些更具体,我认为应该在单独的类中。