ScalaでMLやHaskellのalgebraic data typeを模倣するときの定番は、abstract class(or trait)とcase classを使って、 trait Exp case class Add(l: Exp, r: Exp) extends Exp case class Num(v: Int) extends Exp のようにすることだが、非常に残念なことに、これでは、MLなどと違って、パターンマッチ時にパターンの漏れがあってもコンパイル時にそれを検出することができない。たとえば、 def eval(e: Exp): Int = e match { case Add(l, r) => eval(l) + eval(r) //case Num(...)が抜けてる! } のようなコードを書いても、コンパイラは警告を出すことなく、黙って受け入れてしまう。このよう