Solutions to Problem Set 1 ========================== Written by Paul Hudak in literate Haskell style. > module PS1 where > > import SOEGraphics > import Shape > import SimpleGraphics > import Draw Chapter 1 ========= 1. Do exercise 1.2 in SOE. "Prove by calculation that simple (a-b) a b => a^2 - b^2." Solution: simple (a-b) a b => (a-b)*(a+b) => a^2 - b^2 2. Do exercise 1.3 in SOE. "Identify the well-typed expressions in the following and, for each, give its proper type:" Solution: [ (2,3), (4,5) ] :: [ (Integer,Integer) ] [ 'z', 42 ] -- ill-typed ( 'z', -42 ) :: ( Char, Integer ) simple 'a' 'b' 'c' -- ill-typed ( simple 1 2 3, simple ) :: ( Integer, Integer -> Integer -> Integer -> Integer ) Chapter 2 ========= 3. Do exercise 2.2 in SOE. "Define a function regularPolygon :: Int -> Side -> Shape such that 'regularPolygon n s' is a regular polygon with n sides, each of length s. (Hint: consider using some of Haskell's trigonometric functions, such as sin :: Float -> Float, cos :: Float -> Float, and tan :: Float -> Float.)" Solution: > regularPolygon :: Int -> Side -> Shape > regularPolygon n s = > if n<3 then Polygon [] -- triangle is smallest polygon > else Polygon (makeVertices n s) > > makeVertices :: Int -> Side -> [Vertex] > makeVertices n s = > let nf = intToFloat n > r = s / (2 * sin (pi/nf)) -- "radius" of polygon > makeV i = (r*sin(2*i*pi/nf), r*cos(2*i*pi/nf)) > in take n (map makeV [0,1..]) > makeVertices' :: Int -> Side -> [Vertex] > makeVertices' n s = > let nf = intToFloat n > r = s / (2 * sin (pi/nf)) -- "radius" of polygon > makeV i = (fun i sin, fun i cos) > fun i f = r*f(2*i*pi/nf) > in take n (map makeV [0,1..]) For testing purposes, draw a red regular polygon: > test1 n s > = runGraphics ( > do w <- openWindow "Regular Polygons" (xWin,yWin) > let sh = regularPolygon n s > drawInWindow w (withColor Red (shapeToGraphic sh)) > Draw.spaceClose w > ) Chapter 3 ========= In Hugs, load the file SimpleGraphics, which is the code from Chapter 3, by doing the following from the command line: Hugs>:l SimpleGraphics Browse the source code with your favorite editor, and try running some of the graphics examples, such as names that begin with "main". Also type :? at the command line, to see the various commands that Hugs supports, and try them out. Remember that one letter can be used as an abbreviation for any command (e.g., ":l" for ":load", ":t" for ":type", etc.). 4. Do exercise 3.1 in SOE. "Rewrite the definition of putStr from Section 3.1 so that it does not use sequence_ nor create a list of actions; rather, express it recursively, using the looping idea above. Similarly, define the function getLine (also from Section 3.1) recursively, using the more primitive function getChar :: IO Char. Hint: To define these two functions in this way you will need to use the expressions return () :: IO () and return "" :: IO String (recall the earlier discussion about return)." Solution: > putStr' :: String -> IO () > putStr' [] = return () > putStr' (c:cs) = do putChar c > putStr' cs > > getLine' :: IO String > getLine' = > do c <- getChar -- get a character > if c == '\n' -- if it’s a newline, > then return "" -- then return empty string > else do l <- getLine' -- else get rest of line > return (c:l) -- and return entire line Chapter 4 ========= Load the module Draw into Hugs, which contains the source code from Chapter 4. Browse the source code, and run some of the examples. 5. Use your solution to Exercise 2.2 to do the following: Define a function "conPoly" whose type is Int -> IO (), so that "conPoly n" draws n concentric regular polygons, with a triangle in the middle, and successively larger regular polygons surrounding it. Use your aesthetic prowess to make it look good -- e.g. using colors and arrange sizes of successive polygons so that they enclose one another. Solution: > colors :: [Color] > colors = cycle [Black,Blue,Green,Red,Magenta,Yellow] > > conPoly :: Int -> IO () > conPoly n > = runGraphics ( > do w <- openWindow "Concentric Regular Polygons" (xWin,yWin) > let shs = [ regularPolygon i 1 | i <- [n+3,n+2 .. 3] ] > drawShapes w (zip colors shs) > Draw.spaceClose w > ) > conPoly' :: Int -> IO () > conPoly' n > = runGraphics ( > do w <- openWindow "Concentric Regular Polygons" (xWin,yWin) > let fun i = regularPolygon i 1 > let shs = map fun [n+3,n+2 .. 3] > drawShapes w (zip colors shs) > Draw.spaceClose w > ) ColoredShapes and drawShapes are re-defined here because for some reason I forgot to export them from Draw: > type ColoredShapes = [(Color,Shape)] > > drawShapes :: Window -> ColoredShapes -> IO () > drawShapes w [] > = return () > drawShapes w ((c,s):cs) > = do drawInWindow w (withColor c (shapeToGraphic s)) > drawShapes w cs