2016-06-27 10 views
11

ich nach einer Möglichkeit, Funktionsmuster zu vereinfachen, wenn die Ist-Daten nicht erforderlich sind:Haskell Rekord Pattern-Matching

data X = A | B String | C Int Int String 
myfn :: X -> Int 
myfn A = 50 
myfn (B _) = 200 
myfn (C _ _ _) = 500 

Gibt es eine Möglichkeit, ein einfacheres Muster zum Abgleichen C zu machen, nur um die Werte zu verwerfen ?

hsdev fügt einen Hinweis "Tipp: Benutze Aufzeichnungsmuster" hinzu, aber Google hat mir nicht geholfen.

Antwort

28

Sie können Rekord Muster wie folgt verwenden:

data X = A | B {name :: String} | C {x::Int, y::Int, name::String} 

myfn :: X -> Int 
myfn A = 50 
myfn B{} = 200 
myfn C{} = 500 

Rekord Muster können Sie Namen auf die Felder der Konstrukteure geben. Sie können auch Dinge wie:

myfn C{name=n} = length n 

so können Sie sehen, dass Sie Mustererkennung kann nur auf dem spezifischen Gebiet Sie benötigen.

Hinweis: können Sie die leer Aufzeichnungsmuster verwenden, auch mit Datentypen, die Datensatz-Syntax nicht verwenden:

data A = A Int | B Int Int 

myfn A{} = 1 
myfn B{} = 2 

Das ist in Ordnung. Es gibt eine Reihe von anderen Erweiterungen Rekord Muster bezogen werden:

  • RecordWildCards Sie Dinge wie C{..} schreiben können, die dem Muster entspricht: C{x=x, y=y, name=name}, dh alle Felder übereinstimmt, und Sie haben jetzt in ihrem Umfang x mit der Wert für das x Feld angepasst usw.

  • NamedFieldPuns Sie C{name} als äquivalent zu C{name=name} schreiben können, so dass name jetzt im Umfang und enthält den Wert für dieabgestimmtFeld.

Beachten Sie, dass Rekord-Muster verwenden Sie nicht verhindern, dass Ihre Konstrukteure in einer Positions Art und Weise verwendet wird, so kann man noch schreiben:

myfn (B _) = 200 

Es nur Funktionalität hinzufügt.

+0

Großartig, danke. Ich habe tatsächlich C und C versucht, ohne Erfolg. Nur ein Zeichen zu viel. ^^ – theduke

+2

Schade, dass Google Ihnen mit "haskell record pattern" nicht viel hilft. Ich habe die Frage umbenannt, vielleicht wird sie dadurch für andere besser erkennbar. – theduke

+0

@theduke: Beachten Sie auch, dass Sie das leere Datensatzmuster ('B {}') verwenden können, auch wenn Sie 'B' als normalen Datentyp ohne Datensatz deklariert haben. – Lii