編集:質問への本当の答えを提供する...
私はパターンが一致しているかを確認する最も簡単な方法はそうのような、trace
ステートメントを追加することです見つける:
import Debug.Trace
instance Eq Expr where
(Add (Const a1) (Const a2)) == Const b = trace "Expr Eq pat 1" $ a1+a2 == b
(Add (Const a1) (Const a2)) == (Add (Const b1) (Const b2)) = trace "Expr Eq pat 2" $ a1+a2 == b1 + b2
-- catch any unmatched patterns
l == r = error $ "Expr Eq failed pattern match. \n l: " ++ show l ++ "\n r: " ++ show r
あなたドン場合そうでなければ他に類のないパターンをキャッチするための最終的なステートメントを含めると、実行時例外が発生しますが、どのデータを取得するのがより有用かを知ることができます。その後、それが以前のパターンと一致しない理由は簡単です。
もちろん、これをプロダクションコードに残したくない場合もあります。必要に応じてトレースを挿入し、終了したらトレースを削除します。また、CPPを使用してプロダクションビルドの外に置くこともできます。
私はパターンマッチングがこれについて間違った方法だとも言いたいと思います。あなたはパターンの数の組み合わせの爆発で終わるでしょう。急速に手に負えないほど成長します。たとえば、Expr
のインスタンスをFloat
にしたい場合は、さらにいくつかのプリミティブコンストラクタが必要になります。
代わりに、おそらくインタープリタ機能interpret :: Expr -> Double
を持っているか、少なくとも1つ書くことができます。そして、あなたはパターンマッチングにより
instance Eq Expr where
l == r = interpret l == interpret r
を定義することができ、あなたは本質的Eq
インスタンスであなたの解釈機能を再度書いています。 Ord
インスタンスを作成したい場合は、もう一度解釈関数を書き直してください。
GHCはコンパイル時に問題を検出できます。 '-Wall'を使ってコンパイルすると、不完全なパターンについて警告し、あなたが見逃したケースを表示します。 – hammar
正確なオプションは '-fwarn-incomplete-patterns'です。どのように動作するかは、http://stackoverflow.com/questions/7883023/algorithm-for-type-checking-ml-like-pattern-matchingで確認してください。ところで、あなたの例では、 'eval :: Expr - > Double'と' x == y = eval x == eval y'と書くことをお勧めしますが、まだ非標準です。 – sdcvvc
私は警告について知っています。私は、例えば、私が考えなければならないパターンがなぜ一致しなければならないのかを知りたいと思います。 –