Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

This pattern seems exhaustive, but I'm still getting warnings

I'm learning sml, and wrote the following simple function:

(* 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;

Which is generating the following warning:

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

I believe the function can never fail, since val head::head2::tail will always work for lists with two or more elements and the case of one element and zero elements is covered. As far as I can tell, this function works as expected. I think the issue might be related to the use of [] but I really don't know.

My question is actually three fold:

  1. Why does sml think that this is not exhaustive (how am I misinterpreting this)?
  2. Is there a case where this function will fail?
  3. Am I doing something dumb writing the function this way?
like image 943
Wilduck Avatar asked Jan 31 '12 03:01

Wilduck


1 Answers

  1. SML gives you that warning because it doesn't know that x has at least two elements. All it knows is that x is a list, it doesn't remember the fact that x had to have not matched the first two patterns, to go into the third case.

  2. No, the code can not fail.

  3. There is no reason to perform the pattern match in the let-statement. You can just put the pattern to the fun statement, which will result in less code and remove the warning:

    fun everyOther [] = []
      | everyOther [x] = [x]
      | everyOther (head::head2::tail) = head :: everyOther tail;
    
like image 153
sepp2k Avatar answered Sep 22 '22 12:09

sepp2k