bcl*_*man 0 functional-programming sml
我正在阅读Harper的书,标准ML简介,并且在第11.3节"返回函数"中有点困惑.
1)他定义了一个创建常数函数的函数.他写:
"给定一个值k,应用程序constantly k产生一个函数,k无论何时应用它都会产生.这是一个定义constantly:
val constantly = fn k => (fn a => k)
Run Code Online (Sandbox Code Playgroud)
函数经常有类型'a -> ('b -> 'a)."这对我来说很有意义:你提供一个'a'类型的值,它返回一个总是返回该值(类型为'a)的函数,无论输入是什么(类型'b,可能是或者可能与'a)类型不同.
但他说我们也可以将此功能定义为:
fun constantly k a = k
Run Code Online (Sandbox Code Playgroud)
这看起来像一个函数,它接受两个参数并返回第一个...但不是一个返回另一个函数的函数...
我错过了什么?
2)稍后,哈珀讨论了一个地图功能.我理解基本的地图功能.然后他讨论了一个map函数,它允许我们将传入的函数应用于许多列表(而不是使用相同的传入函数调用我们的原始映射函数多次).他写:
fun map' f nil = nil
| map' f (h::t) = (f h) :: (map' f t)
Run Code Online (Sandbox Code Playgroud)
"如此定义的函数映射具有类型('a -> 'b) -> 'a list -> 'b list.它采用类型'a - >'b的函数作为参数,并产生另一个类型的函数'a list -> 'b list作为结果."
我在这里很丢失,因为看起来map'只是将f应用于列表中的所有元素并返回结果列表.所以我原以为它会是这样的类型:
('a -> 'b) * 'a list -> 'b list
Run Code Online (Sandbox Code Playgroud)
我哪里错了?
谢谢你的帮助,bclayman
你的两个问题都源于对一个函数的实际参数缺乏明确性.在SML中,每个函数(回想一下函数是值)只需要一个参数.该参数可能是一个元组(类型'a * 'b但它仍然是一个参数(需要被解构).
在SML中,fun f x1 x2 ... = T是语法糖val 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".(元组版本是"uncurried",另一个是"curried".)
神奇的词是"currying":https://en.wikipedia.org/wiki/Currying
在ML(以及Haskell)中,函数应用程序比任何其他运算符都更紧密.因此constantly k a解析为(constantly k) a.constantly k绑定到一个函数.要了解什么功能,您可以在心理上考虑定义
fun constantly k a = k
Run Code Online (Sandbox Code Playgroud)
相当于
fun (constantly k) a = k
Run Code Online (Sandbox Code Playgroud)
这表示这(constantly k)是将任何a映射到k的函数.
因此'a -> ('b -> 'a),正如文中所要求的那样.
定义constantlyvia 没有任何违法行为
fun constantly (k,a) = k
Run Code Online (Sandbox Code Playgroud)
它将具有'a * 'b -> 'a您似乎期望的类型,但是"不断地"调用它然后有点奇怪,因为它不是一个常量函数.
我相信哈珀迟早会得到它.ML和Haskell(尤其是Haskell)都大量使用这些函数.
| 归档时间: |
|
| 查看次数: |
60 次 |
| 最近记录: |