【问题标题】:SML tuples - CombinationSML 元组 - 组合
【发布时间】:2016-03-02 02:59:50
【问题描述】:

我遇到了一个元组问题,给定一对元组列表,它应该变成一对列表:即[(1,2),(3,4),(5,6)] 应该返回([1,3,5],[2,4,6])

我尝试使用此代码解决它:

 fun convert L = foldl (fn(a,b) => #1a::b) [] L;

但我收到一条错误消息:未解析的弹性记录。 谁能解释我为什么会得到这个以及如何解决它?

【问题讨论】:

    标签: sml smlnj


    【解决方案1】:

    查看a,编译器可以判断它应该是一个元组(因为您调用的是#1a),但它无法判断它有多大。 SML 类型系统不允许未知大小的元组;你需要明确a 是一对。

    虽然你可以通过给a 一个类型声明来解决这个问题,但更好的方法是模式匹配它。不要将参数定义为(a,b) 并使用#1a#2a,而是将参数定义为((x,y),b) 并使用xy

    不过,您的解决方案还有另一个问题。您的函数正在将该对的第一个元素添加到结果列表中,但您忽略了第二个元素 (#2a),并且您的结果缺少第二个列表。你传递给foldl的函数应该是fn ((x,y),(u,v)) => ...,你的初始值应该是([],[])


    这个神秘的错误消息“未解析的弹性记录”的原因是 SML 中的元组被实现为带有整数标签的记录。元组 (a,b) 与记录 {1=a,2=b}相同。事实上,如果你在 SML/NJ shell 中输入{1=1,2=2},它会返回

    val it = (1,2) : int * int
    

    所以当您说#1a 时,您实际上是在说“从记录a 中提取标签为1 的元素”。

    SML/NJ 没有record polymorphism 的概念。它知道a 必须是一条记录,并且此记录类型必须至少包含标签1(可能还有其他标签),但在SML/NJ 类型系统中无法表达这一点。

    因此编译器需要知道记录的确切结构才能推断a 的类型,如果无法确定,则会抛出“未解析记录”错误。

    【讨论】:

      【解决方案2】:

      我手边没有 SML 解释器,但我认为您正在寻找 unzip。试试:

      unzip([(1,2), (3,4), (5,6)]);
      

      IIRC,“未解决的弹性记录”与您在这里没有使用的记录匹配有关?!查看 smlnj 的错误文档 (http://www.smlnj.org/doc/errors.html)。您需要在底部附近搜索错误[99]

      【讨论】:

        【解决方案3】:
        - ListPair.unzip([(1,2), (3,4), (5,6)]);
        > val it = ([1, 3, 5], [2, 4, 6]) : int list * int list
        

        【讨论】:

          猜你喜欢
          • 2021-07-27
          • 1970-01-01
          • 2021-12-20
          • 2021-10-28
          • 2018-03-19
          • 1970-01-01
          • 1970-01-01
          • 2015-11-08
          • 1970-01-01
          相关资源
          最近更新 更多