Functional programming 在标准ML中查找正确的函数类型

Functional programming 在标准ML中查找正确的函数类型,functional-programming,sml,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 我想知道是否有一个好的算法,我可以遵循,以解决这类问题。每次我试图解决其中一个问题时,我都会感到困惑并失

通常,包含有关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

我想知道是否有一个好的算法,我可以遵循,以解决这类问题。每次我试图解决其中一个问题时,我都会感到困惑并失败。

从你所知道的开始,然后在这里和那里想一想,直到没有未知

这里有一种可能性:

分别调用未知类型
FOO
F
G
X
Y

然后找一些小而简单的东西,开始分配类型

(g x)
显然是一个函数对一个参数的应用。
设置
X
=
a
G
=
a->b

然后查看封闭表达式:

(f x (g x) y)
   |   |
   v   v
   a   b
到目前为止,我们知道对于一些
C
,F=
a->b->Y->C

再向外走:

f (f x (g x) y) y
由于
x
(fx(gx)y)
都是
f
的第一个参数,因此它们必须是相同类型的
a
,相同的思想适用于
y
(gx)
,给它们类型
b

因此,
F
=
a->b->b->a
并且,由于外部的
F
只提供了两个参数,因此右侧的类型必须是
b->a

因此

而且,由于箭头与右侧关联,
FOO
相当于

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

有几种方法可以导出函数的类型,这取决于你想走的距离有多近,以及你想用直觉走捷径的程度,这在实践中可能很方便,在考试中也可能很方便,这取决于考试的重点

  • 切入很少,并且有一个相当详细的符号。这种机械方法是非常安全的,可以解释一切,并且需要一些时间

  • molbdnilo目前的例子采取了中间立场,进行了一些等式推理,但也依赖于某种程度的直觉。我认为这通常是你希望能够做到的方式,因为手工操作花费的时间和空间更少

  • 链接到实践方法多样性的各种其他示例


SML使用类型推断,但不知何故,我不认为您要求的是一个实际的算法,而是一个简单的启发式算法。如果是这样的话,这个问题就太模糊了。@SimonShine的可能重复我不认为它是重复的(尽管它们相似),因为另一个问题是针对一些具体的例子,这个问题更多的是关于一般方法。这也许有点太笼统了,但既然molbdnilo给出了一个有用的答案,我想我会收回我的“过于广泛”的接近票。我已经看过好几次这个问题,是“我如何执行类型推断?”和“…给出了这个实际的例子。”上次我回答时,我链接到了这个问题的其他五个例子。因此,如果这个问题是一般性的,那么就应该有一个答案,如果它有助于一个具体的例子,那么它们似乎通常不被使用。或许,我不应该投票以“重复的”作为结束,而应该简单地链接到现有的问题,因为其他具体的例子之一可能已经足够相似了。此外,我对@molbdnilo的回答表示赞赏并投了赞成票。我一般不介意SML的问题是家庭作业,因为这似乎是SML的命运。:-)
(a -> b -> b -> a) -> (a -> b) -> a -> b -> b -> a