在标准ML中找到正确的函数类型

时间:2019-01-25 23:07:51

标签: functional-programming sml

通常包含有关SML的问题的测试会出现一些问题,要求您查找函数的签名/类型。

例如-以下函数的类型是什么?

fun foo f g x y = f (f x (g x) y) y;

解决方案:

val foo = fn : ('a -> 'b -> 'b -> 'a) -> ('a -> 'b) -> 'a -> 'b -> 'b -> 'a

我想知道是否有一个好的算法可以用来解决这些问题。每当我尝试解决其中一个问题时,我都会感到困惑和失败。

2 个答案:

答案 0 :(得分:2)

从您所知道的开始,然后在这里找出一点,直到没有未知为止。

这里是一种可能性:

分别调用未知类型FOOFGXY

然后寻找一些简单易用的东西,然后开始分配类型。

(g x)

显然是一个函数对一个参数的应用。
设置X = aG = a -> b

然后看一下其中的表达式:

(f x (g x) y)
   |   |
   v   v
   a   b

到目前为止,对于某些F,我们知道a -> b -> Y -> C = C

再次向外走:

f (f x (g x) y) y

由于x(f x (g x) y)都是f的第一个参数,因此它们必须具有相同的类型a,并且相同的思想适用于y(g x),为其指定类型b

因此,F = a -> b -> b -> a,并且由于外部f仅给出了两个参数,因此右侧的类型必须为b -> a

因此

X = a
Y = b
G = a -> b
F = a -> b -> b -> a
FOO = (a -> b -> b -> a) -> (a -> b) -> a -> b -> (b -> a)

而且,由于箭头与右侧关联,所以FOO等效于

(a -> b -> b -> a) -> (a -> b) -> a -> b -> b -> a

答案 1 :(得分:0)

有多种方法可以得出函数的类型,具体取决于您想走多近the compiler's algorithm以及您想凭直觉偷工减料,在实践中或考试中可能会很方便,取决于考试重点。

  • An example by Ionuț G. Stan很少出现弯角,并且具有相当冗长的符号。这种机械方法非常安全,可以说明所有内容并花费一些时间。

  • molbdnilo的当前示例具有中间立场,并进行了一些方程式推理,但还依赖于一定程度的直觉。我认为这通常是您希望做到的方式,因为它需要花费较少的时间和空间。

  • An example by me链接到各种其他示例,以实现各种实用方法。