考虑功能
f g h x y = g (g x) (h y)
它是什么类型?显然,我可以使用它:t f
来找出答案,但是如果我需要手动进行推断,那么最好的方法是什么?
我已被证明的方法是将类型从那里分配到的参数和演绎-例如x :: a
,y :: b
为我们提供了g :: a -> c
和h :: b -> d
一些c
,d
(从g x
,h y
)然后我们继续扣减从那里(c = a
距离g (g x) (h y)
等)。
但是,有时这会变成一团糟,通常我不确定如何做进一步的推论或完成后如何解决。有时还会发生其他问题-例如,在这种情况下,结果x
将是一个函数,但是在我作弊和查找类型之前,这对我来说并不明显。
是否存在始终有效的特定算法(并且对于人类快速执行是合理的)?否则,我是否缺少一些启发式或技巧?
让我们在顶层检查功能:
f g h x y = g (g x) (h y)
我们将从为类型分配名称开始,然后随着对函数的更多了解,对它们进行专门化处理。
首先,让我们为顶部表达式分配一个类型。我们称之为a
:
g (g x) (h y) :: a
让我们取出第一个参数并分别分配类型:
-- 'expanding' (g (g x)) (h y) :: a
h y :: b
g (g x) :: b -> a
然后再次
-- 'expanding' g (g x) :: b -> a
g x :: c
g :: c -> b -> a
然后再次
-- 'expanding' g x :: c
x :: d
g :: d -> c
但是请坚持:我们现在拥有g :: c -> b -> a
那个g :: d -> c
。因此,通过检查,我们知道c
和d
是等价的(书面的c ~ d
)以及c ~ b -> a
。
可以通过简单比较g
我们推断出的两种类型来推断出这一点。请注意,这不是类型矛盾,因为类型变量的通用性足以满足其等效要求。这将是一个矛盾,如果我们推断,例如,是Int ~ Bool
什么地方。
因此,我们现在总共获得以下信息:(省略了一些工作)
y :: e
h :: e -> b
x :: b -> a -- Originally d, applied d ~ b -> a.
g :: (b -> a) -> b -> a -- Originally c -> b -> a, applied c ~ b -> a
这是通过用每种类型的变量,即取代的最具体的形式进行c
,并d
用于更具体的b -> a
。
因此,只需检查哪些参数到达哪里,我们就会看到
f :: ((b -> a) -> b -> a) -> (e -> b) -> (b -> a) -> e -> a
这由GHC证实。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句