SML映射函数

SML映射函数,sml,smlnj,currying,partial-application,map-function,Sml,Smlnj,Currying,Partial Application,Map Function,我有以下功能: map(map(fn x =>[x])) [[],[1],[2,3,4]]; 产生: val it = [[],[[1]],[[2],[3],[4]]] 我不明白这个函数是如何工作的。难道不是每个map函数都需要一个函数和一个列表吗?似乎没有足够的理由让它实际执行 如果我跑步: map(fn x =>[x]) [[],[1],[2,3,4]]; 我得到: val it = [[[]], [[1]], [[2,3,4]]]; 这对我来说更有意义,因为它接受列表中

我有以下功能:

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

val it = [[],[[1]],[[2],[3],[4]]]
我不明白这个函数是如何工作的。难道不是每个map函数都需要一个函数和一个列表吗?似乎没有足够的理由让它实际执行

如果我跑步:

map(fn x =>[x]) [[],[1],[2,3,4]];
我得到:

val it = [[[]], [[1]], [[2,3,4]]];
这对我来说更有意义,因为它接受列表中的每个元素,并将其包装到另一个列表中。但当我在上面放另一张地图时,它会改变输出。谁能给我解释一下吗?谢谢大家!

你说:

我不明白这个函数是如何工作的。难道不是每个map函数都需要一个函数和一个列表吗

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

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

  • 作为第一个参数的函数,返回其余参数的函数

  • 考虑到这一点,我们在REPL中检查
    映射的类型:

    > map;
    val it = fn: ('a -> 'b) -> 'a list -> 'b list
    
    (我使用Poly/ML,而不是SML/NJ,但除了格式问题,输出应该是相同的。)

    没有元组,就没有记录<代码>映射显然采用第二种方法来模拟两个参数的函数:它采用类型为
    'a->'b
    的函数,并返回类型为
    'a list->'b list
    的另一个函数

    现在,这里有一个问题:对于任何函数
    foo
    map foo
    也是一个函数!由于
    map
    可以将任何函数作为参数,因此
    map foo
    本身就是
    map
    的一个完全合法的参数。这意味着
    map(mapfoo)
    类型检查任何函数
    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
    )对其参数的作用:

  • foo
    获取单个元素
    x
    并将其包装到列表数据构造函数中
  • bar
    获取元素列表,将每个元素包装在列表数据构造函数中,并返回一个包含结果包装元素的列表(列表列表)
  • baz
    获取元素(子)列表的(超级)列表,将
    bar
    应用于每个子列表,并返回一个包含结果的列表
  • 手动执行所有这些操作,以使自己确信结果,
    [[]、[[1]]、[[2]、[3]、[4]]]
    确实正确

     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
    
    我认为地图的功能是明确的