Reputation: 3061
LYAH says at Derived Instances that
[...] all the value constructors are nullary (take no parameters, i.e. fields), we can make it part of the Enum typeclass.
data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday deriving (Eq, Ord, Show, Read, Bounded, Enum)
Now, if I take months, it will be
data month = January | February | March | April | May | June | July | August |September | October | November |December deriving (Eq, Ord, Show, Read, Bounded, Enum)
My questions are:
In Java one can code like given below:
public enum Month {
January (31),
February (29),
March (31),
April (30),
May (31),
June (30),
July (31),
August (31),
September (30),
October (31),
November (30),
December (31),
;
private int maxDays; // instance variables
private (int maxDays) { // constructors always private
this.maxDays = maxDays;
}
Public int getMaxDays () {
return maxDays;
}
Upvotes: 3
Views: 1429
Reputation: 8078
This should work.
data Month = January | February | March | April | May
| June | July | August |September | October
| November | December
deriving (Eq, Ord, Show, Read, Bounded, Enum)
type Year = Int
isLeapYear :: Year -> Bool
isLeapYear year = year `mod` 4 == 0 && (year `mod` 100 /= 0 || year `mod` 400 == 0)
getMaxDays :: Year -> Month -> Int
getMaxDays _ January = 31
getMaxDays year February
| isLeapYear year = 29
| otherwise = 28
getMaxDays _ March = 31
getMaxDays _ April = 30
getMaxDays _ May = 31
getMaxDays _ June = 30
getMaxDays _ July = 31
getMaxDays _ August = 31
getMaxDays _ September = 30
getMaxDays _ October = 31
getMaxDays _ November = 30
getMaxDays _ December = 31
Upvotes: 7
Reputation:
Why do you need Month
to be an Enum? It seems to me that you are trying to force an OO style in your code, which is not a good idea. The Java object oriented style of writing code does not cleanly translate to functional languages like Haskell.
Where in OO, you would bundle the data structure and all associated operations on that data in a class, in FP, you would define the data structure separately from the associated operations. This means that the FP approach makes it easier to define new operations on data, where as OO approach makes it easier to add new information to your data structure. Personally I find myself defining new operations a lot more than adding new fields and FP style suits that well.
The closest analogue to the Java example in Haskell would be to define a Typeclass -
data Month = January | February | March | April
| May | June | July | August |September
| October | November |December
deriving (Eq, Ord, Show, Read, Bounded, Enum)
data Year = Int
class HasDays X where
maxdays :: X -> Int
days :: X -> Year -> Int
-- Any other "methods" here
instance HasDays Month where
maxdays January = 31
maxdays February = 29
maxdays .. = .. -- Similar code for other months
days February y = .. -- Leap year calculation
days m _ = maxdays m
Upvotes: 7