Monad法律适用于基于应用的公式

时间:2017-10-17 17:50:51

标签: haskell monads applicative

通常在Haskell中,我们根据Monadreturn来定义>>=。有时将>>=分解为fmapjoin会很方便。一旦你习惯了,这两种配方的Monad定律是众所周知的,并且相当直观。

根据Applicative仿函数,还有另一种定义monad的方法:

class Applicative f => MyMonad f where
    myJoin :: f (f a) -> f a

我想知道这种配方的法律。显然,我们可以只调整fmap + join法则,如下所示(我不确定名称是否特别合适,但是很好):

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定律,上述法律的某些特征可能是非常规的。

(如果您想知道为什么我们甚至会遇到这两种标准可能性中的任何一种困扰:我不确定它是什么在编程上下文中有用或明显,但当你使用goBack()do natural langauge semantics时,结果却是如此。)

1 个答案:

答案 0 :(得分:2)

身份法更容易编写

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

ApplicativeMonad之间关系的有趣法则是

(<*>) = ap
-- or
m1 <*> m2 = m1 >>= (\x1 -> m2 >>= \x2 -> return (x1 x2)) -- definition of ap

Applicativejoin而言,这是

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是基于

的关联
  • FunctorApplicative法律 - 特别是<*>
  • 的组成
  • 身份join . fmap pure = join . pure = id
  • (<*>) = ap

我不确定它是否属实。我认为你需要结合法join . join = join . fmap join