【问题标题】:SML How to prepend an element to the beginning of every list in a list of lists?SML 如何在列表列表中的每个列表的开头添加一个元素?
【发布时间】:2016-09-09 22:29:23
【问题描述】:

我尝试了以下方法:

fun consAll (nil, n) = [n]
  | consAll ((x::xs), n) = [[n::x], [consAll(xs, n)]];

但它返回此错误:

"错误:运算符和操作数不一致[循环性] operator domain: 'Z list list * 'Z list list list 操作数:'Z list list * 'Z list list 表达: ((n :: x) :: nil) :: (consAll (,) :: nil) :: nil"

请告诉我哪里出错了,我是 SML 的初学者。

【问题讨论】:

    标签: sml


    【解决方案1】:

    SML 列表构造语法并不完全简单。由于我们使用[...] 来构造文字列表,因此很容易认为我们也可以使用该符号来解构列表并将 cons 元素放在列表的头部(例如,在 Prolog 中)。但是 cons 运算符 :: 只是一个中缀值构造函数,它接受 'a 类型的项目和 'a list 类型的列表,并返回一个新列表,其中包含在列表头部的项目。如果您随后将评估此构造的结果括在方括号中,则您现在已将结果列表包装在另一个列表中:

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

    您的定义中还有两个额外的错误:

    首先,当您的意思是在第二个受保护函数定义的主体中将头放在列表的尾部时,您正在创建一个包含两项的列表。

    第二,你的基地不正确:

      fun consAll (nil, n) = [n]
    

    这就是说,如果列表列表为空,则返回一个单例列表,其中包含要包含在每个列表中的项目。但是您正在定义一个函数,该函数应该将n 放在每个列表的头部,该列表是第一个参数中列表的成员。当您在第一个参数中用完列表时,您应该只返回一个空列表,因为没有更多的列表可供使用。有意义吗?

    这里有两种写你描述的函数的方法。一个使用简单递归,另一个使用高阶函数List.map

    fun consAll ([], _) = []
      | consAll ((x::xs), n) = (n::x) :: consAll(xs, n)
    
    fun mapCons x lists = List.map (fn ls => x :: ls) lists
    

    【讨论】:

    • val mapCons = map o curry op:: 给定fun curry f x y = f (x, y)。 :)
    • 当你说“::只是一个中缀类型的构造函数”时,你不是说值构造函数吗?
    • @SimonShine 谢谢指正!我已经做出了适当的改变。我考虑过推荐使用op ::,但由于可能会增加复杂性而回避了。它可能应该包括在内!尤其是 SML/NJ 标准库中包含的Fn 结构。 :)
    【解决方案2】:

    [[n::x], [consAll(xs, n)]] 创建一个包含两个元素的列表,但您想添加到列表中。请改用(n :: x) :: consAll(xs, n)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-21
      • 2022-08-11
      • 1970-01-01
      • 2012-12-13
      • 2014-07-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多