运算符结合性、结合律和 monad 的值依赖如何结合在一起?

How do operator associativity, the associative law and value dependencies of monads fit together?

一方面,单子绑定运算符 >>= 是左关联的(AFAIK)。另一方面,monad 法则要求结合性,即求值顺序无关紧要(就像幺半群一样)。此外,monads 通过使下一个效果依赖于前一个效果的结果来编码值依赖性,即 monads 有效地确定了评估顺序。这对我来说听起来很矛盾,这清楚地表明我对所涉及概念的心理表征是错误的。它们是如何组合在一起的?

On the one hand the monadic bind operator >>= is left associative

是的。

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

这就是它的定义方式+ 也是 left-associative,尽管(加法)群法则要求结合性。

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

所有 infixl 声明意味着编译器将 解析 a+b+c(a+b)+c;这是否恰好等于 a+(b+c) 是另一回事。

the monad law demands associativity

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

Besides, monads encode a value dependency by making the next effect depend on the result of the previous one

是的,但这并不与 >=> 的结合律相矛盾。示例:

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

左右翻转不会改变 顺序 / 动作之间的依赖关系(那将是交换律,而不是结合律),它只是改变了 分组个动作。