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

Wil*_*uck 6 recursion types 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;
Run Code Online (Sandbox Code Playgroud)

哪个产生以下警告:

! Toplevel input:
!   val head::head2::tail = x
!       ^^^^^^^^^^^^^^^^^
! Warning: pattern matching is not exhaustive
Run Code Online (Sandbox Code Playgroud)

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

我的问题实际上是三个方面:

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

sep*_*p2k 5

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

  2. 不,代码不能失败.

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

    fun everyOther [] = []
      | everyOther [x] = [x]
      | everyOther (head::head2::tail) = head :: everyOther tail;
    
    Run Code Online (Sandbox Code Playgroud)