【问题标题】:SML function as lookup tableSML 功能作为查找表
【发布时间】:2020-04-03 16:42:42
【问题描述】:

在深入研究 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"

在我看来,它就像一个用作查找表的函数。 (我什至不确定这种 SML 函数实际上叫什么。它看起来像一个 Haskell 归纳公式?)有没有办法通过处理输入的情况来避免“非详尽”警告是<= 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-like 方法?

【问题讨论】:

  • “样式”不是有名字的样式,它是一个带有许多模式匹配子句的常规函数​​。

标签: function sml lookup-tables


【解决方案1】:

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

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

现在,如何处理错误取决于您。

简单且最不可靠的解决方案是只返回“无效的月份数”或类似的内容。

您也可以引发异常,或使用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;

【讨论】: