标准ML:不确定高阶函数的类型

时间:2015-07-16 22:01:11

标签: functional-programming sml

我正在阅读Harper的书,标准ML简介,并且在第11.3节“返回函数”中有点困惑。

1)他定义了一个创建常数函数的函数。他写道:

"给定值k,应用程序constantly k生成一个函数,无论何时应用它都会产生k。这是constantly

的定义
val constantly = fn k => (fn a => k)

该功能始终具有'a -> ('b -> 'a)类型。"这对我来说很有意义:你提供了一个类型为' a的值,它返回一个总是返回该值(类型为' a)的函数,无论输入是什么(类型为' b,可能与a&a; a)类型相同或不同。

但他说我们也可以将此功能定义为:

fun constantly k a = k

这看起来像一个函数,它接受两个参数并返回第一个......但不是一个返回另一个函数的函数...

我错过了什么?

2)稍后,哈珀讨论了一个地图功能。我理解基本的地图功能。然后他讨论了一个map函数,它允许我们将传入的函数应用于许多列表(而不是使用相同的传入函数调用我们的原始映射函数多次)。他写道:

fun map' f nil = nil
    | map' f (h::t) = (f h) :: (map' f t)

"如此定义的函数映射具有类型('a -> 'b) -> 'a list -> 'b list。它需要类型' a - >的功能。 ' b作为参数,并产生类型为'a list -> 'b list的另一个函数。"

我很丢失,因为它看起来像地图'只需将f应用于列表中的所有元素并返回结果列表。所以我原以为它会是类型:

('a -> 'b) * 'a list -> 'b list

我哪里错了?

感谢您的帮助, bclayman

2 个答案:

答案 0 :(得分:5)

你的两个问题都源于对函数的实际参数缺乏清晰度。在SML中,每个函数(回想一下函数是值)只需要一个参数。该参数可能是一个元组(类型'a * 'b但它仍然是一个参数(需要被解构)。

在SML中,fun f x1 x2 ... = Tval rec f = fn x1 => fn x2 => ... => T的语法糖。因此constantly k评估为fn a => k

是否为地图提供类型('a -> 'b) * 'a list -> 'b list('a -> 'b) -> 'a list -> 'b list是图书馆设计问题,但效果是一样的。他们做同样的事情,虽然第一个采用函数和列表的元组,而第二个采用函数优先,并从列表返回一个函数到列表。这被称为" currying"在编程语言文学中。 (元组版本是"没有结果",另一个是"咖喱"。)

答案 1 :(得分:5)

这个神奇的词是" currying":https://en.wikipedia.org/wiki/Currying

在ML(以及Haskell)函数应用程序中绑定比任何其他运算符更紧密。因此constantly k a解析为(constantly k) aconstantly k绑定到一个函数。要了解什么功能,您可以在心理上考虑定义

fun constantly k a = k

等同于

fun (constantly k) a = k

这表示(constantly k)是将任何a映射到k的函数。

因此,其类型为'a -> ('b -> 'a),如文中所述。

通过

定义constantly没有任何违法行为
fun constantly (k,a) = k

它将具有您似乎期望的类型'a * 'b -> 'a,但不断地称它为#34;#34;然后有点奇怪,因为它不会是一个常数函数。

我确信哈珀迟早会得到它。 ML和Haskell(尤其是Haskell)都大量使用这些函数。