【发布时间】:2019-07-28 15:55:18
【问题描述】:
在 Haskell 中 Monad 被声明为
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
return = pure
我想知道是否可以将绑定运算符重新声明为
(>>=) :: (a -> m b) -> m a -> m b
?
第二个声明更清楚地表明(>>=) 将a -> m b 类型的函数映射到m a -> m b 类型的函数是否正确,而原始声明不太清楚它的含义?
声明的改变是否会使某些事情从可能变为不可能,或者只是需要改变使用 monad(这对 Haskell 程序员来说似乎可以忍受)?
谢谢。
【问题讨论】:
-
不,那是翻转版本。这被实现为
(=<<)。 -
谢谢。你对什么“不”?第二个声明更清楚地表明 (>>=) 将 a -> m b 类型的函数映射到 m a -> m b 类型的函数是否正确,而原始声明却不太清楚它的含义?声明的更改会使某些事情从可能变为不可能,还是只需要对使用 monad 进行一些更改(这对 Haskell 程序员来说似乎可以忍受)?
-
这实际上是一个值得讨论的有趣话题 - 正如您所注意到的,
>>=的类型签名与其相似的fmap和<*>相比是“倒退”的。我认为@leftaroundabout 的回答很好地回答了为什么 Haskell 选择按该顺序使用参数定义>>=- 但最终它是相当武断的,并且哪种方式更好是一个意见问题。我不清楚你的问题到底是什么。 -
声明的顺序是为了促进 Kleisli 箭头从左到右的链接,而不是建议任何特定的映射。给定两个这样的箭头
f :: a -> m b和g :: b -> m c,你可以写成h x = x >>= f >>= g。考虑到使用 monad 来表示顺序计算,从左到右的“组合”被认为更自然。 -
明确回答您的第二个问题:它只是
flip (>>=),也被定义为(=<<),所以不,它不会使以前没有的任何事情变得不可能或可能。flip f y x = f x y,就是这样。