彻底解构 SML 中的列表

Exhaustively destructuring lists in SML

SML 片段 ... let val (x::xs) = String.explode s in ... 总是会抱怨模式不够全面,即使我在函数定义中对空字符串大小写进行模式匹配。有什么方法可以修改它,使匹配详尽无遗吗?

您必须使用 case 而不是 let:

... case String.explode s of x::xs => ... | nil => raise Domain

或者,如果您绝对想保留 let,请将其变成一对:

val (x, xs) = case ... of x::xs => (x, xs) | nil => raise Domain

你可以将后者抽象成辅助函数:

fun decons (x::xs) = (x, xs)
  | decons nil = raise Domain

let val (x::xs) = ... 之所以不详尽,是因为 val 声明只有一个模式占位符(此处用于 x::xs)。列表作为一种求和类型,有两个构造函数,::[]。正如 Andreas Rossberg 所说,case 是当你有多个模式时要走的路。请参阅 进行自以为是的比较(TL;DR:我有时喜欢使用 case,即使只有一种情况。)

[...] even if I pattern-match the empty string case in the function definition

您可以考虑删除空字符串大小写,对所有输入调用 String.explode 并以与处理空字符串大小写相同的方式处理 [] 的输出。

所以下面的代码:

fun f "" = <foo>
  | f s = case String.explode s of
               x::xs => <bar>
             | []    => raise Fail "impossible"

变为:

fun f s = case String.explode s of
               []    => <foo>
             | x::xs => <bar>