edición: proporcionar una verdadera respuesta a la pregunta ...
me parece la forma más fácil de ver lo que los patrones son coincidentes es agregar trace
declaraciones, así:
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
Si Don Incluya una declaración final para capturar cualquier otro patrón que no se haya igualado, obtendrá una excepción de tiempo de ejecución, pero creo que es más útil para ver qué datos está obteniendo. Entonces, generalmente es simple ver por qué no coincide con los patrones anteriores.
Por supuesto que no desea dejar esto en el código de producción. Solo inserto rastros según sea necesario y luego los elimino cuando termine. También puede usar CPP para dejarlos fuera de las compilaciones de producción.
También quiero decir que creo que la coincidencia de patrones es la forma incorrecta de hacerlo. Terminará con una explosión combinatoria en el número de patrones, que rápidamente se vuelve inmanejable. Si quiere hacer una instancia de Float
por ejemplo, Expr
, necesitará varios constructores más primitivos.
En su lugar, presumiblemente tiene una función de intérprete interpret :: Expr -> Double
, o al menos podría escribir una.A continuación, puede definir
instance Eq Expr where
l == r = interpret l == interpret r
Por coincidencia de patrones, básicamente estás re-escritura de su función de interpretar en el Eq
ejemplo. Si desea hacer una instancia de Ord
, terminará por volver a escribir la función de interpretación una vez más.
GHC puede detectar el problema en tiempo de compilación. Si compila con '-Wall', le advertirá sobre el patrón incompleto y le mostrará los casos que omitió. – hammar
La opción precisa es '-fwarn-incomplete-patterns'. Consulte http://stackoverflow.com/questions/7883023/algorithm-for-type-checking-ml-like-pattern-matching para ver cómo funciona. Por cierto, en tu ejemplo, recomiendo escribir 'eval :: Expr -> Double' y luego' x == y = eval x == eval y', pero sigue siendo bastante no estándar. – sdcvvc
Sé sobre las advertencias. Me gustaría saber, por ejemplo, por qué un patrón que creo debería coincidir, no. –