【问题标题】:Standard ML: Unsure of Type of Higher Order Function标准 ML:不确定高阶函数的类型
【发布时间】:2015-10-06 13:15:31
【问题描述】:

我正在阅读 Harper 的书《标准机器学习简介》,对第 11.3 节“返回函数”有点困惑。

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

“给定一个值 k,应用程序 constantly k 产生一个函数,该函数在应用它时产生 k。这是 constantly 的定义:

val constantly = fn k => (fn a => k)

该函数始终具有 'a -> ('b -> 'a) 类型。” 这对我来说很有意义:您提供一个类型为 'a 的值,它返回一个始终返回该值的函数(类型为 'a),而不管输入( type 'b,可能与 type 'a) 相同,也可能不同。

然后他说我们也可以将这个函数定义为:

fun constantly k a = k

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

我错过了什么?

2) 稍后,Harper 讨论了 map 函数。我了解基本的地图功能。然后他谈到了一个 map 函数,它可以让我们将传入的函数应用于许多列表(而不是多次调用我们的原始 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 类型的函数作为结果。”

我在这里很迷茫,因为它看起来像 map' 只是将 f 应用于列表中的所有元素并返回结果列表。所以我会认为它是类型:

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

我哪里错了?

感谢您的帮助, 布莱曼

【问题讨论】:

标签: functional-programming sml


【解决方案1】:

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

在 SML 中,fun f x1 x2 ... = Tval rec f = fn x1 => fn x2 => ... => T 的语法糖。所以constantly k 计算为fn a => k

你给map的类型('a -> 'b) * 'a list -> 'b list还是('a -> 'b) -> 'a list -> 'b list是库设计问题,但是效果是一样的。他们做同样的事情,虽然第一个接受一个函数和一个列表的元组,而第二个接受这个函数并将一个函数从列表返回到列表。这在编程语言文献中称为“currying”。 (元组版本是“uncurried”,另一个是“curried”。)

【讨论】:

  • 嗯,如果我们给地图第一种类型,不是两个参数都需要在括号内的元组(通常是同质的)中吗?感谢您的帮助!
  • 是的,在第一种形式中,您将参数作为函数和列表的元组传递,例如map (fn x => x + 1, [1,2,3]) 对于期望柯里化形式(SML、Haskell)的函数式程序员来说,这看起来很奇怪,但对于其他人(Lisp、Python)来说却不是。
【解决方案2】:

神奇的词是“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 类型,但是“不断地”调用它有点奇怪,因为它不是一个常量函数。

我相信 Harper 迟早会解决的。此类函数在 ML 和 Haskell(尤其是 Haskell)中大量使用。

【讨论】:

  • 但这只是一个函数定义,对吗?总是不返回函数,对吧?
  • second 定义不是高阶函数(因此它不返回函数),但原始定义是。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-25
  • 1970-01-01
  • 2011-04-07
相关资源
最近更新 更多