From 4e987026148fe65c323afbc93cd560c07bf06b3f Mon Sep 17 00:00:00 2001 From: Yale AI Dept Date: Wed, 14 Jul 1993 13:08:00 -0500 Subject: Import to github. --- progs/demo/Calendar.hs | 138 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 progs/demo/Calendar.hs (limited to 'progs/demo/Calendar.hs') diff --git a/progs/demo/Calendar.hs b/progs/demo/Calendar.hs new file mode 100644 index 0000000..fa2e4a4 --- /dev/null +++ b/progs/demo/Calendar.hs @@ -0,0 +1,138 @@ +-- This is a modification of the calendar program described in section 4.5 +-- of Bird and Wadler's ``Introduction to functional programming'', with +-- two ways of printing the calendar ... as in B+W, or like UNIX `cal': +-- +-- Use from within Yale Haskell: +-- +-- Main> :l Calendar +-- Now in module Calendar. +-- Calendar> @ do cal 1992 +-- Calendar> :e +-- +-- ... Unix style calendar ... +-- +-- Calendar> @ do calendar 1992 +-- Calendar> :e +-- +-- ... Bird and Wadler style calendar ... +-- +-- Calendar> + +module Calendar(cal,calendar) where + +infixr 5 `above`, `beside` + +do cal year = appendChan stdout (cal year) exit done + +-- Picture handling: + +type Picture = [[Char]] + +height, width :: Picture -> Int +height p = length p +width p = length (head p) + +above, beside :: Picture -> Picture -> Picture +above = (++) +beside = zipWith (++) + +stack, spread :: [Picture] -> Picture +stack = foldr1 above +spread = foldr1 beside + +empty :: (Int,Int) -> Picture +empty (h,w) = copy h (copy w ' ') + +block, blockT :: Int -> [Picture] -> Picture +block n = stack . map spread . group n +blockT n = spread . map stack . group n + +group :: Int -> [a] -> [[a]] +group n [] = [] +group n xs = take n xs : group n (drop n xs) + +lframe :: (Int,Int) -> Picture -> Picture +lframe (m,n) p = (p `beside` empty (h,n-w)) `above` empty (m-h,n) + where h = height p + w = width p + +-- Information about the months in a year: + +monthLengths year = [31,feb,31,30,31,30,31,31,30,31,30,31] + where feb | leap year = 29 + | otherwise = 28 + +leap year = if year`mod`100 == 0 then year`mod`400 == 0 + else year`mod`4 == 0 + +monthNames = ["January","February","March","April", + "May","June","July","August", + "September","October","November","December"] + +jan1st year = (year + last`div`4 - last`div`100 + last`div`400) `mod` 7 + where last = year - 1 + +firstDays year = take 12 + (map (`mod`7) + (scanl (+) (jan1st year) (monthLengths year))) + +-- Producing the information necessary for one month: + +dates fd ml = map (date ml) [1-fd..42-fd] + where date ml d | d<1 || ml String +calendar = unlines . block 3 . map picture . months + where picture (mn,yr,fd,ml) = title mn yr `above` table fd ml + title mn yr = lframe (2,25) [mn ++ " " ++ show yr] + table fd ml = lframe (8,25) + (daynames `beside` entries fd ml) + daynames = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"] + entries fd ml = blockT 7 (dates fd ml) + months year = zip4 monthNames + (copy 12 year) + (firstDays year) + (monthLengths year) + +-- In a format somewhat closer to UNIX cal: + +cal :: Int -> String +cal year = unlines (banner year `above` body year) + where banner yr = [cjustify 75 (show yr)] `above` empty (1,75) + body = block 3 . map (pad . pic) . months + pic (mn,fd,ml) = title mn `above` table fd ml + pad p = (side`beside`p`beside`side)`above`end + side = empty (8,2) + end = empty (1,25) + title mn = [cjustify 21 mn] + table fd ml = daynames `above` entries fd ml + daynames = [" Su Mo Tu We Th Fr Sa"] + entries fd ml = block 7 (dates fd ml) + months year = zip3 monthNames + (firstDays year) + (monthLengths year) + +-- Additional (B+W)-isms: these really ought to go in a separate module, +-- in a spearate file. But for ease of packaging this simple application, +-- it doesn't seem worth the trouble! + +copy :: Int -> a -> [a] +copy n x = take n (repeat x) + +space :: Int -> String +space n = copy n ' ' + +-- Simple string formatting: + +cjustify, ljustify, rjustify :: Int -> String -> String + +cjustify n s = space halfm ++ s ++ space (m - halfm) + where m = n - length s + halfm = m `div` 2 +ljustify n s = s ++ space (n - length s) +rjustify n s = space (n - length s) ++ s + +-- End of calendar program -- cgit v1.2.3