[英]Monad laws for an applicative-based formulation
通常在Haskell中我们用return
和>>=
来定义Monad
s。 有时将>>=
分解为fmap
并join
是很方便的。 一旦你习惯了这两种配方的Monad
法则是众所周知的并且相当直观。
根据Applicative
仿函数,还有另一种定义monad的方法:
class Applicative f => MyMonad f where
myJoin :: f (f a) -> f a
我想知道这种配方的法律。 显然,我们可以调整fmap
+ join
法则,如下所示(我不确定这些名称是否特别fmap
,但是很好):
myJoin . myJoin = myJoin . (pure myJoin <*>) ('Associativity')
myJoin . pure = myJoin . (pure pure <*>) = id ('Identity')
很明显,这些条件对于pure
(<*>)
和myJoin
足以构成一个monad(从某种意义上说,他们保证m `myBind` f = myJoin (pure f <*> m)
将是一个表现良好的>>=
)。 但它们也是必要的吗? 至少有可能的是, Applicative
支持以上和Functor
之外的其他结构可能允许我们简化这些法则 - 换句话说,上述法律的某些特征可能是非常的,因为已知pure
和(<*>)
已满足Applicative
法律。
(如果你想知道为什么我们甚至会遇到困扰这个公式的两种标准可能性:我不确定它在编程环境中是否有用或显而易见,但事实证明是所以当你使用Monad
s 做自然语言语义时 。)
身份法更容易编写
join . fmap pure = join . pure = id
传统的monad权利身份法立即遵循>>=
的定义。 左侧身份法使用Applicative
法律
m >>= k = join (fmap k m)
-- proof for right identity
m >>= return = m
join (fmap pure m) = m -- definition of >>=
id m = m -- identity
m = m -- definition of id
-- proof for left identity
return a >>= f = f a
join (fmap f (pure a)) = f a -- definitions of >>= and return
join (pure (f a)) = f a -- fmap f . pure = pure . f
id (f a) = f a -- identity
f a = f a -- definition of id
Applicative
和Monad
之间关系的有趣法则是
(<*>) = ap
-- or
m1 <*> m2 = m1 >>= (\x1 -> m2 >>= \x2 -> return (x1 x2)) -- definition of ap
在Applicative
和join
方面,这是
m1 <*> m2 = join (fmap (\x1 -> fmap x1 m2) m1)
-- proof
m1 <*> m2 = join (fmap (\x1 -> m2 >>= \x2 -> return (x1 x2)) m1) -- definition of ap
m1 <*> m2 = join (fmap (\x1 -> join (fmap (\x2 -> return (x1 x2)) m2)) m1) -- definition of >>=
m1 <*> m2 = join (fmap (\x1 -> join (fmap (\x2 -> pure (x1 x2)) m2)) m1) -- return = pure
m1 <*> m2 = join (fmap (\x1 -> join (fmap (pure . x1) m2)) m1)
m1 <*> m2 = join (fmap (\x1 -> join (fmap pure (fmap x1 m2))) m1) -- fmap (f . g) = fmap f . fmap g
m1 <*> m2 = join (fmap (\x1 -> fmap x1 m2) m1) -- identity
可能有更优雅的方式来写这个。
我还没有找到一种方法来表明Monad
是基于联想的
Functor
和Applicative
Functor
- 特别是<*>
join . fmap pure = join . pure = id
join . fmap pure = join . pure = id
(<*>) = ap
我不确定这是不是真的。 我认为你需要联想法join . join = join . fmap join
join . join = join . fmap join
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.