h1 f g x y = f (g x y) x
因此,从左到右获取参数列表:
f
是一个应用于两个参数的函数:第一个是结果,(g x y)
第二个是x
- 我们还不知道第一个参数是什么类型,所以我们称之为
a
- 我们也不知道第二种类型,所以我们称之为
b
- 我们也不知道结果类型(所以我们称之为
c
),但我们知道这一定是返回的类型h1
g
是应用于两个参数的函数:第一个是x
,第二个y
- 我们知道 的第一个参数
g
与 的第二个参数相同f
,所以它必须是相同的类型:我们已经标记了b
g
is的第二个参数y
,我们还没有分配占位符类型,所以它会依次获得下一个,d
g
的结果是 的第一个参数f
,我们已经将其标记为a
- 第三个参数是
x
,因为这是 的第二个参数f
,我们已经标记了它的类型b
- 第四个参数是
y
,这是 的第二个参数g
,所以我们已经标记了它的类型d
- 的结果
h1
是应用f
到的结果(g x y) x
,正如我们之前所说,所以它具有相同的类型,已经标记c
尽管我们按顺序处理了参数列表,但为每个参数标记、推断和统一类型的实际过程是通过查看.h1
因此,我的第一个项目符号可以详细说明为:
f
是要考虑的第一个参数,所以让我们看看h1
(之后的所有内容=
)的主体,看看它是如何使用的
f (g x y) x
表示f
应用于(g x y) x
,因此f
必须是函数
(g x y)
在括号中,这意味着正在评估这些括号内的任何内容,并且该评估的结果是f
x
只是一个简单的参数f
,直接从h1
自己的参数列表传递
- 所以,
f
是一个有两个参数的函数
如果它有助于阅读f (g x y) x
,您可以考虑使用类 C 表示法的等效表达式是f(g(x,y), x)
. 在这里,您可以立即看到f
和g
是带有两个参数的函数,f
第一个参数是g
返回的值,等等。
请注意,表达式的左侧h1 f g x y
仅给出了一条类型信息:它h1
是一个有四个参数的函数。参数名称本身只是表达式右侧(的主体h1
)中使用的占位符。这里参数的相对顺序只是告诉我们如何调用h1
,但没有告诉我们如何h1
在内部使用参数。
同样,这是一个程序样式的等价物(我将使用 Python,因此不必填写任何类型):
def h1(f, g, x, y):
return f(g(x,y),x)
这意味着与
h1 f g x y = f (g x y) x
(有一个警告 - 部分应用 - 我怀疑只会在这里进一步混淆问题)。
在这两种情况下,声明(=
在 Haskell 中的左侧,:
在 Python 中的之前)只告诉我们函数名称和它需要多少个参数。
在这两种情况下,我们可以从定义(Haskell 中的右侧,Python 中的缩进块)推断出和都是两个参数的函数,第一个参数与第二个参数相同,等等。在 Haskell ,编译器为我们做这件事;如果我们使用错误数量的参数调用,Python 只会在运行时抱怨,或者它返回的东西不能用作第一个参数。:
f
g
g
f
g
f