Types 这种模式似乎详尽无遗,但我';我仍然收到警告

Types 这种模式似乎详尽无遗,但我';我仍然收到警告,types,recursion,sml,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; 这将生成以下警告: ! T

我正在学习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
将始终适用于包含两个或更多元素的列表,并且涵盖了一个元素和零个元素的情况。据我所知,这个函数按预期工作。我认为这个问题可能与
[]
的使用有关,但我真的不知道

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

  • 为什么sml认为这不是详尽无遗的(我怎么会误解这一点)
  • 是否存在此功能将失败的情况
  • 我这样写函数是不是有点傻
  • SML给您这个警告是因为它不知道
    x
    至少有两个元素。它只知道
    x
    是一个列表,它不记得
    x
    必须不匹配前两种模式才能进入第三种情况

  • 不,代码不能失败

  • 没有理由在let语句中执行模式匹配。您只需将模式放到
    fun
    语句中,这将减少代码并删除警告:

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

  • 谢谢我仍在试图把我的头脑集中在模式中的东西上。快速提问:这是否会删除警告,因为在模式中放置
    head::head2::tail
    可以让sml知道至少有两个元素?或者这里还有其他原因吗?@Wilduck It会删除警告,因为对于列表中的每个值,都有一个匹配的模式。当您执行
    val head::head2::tail=x时,情况并非如此,因为对于至少包含2个元素的列表,该模式匹配只有一种情况。这非常有意义。在15分钟内,你就解开了我花了半个小时的谜团。再次感谢你。