[英]Understanding monadic function composition
我正在从“Learn You a Haskell for Great Good!”一书中学习 monads。 通过米兰利波瓦卡。 我试图理解 monad 的结合律。 本质上,法律规定,当您拥有一串带有>>=
的单子函数应用程序时,它们的嵌套方式无关紧要。
以下代码可以将a -> mb
类型的函数的结果传递给b -> mc
类型的函数:
(<=<) :: (Monad m) => (b -> m c) -> (a -> m b) -> (a -> m c)
f <=< g = (\x -> g x >>= f)
但是,对于下面的示例:
ghci> let f x = [x, -x]
ghci> let g x = [x*3, x*2]
ghci> let h = f <=< g
ghci> h 3
[9, -9, 6, -6]
fx
和gx
都是函数吗? 似乎它们是具有不同 x 值而不是函数的列表。 在上面的代码中,这行let h = f <=< g
工作的? f
和g
必须是函数,因为它们与<=<
一起使用,但我不确定它们是什么。
f x = [x, -x]
这是普通的函数定义语法。 我们正在定义一个新函数f
,写下它应用于假设值x
时会产生什么。
let
(无论是作为语句还是let ... in ...
表达式)只是引入了一个可以进行定义的块,就像where
一样。 定义本身使用与全局定义相同的语法。
如果您知道如何通过在文件中编写例如plusOne n = n + 1
来定义函数,那么此语法是完全相同的(如果您不知道该怎么做,那么我建议您阅读一些介绍性教程在尝试理解 monadic 函数组合之前,请先了解基本的 Haskell 语法)。
所以在这些定义之后f
和g
是函数。 fx
和gx
没有真正意义,因为您没有将它们应用到的x
范围。
如果您在范围内确实有这样的值,那么fx
将是一个计算结果为列表的表达式,其中涉及调用函数f
。 说fx
或gx
是函数仍然是不正确的。
所以现在应该清楚let h = f <=< g
通过将<=<
运算符应用于f
和g
来定义一个新值h
。
没有什么比在一张纸上手工完成定义更能获得理解的感觉了。
fx = [x, -x]
也可以写成f = (\\ x -> [x, -x])
。 因此
h 3
= {- by def of h -}
(f <=< g) 3
= {- by def of (<=<) -}
(\x -> g x >>= f ) 3
= {- by defs of f and g -}
(\x -> (\ x -> [x*3, x*2]) x >>= (\ x -> [x, -x])) 3
= {- by substitution -}
(\ x -> [x*3, x*2]) 3 >>= (\ x -> [x, -x])
= {- by substitution -}
[3*3,
3*2] >>= (\ x -> [x, -x])
= {- by definition of (>>=) for [] -}
concat [ (3*3) & (\ x -> [x, -x]) -- x & f == f x
, (3*2) & (\ x -> [x, -x])
]
= {- by definition of concat -}
(3*3) & (\ x -> [x, -x])
++ (3*2) & (\ x -> [x, -x])
=
[9, -9, 6, -6]
(编辑)有关图片以及对这些Kleisli 箭头及其可组合性的更多讨论,请参阅我的这个较旧的答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.