This pattern seems comprehensive, but I still get warnings

I learn 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 causes the following warning:

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

I believe that a 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 considered. As far as I can tell, this function works as expected. I think the problem may be related to using [] , but I really don't know.

My question is actually three times:

  • Why does sml think this is not exhaustive (how do I misinterpret it)?
  • Is there a case where this function will not be executed?
  • Am I doing something stupid by writing a function this way?
+6
source share
1 answer
  • SML gives you this warning because it does not know that x has at least two elements. All he knows is that x is a list, he does not remember the fact that x had to not match the first two patterns in order to go into the third case.

  • No, the code cannot fail.

  • There is no reason to match the pattern in let-statement. You can simply put the template in the fun statement, which will reduce the amount of code and remove the warning:

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

Source: https://habr.com/ru/post/907279/


All Articles