There is some type Record:
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)
And function, which filter these record by date:
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
This definition of getAssignment is not correct because of error:
warning: Defined but not used: `year'
Actually, it is kind of surprise for me, that year in pattern matched part of getAssignment and year in pattern matched part of matchDate are not the same.
So, where is the scope bounds of year variable started and finished? It happens because of where section?
Btw, this error can be avoided with some redundant numerous using of (year, month, day) variables.
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
How can it be rewritten?
The scope is the whole expression (including the definitions in the where-clause), EXCEPT that variables in a pattern always define a new variable binding.
Instead of reusing the same names, you should use different variable names in the inner bindings.
Reusing a variable name so that it hides a variable from an outer scope is called shadowing. GHC should warn you when you do this if you use
-Wall(or-fwarn-name-shadowingto enable only this warning).Edit: For your particular function, this is probably a clearer way to write it:
But you can’t avoid giving a name to part of the pattern if you want to use it, even if only to compare it to something else.