2012-08-23 16 views
10

Sto scrivendo una funzione per semplificare un'espressione booleana. Ad esempio, Nand(A, A) == Not(A). Ho cercato di attuare questa regola particolare utilizzando pattern matching, in questo modo:L'uguaglianza implicita in un modello Haskell corrisponde a

-- 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') 

Su compilazione, ottengo l'errore:

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

Credo di capire cosa sta succedendo, e non ho intorno a questo, ma vorrei solo sapere:

  1. Perché questo tipo di abbinamento di pattern non è possibile?
  2. Esiste una soluzione idiomatica?

Full disclosure: questo è legato al lavoro, ma lo scopo del corso è di non imparare Haskell, e ho risolto a modo mio in ogni caso.

+11

Un modello che utilizza una variabile due volte è chiamato non modello lineare. Ci sono linguaggi che forniscono modelli non lineari come Erlang e penso che sia stata una scelta di design non includerli in Haskell. La mailing list post http://www.mail-archive.com/[email protected]/msg03721.html contiene alcuni argomenti contro i pattern non lineari ma sono argomenti piuttosto di alto livello. –

+1

Nota che (Nand q q ') non implica che q eq' siano diversi. q = 3 q '= 3 (penso che questo sia il motivo della scelta del design) –

+1

@Vixen, beh, se il primo modello non corrispondesse, significherebbe che sono diversi nel secondo modello ... – dflemstr

risposta

2

Si potrebbe attaccare al vostro stile originale:

-- 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') 

Inoltre, penso che si dovrebbe semplificare la prima test di uguaglianza e non dopo:

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

Buona presa con la semplificazione prima dei test di parità! –

14

La soluzione che ho trovato è quello di utilizzare le guardie per verificare l'uguaglianza delle sottostrutture:

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

Questo è probabilmente il modo per farlo, il problema è che non è possibile riutilizzare lo stesso modello come si è tentato di fare. Ho già fatto lo stesso prima e ho praticamente raggiunto la stessa soluzione. –

1

La "risposta" è che non è permesso di parlare la stessa variabile due volte in un modello. Non in Haskell, comunque. Il modo migliore per risolvere questo problema è quello che sembri aver già scoperto: usa le guardie del modello per testare l'uguaglianza o la disuguaglianza.

Problemi correlati