【问题标题】:Can `(>>=)` be redeclared as `(a -> m b) -> m a -> m b`?`(>>=)` 可以重新声明为 `(a -> m b) -> m a -> m b` 吗?
【发布时间】: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 bg :: b -> m c,你可以写成h x = x >>= f >>= g。考虑到使用 monad 来表示顺序计算,从左到右的“组合”被认为更自然。
  • 明确回答您的第二个问题:它只是flip (>>=),也被定义为(=<<),所以不,它不会使以前没有的任何事情变得不可能或可能。 flip f y x = f x y,就是这样。

标签: haskell monads


【解决方案1】:

>>= 在实践中往往比它的翻转对应物=<< 更有用的原因之一:它与 lambda 表示法配合得很好。也就是说,\ 充当语法先驱,因此您可以继续计算而无需任何括号。例如,

 do x <- [1..5]
    y <- [10..20]
    return $ x*y

可以很容易地用&gt;&gt;= 重写为

   [1..5] >>= \x -> [10..20] >>= \y -> return $ x*y

您仍然拥有与do 版本大致相同的“势在必行”的感觉。

=&lt;&lt; 则需要笨拙的括号并且似乎是倒着读的:

   (\x -> (\y -> return $ x*y) =<< [10..20]) =<< [1..5]

好吧,你可能会说这感觉更像是函数应用程序。但在有用的地方,只使用 applicative functor 接口而不是 monadic 接口通常更令人心酸:

  (\x y -> x*y) <$> [1..5] <*> [10..20]

或短

  (*) <$> [1..5] <*> [10..20]

请注意,(&lt;*&gt;) :: f (a-&gt;b) -&gt; f a -&gt; f b 基本上具有您建议的=&lt;&lt; 的顺序,只是在函子内部而不是外部的a-&gt;

【讨论】:

  • 谢谢。我的第二个声明更清楚地表明 (>>=) 将 a -> m b 类型的函数映射到 m a -> m b 类型的函数,这是否正确,而原始声明却不太清楚它的含义?
  • 我不知道。也许吧。
  • 它并没有让它更清楚;它使它成为true。原始声明没有a -&gt; m b 类型的函数映射到m a -&gt; m b 类型的函数;它将m a 类型的值映射到(a -&gt; m b) -&gt; m b 类型的函数。但是&gt;&gt;= 的目的不是映射事物,而是“链接”计算; x &gt;&gt;= f 的输出是适合于另一个调用 &gt;&gt;= 的左参数的值:x &gt;&gt;= f &gt;&gt;= g &gt;&gt;= ...
猜你喜欢
  • 1970-01-01
  • 2014-03-23
  • 2015-01-31
  • 2012-04-07
  • 2021-10-15
  • 1970-01-01
  • 2018-01-12
  • 1970-01-01
  • 2016-11-14
相关资源
最近更新 更多