편집 :
내가 어떤 패턴이 일치하는 것은과 같이,
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를 사용하여 프로덕션 빌드에서 CPP를 둘 수 있습니다.
나는 또한 패턴 매칭이 이것에 대해 잘못된 길로 생각한다고 말하고 싶다. 패턴 수가 많아지면 조합 적 폭발로 끝날 것이며, 관리하기 어려울 정도로 빠르게 커지게됩니다. 예를 들어 Expr
에 Float
인스턴스를 만들려면 몇 가지 기본 생성자가 더 필요합니다.
대신 아마도 인터프리터 기능이 interpret :: Expr -> Double
이거나 적어도 하나를 쓸 수 있습니다.그럼 당신은 패턴 매칭에 의해
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
경고에 대해 알고 있습니다. 예를 들어, 필자가 생각해야 할 패턴이 왜 일치해야하는지에 대해 알고 싶습니다. –