Exercise 2.2


There are several ways to solve this problem. I used the approach of rotating around the origin incrementing the angle by 2Ï€/n each time. The radius of the figure is given by application of the sine rule to the isosceles triangle formed by two adjacent vertices and the origin.

type Side = Float
{-
Construct a regular polygon, given number of sides n and side length s.
-}
regularPolygon :: Int -> Side -> Shape
regularPolygon n s
    = let angleinc = pi * 2 / fromIntegral n
          radius = s * sin ((pi - angleinc) / 2) / sin angleinc
          regularVerts 0 _ = []
          regularVerts n angle = (radius * cos angle, radius * sin angle)
                                 : regularVerts (n-1) (angle + angleinc)
      in Polygon (regularVerts n 0)

Note that the vertex list is in anticlockwise order. This is also the case with Exercise 2.1. Note also the use of fromIntegral to convert between types.


6 responses to “Exercise 2.2”

  1. This solution uses a transformation of a list rather than building one up with recursion:

    regularPolygon :: Int -> Side -> Shape
    regularPolygon n s = Polygon (map makeVertex [1 .. n])
        where makeVertex i = (radius * cos (angle i), radius * sin (angle i))
              radius = s / (2 * sin halfExterior)
              angle i = fromIntegral (2 * i) * halfExterior
              halfExterior = pi / fromIntegral n
    
  2. What the hell! I figured that I needed to use recursion to construct the list, but why do I need to use fromIntegral? I understand that my implementation had typing errors (ghci was telling me), but that function hasn’t been introduced yet.

    Does this mean that the exercises assume that I know the language already?

  3. They don’t assume you know the language, but there are areas where some extra digging comes in handy. I’d say this is true of some of the early exercises, which are sometimes a little contrived in the absence of higher-level functional knowledge.

    If you are coming from a weakly-typed language with implicit conversions between numerical types, then Haskell can be a bit irksome to start with.

    Also, I take the view that no one book need be your only reference, anyway.

  4. I’m with Jeff on this one! I did search around – let me tell you – and solved the problem via list comprehension. I had an earlier solution that should have worked but I got so much type confusion that I scrapped it and wrote another. Thereafter I could see the solution sitting there producing correct answers in the WinHugs console when I would directly enter the values for the number of sides and the side length, but I could *not* get the code to work using passed in parameters, even when the parameters had the exact same values! Very frustrating. The error messages were unhelpful and the solution non-intuitive. I think some mention of fromIntegral was truly in order, even if only in a Details box. At this point there are so many new concepts that could be causing the problem…

    Anyway, thank you for writing up your solutions.

  5. I also tried to compute the vertices with the radius of the whole shape, i.e.
    radius = s / (2 * sin (pi / fromIntegral n))

    As it seems, this computes an incorrect value. Why? The formula is correct!

Leave a Reply

Your email address will not be published. Required fields are marked *