有人可以解释为什么这两个函数有这些类型吗?我想我得到的第一个应该强制g的返回值与x相同,因为(gy)在函数参数中x的位置对应的let的位置,但似乎在第二个功能中,它不能像那样工作。
f3 g x = let h y = f3 g (g y) in g x
(t -> t) -> t -> t
f4 g x = let h y = f4 g (g y) in x
(t1 -> t) -> t -> t
答案 0 :(得分:3)
f3
是两个参数的函数,因此具有类型t2 -> t1 -> t
。由于函数的结果是g x
,因此类型为t
。 g
本身必须是一个参数的函数,x
类型为t1
,因此g
的类型为t2
= t1 -> t
。未使用的h y
定义要求g
接受其结果类型作为导致t1
= t
的参数类型。这将导致(t -> t) -> t -> t
。
f4
也是两个参数的函数,因此具有类型t3 -> t2 -> t
。由于它只返回x
,t2
必须等于t
。 h y
的定义
将g y
约束为t2
类型t
,但不对y
的类型设置约束,让我们调用t1
。这导致t1 -> t
作为g
的类型。替换等式然后导致(t1 -> t) -> t -> t
。
答案 1 :(得分:2)
f3 g x = let h y = f3 g (g y) in g x
让我们先看一个更简单的版本:
f3' g x = g x
此处g
已应用于x
,g
的结果将成为f3'
的结果。因此f3'
的类型为(a -> b) -> a -> b
。
完整的f3
包含子表达式f3 g (g y)
,它引入了一些额外的约束:f3 g
是无害的(没有其他约束,因为g
是我们调用的参数在开头),但(正如你在你的问题中所说)传递g y
作为第二个参数意味着g
的结果必须与x
的结果相同(第二个参数)
这意味着a = b
,因此f3 :: (a -> a) -> a -> a
。
在你的第二个例子中我们有
f4 g x = let h y = f4 g (g y) in x
没有let
,它只是:
f4' g x = x
,其类型为a -> b -> b
。
完整f4
包含f4 g (g y)
。首先,这意味着g
必须是一个函数(因为它应用于y
),所以我们的约束集如下所示:
f4 :: a -> b -> b
g :: a
x :: b
g :: c -> d
a = c -> d
然后(g y)
被用作f4
的第二个参数,这意味着它的类型必须等于b
:
g y :: b
g :: c -> b
y :: c
d = b
h
未被使用,因此y
或f4
没有附加限制。替换f4
类型的变量,我们得到
f4 :: (c -> b) -> b -> b
(相当于(t1 -> t) -> t -> t
模数命名)。