3

我有这个功能:

map(map(fn x =>[x])) [[],[1],[2,3,4]];

产生:

val it = [[],[[1]],[[2],[3],[4]]]

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

如果我运行:

map(fn x =>[x]) [[],[1],[2,3,4]];

我得到:

val it = [[[]], [[1]], [[2,3,4]]];

这对我来说更有意义,因为它获取列表中的每个元素,并将其包装在另一个列表中。但是当我在上面放另一张地图时,它会改变输出。谁能给我解释一下?谢谢!

4

2 回答 2

13

你说:

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

好吧,请记住,在标准 ML(以及一般来说,所有应用语言)中,对于除 1 之外的“n”,没有“n 个参数的函数”之类的东西。但是,多个函数可以通过两种方式模拟参数:

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

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

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

> map;
val it = fn: ('a -> 'b) -> 'a list -> 'b list

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

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

现在,这里有一个问题:对于任何函数foomap foo它也是一个函数!由于map可以将任何函数作为参数,map foo它本身就是一个完全合法的参数map。这意味着map (map foo)对任何功能进行类型检查foo。特别是,如果val foo = fn x => [x].


你说:

似乎没有足够的论据来实际执行。

如果它进行类型检查,它就会运行。


你说:

如果我跑

map (fn x => [x]) [[], [1], [2,3,4]]

我明白了

val it = [[[]], [[1]], [[2,3,4]]];

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

让我们在不改变其含义的情况下稍微重构您的代码:

let
  val foo = fn x => [x]
  val bar = map foo
  val baz = map bar
in
  baz [[], [1], [2,3,4]]
end

现在我们可以分析每个函数 ( foo, bar, baz) 对其参数做了什么:

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

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

于 2013-12-13T01:00:43.507 回答
2
 map ;
 val it = fn : ('a -> 'b) -> 'a list -> 'b list

所以 map 接受一个函数,该函数再次接受一个列表并给出一个列表。

所以用函数定义地图

-fun f x = x+1 ;
val f = fn : int -> int
-map f ;
val it = fn : int list -> int list

现在it是那种接受列表并返回列表的函数

- it [1,2] ;
val it = [2,3] : int list

我认为地图功能很清楚

于 2017-09-20T18:32:53.453 回答