-- ################################################################### -- -- Pictures.lhs -- -- Simon Thompson -- -- June 1998 -- Last modified 19 October 1998 -- -- An implementation of a type of rectangular pictures using lists of -- lists of characters. -- -- ################################################################### -- -- The basics -- ^^^^^^^^^^ -- module Pictures where type Picture = [[Char]] -- The example used in Craft2e: a polygon which looks like a horse. Here -- taken to be a 16 by 12 rectangle. -- horse :: Picture horse = [".......##...", ".....##..#..", "...##.....#.", "..#.......#.", "..#...#...#.", "..#...###.#.", ".#....#..##.", "..#...#.....", "...#...#....", "....#..#....", ".....#.#....", "......##...."] -- Getting a picture onto the screen. -- printPicture :: Picture -> IO () printPicture = putStr . concat . map (++"\n") -- Transformations of pictures. -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- -- Reflection in a vertical mirror. -- flipV :: Picture -> Picture flipV = map reverse -- Reflection in a horizontal mirror. -- flipH :: Picture -> Picture flipH = reverse -- Rotation through 180 degrees, by composing vertical and horizontal -- reflection. Note that it can also be done by flipV.flipH, and that we -- can prove equality of the two functions. -- rotate :: Picture -> Picture rotate = flipH . flipV -- One picture above another. To maintain the rectangular property, -- the pictures need to have the same width. -- above :: Picture -> Picture -> Picture above = (++) -- One picture next to another. To maintain the rectangular property, -- the pictures need to have the same height. -- sideBySide :: Picture -> Picture -> Picture sideBySide = zipWith (++) -- Superimpose one picture above another. Assume the pictures to be the same -- size. The individual characters are combined using the combine function. -- superimpose :: Picture -> Picture -> Picture superimpose = zipWith (zipWith combine) -- For the result to be '.' both components have to the '.'; otherwise -- get the '#' character. -- combine :: Char -> Char -> Char combine topCh bottomCh = if (topCh == '.' && bottomCh == '.') then '.' else '#' -- Inverting the colours in a picture; done pointwise by invert... -- invertColour :: Picture -> Picture invertColour = map (map invert) -- ... which works by making the result '.' unless the input is '.'. -- invert :: Char -> Char invert ch = if ch == '.' then '#' else '.' -- Local flavor -- unc :: Picture unc = [".#.#........", ".#.#....##..", ".#.#....##..", ".###........", "....#..#....", "....##.#....", "....#.##....", "....#..#....", "........###.", "........#...", "........#...", "........###."] -- pp: easier-to-type function name with same -- behavior as printPicture -- pp :: Picture -> IO () pp pic = printPicture pic