首页 > 解决方案 > SML 数据类型匹配冗余产生冗余

问题描述

我从The Little MLer那里得到了这个

datatype 'a pizza =
         Bottom
         | Topping of ('a * ('a pizza))

和这个

datatype fish =
         Anchovy
         | Lox
       | Tuna

和这个工作代码

fun rem_fish (f, fp) =
    let
        fun eq_fish (Anchovy,Anchovy) = true
          | eq_fish (Lox,Lox) = true
          | eq_fish (Tuna,Tuna) = true
          | eq_fish (_,_) = false
    in
        case fp of
            Bottom => Bottom
          | Topping(x,y) =>
            case eq_fish (f,x) of
                true => rem_fish (f,y)
              | false => Topping (x,rem_fish (f,y))
end

这将采用鱼类型和鱼比萨对,并在第一个参数中删除特定的鱼

- rem_fish (Tuna, Topping (Tuna, (Topping (Anchovy, Topping (Lox, Topping (Tuna, Bottom))))));
Topping (Anchovy,Topping (Lox,Bottom)) : fish pizza

好,然后我看到这段代码(我已经改成case基于)标记为“不合语法”

fun rem_fish (f, fp) =
        case fp of
            Bottom => Bottom
          | Topping (f,fp') => rem_fish (f,fp')
          | Topping (x,fp') => Topping (x,rem_fish (f,fp'))

但是这个错误

Error: match redundant
:           Bottom => ...
:           Topping (f,fp') => ...
:     -->   Topping (x,fp') => ...

这个错误是什么意思?代码有什么问题?最后一行可能是这样的

Topping (_,fp') => Topping (?,rem_fish (f,fp'))

但后来我不知道?会发生什么。

标签: typessml

解决方案


我认为如果我们在这段代码中消除一些不需要的阴影,它可能会变得更清楚。考虑函数

fun rem_fish (f, fp) =
        case fp of
            Bottom => Bottom
          | Topping (y,fp') => rem_fish (y,fp')
          | Topping (x,fp') => Topping (x,rem_fish (f,fp'))

这相当于你写的。

请注意,两者Topping (y,fp')都是变体Topping (x,fp')的无可辩驳的模式Topping;他们将永远匹配它。因此,在您的代码中,如果您有 a Topping,它将匹配您casealways 的第二个分支,因此第三个分支是多余的(错误在说什么)。

如果您希望能够检查被包裹的元组中的第一个元素是否Topping等于要检查的参数(或者像在初始示例中那样在内部使用它)。后者可能看起来像fop=

fun rem_fish (_, Bottom) _ = Bottom
  | rem_fish (f, Topping (x, fp)) cmp = 
      if cmp (f, x) then
        rem_fish (f, fp)
      else
        Topping (x, rem_fish (f, fp))

(对于具有平等功能的鱼以外的浇头,这可能会更通用一些)


推荐阅读