SML 函数作为查找 table

SML function as lookup table

在研究 SML 中的类型时,我发现了这个

fun monthI2S 1 = "January"
  | monthI2S 2 = "February"
  | monthI2S 3 = "March"
  | monthI2S 4 = "April"
  | monthI2S 5 = "May"
  | monthI2S 6 = "June"
  | monthI2S 7 = "July"
  | monthI2S 8 = "August"
  | monthI2S 9 = "September"
  | monthI2S 10 = "October"
  | monthI2S 11 = "November"
  | monthI2S 12 = "December"

对我来说,这看起来像是一个用作查找的函数 table。 (我什至不确定这种 SML 函数的样式实际上是什么。它看起来像一个 Haskell 归纳公式?)有没有办法通过照顾来避免 "non-exhaustive" 警告输入为 <= 0 orelse > 12?

的情况
fun monthI2S m = if m <= 0 orelse M > 12 then NONE else ...?
  | monthI2S 1 = "January"
  | monthI2S 2 = "February"
  | monthI2S 3 = "March"
  | monthI2S 4 = "April"
...

显然不起作用,因为我无法将 else| ... 协调一致。还是我完全找错了树,应该使用类似 case 的方法?

模式匹配从最顶层的子句向底部进行,因此您希望最一般的情况最后出现。

fun monthI2S 1 = "January"
  | monthI2S 2 = "February"
  ...
  | monthI2S m = nothing else matched, so m must be < 1 or > 12...

现在,如何处理错误由您决定。

简单且最不可靠的解决方案是 return "Invalid month number" 或类似的东西。

您也可以提出异常,或使用 Option.

如果你使用后者,我会亲自重写一个局部函数以避免到处都是 SOME:

fun monthI2S m = let
    fun monthI2S_safe 1 = "January"
      | monthI2S_safe 2 = "February"
      | monthI2S_safe 3 = "March"
      | monthI2S_safe 4 = "April"
      | monthI2S_safe 5 = "May"
      | monthI2S_safe 6 = "June"
      | monthI2S_safe 7 = "July"
      | monthI2S_safe 8 = "August"
      | monthI2S_safe 9 = "September"
      | monthI2S_safe 10 = "October"
      | monthI2S_safe 11 = "November"
      | monthI2S_safe 12 = "December"
      | monthI2S_safe _ = "Can never happen" 
in
    if m >= 1 andalso m <= 12 then SOME (monthI2S_safe m) else NONE
end;