当前位置:  开发笔记 > 编程语言 > 正文

monad绑定(>> =)运算符更接近函数组合(链接)或函数应用程序吗?

如何解决《monad绑定(>>=)运算符更接近函数组合(链接)或函数应用程序吗?》经验,为你挑选了2个好方法。

在许多文章中我都读过monad >>=运算符是一种表示函数组合的方法.但对我来说,它更接近某种高级功能应用程序

($)   :: (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

请澄清.



1> leftaroundab..:

显然,>>=这不是表示功能组合的一种方式.功能组合简单完成..但是,我认为你读过的任何文章都不是这个意思.

他们的意思是"升级"功能组合以直接使用"monadic functions",即表单的功能a -> m b.这些功能的技术术语是Kleisli箭头,实际上它们可以用<=<或组成>=>.(或者,您可以使用Category实例,然后您也可以使用.或组合它们>>>.)

然而,谈论箭头/类别往往会让初学者感到困惑,就像普通函数的无点定义常常令人困惑一样.幸运的是,Haskell允许我们以更熟悉的方式表达函数,这些方式关注函数的结果,而不是函数本身作为抽象的态射.它完成了lambda抽象:而不是

q = h . g . f

你可以写

q = (\x -> (\y -> (\z -> h z) (g y)) (f x))

...当然首选的风格是(这只是lambda抽象的语法糖!)

q x = let y = f x
          z = g y
      in h z

请注意,在lambda表达式中,基本上组合被应用程序替换:

q = \x -> (\y -> (\z -> h z) $ g y) $ f x

适应Kleisli箭头,这意味着而不是

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

所以,的确=<<<=<喜欢$..将其称为合成运算符仍然有意义的原因是,除了"应用于值"之外,>>=运算符还执行关于Kleisli箭头合成的重要位,其中函数合成不需要:加入monadic层.


其工作原因是Hask是一个笛卡尔闭合类别,特别是一个明确的类别.在这样的类别中,广义地说,箭头可以在应用于简单参数值时通过其所有结果的集合来定义.

@adamse评论let对于lambda抽象来说并不是真正的语法糖.这在递归定义的情况下尤为重要,您无法使用lambda直接编写.但是在这样的简单情况下,let对于lambdas来说,表现就像语法糖,就像do符号是lambdas和>>=.的语法糖一样.(顺便说一句,有一个扩展,即使在do表示法中也允许递归...它通过使用定点组合器来规避lambda限制.)


我认为在Haskell中让绑定为lambdas的糖是不正确的:https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-440003.12

2> Will Ness..:

就像一个例子,考虑一下:

($)                ::   (a -> b) ->   a ->   b
let g=g in (g  $)  ::                 a ->   b
            g      ::   (a -> b)
                                     _____
Functor f =>                        /     \
(<$>)              ::   (a -> b) -> f a -> f b
let g=g in (g <$>) ::               f a -> f b
            g      ::   (a -> b) 
                       ___________________
Applicative f =>      /             /     \
(<*>)              :: f (a -> b) -> f a -> f b
let h=h in (h <*>) ::               f a -> f b
            h      :: f (a -> b)
                             _____________
Monad m =>                  /.------.     \
(=<<)              :: (a -> m b) -> m a -> m b
let k=k in (k =<<) ::               m a -> m b
            k      :: (a -> m b)

所以,是的,每一个(g <$>),(h <*>)或者(k =<<),是某种功能应用程序,被提升为Functor,Applicative Functor或Monad"context".并且(g $)只是常规类型功能的常规应用.

随着仿函数,函数有没有影响f整体分量的东西.它们严格地在内部工作,不能影响"包装".

使用Applicatives,函数包含在一个包中f,该包装与一个参数(作为应用程序的一部分)相结合,以产生结果的包装.

使用Monads,函数本身现在可以生成包装结果,从包装参数(作为应用程序的一部分)中以某种方式提取它们的参数.

我们可以看到三个运算符作为函数上的某种标记,就像数学家喜欢写说f'f^f*(在Eugenio Moggi的原始作品中(1) f*正是使用的,表示提升的函数(f =<<)).

当然,通过推广的功能:: f a -> f b,我们可以将它们链接起来,因为现在这些类型排成一行.促销是允许组成的.


(1) "计算和单子的概念",Eugenio Moggi,1991年7月.

更多关于组合性,图片:Monads with Join()而不是Bind()


因此,仿函数"神奇地在里面工作""管道"; 适用的是"预先用部件制造的预制管"; 和monads是"我们去建设管网".举例说明:

在此输入图像描述

推荐阅读
吻过彩虹的脸_378
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有