2012-08-23 11 views
10

Estoy escribiendo una función para simplificar una expresión booleana. Por ejemplo, Nand(A, A) == Not(A). He tratado de poner en práctica esta regla en particular el uso de la coincidencia de patrones, así:Implicando la igualdad en una coincidencia de patrón Haskell

-- Operands equivalent - simplify! 
simplify (Nand q q) = Not (simplify q) 
-- Operands must be different, so recurse. 
simplify (Nand q q') = Nand (simplify q) (simplify q') 

Al compilar, me sale el error:

Conflicting definitions for `q' 
Bound at: boolean.hs:73:21 
      boolean:73:29 
In an equation for `simplify' 

creo que entiendo lo que está pasando, y no tengo funcionó alrededor, pero me gustaría saber:

  1. ¿Por qué no es posible este tipo de patrón?
  2. ¿Hay una solución idiomática?

La revelación completa: esto está relacionado con la tarea, pero el objetivo del curso no es aprender Haskell, y he resuelto a mi manera de todos modos.

+11

Un patrón que utiliza una variable dos veces se denomina un no -patrón lineal. Hay idiomas que proporcionan patrones no lineales como Erlang y creo que fue una opción de diseño no incluirlos en Haskell. La publicación de la lista de correo http://www.mail-archive.com/[email protected]/msg03721.html contiene algunos argumentos en contra de los patrones no lineales, pero son argumentos de alto nivel. –

+1

Tenga en cuenta que (Nand q q ') no implica que q y q' sean diferentes. q = 3 q '= 3 (creo que esta es la razón de la elección de diseño) –

+1

@Vixen, bueno, si el primer patrón no coincide, significaría que son diferentes en el segundo patrón ... – dflemstr

Respuesta

2

Se podía cumplir con su estilo original:

-- Operands equivalent - simplify! 
simplify (Nand q q') | q == q' = Not (simplify q) 
-- Operands must be different, so recurse. 
simplify (Nand q q') = Nand (simplify q) (simplify q') 

Además, creo que se debe simplificar antes de la prueba igualdad y no después:

simplify (Nand q q') = if qs == qs' then Not qs else Nand qs qs' where 
    qs = simplify q 
    qs' = simplify q' 
+1

¡Buena captura con la simplificación antes de la prueba de igualdad! –

14

La solución que he encontrado es usar protectores para comprobar la igualdad de subestructuras:

simplify (Nand q q') 
    -- Operands equivalent - simplify! 
    | q == q' = Not (simplify q) 
    -- Operands different - recurse. 
    | otherwise = Nand (simplify q) (simplify q') 
+0

Esta es probablemente la manera de hacerlo, el problema es que no puede reutilizar el mismo patrón como lo intentó hacer. He hecho lo mismo antes, y alcancé básicamente la misma solución. –

1

La "respuesta" es que no se le permite hablar de la misma variable dos veces en una patrón. No en Haskell, de todos modos. La mejor manera de resolver esto es la que ya parece haber descubierto: use patrones de protección para evaluar la igualdad o la desigualdad.

Cuestiones relacionadas