bob*_*bob 4 monads haskell functional-programming associativity monoids
一方面,一元绑定运算符>>=是左结合的(AFAIK)。另一方面,monad 定律需要结合性,即评估顺序无关紧要(就像幺半群一样)。此外,monads 通过使下一个效果依赖于前一个效果的结果来编码值依赖,即 monads 有效地确定评估顺序。这对我来说听起来很矛盾,这显然意味着我对所涉及概念的心理表征是错误的。这一切是如何结合在一起的?
一方面,一元绑定运算符
>>=是左结合的
是的。
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声明意味着,编译器将解析 a+b+c为(a+b)+c; 这是否恰好等于是a+(b+c)另一回事。
monad 法则需要结合性
嗯,>>=其实是不联想的。关联运算符是>=>。对于>>=,类型已经表明它不能是关联的,因为第二个参数应该是一个函数,第一个不是。
此外,monad 通过使下一个效果依赖于前一个效果的结果来编码值依赖
是的,但这与 的结合性并不矛盾>=>。例子:
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
翻转括号不会改变动作之间的顺序/依赖关系(这将是交换律,而不是结合律),它只是改变了动作的分组。