即使我在功能定义中将空字符串大小写匹配,SML片段... let val (x::xs) = String.explode s in ...
仍会抱怨不恰当的模式。有什么方法可以修改它,使匹配变得详尽无遗吗?
答案 0 :(得分:2)
您必须使用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
答案 1 :(得分:1)
let val (x::xs) = ...
从未穷尽的原因是,val
声明仅具有一个模式占位符(此处用于x::xs
)。列表是一种求和类型,具有两个构造函数::
和[]
。正如Andreas Rossberg所说,case
是拥有多种模式时要走的路。见this Q&A进行比较(TL; DR:即使只有一种情况,我有时还是喜欢使用case
。)
[...] ,即使我在函数定义中将空字符串大小写进行模式匹配
您可以考虑删除空字符串大小写,在所有输入上调用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>