以连接而不是绑定的方式表达的 Monad 法则?
Monad laws expressed in terms of join instead of bind?
Monad 法则传统上用 >>=
和 pure
来描述:
pure a >>= k = k a
m >>= pure = m
m >>= (\x -> k x >>= h) = (m >>= k) >>= h
然而,monads 也可以用 join
而不是 >>=
来定义。我想根据 join
.
提出 monad 法则的表述
使用x >>= f = join (fmap f x)
,很容易重写现有的单子法则来消除>>=
。借助应用法则稍微简化一下结果,前两个法则表达得相当愉快:
join . pure = id
join . fmap pure = id
这些定律的直觉也很容易,因为很明显,在与 join
结合使用时,使用 pure
引入额外的“层”应该是空操作。然而,第三定律就没那么好了。它最终看起来像这样:
join (fmap (\x -> join (fmap h (k x))) m)
= join (fmap h (join (fmap k m)))
这并没有令人愉快地减少应用法则的使用,而且如果不盯着它看一会儿就更难理解了。它当然没有同样简单的直觉。
是否有更容易理解的 join
单子法则的等效替代表述?或者,有没有什么办法可以简化上述法则,或者让它更容易理解? >>=
的版本已经不如 Kleisli 组合表达的好,但是 join
的版本几乎不可读。
直接从Wikipedia偷来的:
(自然变换η: 1 -> T
为pure
;自然变换µ: T^2 -> T
为join
)
µ . Tµ = µ . µT
在Haskell中:
join . fmap join = join . join
英文:如果你从三层monad开始,如mmma :: Monad m => m (m (m a))
,先压平内层再压外层,还是先压压外层再压内层都无所谓。这与您列为第三条(结合律)的定律相同。
µ . Tη = µ . ηT = 1
在Haskell中:
join . fmap pure = join . pure = id
英文:如果你从一层 monad 开始,如 ma :: Monad m => m a
,无论你在里面创建一个新层然后展平它,还是在它外面创建一个新层都没有关系然后压扁它,两者都和什么都不做一样。这个定律是你前两个的结合。
此外,join
是自然变换意味着
join . fmap (fmap f) = fmap f . join
因为参数化。
Monad 法则传统上用 >>=
和 pure
来描述:
pure a >>= k = k a
m >>= pure = m
m >>= (\x -> k x >>= h) = (m >>= k) >>= h
然而,monads 也可以用 join
而不是 >>=
来定义。我想根据 join
.
使用x >>= f = join (fmap f x)
,很容易重写现有的单子法则来消除>>=
。借助应用法则稍微简化一下结果,前两个法则表达得相当愉快:
join . pure = id
join . fmap pure = id
这些定律的直觉也很容易,因为很明显,在与 join
结合使用时,使用 pure
引入额外的“层”应该是空操作。然而,第三定律就没那么好了。它最终看起来像这样:
join (fmap (\x -> join (fmap h (k x))) m)
= join (fmap h (join (fmap k m)))
这并没有令人愉快地减少应用法则的使用,而且如果不盯着它看一会儿就更难理解了。它当然没有同样简单的直觉。
是否有更容易理解的 join
单子法则的等效替代表述?或者,有没有什么办法可以简化上述法则,或者让它更容易理解? >>=
的版本已经不如 Kleisli 组合表达的好,但是 join
的版本几乎不可读。
直接从Wikipedia偷来的:
(自然变换η: 1 -> T
为pure
;自然变换µ: T^2 -> T
为join
)
µ . Tµ = µ . µT
在Haskell中:
join . fmap join = join . join
英文:如果你从三层monad开始,如mmma :: Monad m => m (m (m a))
,先压平内层再压外层,还是先压压外层再压内层都无所谓。这与您列为第三条(结合律)的定律相同。
µ . Tη = µ . ηT = 1
在Haskell中:
join . fmap pure = join . pure = id
英文:如果你从一层 monad 开始,如 ma :: Monad m => m a
,无论你在里面创建一个新层然后展平它,还是在它外面创建一个新层都没有关系然后压扁它,两者都和什么都不做一样。这个定律是你前两个的结合。
此外,join
是自然变换意味着
join . fmap (fmap f) = fmap f . join
因为参数化。