我试图了解Kleisli,即>=>
提供的内容超过bind
(>>=
)。
分别查看bind
和Klesli
的签名:
λ: :t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
λ: :t (>=>)
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
然后这个例子:
λ: let plus10 = \x -> return (x + 10)
λ: let minus5 = \x -> return (x - 5)
我可以使用任一函数调用:
λ: return 5 >>= plus10 >>= minus5
10
λ: (>=>) plus10 minus5 5
10
当然这只是一个简单的例子。但是,Kleisli
对bind
的重要性是什么?通过查看它们的函数定义,我想知道是否可以使用Kleisli
重写每个bind
函数用法。
答案 0 :(得分:3)
它与(.)
和($)
(或函数应用程序)之间的差异或多或少相似。
例如,如果我想计算列表中偶数的数量,我可以这样做:
countEven = length . filter even
或者我能做到
countEven xs = length $ filter even $ xs
这真的是一样的东西,最后编译/内联到同一个东西,但这两个“意味着”不同的东西。
第一个说,“countEven
是偶数过滤列表的长度”。第二个说,“要获取此列表中的平均数,请使用filter even
进行过滤,然后将length
应用于结果”。
说同样事情的不同方式。你绝对可以用另一个来实现一个:
f . g = \x -> f $ g $ x
答案 1 :(得分:0)
正如贾斯汀说的那样.
。您可以将(>=>) plus10 minus5 5
重写为return 5 >>= (plus10 >=> plus5)
,您可以轻松比较两个版本
λ: return 5 >>= plus10 >>= minus5
10
λ: return 5 >>= (plus10 >=> minus5)
10
换句话说,如果你想写一个无点版本,你不能只写plus10 >>= minus5
,而是需要使用>=>
。