haskellenumsderived-typesderived-instances

haskell enum - what to do in case value constructors require value instead of nullary? Requirement scenario is given


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:

  1. Where to store Max Days value for each month?
  2. How to mention and control that for February month if it is leap year then maxDays for February is 29 days otherwise it will be 28 days?

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;  
    }

Solution

  • 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