SML地图功能

use*_*815 3 sml smlnj currying partial-application map-function

我有这个功能:

map(map(fn x =>[x])) [[],[1],[2,3,4]];
Run Code Online (Sandbox Code Playgroud)

哪个产生:

val it = [[],[[1]],[[2],[3],[4]]]
Run Code Online (Sandbox Code Playgroud)

我不明白这个功能是如何工作的.每个地图功能都不需要功能和列表吗?似乎没有足够的参数来实际执行.

如果我跑:

map(fn x =>[x]) [[],[1],[2,3,4]];
Run Code Online (Sandbox Code Playgroud)

我明白了:

val it = [[[]], [[1]], [[2,3,4]]];
Run Code Online (Sandbox Code Playgroud)

这对我来说更有意义,因为它需要列表中的每个元素,并将其包装在另一个列表中.但是当我在其上放置另一张地图时,它会改变输出.任何人都可以向我解释这个吗?谢谢!

pyo*_*yon 12

你说:

我不明白这个功能是如何工作的.每个地图功能都不需要功能和列表吗?

好吧,请记住,在标准ML(以及一般来说,所有应用语言)中,没有"n参数的功能"这样的东西,除了1之外的"n".但是,不止一个的功能参数可以通过两种方式模拟:

  1. 作为元组或记录的单个参数的函数.原始预期参数可以通过元组或记录的投影在函数体中恢复.

  2. 作为返回其余参数的函数的第一个参数的函数.

考虑到这一点,我们检查mapREPL中的类型:

> map;
val it = fn: ('a -> 'b) -> 'a list -> 'b list
Run Code Online (Sandbox Code Playgroud)

(我使用Poly/ML,而不是SML/NJ,但除格式化问题外,输出应该相同.)

没有元组,没有记录.map显然采用第二种方法来模拟两个参数的函数:它接受一个类型的函数'a -> 'b并返回另一个类型的函数'a list -> 'b list.

现在,这里是捕获:对于任何功能foo,map foo也是一个功能!既然map可以将任何函数作为参数,那么map foo它本身就是一个完全合法的参数map.这意味着map (map foo)任何功能的类型检查foo.特别是,如果是这样的话val foo = fn x => [x].


你说:

似乎没有足够的参数来实际执行.

如果它是typechecks,它会运行.


你说:

如果我跑

map (fn x => [x]) [[], [1], [2,3,4]]
Run Code Online (Sandbox Code Playgroud)

我明白了

val it = [[[]], [[1]], [[2,3,4]]];
Run Code Online (Sandbox Code Playgroud)

这对我来说更有意义,因为它需要列表中的每个元素,并将其包装在另一个列表中.但是当我在其上放置另一张地图时,它会改变输出.

让我们稍微重构你的代码,而不改变它的含义:

let
  val foo = fn x => [x]
  val bar = map foo
  val baz = map bar
in
  baz [[], [1], [2,3,4]]
end
Run Code Online (Sandbox Code Playgroud)

现在,我们可以分析功能(是每一位foo,bar,baz)确实给它的参数:

  1. foo采用单个元素x并将其包装在列表数据构造函数中.
  2. bar 获取元素列表,将每个元素包装在列表数据构造函数中,并返回包含结果包装元素的列表(列表列表).
  3. baz获取(子)元素列表的(超级)列表,应用于bar每个子列表,并返回包含结果的列表.

手动执行所有这些操作以使自己相信结果[[], [[1]], [[2], [3], [4]]]确实是正确的.