Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 功能组合(.)是如何从内部工作的?_Haskell_Lambda_Syntax_Function Composition - Fatal编程技术网

Haskell 功能组合(.)是如何从内部工作的?

Haskell 功能组合(.)是如何从内部工作的?,haskell,lambda,syntax,function-composition,Haskell,Lambda,Syntax,Function Composition,我在学习哈斯克尔。目前,我正在学习函数合成。我了解(至少在基本层面上)如何使用函数(.),但有两件事我不了解 因此,函数如下所示: (.) :: (b -> c) -> (a -> b) -> a -> c f . g = \x -> f (g x) 首先,类型声明(b->c)->(a->b)本质上意味着函数f从函数g(取值a)的结果值(b)中获取一个参数,并返回c类型的值。我不明白下面的部分->a->c,为什么那里应该有->a?为什么(b->c)->(a-

我在学习哈斯克尔。目前,我正在学习函数合成。我了解(至少在基本层面上)如何使用函数
(.)
,但有两件事我不了解

因此,函数如下所示:

(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> f (g x)
首先,类型声明
(b->c)->(a->b)
本质上意味着函数
f
从函数
g
(取值
a
)的结果值(
b
)中获取一个参数,并返回
c
类型的值。我不明白下面的部分
->a->c
,为什么那里应该有
->a
?为什么
(b->c)->(a->b)->c
错了?在我看来(这显然是错误的),函数
g
已经将
a
作为参数

第二,函数体
f。g=\x->f(gx)
\x->
在这里做什么?Lambda非常直截了当。例如
过滤器(\(a,b)->a+b>4)[(1,2)、(3,4)]
,但是一个简单的
\x->
会让我陷入困境。我可能会这样写身体
f。(gx)=f(gx)
(这显然又错了)。

(b->c)->(a->b)->c
将是一个函数,它包含两个函数
f::b->c
g::a->b
,并以某种方式调用
g
,而不使用
a
类型的初始参数

对于第二个问题,考虑如何使用前缀表示法来定义<代码>(?)/COD>。(如果我们为函数使用“常规”名称,可能会更容易看到;我将在每个代码片段后面添加注释):

x
(.)
的“第三个参数”,或者更准确地说是
(.)f g
返回的函数的参数。这相当于通过将函数放在右侧而不是该函数的最终返回值,将
(.)f g
直接定义为函数:

(.) f g x =       f (g x)  -- Implicit function def: compose f g x =       f (g x)
(.) f g   = \x -> f (g x)  -- Explicit function def: compose f g   = \x -> f (g x)
也可以使用括号隐式定义函数:

(f . g) x = f (g x)

可能更容易理解为
()::Fun1->Fun2->Fun3
,也就是说,
(。
接受一个
Fun1
类型的参数(一个函数),然后是另一个
Fun2
类型的参数(另一个函数),并返回一个
Fun3
类型的值(另一个函数,“组合”函数)。具体来说,
Fun1=(b->c)
Fun2=(a->b)
,以及
Fun3=(a->c)
。实际上,你可以在你的类型中的
a->c
周围加上括号——它们是隐式的;这里有一对隐含的括号,尽可能向右,所以
f。g=\x->f(gx)
实际上是
f。g=(\x->f(gx))
,一个lambda(a的表示法)函数。使用显式lambda定义它的原因与GHC编译器中程序优化的细节有关。作为初学者,您当然不必担心这些问题,但编写关键库函数的人确实考虑到了这一点,这是很有帮助的,这样您的代码运行得更快。
(f . g) x = f (g x)