Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Warning 8: Incomplete pattern matching warning in a let statement

Tags:

ocaml

I often do pattern matching in a let statement, where I know shape of the result. It is clear that i cannot expect the compiler to generally infer this knowledge, but perhaps there's a more idiomatic way to do this in a concise way.

As an example, please look at the following code:

type foo = A of int | B of string
let x = (true, A 0)
let (b, A i) = x in i + 2 

Which correctly warns me, that a result of (_, B _) is not matched. A possible way is to explicitly handle the missing case as in:

let (b,i)  = match x with 
    | (a, A j) -> (a,j+2)
    | _ -> failwith "implementation error!" 

But this obscures the actual computation. Is there a more concise alternative?

Edit: Jeffrey Scofield remarked that in the case without nesting, an explicit conversion function work out well. Is there also a version for nested type matching?

like image 374
lambda.xy.x Avatar asked Apr 22 '15 14:04

lambda.xy.x


3 Answers

If you are sure you get to the right case and you are using OCaml 4.02 or higher, you can add [@@warning "-8"] to your declaration.

See the OCaml manual for more details on attributes.

On previous versions of OCaml, you can disable the warning with respect to the whole file (this depends on your building workflow) or use an explicit pattern matching as described in Jeffrey Scofield's answer.

I would advise against the "disable the warning on whole file" though, as it will obscure other incomplete pattern matching which may break your code in unexpected ways in the present (which is easy to spot)... or somewhere in the future (like, if you change a type you match on in a later upgrade).

like image 197
PatJ Avatar answered Nov 13 '22 06:11

PatJ


For simple cases you can write a partial function to extract the value of interest, similar in spirit to List.hd.

let int_of_foo = function
   | A i -> i
   | _ -> raise (Invalid_argument "int_of_foo")

let string_of_foo = function
   | B s -> s
   | _ -> raise (Invalid_argument "string_of_foo")

let (_, f) = x in int_of_foo f + 2

There are also (non-partial) functions for projecting pairs:

int_of_foo (snd x) + 2

(I updated my use of x to match yours, sorry.)

like image 4
Jeffrey Scofield Avatar answered Nov 13 '22 05:11

Jeffrey Scofield


Often you can do this without an assertion (i.e. have your code checked at compile time) if you use a polymorphic variant instead, e.g.

type foo = [`A of int | `B of string]
let x = (true, `A 0)
let (b, `A i) = x in i + 2
like image 1
Thomas Leonard Avatar answered Nov 13 '22 04:11

Thomas Leonard