在SML中彻底破坏列表

时间:2018-08-10 04:37:19

标签: pattern-matching sml smlnj

即使我在功能定义中将空字符串大小写匹配,SML片段... let val (x::xs) = String.explode s in ...仍会抱怨不恰当的模式。有什么方法可以修改它,使匹配变得详尽无遗吗?

2 个答案:

答案 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>