2012-03-23 72 views
1

我碰到一个元组问题,其中给出了一对元组列表,它应该成为一对列表:即[(1,2),(3,4),(5,6)]应该返回([1,3,5],[2,4,6])SML元组 - 组合

我尝试使用此代码来解决这个问题:

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

,但我得到一个错误说:无法解析的柔性纪录。 任何人都能解释为什么我得到这个以及它如何被修复?

回答

3

看着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}。而事实上,如果你输入{1=1,2=2}到SML/NJ外壳,它会返回

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

所以,当你说#1a,你真的说:“从记录a标签1提取元素”。

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

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

0

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

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

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

0
- ListPair.unzip([(1,2), (3,4), (5,6)]); 
> val it = ([1, 3, 5], [2, 4, 6]) : int list * int list