这种模式似乎很详尽,但我仍然收到警告

时间:2012-01-31 03:36:33

标签: types recursion sml

我正在学习sml,并编写了以下简单的函数:

(* Return a list with every other element of the input list *)
fun everyOther [] = []
  | everyOther [x] = [x]
  | everyOther x = let
        val head::head2::tail = x
    in
        head::everyOther(tail)
    end;

产生以下警告:

! Toplevel input:
!   val head::head2::tail = x
!       ^^^^^^^^^^^^^^^^^
! Warning: pattern matching is not exhaustive

我相信函数永远不会失败,因为val head::head2::tail将始终适用于具有两个或更多元素的列表,并且涵盖了一个元素和零元素的情况。据我所知,这个功能按预期工作。我认为这个问题可能与使用[]有关,但我真的不知道。

我的问题实际上是三折:

  1. 为什么sml认为这不是详尽无遗的(我怎么会误解这个?)
  2. 是否存在此功能失败的情况?
  3. 我是不是以这种方式写了这个功能?

1 个答案:

答案 0 :(得分:5)

  1. SML会向您发出警告,因为它不知道x至少有两个元素。它只知道x是一个列表,它不记得x必须与前两个模式不匹配的事实,进入第三种情况。

  2. 不,代码不会失败。

  3. 没有理由在let语句中执行模式匹配。您可以将模式放到fun语句中,这将导致更少的代码并删除警告:

    fun everyOther [] = []
      | everyOther [x] = [x]
      | everyOther (head::head2::tail) = head :: everyOther tail;