在Haskell Monad中声明为
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
return = pure
Run Code Online (Sandbox Code Playgroud)
我想知道是否可以将bind运算符重新声明为
(>>=) :: (a -> m b) -> m a -> m b
Run Code Online (Sandbox Code Playgroud)
?
第二个声明使将(>>=)type a -> m b的函数映射到type 的函数m a -> m b更清晰,而原始的声明却使它的含义更不清楚,是否正确?
声明的更改是否会使某些事情变为可能,甚至是不可能,或者只需要对使用monad进行一些更改(Haskell程序员似乎可以接受)?
谢谢。
lef*_*out 15
为什么>>=在实践中比在翻转中更有用的原因是一个原因=<<:它与lambda表示法配合得很好。即,\充当语法先驱,因此您可以继续计算而无需任何括号。例如,
do x <- [1..5]
y <- [10..20]
return $ x*y
Run Code Online (Sandbox Code Playgroud)
可以很容易地重写>>=为
[1..5] >>= \x -> [10..20] >>= \y -> return $ x*y
Run Code Online (Sandbox Code Playgroud)
您仍然具有与do版本相同的“命令式”感觉。
与=<<此相反,它需要笨拙的括号,并且似乎向后看:
(\x -> (\y -> return $ x*y) =<< [10..20]) =<< [1..5]
Run Code Online (Sandbox Code Playgroud)
好的,您可能会说这更像是函数应用程序。但是,如果有用,通常只使用应用函子接口而不是单子函数就更令人毛骨悚然了:
(\x y -> x*y) <$> [1..5] <*> [10..20]
Run Code Online (Sandbox Code Playgroud)
或短
(*) <$> [1..5] <*> [10..20]
Run Code Online (Sandbox Code Playgroud)
请注意,这(<*>) :: f (a->b) -> f a -> f b实际上=<<是您建议的顺序,只是a->在函子的内部而不是外部。