未解决的弹性记录(需要知道此上下文中所有字段的名称)

gio*_*ude 5 tuples smlnj pattern-matching

我一直在尝试使用元组列表作为参数创建一个函数,但我不断收到错误:"未解析的flex记录(需要知道此上下文中所有字段的名称)"我的代码是:

fun convert d = ( (map (#1) d) , (map (#2) d) );
Run Code Online (Sandbox Code Playgroud)

这是基本上试图将一对列表转换为一对列表.我也尝试声明类型d:('a * 'b) list但导致更多错误.我认为这与tupple的未知大小有关,可以使用一些帮助来了解它.

mic*_*kig 5

我怀疑你在注释类型时遇到的问题d实际上就是你没有用parens包围注释,这对我有用:

fun convert (d : ('a * 'b) list) = ( (map (#1) d) , (map (#2) d) )
Run Code Online (Sandbox Code Playgroud)

但是,这并不是很好的SML风格.使用#1,#2,#n等在一定程度上鼓励,因为它会导致这样的问题,你已经失去了一些常用的succintness这种类型的推理给你的.

相反,您可以为对定义一些显式选择函数:

fun first  (a, _) = a
fun second (_, b) = b

fun convert d = (map first d, map second d)
Run Code Online (Sandbox Code Playgroud)

(请注意,我还从主体中删除了一些多余的括号convert,因为函数应用程序具有比元组构造更高的优先级,并且我还删除了在对命令式代码进行排序或在键入代码时才真正需要的分号REPL)

是标准ML的一个非常好的风格指南,来自哈佛大学(或者塔夫茨大学)的课程.该文档的旧版本在"要避免的常见错误"中明确提到了这一点.

避免#1和#2

一些初学者认为获得一对的第二个元素的好方法p是写#2 p.

这种风格不是惯用的或可读的,它可能会混淆类型检查器.处理对的正确方法是通过模式匹配,所以

fun first (x, _) = x
fun second (_, y) = y
Run Code Online (Sandbox Code Playgroud)

是优选的,而不是

fun bogus_first p = #1 p (* WRONG *)
fun bogus_second p = #2 p
Run Code Online (Sandbox Code Playgroud)

(由于我不想讨论的原因,这些版本甚至不进行类型检查.)

如果你的对或元组不是函数的参数,请使用val模式匹配:

val (x, y) = lookup_pair mumble
Run Code Online (Sandbox Code Playgroud)

但通常你可以在普通的有趣匹配中包含匹配.