2017-09-21 1 views
1

ich versuchte, einen ADT kürzlich zu Umgestalten - wo die Anzahl der kombinato Konstruktoren gewachsen ist - in eine rückwärtskompatibel Satz Darstellung:Karte über PatternSynonyms Argumente vor dem Abgleich mit ViewPatterns?

data Tag = TagFoo | TagBar !Text | TagBaz !Int ... -- many more 
      deriving (Eq, Generic, Ord, Show) 

newtype Label = Label (HashSet Tag) 
       deriving (Eq, Generic, Show) 

Dazu I definiert mehrere Muster Synonyme auf die Wirkung von :

{-# LANGUAGE PatternSynonyms #-} 
{-# LANGUAGE ViewPatterns #-} 

pattern Foo :: Label 
pattern Foo <- Tags [TagFoo] where 
    Foo = Label $ HashSet.singleton TagFoo 

-- (let's say a lone TagBar is invalid) 

pattern FooWithBar :: Text -> Label 
pattern FooWithBar b <- Tags [TagFoo, TagBar b] where 
    FooWithBar b = Label $ HashSet.fromList [TagFoo, TagBar b] 

mit Tags Muster wie folgt definiert:

pattern Tags :: [Tag] -> Label 
pattern Tags ts <- ((\(Label ts') -> sort $ HashSet.toList ts') -> ts) 

Leider ist dies Das Formular ist fehleranfällig, da die Benutzer die [Tag]-Liste im richtigen Ord eingeben müssen. Andernfalls stimmt ein Muster wie Tags [TagBar "x", TagFoo] nicht mit Label $ HashSet.fromList [TagBar "x", TagFoo] überein. (Die sort nicht zu tun ist sogar noch schlimmer, da dann die Reihenfolge der Tags beliebig wäre).

Idealerweise würde Haskell (oder ungeordnete Container?) Eine Möglichkeit bieten, Elemente eines HashSet s zu pattern-match. Aber eine andere Art und Weise könnte das ts Argument von Tags ts Muster durch HashSet.fromList und dann vergleichen die resultierenden Sätze zuzuordnen sein:

pattern Tags ts <- ((\(Label ts') -> ts' == HashSet.fromList ts) -> True) 

Dies ist jedoch unmöglich, weil Argumente eines Musters Synonym nicht durch eine Ansicht Musterfunktion verwendet werden kann. Doch der Versuch, die Transformation außerhalb der View-Funktion zu tun:

pattern Tags ts <- ((\(Label ts') -> ts') -> HashSet.fromList ts == ts') 

auch nicht möglich ist, da der Teil nach -> ein Muster ist und nicht Funktionsanwendung ermöglichen.

Gibt es eine andere Möglichkeit, das Mustersynonym zu definieren, das diese Art des Abgleichs zulässt?

+0

'ungeordnete-containers' kann so ein Synonym entweder nicht definieren! – dfeuer

Antwort

1

Muss Tags wirklich ein Muster sein? Was einfach nicht stimmt mit einer Funktion bereitstellt:

toLabel :: [Tags] -> Label 

und haben Benutzer Wachen verwenden:

someFunction lab | lab == toLabel [TagFoo, TagBar "bar"] = ... 
Verwandte Themen