2012-04-07 18 views
1

Es gibt eine Art Record:Umfang der Muster Anpaßvariablen

type Day   = Integer 
type Description = String 
type Name  = String 
type PhoneNumber = String 
type Year  = Integer 

data Month = January | February | March | April | May | June | July 
      | August | September | October | November | December 
      deriving (Eq, Ord, Enum, Show) 
data Birthday = Birthday Month Day 
    deriving (Eq, Show) 
data DatingDate = DatingDate Year Month Day 
    deriving (Eq, Show) 

data Record = BirthdayRecord Name Birthday 
      | PhoneRecord Name PhoneNumber 
      | DatingRecord DatingDate Description 
      deriving (Eq, Show) 

und Funktion, welche Filter diese Aufzeichnung von Datum:

getAssignment :: (Year, Month, Day) -> [Record] -> [Record] 
getAssignment (year, month, day) = filter matchDate 
    where matchDate (BirthdayRecord _ (Birthday month day)) = True 
     matchDate (DatingRecord (DatingDate year month day) _) = True 
     matchDate _ = False 

Diese Definition von getAssignment ist aufgrund eines Fehlers nicht korrekt:

warning: Defined but not used: `year' 

Eigentlich ist es eine Art Überraschung für mich, dass im Muster passender Teil von getAssignment und year im Muster übereinstimmenden Teil von matchDate sind nicht das Gleiche.

Also, wo sind die Bereichsgrenzen von Variable gestartet und beendet? Es passiert wegen where Abschnitt?

Btw, dieser Fehler kann mit einigen redundanten zahlreiche Verwendung von (year, month, day) Variablen vermieden werden.

getAssignment' :: (Year, Month, Day) -> [Record] -> [Record] 
getAssignment' date = filter (matchDate date) 
    where matchDate (_, m, d) (BirthdayRecord _ (Birthday month day)) = 
      month == m && day == d 
     matchDate (y, m, d) (DatingRecord (DatingDate year month day) _) = 
      year == y && month == m && day == d 
     matchDate _ _ = False 

Wie kann es umgeschrieben werden?

Antwort

4

Der Bereich ist der gesamte Ausdruck (einschließlich der Definitionen in der Where-Klausel), mit der Ausnahme, dass Variablen in einem Muster immer eine neue Variablenbindung definieren.

Anstatt die gleichen Namen wiederzuverwenden, sollten Sie verschiedene Variablennamen in den inneren Bindungen verwenden.

getAssignment :: (Year, Month, Day) -> [Record] -> [Record] 
getAssignment (year, month, day) = filter matchDate 
    where matchDate (BirthdayRecord _ (Birthday month' day')) 
      = month == month' && day == day' 
     matchDate (DatingRecord (DatingDate year' month' day') _) 
      = year == year' && month == month' && day == day' 
     matchDate _ = False 

einen Variablennamen wiederverwendet, so dass es eine Variable von einem äußeren Umfang versteckt ist Abschattung bezeichnet. GHC sollte Sie warnen, wenn Sie dies tun, wenn Sie -Wall (oder -fwarn-name-shadowing verwenden, um nur diese Warnung zu aktivieren).

Edit: Für Ihre spezielle Funktion, ist dies wahrscheinlich ein klarer Weg, es zu schreiben:

getAssignment :: (Year, Month, Day) -> [Record] -> [Record] 
getAssignment (year, month, day) = filter matchDate 
    where matchDate (BirthdayRecord _ birthday) = birthday == Birthday month day 
     matchDate (DatingRecord date _)  = date == DatingDate year month day 
     matchDate _       = False 

Aber man kann nicht umhin, einen Namen Teil des Musters geben, wenn Sie es verwenden möchten , wenn auch nur um es mit etwas anderem zu vergleichen.

+0

Gibt es eine Möglichkeit, diese Variablen "Monat" und "Monat" zu unterdrücken? –

+0

Entschuldigung, ich verstehe Ihren Kommentar nicht. Kannst du mehr Details zu dem geben, was du verlangst? – dave4420

+0

Wenn ich 'f x = x == y 'Definition gesehen habe, möchte ich es wegen der redundanten Verwendung von' x 'Variable wie' f y == True' umschreiben. In diesem Fall würde ich den gleichen Trick verwenden, um "Jahr", "Monat" und "Tag" Variablen loszuwerden. –

0

Mustererkennung hat die Form: Konstruktor binding1 binding2 ... wo Bindungen nur (und nur!) Erlauben, einen Teil des Wertes für die Verwendung zu nennen, ist die rechte Seite. Das ist alles, was Sie tun können, wenn Sie Werte auf der linken Seite mähen. In Ihrem ersten Beispiel scheinen Sie die Übereinstimmung zu beschränken, indem Sie einen gebundenen Namen in die Bindung bringen, aber das wird nicht so funktionieren. Sehen Sie die Wachen für das, was Sie wollen.