【发布时间】:2020-09-30 03:36:58
【问题描述】:
我已经学习 Haskell 几个星期了(只是为了好玩),刚刚看了 Brian Beckman 的精彩 video introducing monads。他激励 monads 需要创建一个更通用的组合运算符。按照这个思路,如果我有两个功能:
f :: a -> b
g :: b -> c
合成运算符应满足
h = g . f :: a -> c
由此我可以推断出. 运算符的正确类型:
(.) : (b -> c) -> (a -> b) -> (a -> c)
说到 monad,假设我有两个函数:
f :: a -> m b
g :: b -> m c
在我看来,自然的选择是定义一个通用的组合运算符,其工作原理如下:
h = f >>= g :: a -> m c
在这种情况下,>>= 运算符的类型签名为:
(>>=) :: (a -> m b) -> (b -> m c) -> (a -> m c)
但实际上操作符似乎是这样定义的
h a = (f a) >>= g :: m c
因此
(>>=) : m b -> (b -> m c) -> m c
有人可以解释选择绑定定义背后的原因吗?我认为这两种选择之间存在一些简单的联系,其中一种可以用另一种来表达,但我目前还没有看到。
【问题讨论】:
-
您的运营商存在and is called
(>=>)。正如您所怀疑的,它可以用(>>=)来定义,反之亦然。(>>=)比(>=>)更常用,因为在实践中,它在大多数情况下往往更方便。相关讨论见this answer,以及this one 的第一部分(尽管反过来看问题)。 -
简而言之,组合与应用类似。两者都很有用,但应用程序通常在编程中更常见。
-
Awesome... 应用程序语法在大多数情况下应该更方便是有道理的。
-
我会说你的提议(被称为“kleisli composition”
(<=<))实际上比(>>=)更基本,从数学上讲,(>>=)主要是程序员偏向的方便。