-- NOTE THAT THIS IS JUST *ONE* POSSIBLE SOLUTION TO THE QUESTION -- type declarations type Day = Int type Month = Int type Year = Int type Date = (Day,Month,Year) -- basic functions dpm :: Year -> [Int] dpm year = [31,feb,31,30,31,30,31,31,30,31,30,31] where feb | (leap year) = 29 | otherwise = 28 dayName :: Int -> String dayName day | day==0 = "monday" | day==1 = "tuesday" | day==2 = "wednesday" | day==3 = "thursday" | day==4 = "friday" | day==5 = "saturday" | day==6 = "sunday" leap :: Year -> Bool leap year | (year `mod` 100)==0 && (year `mod` 400)==0 = True | (year `mod` 100)==0 && (year `mod` 400)>0 = False | (year `mod` 4)==0 = True | otherwise = False -- functions for dates after 01/01/2000 numDaysSince2000 :: Date -> Int numDaysSince2000 (day,month,year) = day -- days this month + sum (take (month-1) (dpm year)) -- days this year + (year-2000) * 365 + length [yr | yr <- [2000..year-1], leap yr] -- days this century dayOfWeekPost2000 :: Date -> String dayOfWeekPost2000 date | (numDaysSince2000 date) == 1 = dayName 5 | (numDaysSince2000 date) == 2 = dayName 6 | (numDaysSince2000 date) == 3 = dayName 0 | (numDaysSince2000 date) == 4 = dayName 1 | (numDaysSince2000 date) == 5 = dayName 2 | (numDaysSince2000 date) == 6 = dayName 3 | ((numDaysSince2000 date) `mod` 7)==0 = dayName 4 | ((numDaysSince2000 date) `mod` 7)==1 = dayName 5 | ((numDaysSince2000 date) `mod` 7)==2 = dayName 6 | ((numDaysSince2000 date) `mod` 7)==3 = dayName 0 | ((numDaysSince2000 date) `mod` 7)==4 = dayName 1 | ((numDaysSince2000 date) `mod` 7)==5 = dayName 2 | ((numDaysSince2000 date) `mod` 7)==6 = dayName 3 | otherwise = "???" -- functions for dates prior to 01/01/2000 numDaysBefore2000 :: Date -> Int numDaysBefore2000 (day,month,year) = (((dpm year) !! (month-1)) - (day-1)) -- days left in this month + sum (take (12-month) (reverse (dpm year))) -- days left in this year + (1999-year) * 365 + length [yr | yr <- [year+1..1999], leap yr] -- days left in years up to 2000 dayOfWeekPrior2000 :: Date -> String dayOfWeekPrior2000 date | (numDaysBefore2000 date) == 1 = dayName 4 | (numDaysBefore2000 date) == 2 = dayName 3 | (numDaysBefore2000 date) == 3 = dayName 2 | (numDaysBefore2000 date) == 4 = dayName 1 | (numDaysBefore2000 date) == 5 = dayName 0 | (numDaysBefore2000 date) == 6 = dayName 6 | ((numDaysBefore2000 date) `mod` 7)==0 = dayName 5 | ((numDaysBefore2000 date) `mod` 7)==1 = dayName 4 | ((numDaysBefore2000 date) `mod` 7)==2 = dayName 3 | ((numDaysBefore2000 date) `mod` 7)==3 = dayName 2 | ((numDaysBefore2000 date) `mod` 7)==4 = dayName 1 | ((numDaysBefore2000 date) `mod` 7)==5 = dayName 0 | ((numDaysBefore2000 date) `mod` 7)==6 = dayName 6 | otherwise = "???" -- top-level function whatDay :: Date -> String whatDay (day,mth,yr) | yr < 2000 = dayOfWeekPrior2000 (day,mth,yr) | otherwise = dayOfWeekPost2000 (day,mth,yr)