################################################################### 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 = [".......##...", > ".....##..#..", > "...##.....#.", > "..#.......#.", > "..#...#...#.", > "..#...###.#.", > ".#....#..##.", > "..#...#.....", > "...#...#....", > "....#..#....", > ".....#.#....", > "......##...."] A completely white picture. > white :: Picture > white = ["............", > "............", > "............", > "............", > "............", > "............", > "............", > "............", > "............", > "............", > "............", > "............"] 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 (++) Superimose 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 '.'