Haskell 用连接而不是绑定表示的单子定律?

Haskell 用连接而不是绑定表示的单子定律?,haskell,monads,Haskell,Monads,单子定律传统上用>=和纯来描述: pure a >>= k = k a m >>= pure = m m >>= (\x -> k x >>= h) = (m >>= k) >>= h 但是,monad也可以定义为join,而不是>=。我想从join的角度提出单子定律的公式 使用x>=f=join(fmap fx),很容易重写现有的单子定律以消除>=。在应用定律的帮助下,将结果稍微简化,前两个定律表达得非常愉快: j

单子定律传统上用
>=
来描述:

pure a >>= k = k a
m >>= pure = m
m >>= (\x -> k x >>= h) = (m >>= k) >>= h
但是,monad也可以定义为
join
,而不是
>=
。我想从
join
的角度提出单子定律的公式

使用
x>=f=join(fmap fx)
,很容易重写现有的单子定律以消除
>=
。在应用定律的帮助下,将结果稍微简化,前两个定律表达得非常愉快:

join . pure = id
join . fmap pure = id
对这些定律的直觉也很容易,因为很明显,当与
连接时,引入一个额外的
层应该是不可行的。然而,第三定律并不那么好。结果是这样的:

  join (fmap (\x -> join (fmap h (k x))) m)
= join (fmap h (join (fmap k m)))
这并不能令人愉快地减少应用定律的使用,如果不盯着它看一段时间,就很难理解它。它当然没有同样简单的直觉

join
方面,是否有一种更容易理解的单子定律的等效替代公式?或者,有没有办法简化上述法律,或使其更容易摸索?带有
>=
的版本已经不如使用Kleisli组合表示的版本好,但是带有
连接的版本几乎无法读取。

直接从以下位置被盗:

(自然转换
η:1->T
纯的
;自然转换
µ:T^2->T
连接

µ。Tµ=µ。µT

在哈斯克尔:

join . fmap join = join . join
中文:如果你从三层monad开始,如
mmma::monad m=>m(m(ma))
,那么你是先展平它的内层再展平它的外层,还是先展平它的外层再展平它的内层并不重要。这与您列出的第三条(关联性)相同

µ。Tη=µ。ηT=1

在哈斯克尔:

join . fmap join = join . join
加入。fmap pure=join。pure=id

中文:如果你从一层monad开始,作为
ma::monad m=>ma
,在它里面创建一个新层然后展平它,或者在它外面创建一个新层然后展平它,这都无关紧要,两者都等同于什么都不做。这条法则是前两条法则的结合

而且,
join
作为一种自然转换意味着

加入。fmap(fmap f)=fmap f。加入


因为参数性。

如果你可以使用这种简洁的数学语言,我认为这是一个明确的定义。基本上,左边的图表对应于您所陈述的前两条定律(
join.pure=join.fmap pure=id
),右边的图表可以表述为
join。join=join。fmap连接
。请注意,
(\hkm->join(fmap h(join(fmap km)))id=\m->join(join m)
-这源于
fmap id=id
(同样适用于两个等式的另一侧)。换句话说,你的定律在一条语句中同时表达了函子定律和单子定律。根据你的英语解释,我想我实际上更喜欢这些定律,而不是Kleisli合成版本。你缺少一条定律:
join。fmap(fmap f)≡ fmap f。join
@Shersh这是由
join
作为自然转换所暗示的。自然变换是
f:f->G
必须具有
f。F(m)=G(m)。f
对于所有态射
m
。所有这些都非常好。。。但我看不出如何从你问题中的另外两个定律推导出这个定律。起源问题是关于连接方面的单子定律,所以看到单子的所有定律是很合理的。事实上,并不是每个人都知道范畴理论,但这个人可能会在谷歌上搜索“单子定律中的连接”,并不会找到所有的定律。
join::forall m a。Monad m=>m(ma)->ma
join
m
索引,并在
a
中参数化)。参数类型产生定理。特别是,如果
函子f,g
,则对于所有a。f a->g a
,类型告诉您
r。fmap@Fk=fmap@Gk。r
适用于所有
k
。在
join
的情况下,
g=m
f=m。m
,所以
fmap@fk=fmap@m(fmap@mk)
你就得到了加入的法则。(fmap(fmap k))=fmap k。join
因此,
join
的类型暗示了这一法则,并由类型检查器进行检查。