monad绑定(>> =)运算符更接近函数组合(链接)还是函数应用程序? [英] Is monad bind (>>=) operator closer to function composition (chaining) or function application?
问题描述
在很多文章中,我已经读过monad >> =
操作符是表示函数组合的一种方法。但对我来说,它更接近某种高级函数应用程序。
($)::(a - > b) - > a - > b
(>> =):: Monad m => m a - > (a - > m b) - > mb
对于构图,我们有
<$ p $ (。)::(b - > c) - > (a - > b) - > a - > c
(> =>):: Monad m => (a - > m b) - > (b→m c)→> a - > mc
请澄清。
>> =
不是表示函数组合的方法。 函数组合只需使用。
完成。然而,我认为你读过的任何文章都不意味着这一点。 他们的意思是升级函数组合直接与一元函数一起工作,即 a - >的函数。 m b
。这些功能的技术术语是Kleisli箭头,实际上它们可以由< =< / code>或>组成; =>
。 (或者,您可以使用 类别
实例,那么你也可以用。
或>>> $ )然而,谈论箭头/类别往往会让初学者感到困惑,就像 .org / Point-free>普通函数的无点定义常常令人困惑。幸运的是,Haskell允许我们以更熟悉的风格来表达函数,这些函数专注于函数的结果,而函数本身就是抽象态射体† 。它完成了lambda抽象:而不是
q = h。 G 。 f
您可以写出
q =(\ x - >(\ y - >(\ z - > hz)(gy))(fx))
...当然,首选样式是 (这只是lambda抽象的语法糖!) ‡
qx = let y = fx
z = gy
in hz
请注意,在lambda表达式中,基本组合是如何被应用程序替换的:
q = \x - > (\y->(\z-> hz)$ gy)$ fx
根据Kleisli箭头,这意味着代替
q = h <=< g< =< f
您写下
q = \x - > (\ z→> h z)=<< g y)=<< fx
当然翻转后的操作符或语法糖看起来更好:
qx = do y < - fx
z < - gy
hz
因此,实际上, = <
$
就是。
。把它称为组合运算符仍然有意义的原因是,除了应用于值之外,>> =
运算符也会执行非平凡位Kleisli箭头组成,其功能组成不需要:加入monadic层。
† 其原因是 Hask 是笛卡尔封闭类别,in特别是高分类。在这样的类别中,广义上讲,箭头可以通过将其所有结果的集合应用于简单参数值来定义。 ; @adamse注释 In many articles I have read that monad For composition we have Please clarify. Clearly, What they meant was “upgrading” function composition to work directly with “monadic functions”, i.e. functions of the form 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 you may write ...of course the preferred style would be (this being only syntactic sugar for lambda abstraction!)‡ Note how, in the lambda expression, basically composition was replaced by application: Adapted to Kleisli arrows, this means instead of you write which again looks of course much nicer with flipped operators or syntactic sugar: So, indeed, †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 remarks that 这篇关于monad绑定(>> =)运算符更接近函数组合(链接)还是函数应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! let
对于lambda抽象来说并不是真正的语法糖。在递归定义的情况下,这是非常重要的,你不能直接用lambda来写。但在这样的简单情况下, let
的行为就像lambda表达式的语法糖一样,就像 do notation是语法糖为lambdas和
>> =
。 (顺便说一句,有一个扩展允许递归甚至在 do
>符号中。它通过使用定点组合器规避了lambda限制。)>>=
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
>>=
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
. 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 >>>
.)q = h . g . f
q = (\x -> (\y -> (\z -> h z) (g y)) (f x))
q x = let y = f x
z = g y
in h z
q = \x -> (\y -> (\z -> h z) $ g y) $ f x
q = h <=< g <=< f
q = \x -> (\y -> (\z -> h z) =<< g y) =<< f x
q x = do y <- f x
z <- g y
h z
=<<
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.
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.)