我是SML / NJ的新手,我正在尝试制作一个递归函数 这使得listOfLists。例如:
listOf([1,2,3,4])
将输出[[1],[2],[3],[4]]
。我在SML / NJ中找到了一个递归merge
,我就是 试图用它作为一个大纲:
- fun merge(xs,nil) = xs
= | merge(nil,ys) = ys
= | merge(x::xs, y::ys) =
= if (x < y) then x::merge(xs, y::ys) else y::merge(x::xs,ys);
- fun listOf(xs) = xs
= | listOf(x::xs) = [x]::listOf(xs);
我正在尝试使用模式匹配,我对它有点困惑。我 非常确定x是头部,然后xs是尾部,但我可以 错误。所以我要做的就是使用列表的头部,使它成为一个 列表,然后将其添加到列表的其余部分。但是在尝试的时候 这个函数,我收到错误:
stdIn:15.19-15.34 Error: operator and operand don't agree [circularity]
operator domain: 'Z list * 'Z list list
operand: 'Z list * 'Z list
in expression:
(x :: nil) :: listOf xs
这个错误对我来说很陌生,因为我没有任何经验 与sml / nj。如何修复listOf函数?
答案 0 :(得分:0)
你很亲密。问题是在模式匹配中,像xs
(只是变量)这样的模式可以匹配任何。以s
结束它的事实并不意味着该模式只能匹配列表的尾部。以这种方式使用s
只是SML中的程序员约定。
因此,在你的定义中:
fun listOf(xs) = xs
| listOf(x::xs) = [x]::listOf(xs);
第一行告诉SML将所有值保持不变,这显然不是你的意图。 SML检测到这与您 尝试更改值的第二行不一致。
您需要更改第一行,以便它不匹配所有内容。将merge
函数视为模板,需要与基础案例匹配的内容。自然基础情况为nil
(也可以写为[]
)。请注意nil
在merge
定义中扮演的角色。如果对函数定义第一行中的模式使用nil
而不是xs
,则第二行完全符合您的要求,并且函数将按预期工作:
fun listOf(nil) = nil
| listOf(x::xs) = [x]::listOf(xs);