通常包含有关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
我想知道是否有一个好的算法可以用来解决这些问题。每当我尝试解决其中一个问题时,我都会感到困惑和失败。
答案 0 :(得分:2)
从您所知道的开始,然后在这里找出一点,直到没有未知为止。
这里是一种可能性:
分别调用未知类型FOO
,F
,G
,X
和Y
。
然后寻找一些简单易用的东西,然后开始分配类型。
(g x)
显然是一个函数对一个参数的应用。
设置X
= a
和G
= 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链接到各种其他示例,以实现各种实用方法。