2017-06-04 3 views
0

Also, ich einen Datentyp erstellenMuster für Alternate Instanzen von Eq Passende

data Expr a = Const a 
    | Expr a :*: Expr a 

Und ich definieren eine Instanz für Eq für diesen Datentyp

instance (Eq m) => Eq (Expr m) where 
    Const a == Const b = a == b 
    (a :*: b) == (c :*: d) = ((a == c) && (b == d)) || ((a == d) && (b == c)) 

Diese Definition bedeutet, dass Reihenfolge keine Rolle spielt wenn zwei Ausdrücke verglichen werden. Allerdings, wenn ich Muster verwenden passende, eine Funktion zu schreiben, die Expr s dauert kann ich nicht nur

schreiben
f (Const 1 :*: a) = ... 

sondern auch

f (a :*: Const 1) = ... 

, um alle Fälle schreiben zu fangen, obwohl, wenn ich wo zu Vergleichen Sie die beiden mit (==) würde es wahr zurückgeben.

Gibt es eine Möglichkeit, nur einen der oben genannten Ausdrücke zu schreiben und die Instanz Eq sich um den Rest kümmern? Wird bei der Mustererkennung eine Instanz von Eq verwendet oder benötigt?

Antwort

3

Eine Eq Instanz hat keinerlei Auswirkungen auf Musterübereinstimmungen. == ist nur eine Bibliotheksfunktion und prüft eine bestimmte Eigenschaft, die nicht unbedingt viel mit der Implementierungsstruktur zu tun hat, während Musterübereinstimmungen allesamt um das Dekonstruieren eines Typs in seiner tatsächlichen ADT-Struktur gehen.

Das heißt, es ist möglich zu fälschen etwas ähnliches wie Sie gefragt, aber ich wage zu behaupten, es ist keine sehr gute Idee, dies tatsächlich zu tun - nicht skalieren und könnte zu seltsamen Problemen später führen.

{-# LANGUAGE PatternSynonyms, ViewPatterns #-} 

matchConstFactor :: Expr a -> Maybe (a, Expr a) 
matchConstFactor (Const a :*: b) = Just (a, b) 
matchConstFactor (a :*: Const b) = Just (b, a) 
matchConstFact _ = Nothing 

pattern (:.*:) :: a -> Expr a -> Expr a 
pattern a :.*: b <- (matchConstFactor -> Just (a, b)) 
where a :.*: b = Const a :*: b 
3

Gibt es eine Möglichkeit nur eine der oben genannten Ausdrücke zu schreiben, und die Instanz (Eq) kümmern sich um den Rest zu lassen?

Nr

Hat Muster eine Instanz (Eq) passend auch

Nur wenn Abgleich mit (Anzahl, Zeichen oder eine Zeichenkette) Literale verwenden oder benötigen. Sie können die Regeln in 3.17.2 von https://www.haskell.org/onlinereport/exps.html#pattern-matching sehen und beachten, dass Fall 7 der einzige ist, der == erwähnt.

Aber Sie können Ansicht Muster verwenden:

const1 (Const 1 :*: a) = Just a 
const1 (a :*: Const 1) = Just a 
const1 _ = Nothing 

f (const1 -> Just a) = ... 

Auch dies kann hässlich, wenn Sie andere Symmetrien in anderen Fällen brauchen und ich kann diese eine Lösung im Moment nicht denken.

Verwandte Themen