This code was automatically extracted from a .lhs file that
uses the following convention:

-- lines beginning with ">" are executable
-- lines beginning with "<" are in the text,
     but not necessarily executable
-- lines beginning with "|" are also in the text,
     but are often just expressions or code fragments.

> module Perimeter ( perimeter,
>                    module Shape
>                  ) where
> import Shape

< perimeter                   :: Shape -> Float

< perimeter (Rectangle  s1 s2) = 2*(s1+s2)
< perimeter (RtTriangle s1 s2) = s1 + s2 + sqrt(s1^2+s2^2)

> sides        :: [Vertex] -> [Side]
> sides  []    = []
> sides (v:vs) = aux v vs
>       where aux v1 (v2:vs') = distBetween v1 v2 : aux v2 vs'
>             aux vn  []      = distBetween vn v  : []

| zipWith (+) [1,2,3] [4,5,6] ==> [5,7,9]

< sides    :: [Vertex] -> [Side]
< sides vs = zipWith distBetween vs (tail vs ++ [head vs])

< perimeter (Polygon vs)      = foldl (+) 0 (sides vs)

> epsilon = 0.0001 :: Float

< e = sqrt (r1^2 - r2^2) / r1

> nextEl      :: Float -> Float -> Float -> Float
> nextEl e s i = s*(2*i-1)*(2*i-3)*(e^2) / (4*i^2)

| scanl (+) 0 [1,2,3]  ==>  [0,1,3,6]

< scanl            :: (a -> b -> a) -> a -> [b] -> [a]
< scanl f q  []    = q : []
< scanl f q (x:xs) = q : scanl f (f q x) xs

< s = let aux s i = nextEl e s i
<     in scanl aux (0.25*e^2) [2..]

< s = scanl (nextEl e) (0.25*e^2) [2..]

< takeWhile               :: (a -> Bool) -> [a] -> [a]
< takeWhile p []          =  []
< takeWhile p (x:xs) 
<             | p x       =  x : takeWhile p xs
<             | otherwise =  []

> data Bool = False | True

| let test x = x > epsilon
| in takeWhile test s

< perimeter (Ellipse r1 r2)
<   | r1 > r2   = ellipsePerim r1 r2
<   | otherwise = ellipsePerim r2 r1
<   where ellipsePerim r1 r2
<           = let e = sqrt (r1^2 - r2^2) / r1
<                 s = scanl aux (0.25*e^2) [2..]
<                 aux s i = nextEl e s i
<                 test x = x > epsilon
<                 sSum = foldl (+) 0 (takeWhile test s)
<             in 2*r1*pi*(1-sSum)

> perimeter                   :: Shape -> Float
> perimeter (Rectangle  s1 s2) = 2*(s1+s2)
> perimeter (RtTriangle s1 s2) = s1 + s2 + sqrt(s1^2+s2^2)
> perimeter (Polygon vs)       = foldl (+) 0 (sides vs)
> perimeter (Ellipse r1 r2)
>   | r1 > r2   = ellipsePerim r1 r2
>   | otherwise = ellipsePerim r2 r1
>   where ellipsePerim r1 r2
>             = let e    = sqrt (r1^2 - r2^2) / r1
>                   s    = scanl (nextEl e) (0.25*e^2) [2..]
>                   test x = x > epsilon
>                   sSum = foldl (+) 0 (takeWhile test s)
>               in 2*r1*pi*(1-sSum)

< module Shape   ( Shape (Rectangle, Ellipse, RtTriangle, Polygon),
<                  Radius, Side, Vertex,
<                  area, perimeter
<                ) where 
< ...

