monads的算子关联性,关联律和值依存关系如何融合在一起?

问题描述

一方面,单子绑定操作符>>=保持关联(AFAIK)。另一方面,单子法则要求关联性,即评估顺序无关紧要(与Monoid一样)。此外,单子通过使下一个效果依赖于前一个的结果来编码值依赖性,即,单子有效地确定评估顺序。这听起来与我自相矛盾,这显然暗示着我对所涉概念的心理表述是错误的。它们如何融合在一起?

解决方法

一方面,单子绑定操作符>>=保持关联状态

是的

Prelude> :i >>=
class Applicative m => Monad (m :: * -> *) where
  (>>=) :: m a -> (a -> m b) -> m b
  ...
    -- Defined in ‘GHC.Base’
infixl 1 >>=

那只是定义的方式+也是左关联的,尽管(加法)组定律要求具有关联性。

Prelude> :i +
class Num a where
  (+) :: a -> a -> a
  ...
    -- Defined in ‘GHC.Num’
infixl 6 +

所有infixl声明的意思是编译器将{em>解析 a+b+c(a+b)+c;碰巧是否等于a+(b+c)是另一回事。

莫纳德定律要求结合性

嗯,>>=实际上是不关联的。关联运算符为>=>。对于>>=,该类型已经表明它不能关联,因为第二个参数应该是一个函数,第一个则不是。

此外,单子通过使下一个效果依赖于前一个的结果来编码值依赖

是的,但这与>=>的关联性并不矛盾。示例:

teeAndInc :: String -> Int -> IO Int
teeAndInc name val = do
   putStrLn $ name ++ "=" ++ show val
   return $ val + 1
Prelude Control.Monad> ((teeAndInc "a" >=> teeAndInc "b") >=> teeAndInc "c") 37
a=37
b=38
c=39
40
Prelude Control.Monad> (teeAndInc "a" >=> (teeAndInc "b" >=> teeAndInc "c")) 37
a=37
b=38
c=39
40

翻转括号不会改变动作之间的 order /依赖关系(这将是可交换性定律,而不是关联性定律),而只会更改分组动作。