3
votes

I have a function defined like this:

 let test_func lis =
   match lis with h::t ->
    match h with h2::t2 ->
      h2
    | [] ->
      []
  | [] ->
    [];;

When compiled, I get a warning that this function does not match the pattern [] - even though I defined it as the second case! I have found that I can fix this by surrounding the second match statement with parens:

 let test_func lis =
   match lis with h::t ->
    (match h with h2::t2 ->
      h2
    | [] ->
      [])
  | [] ->
    [];;

but I was wondering why this is necessary. In addition, swapping the first and second case in the top level match statement also works:

 let test_func lis =     
   match lis with [] ->
     []
   | h::t ->
    match h with h2::t2 ->
      h2
    | [] ->
      [];;

Thanks!

1
I always suggest using begin ... end instead of parens. It's much easier to discern the blocks of code.nlucaroni
Thanks for the tip! I was not familiar with those keywords.Ted Kalaw

1 Answers

8
votes

If we fix the indentation of your code, it looks like this:

let test_func lis =
  match lis with h::t ->
    match h with h2::t2 ->
      h2
    | [] ->
      []
    | [] ->
      [];;

If you look at that, it becomes obvious that there's no difference between the first and the second | [] -> []. So the compiler has no way of knowing that you intended the second one to belong to the outer match-statement and not to the inner one. Thus you need to parentheses to tell the compiler that the inner match statement should end after the first | [] -> [].

In your second version the first | [] -> [] clearly belongs to the outer match-statement because the inner match-statement doesn't even appear until farther down in the program. So there's no ambiguity and thus no need for parentheses.