运算符结合性、结合律和 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
左右翻转不会改变 顺序 / 动作之间的依赖关系(那将是交换律,而不是结合律),它只是改变了 分组个动作。
一方面,单子绑定运算符 >>=
是左关联的(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
左右翻转不会改变 顺序 / 动作之间的依赖关系(那将是交换律,而不是结合律),它只是改变了 分组个动作。