Haskell monad bind(>;=)运算符是否更接近函数组合(链接)或函数应用程序?
在许多文章中,我读到monadHaskell monad bind(>;=)运算符是否更接近函数组合(链接)或函数应用程序?,haskell,functional-programming,bind,monads,category-theory,Haskell,Functional Programming,Bind,Monads,Category Theory,在许多文章中,我读到monad>=操作符是表示函数组合的一种方法。但对我来说,它更接近于某种高级功能应用 ($) :: (a -> b) -> a -> b (>>=) :: Monad m => m a -> (a -> m b) -> m b 我们的作文 (.) :: (b -> c) -> (a -> b) -> a -> c (>=>) :: Monad m => (a -&g
>=
操作符是表示函数组合的一种方法。但对我来说,它更接近于某种高级功能应用
($) :: (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
请澄清。显然,
>=
不是表示函数组合的方式。函数组合只需使用
即可完成。然而,我认为你读过的任何文章也不是这个意思
他们的意思是“升级”函数组合以直接使用“一元函数”,即a->mb
形式的函数。这些函数的技术术语是Kleisli箭头,实际上它们可以由
组成。(或者,您可以使用,然后也可以使用
或>>
组合它们)
然而,谈论箭头/类别往往会让人困惑,特别是对初学者来说,就像普通函数一样,通常会让人困惑。幸运的是,Haskell允许我们以一种更熟悉的方式来表达函数,这种方式侧重于函数的结果,而不是函数本身作为抽象态射†。它是用lambda抽象完成的:而不是
q = h . g . f
q = h <=< g <=< f
你可以写信
q = (\x -> (\y -> (\z -> h z) (g y)) (f x))
…当然,首选的样式是(这只是lambda抽象的语法糖!)&ddagger
请注意,在lambda表达式中,基本上合成是如何被应用程序替换的:
q = \x -> (\y -> (\z -> h z) $ g y) $ f x
适用于Kleisli箭头,这意味着
q = h . g . f
q = h <=< g <=< f
q=h(\z->hz)=>=
。(BTW,有一个扩展,它允许递归……它通过使用定点组合器绕过λ限制。) < P>作为一个例子,考虑如下:
($) :: (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)
($)::(a->b)->a->b
设g=g(g$)::a->b
g::(a->b)
_____
函子f=>/\
()::(a->b)->f a->f b
设g=g(g)::fa->fb
g::(a->b)
___________________
应用f=>//\
()::f(a->b)->f a->f b
设h=h(h)::fa->fb
h::f(a->b)
_____________
单子m=>/.----\
(=MA->MB
设k=k in(k=mb)
是的,每一个都是,
(g)
,(h)
或(k=我认为关于表示函数组合的引用引用是指函数作为monad实例的>=
。我认为在Haskell中说let绑定是lambdas的糖分是不正确的:@adamse:right,let
确实比lambdas更一般。它们的flippe更为明显d变体:(=mb)->ma->mb
和((a->mb)->(a->mc)
。还有Applicative
版本:()::Applicative m=>m(a->b)->ma->mb和liftA2(::Applicative m=>m(b->c)->m(a->b)->m(a->b)->c)
你的问题没有真正的答案。归根结底,一元绑定就是它,不多不少。也就是说,你的观点是完全“合理的”*-只是你不应该试图在这里发现“真理”,也许你应该接受“组合”的类比让你走到了这一步(这是非常远的!)不要担心它的缺陷。一种考虑方法是函数应用程序获取一个普通类型的值并将函数应用于它。另一方面,Bind获取一个修饰类型的值,ma
。这个值一定是由某个修饰函数创建的(可能是return
)。所以bind实际上是用另一个函数(continuation)组合创建值的函数。应用程序也可以用于组合,但它也可以作用于文本。当然,可以用以单位为单位的lambda替换文本,然后应用程序就是简化的组合。
($) :: (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)