I whined on IRC about my inability to do simple trig and dakkar kindly

took me through the basics of a cosine. So I sat down later to look

again at an exercise I'd skipped: *2.2* to defined the function:

> regularPolygon::Int->Side->Shape>

But I realised that I still couldn't remember what I was doing and so

consulted Wikipedia's handy page on trigonometry. Armed with `Cos A =
adjacent/hypotenuse` I knocked together

> regularPoly::Int->Float->Shape

> regularPoly nsides r=Polygon $_poly

> where_poly::Int->[(Float,Float)]

>_polyside

>=let frac=1 / fromIntegral nsides

> xyRay::Int->(Float,Float)

> xyRay side=

> let ratio=frac * fromIntegral side

> rad=ratio * 2*pi

> adj=cos rad * r

> opp=sin rad * r

> in (adj, opp)

> in if side == nsides then[]

> else xyRay side :_poly(side+1)

OK, so this is certainly baby-Haskell, but I was quite pleased with it.

I'm liking `let` clauses, which is interesting, coming from Perl 5

where lexical subs don't exist and so I never saw the need for them

before. I'm finding that `where` clauses have slightly different

scoping rules (I had to move the definition of `xyRay` into a let as it

didn't work as a where. Then I realized that `_poly` on the other hand

would work in a where as well as a let).

To check if it worked, I plugged it into the code for chapter 4, first of all forgetting to add

`regularPoly` to the list of functions exported by Shape.hs. The

function works fine, though I've realised now it's not to specification

- it takes a â€œradiusâ€ rather than the length of the side. *Sigh*,

I'll come back to that problem later.

*… (some time later)*

The line `AB` is of length `s`, which is how the input is

specified. We're using `r` instead. Bisecting the line, we have

2 triangles with perpendicular sides `s/2` and `r`. The

angle `AOB` is of `360/n` where `n` is the number

of sides. So `AOC` is `180/n`. Using the tangent

identity:

> tan 180/n=s/2 / r

> s=2r * tan 180/n

> r=s/(2 * tan 180/n)

So in Haskell, we can define a facade on `regularPoly` like so:

>-- #sides -> side -> Polygon [(x,y)]

> regularPoly2::Int->Float->Shape

> regularPoly2 nsides s=regularPoly nsides r

> where r=s / (2 * tan (pi / fromIntegral nsides))

Then of course, on IRC, Apocalisp showed his version of it which is

significantly more beautiful, and which uses the clever idea of rotating

a point an infinite number of times and then `take`â€˜ing from it.

I asked permission to post it here, which he gave, but then told me that

there was a bug in it for larger polygons, which could just be to do

with floating point precision so he was proving it correct first.

Which is the kind of rigour that I'm quite manifestly lacking.

I have an up-to-date version of his code now, but I think I'll do a

proper analysis of his and David's versions of a couple of answers and

possibly (eeeek!) try to prove them correct/equivalent.