Haskell中的手动类型推断

上午

考虑功能

f g h x y = g (g x) (h y)

它是什么类型?显然,我可以使用它:t f来找出答案,但是如果我需要手动进行推断,那么最好的方法是什么?

我已被证明的方法是将类型从那里分配到的参数和演绎-例如x :: ay :: b为我们提供了g :: a -> ch :: b -> d一些cd(从g xh 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因此,通过检查,我们知道cd是等价的(书面的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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章