SML:多个案例陈述

时间:2017-02-09 23:33:35

标签: sml

我怎样才能有多个不相互交错的case语句。 例如玩具示例:

 fun multi_cases(xs) =
     case xs of
       [] => 5
      | x::ys => case x of
                    1 => 2
                   |_ => 3
      | x::[] => case x of
                    1 => 5
                    | _ => 7
 ;

stdIn:59.17-64.28 Error: types of rules don't agree [overload conflict]
  earlier rule(s): [int ty] -> [int ty]
  this rule: [int ty] list -> [int ty]
  in rule:
    :: (x,nil) =>
      (case x
        of 1 => 5
         | _ => 7)

最后两个案例陈述混淆了我怎么能告诉SML他们确实是两个独立的案例陈述而不是案件x的延续/单独分支1 => 2 ...

以下答案中指出的上述模式存在一般性问题。

1 个答案:

答案 0 :(得分:2)

此代码有两个不同的问题:

  1. 正如约翰所链接的问题Nested case statements in SML所说, case-of 在语法上有点棘手,因为他们的案例陈述列表永远不会#34;停止&#34 ;。也就是说,您的代码实际上被解析为:

    fun multi_cases xs =
        case xs of
             [] => 5
           | x::ys => case x of
                           1 => 2
                         | _ => 3
                         | x::[] => case x of
                                         1 => 5
                                       | _ => 7
    

    这是荒谬的,因为第三个模式应该属于外部 case-of 而不是内部(内部 case-of 属于x作为 int ,外部带x::[]作为 int列表)。

    由于您的缩进不会主动帮助编译器达到预期的含义,因此使用括号来停止"停止"交错的案例,就像帖子所说,是修复:

    fun multi_cases xs =
        case xs of
             [] => 5
           | x::ys => (case x of
                           1 => 2
                         | _ => 3)
           | x::[] => (case x of
                            1 => 5
                          | _ => 7)
    

    或者,您可以将外部 case-of 转换为函数参数本身的匹配项,并将内部 case-of 与它混合在一起,因为单个模式匹配允许任意深度匹配:

    fun fun_cases [] = 5
      | fun_cases [1] = 5
      | fun_cases [_] = 7
      | fun_cases (1::_) = 2
      | fun_cases (_::_) = 3
    
  2. 您的两个案例重叠,因为x::xs是一种比x::[]更通用的模式。也就是说,它还通过将x::[]设置为xs来涵盖列表[]。您可以通过以下两种方式之一解决这个问题:

    1. 首先列出最不常见的模式,例如

      case xs of
           [] => 5
         | [x] => ...
         | x::_ => ...
      
    2. 通过指定列表应至少包含两个元素,将x::xs一般模式变为不太通用的模式:

      case xs of
           x :: _ :: _ => ...
         | [x] => ...
         | [] => ...