Haskell中(.)(.)函数的去无点式推导及原理咨询
拆解 Haskell 中的
(.)(.) 函数 我太懂这种对着无点式一脸懵的感觉了——尤其是这种全是运算符的组合,完全像看天书!咱们一步一步来,先搞清楚(.)(.)的去无点式版本,再反向推回无点式,保证你能彻底搞明白。
先回忆(.)的核心定义
函数组合运算符(.)的标准定义和类型是:
(.) :: (b -> c) -> (a -> b) -> a -> c (.) f g x = f (g x)
简单说就是:把g运行在x上的结果,再传给f运行,f . g等价于\x -> f (g x)。
第一步:写出(.)(.)的去无点式版本
我们给(.)(.)起个名字f,也就是f = (.)(.)。现在通过展开定义,把它转换成带参数的形式:
(.)是柯里化函数,所以(.)(.)其实是(.)作为第一个参数,传给另一个(.),也就是(.) (.)。- 根据
(.)的定义,(.) f1 f2 = \x -> f1 (f2 x),所以(.) (.) = \g -> (.) ((.) g)。 - 再展开
(.) ((.) g):(.) f1 f2 = \x -> f1 (f2 x),这里f1是(.) g,所以(.) ((.) g) = \h -> (.) g h。 - 再展开
(.) g h:根据定义,(.) g h = \x -> g (h x)。 - 现在,
\x -> g (h x)是一个接受x后返回c->d类型的函数(因为g是b->c->d,h x是b,所以g (h x)是c->d),它还能接受一个参数y,最终得到g (h x) y。
把这些步骤整合起来,f的带参数版本(去无点式)就是:
f g h x y = g (h x) y
我们用ghci验证一下:
-- 定义带参数的版本 f g h x y = g (h x) y -- 无点式版本 f' = (.)(.) -- 测试减法的情况 f (-) (*) 2 3 -- 结果是 (- ((*2))) 3 = 6 - 3 = 3 f' (-) (*) 2 3 -- 结果同样是3,完全一致!
第二步:从去无点式逐步推回(.)(.)
现在按照你给的示例风格,一步步反向推导,从带参数的版本回到无点式:
- 从最基础的带参数版本开始:
f g h x y = g (h x) y - 注意到
g (h x)是一个接受y的函数,所以g (h x) y等价于(g (h x)) y。两边都应用了y,可以直接去掉y:f g h x = g (h x) - 现在,
g (h x)正好符合(.)的定义:(.) g h x = g (h x),替换成组合的形式:f g h x = (.) g h x - 两边都应用了
x,可以直接去掉x:f g h = (.) g h - 现在,
(.) g h是(.)先接受g再接受h,也就是((.) g) h。而\h -> ((.) g) h就是(.) g(柯里化特性:函数本身就是接受参数的),所以:f g = (.) g - 最后,
\g -> (.) g就是把(.)作为参数传给(.),也就是(.)(.)——因为(.)是柯里化的,(.) (.)等价于\g -> (.) g,至此我们就推回了无点式版本:f = (.)(.)
内容的提问来源于stack exchange,提问作者Erik
相关产品推荐
相关产品推荐

