2012-08-23 14 views
10

Piszę funkcję upraszczającą wyrażenie Boole'a. Na przykład: Nand(A, A) == Not(A). Starałem się wdrożyć tę szczególną regułę za pomocą dopasowywania wzorców, tak:Przypisywanie równości w dopasowaniu wzorca Haskella

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

Po kompilacji, pojawia się błąd:

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

Chyba rozumiem, co się dzieje, a ja obrobiłem to, ale chciałbym wiedzieć:

  1. Dlaczego tego rodzaju dopasowywanie wzorców nie jest możliwe?
  2. Czy istnieje obejście idiomatyczne?

Pełne ujawnienie: jest to związane z zadaniami domowymi, ale celem kursu nie jest poznanie Haskella, a ja i tak rozwiązałem go na swój własny sposób.

+11

wzór, który wykorzystuje zmienną dwukrotnie nazywany jest zakaz -linearny wzór. Istnieją języki, które zapewniają nieliniowe wzorce, takie jak Erlang i myślę, że wybór projektu nie obejmował ich w Haskell. Listę postów na adres http://www.mail-archive.com/[email protected]/msg03721.html zawiera kilka argumentów przeciwko nieliniowym wzorcom, ale są to argumenty wysokiego poziomu. –

+1

Należy zauważyć, że (N i q q ') nie oznacza, że ​​q i q' są różne. q = 3 q '= 3 (myślę, że to jest powód wyboru projektu) –

+1

@Vixen, cóż, jeśli pierwszy wzór nie byłby zgodny, oznaczałoby to, że są one różne w drugim wzorze ... – dflemstr

Odpowiedz

2

Można trzymać się swojego stylu oryginalny:

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

Także myślę, że należy uprościć przed badaniem równości, a nie po:

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

Dobry połów z uproszczeniem przed testami równości! –

14

Rozwiązanie znalazłem jest stosowanie osłon w celu sprawdzenia równości podbudów:

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

Jest to prawdopodobnie sposób, aby to zrobić, problem polega na tym, że nie można ponownie użyć tego samego wzorca, jak próbowałeś. Zrobiłem to samo wcześniej i osiągnąłem w zasadzie to samo rozwiązanie. –

1

z „odpowiedź” jest to, że nie wolno wspominać tę samą zmienną dwukrotnie w wzór. W każdym razie nie w Haskell. Najlepszym sposobem rozwiązania tego problemu jest ten, który już odkryłeś - używaj strażników wzorców do testowania równości lub nierówności.

Powiązane problemy