exhaustive な switch

OCaml ではパターンマッチの抜けを警告してくれます。Haskell より OCaml の方が好きな点の 1 つです*1

type t = Foo | Bar | Baz
let f = function Foo -> "foo" | Bar -> "bar"
$ ocamlc pat-test.ml
File "pat-test.ml", line 2, characters 8-44:
Warning P: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
Baz

今日気がついたのですが、gcc でも enum に対して同様のチェックをしてくれるようです。

enum t { foo, bar, baz };
char *f(enum t x) {
  switch(x) {
    case foo: return "foo";
    case bar: return "bar";
  }
  return NULL;
}
$ gcc -Wall -c pat-test.c
t.c: In function 'f':
t.c:6: warning: enumeration value 'baz' not handled in switch

ふーんと思った。それだけ。


追記: はてなブックマークより

sshi ghcでも-Wつけるとパターンマッチの抜けを警告してもらえるよ

おお知らなんだ。ありがとうございます。

module PatTest where
data Hoge = Foo | Bar | Baz

f Foo = "foo"
f Bar = "bar"
$ ghc -W -c -o pat-test.o pat-test.hs

pat-test.hs:4:0:
    Warning: Pattern match(es) are non-exhaustive
             In the definition of `f': Patterns not matched: Baz

これがデフォルトでオフなのは、Haskell では (ガードに加えて) non-exhaustive なマッチを意図的に書くことが多いからでしょうかね。無限リストとか。
OCaml でもそういう場合がないことはないけど、そういう場合はちゃんとマッチさせて assert false しようという風習がある気がする。

*1:ガードを使いまくる Haskell のスタイルに合わなさそうなのはわかるんだけど。