monad bind (>>=) 运算符更接近于函数组合(链接)还是函数应用? [英] Is monad bind (>>=) operator closer to function composition (chaining) or function application?
问题描述
在我读过的许多文章中,monad >>=
运算符是一种表示函数组合的方式.但对我来说更接近于某种高级功能的应用
In many articles I have read that monad >>=
operator is a way to represent function composition. But for me it is closer to some kind of advanced function application
($) :: (a -> b) -> a -> b
(>>=) :: Monad m => m a -> (a -> m b) -> m b
对于组合,我们有
(.) :: (b -> c) -> (a -> b) -> a -> c
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
请澄清.
推荐答案
显然,>>=
不是表示函数组合的一种方式.函数组合只需使用 .
即可完成.但是,我认为您读过的任何文章都没有这个意思.
Clearly, >>=
is not a way to represent function composition. Function composition is simply done with .
. However, I don't think any of the articles you've read meant this, either.
他们的意思是升级"函数组合直接与一元函数"一起工作,即 a -> 形式的函数m b
.这些函数的技术术语是 Kleisli 箭头,实际上它们可以由 <=<
或 >=>
组成.(或者,您可以使用 Category
实例,那么你也可以用 .
或 >>>>
.)
What they meant was “upgrading” function composition to work directly with “monadic functions”, i.e. functions of the form a -> m b
. The technical term for such functions is Kleisli arrows, and indeed they can be composed with <=<
or >=>
. (Alternatively, you can use the Category
instance, then you can also compose them with .
or >>>
.)
然而,谈论箭头/类别往往会让人感到困惑,尤其是初学者,就像普通的point-free定义功能常常令人困惑.幸运的是,Haskell 还允许我们以更熟悉的风格来表达函数,这种风格侧重于函数的结果,而不是函数本身作为抽象态射†.它是用 lambda 抽象完成的:而不是
However, talking about arrows / categories tends to be confusing especially to beginners, just like point-free definitions of ordinary functions are often confusing. Luckily, Haskell allows us to express functions also in a more familiar style that focuses on the results of functions, rather the functions themselves as abstract morphisms†. It's done with lambda abstraction: instead of
q = h . g . f
你可以写
q = (x -> (y -> (z -> h z) (g y)) (f x))
...当然首选的样式是 (这只是 lambda 抽象的语法糖!)‡
...of course the preferred style would be (this being only syntactic sugar for lambda abstraction!)‡
q x = let y = f x
z = g y
in h z
注意,在 lambda 表达式中,基本上组合是如何被应用程序取代的:
Note how, in the lambda expression, basically composition was replaced by application:
q = x -> (y -> (z -> h z) $ g y) $ f x
适应克莱斯利箭,这意味着代替
Adapted to Kleisli arrows, this means instead of
q = h <=< g <=< f
你写
q = x -> (y -> (z -> h z) =<< g y) =<< f x
使用翻转运算符或语法糖当然看起来更好:
which again looks of course much nicer with flipped operators or syntactic sugar:
q x = do y <- f x
z <- g y
h z
所以,确实,=<<
对 <=<
就像 $
对 一样.
代码>.将其称为组合运算符仍然有意义的原因是,除了应用于值"之外,>>>=
运算符还执行有关 Kleisli 箭头组合的重要部分,其功能组合不需要:加入一元层.
So, indeed, =<<
is to <=<
like $
is to .
. The reason it still makes sense to call it a composition operator is that, apart from “applying to values”, the >>=
operator also does the nontrivial bit about Kleisli arrow composition, which function composition doesn't need: joining the monadic layers.
†这样做的原因是 Hask 是一个 笛卡尔封闭类别,特别是明确的类别.在这样的类别中,从广义上讲,箭头可以通过应用于简单参数值时所有结果的集合来定义.
†The reason this works is that Hask is a cartesian closed category, in particular a well-pointed category. In such a category, arrows can, broadly speaking, be defined by the collection of all their results when applied to simple argument values.
‡@adamse 指出 let
并不是 lambda 抽象的真正语法糖.这在递归定义的情况下尤其重要,您不能直接用 lambda 编写.但是在像这里这样的简单情况下,let
的行为就像 lambdas 的语法糖一样,就像 do
符号是 lambdas 的语法糖一样,>>=代码>.(顺便说一句,有一个扩展允许递归即使在
do
符号中......它绕过了lambda-通过使用定点组合器来限制.)
‡@adamse remarks that let
is not really syntactic sugar for lambda abstraction. This is particularly relevant in case of recursive definitions, which you can't directly write with a lambda. But in simple cases like this here, let
does behave like syntactic sugar for lambdas, just like do
notation is syntactic sugar for lambdas and >>=
. (BTW, there's an extension which allows recursion even in do
notation... it circumvents the lambda-restriction by using fixed-point combinators.)
这篇关于monad bind (>>=) 运算符更接近于函数组合(链接)还是函数应用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!