<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments for The Haskell School of Expression: Exercises</title>
	<atom:link href="http://www.elbeno.com/haskell_soe_blog/?feed=comments-rss2" rel="self" type="application/rss+xml" />
	<link>http://www.elbeno.com/haskell_soe_blog</link>
	<description>solutions from the exercises in the book</description>
	<lastBuildDate>Tue, 27 Jul 2010 21:51:28 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
	<item>
		<title>Comment on Exercise 1.3 by J Martinez</title>
		<link>http://www.elbeno.com/haskell_soe_blog/?p=5&#038;cpage=1#comment-120</link>
		<dc:creator>J Martinez</dc:creator>
		<pubDate>Tue, 27 Jul 2010 21:51:28 +0000</pubDate>
		<guid isPermaLink="false">http://www.elbeno.com/haskell_soe_blog/?p=5#comment-120</guid>
		<description>I&#039;m just starting to learn too, but I&#039;ll try to explain:

(Num a, Num b) =&gt; (b,a -&gt; a -&gt; a -&gt; a) 

this can be read as: being a of type Num and b of type Num, then the type is  (b,a -&gt; a -&gt; a -&gt; a) 

which is the same as saying that the type is  (Num,Num -&gt; Num -&gt; Num -&gt; Num) 

The elements of a tuple don&#039;t have to be of the same value.

(simple 1 2 3, simple) is a tuple composed of:
 - in the first position, a value of type Num. This is a value because &#039;simple 1 2 3&#039; contains all the inputs defined as values, so &#039;simple 1 2 3&#039; is calculated and the result &#039;5&#039; is used instead.
 - in the second position there is a function with 3 inputs and 1 output, all of type Num. In this case the inputs are not defined and thus &#039;simple&#039; can&#039;t be calculated, &#039;simple&#039; is then just the definition of the function, which type is 
(Num a) =&gt; a -&gt; a -&gt; a -&gt; a</description>
		<content:encoded><![CDATA[<p>I&#8217;m just starting to learn too, but I&#8217;ll try to explain:</p>
<p>(Num a, Num b) =&gt; (b,a -&gt; a -&gt; a -&gt; a) </p>
<p>this can be read as: being a of type Num and b of type Num, then the type is  (b,a -&gt; a -&gt; a -&gt; a) </p>
<p>which is the same as saying that the type is  (Num,Num -&gt; Num -&gt; Num -&gt; Num) </p>
<p>The elements of a tuple don&#8217;t have to be of the same value.</p>
<p>(simple 1 2 3, simple) is a tuple composed of:<br />
 &#8211; in the first position, a value of type Num. This is a value because &#8216;simple 1 2 3&#8242; contains all the inputs defined as values, so &#8216;simple 1 2 3&#8242; is calculated and the result &#8217;5&#8242; is used instead.<br />
 &#8211; in the second position there is a function with 3 inputs and 1 output, all of type Num. In this case the inputs are not defined and thus &#8216;simple&#8217; can&#8217;t be calculated, &#8216;simple&#8217; is then just the definition of the function, which type is<br />
(Num a) =&gt; a -&gt; a -&gt; a -&gt; a</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Exercise 7.5 by Amadeo</title>
		<link>http://www.elbeno.com/haskell_soe_blog/?p=29&#038;cpage=1#comment-119</link>
		<dc:creator>Amadeo</dc:creator>
		<pubDate>Tue, 27 Jul 2010 19:53:03 +0000</pubDate>
		<guid isPermaLink="false">http://www.elbeno.com/haskell_soe_blog/?p=29#comment-119</guid>
		<description>I think the book did not want you to change the type of the function. However the solution given has type

&gt; evaluate :: Expr -&gt; [(String, Float)] -&gt; Float

instead of

&gt; evaluate :: Expr -&gt; Float

I would suggest

&gt; evaluate :: Expr -&gt; Float
&gt; evaluate (C x) = x
&gt; evaluate (e1 :+ e2) = evaluate e1 + evaluate e2
&gt; evaluate (e1 :- e2) = evaluate e1 - evaluate e2
&gt; evaluate (e1 :* e2) = evaluate e1 * evaluate e2
&gt; evaluate (e1 :/ e2) = evaluate e1 / evaluate e2
&gt; {- the above are the old definition given in the book -}
&gt; evaluate (Let str val (C x)) = x
&gt; evaluate (Let str val (exp1 :+ exp2)) = (evaluate (Let str val exp1)) + (evaluate (Let str val exp2))
&gt; evaluate (Let str val (exp1 :- exp2)) = (evaluate (Let str val exp1)) - (evaluate (Let str val exp2))
&gt; evaluate (Let str val (exp1 :* exp2)) = (evaluate (Let str val exp1)) * (evaluate (Let str val exp2))
&gt; evaluate (Let str val (exp1 :/ exp2)) = (evaluate (Let str val exp1)) / (evaluate (Let str val exp2))
&gt; evaluate (Let str val (V str2)) &#124; str == str2 = evaluate val
&gt;                                 &#124; otherwise = error (&quot;undefined variable &quot;++str2)</description>
		<content:encoded><![CDATA[<p>I think the book did not want you to change the type of the function. However the solution given has type</p>
<p>&gt; evaluate :: Expr -&gt; [(String, Float)] -&gt; Float</p>
<p>instead of</p>
<p>&gt; evaluate :: Expr -&gt; Float</p>
<p>I would suggest</p>
<p>&gt; evaluate :: Expr -&gt; Float<br />
&gt; evaluate (C x) = x<br />
&gt; evaluate (e1 :+ e2) = evaluate e1 + evaluate e2<br />
&gt; evaluate (e1 :- e2) = evaluate e1 &#8211; evaluate e2<br />
&gt; evaluate (e1 :* e2) = evaluate e1 * evaluate e2<br />
&gt; evaluate (e1 :/ e2) = evaluate e1 / evaluate e2<br />
&gt; {- the above are the old definition given in the book -}<br />
&gt; evaluate (Let str val (C x)) = x<br />
&gt; evaluate (Let str val (exp1 :+ exp2)) = (evaluate (Let str val exp1)) + (evaluate (Let str val exp2))<br />
&gt; evaluate (Let str val (exp1 :- exp2)) = (evaluate (Let str val exp1)) &#8211; (evaluate (Let str val exp2))<br />
&gt; evaluate (Let str val (exp1 :* exp2)) = (evaluate (Let str val exp1)) * (evaluate (Let str val exp2))<br />
&gt; evaluate (Let str val (exp1 :/ exp2)) = (evaluate (Let str val exp1)) / (evaluate (Let str val exp2))<br />
&gt; evaluate (Let str val (V str2)) | str == str2 = evaluate val<br />
&gt;                                 | otherwise = error (&#8220;undefined variable &#8220;++str2)</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Exercise 1.3 by B Williams</title>
		<link>http://www.elbeno.com/haskell_soe_blog/?p=5&#038;cpage=1#comment-118</link>
		<dc:creator>B Williams</dc:creator>
		<pubDate>Tue, 27 Jul 2010 13:48:41 +0000</pubDate>
		<guid isPermaLink="false">http://www.elbeno.com/haskell_soe_blog/?p=5#comment-118</guid>
		<description>For the last example, would anyone mind explaining how a function with no arguments can be in a tuple with a function with arguments?  How does this result in three successive outputs?  Why do there seem to be only two inputs, when there should be three?</description>
		<content:encoded><![CDATA[<p>For the last example, would anyone mind explaining how a function with no arguments can be in a tuple with a function with arguments?  How does this result in three successive outputs?  Why do there seem to be only two inputs, when there should be three?</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Exercise 8.7 by Joe</title>
		<link>http://www.elbeno.com/haskell_soe_blog/?p=36&#038;cpage=1#comment-117</link>
		<dc:creator>Joe</dc:creator>
		<pubDate>Mon, 07 Jun 2010 05:38:42 +0000</pubDate>
		<guid isPermaLink="false">http://www.elbeno.com/haskell_soe_blog/?p=36#comment-117</guid>
		<description>2 minor errors in the first solution:
&gt; flipX (Scale (a,b) r) = Scale (a,-b) (flipX r)
flipX (Scale (a,b) r) = Scale (a,b) (flipX r)
&gt;           flipXShape (Polygon vs) = Polygon (map ((x,y) -&gt; (x,-y)) vs)
          flipXShape (Polygon vs) = Polygon (map (\ (x,y) -&gt; (x,-y)) vs)</description>
		<content:encoded><![CDATA[<p>2 minor errors in the first solution:<br />
&gt; flipX (Scale (a,b) r) = Scale (a,-b) (flipX r)<br />
flipX (Scale (a,b) r) = Scale (a,b) (flipX r)<br />
&gt;           flipXShape (Polygon vs) = Polygon (map ((x,y) -&gt; (x,-y)) vs)<br />
          flipXShape (Polygon vs) = Polygon (map (\ (x,y) -&gt; (x,-y)) vs)</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Exercise 7.5 by Joe</title>
		<link>http://www.elbeno.com/haskell_soe_blog/?p=29&#038;cpage=1#comment-116</link>
		<dc:creator>Joe</dc:creator>
		<pubDate>Wed, 26 May 2010 10:19:51 +0000</pubDate>
		<guid isPermaLink="false">http://www.elbeno.com/haskell_soe_blog/?p=29#comment-116</guid>
		<description>Let &quot;x&quot; (C 3.0) (Let &quot;y&quot; (V &quot;x&quot;) (Let &quot;x&quot; (C 2.0) (V &quot;y&quot;)))
evalutated to 3 by admin&#039;s definition, but 2 by Wieslaw&#039;s definition.

I think the late binding mechanism should keep its environment, so I suggest
&gt; eval (Let arg e1 e2) map = eval e2 (\x-&gt;if x==arg then (C $ eval e1 map) else map x)</description>
		<content:encoded><![CDATA[<p>Let &#8220;x&#8221; (C 3.0) (Let &#8220;y&#8221; (V &#8220;x&#8221;) (Let &#8220;x&#8221; (C 2.0) (V &#8220;y&#8221;)))<br />
evalutated to 3 by admin&#8217;s definition, but 2 by Wieslaw&#8217;s definition.</p>
<p>I think the late binding mechanism should keep its environment, so I suggest<br />
&gt; eval (Let arg e1 e2) map = eval e2 (\x-&gt;if x==arg then (C $ eval e1 map) else map x)</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Exercise 8.12 by Julian</title>
		<link>http://www.elbeno.com/haskell_soe_blog/?p=41&#038;cpage=1#comment-115</link>
		<dc:creator>Julian</dc:creator>
		<pubDate>Wed, 14 Apr 2010 12:04:00 +0000</pubDate>
		<guid isPermaLink="false">http://www.elbeno.com/haskell_soe_blog/?p=41#comment-115</guid>
		<description>Here goes ....

We include a little test program at the end.

&lt;pre lang=&quot;haskell&quot; escaped=&quot;true&quot;&gt;
{-
 A version of containsS for polygons which handles non-convex polygons.
 
 We compute the winding number of the polygon around the point as follows.
 For the point p and consecutive vertices a and b of the polygon (in that
 order), we have to turn from the vector PA = a-p to the vector PB = b-p.
 We wish to know the angle between these vectors, measured in an
 anticlockwise direction, and such the absolute angle is 0 &lt;= angle &lt;= pi.
 If the angle is pi or either PA or PB is zero, then P lies on the line
 segment AB, possibly at an endpoint.  In this case, the point is definitely
 contained within the polygon, and we need go no further.

 Otherwise, we proceed as follows.  We consider the plane as the complex
 plane, and write PA = a-p = z1 = x1 + i*y1,  PB = b-p = z2 = x2 + i*y2.
 Then the rotation+enlargement from PA to PB is given by

   z2/z1 = (x2 + i*y2) / (x1 + i*y1)
         = ( (x2 + i*y2) * (x1 - i*y1) ) / (x1^2 + y1^2)
         = ( (x1*x2 + y1*y2) + i*(x1*y2 - x2*y1) ) / (x1^2 + y1^2)

 Since we are only interested in the angle and not the enlargement, we
 can find this as the angle of the vector (x1*x2 + y1*y2, x1*y2 - x2*y1)
 from the origin.  This also save us from having to perform complicated
 calculations to determine whether either of PA or PB is zero; PA or PB is
 zero if both the real part (x1*x2 + y1*y2) and the imaginary part
 (x1*y2 - x2*y1) are zero, and the angle is pi if the imaginary part is
 zero and the real part is negative.

 We thus compute this for each pair of adjacent vertices, and return a pair
 (hit, angle), with hit==True if the point p lies on the side AB and False
 otherwise, and angle is the required angle.

 We use the Standard Prelude function atan2 y x which returns the angle
 from the origin to the point (x,y), measured anticlockwise from the x-axis
 and lying in the range -pi &lt;= atan2 y x &lt;= pi.  Note the order of the
 arguments of atan2!!

 Finally, if any hit is True, the point is contained within the polygon.
 Otherwise, we add up all the angles, divide the answer by 2*pi, and round
 to the nearest integer (to overcome rounding errors).  If the final answer
 is 0, then the point is outside the polygon, otherwise it is inside.
 (If the final answer is 2, it means that the polygon winds twice around this
 point, and the polygon is self-intersecting.)
-}

winding :: Coordinate -&gt; Ray -&gt; (Bool,Float)
winding (px,py) ((ax,ay),(bx,by))
  = let x1 = ax - px
        y1 = ay - py
        x2 = bx - px
        y2 = by - py
        re = x1*x2 + y1*y2
        im = x1*y2 - x2*y1
    in aux re im
       where aux r i
               &#124; r &lt;= 0 &amp;&amp; i == 0  = (True,0)
               &#124; otherwise         = (False, atan2 i r)

containsS :: Shape -&gt; Coordinate -&gt; Bool
(Rectangle s1 s2) `containsS` (x,y)
   = let t1 = s1/2; t2 = s2/2
     in (-t1&lt;=x) &amp;&amp; (x&lt;=t1) &amp;&amp; (-t2&lt;=y) &amp;&amp; (y&lt;=t2)
(Ellipse r1 r2) `containsS` (x,y)
   = (x/r1)^2 + (y/r2)^2 &lt;= 1
(Polygon pts) `containsS` p
   = let windings       = map (winding p) (zip pts (tail pts ++ [head pts]))
         (hits, angles) = unzip windings
     in or hits &#124;&#124; round (sum angles / (2 * pi)) /= 0
(RtTriangle s1 s2) `containsS` p
   = (Polygon [(0,0),(s1,0),(0,s2)]) `containsS` p

shs :: [Shape]
shs = [
  Polygon [(-1,-1),(-1,1),(1,1),(1,-1)],
  Polygon [(-1,-1),(1,-1),(1,1),(-1,1)],
  Polygon [(-1,-1),(0,-1),(-1,1),(0,1)],
  Polygon [(-1,-1),(-1,1),(1,1),(1,-1),(-1,-1)],  
  Polygon [(-1,-1),(-1,1),(1,-1)],
  Polygon [(-1,-1),(-1,1),(0,0)],
  Polygon [(-1,-1),(-1,1),(0,1)]
  ]

shcontains = map (\x -&gt; x `containsS` (0,0)) shs

main :: IO()
main = do putStrLn (show shcontains)
&lt;/pre&gt;</description>
		<content:encoded><![CDATA[<p>Here goes &#8230;.</p>
<p>We include a little test program at the end.</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;"><span style="color: #5d478b; font-style: italic;">{-
 A version of containsS for polygons which handles non-convex polygons.
&nbsp;
 We compute the winding number of the polygon around the point as follows.
 For the point p and consecutive vertices a and b of the polygon (in that
 order), we have to turn from the vector PA = a-p to the vector PB = b-p.
 We wish to know the angle between these vectors, measured in an
 anticlockwise direction, and such the absolute angle is 0 &lt;= angle &lt;= pi.
 If the angle is pi or either PA or PB is zero, then P lies on the line
 segment AB, possibly at an endpoint.  In this case, the point is definitely
 contained within the polygon, and we need go no further.
&nbsp;
 Otherwise, we proceed as follows.  We consider the plane as the complex
 plane, and write PA = a-p = z1 = x1 + i*y1,  PB = b-p = z2 = x2 + i*y2.
 Then the rotation+enlargement from PA to PB is given by
&nbsp;
   z2/z1 = (x2 + i*y2) / (x1 + i*y1)
         = ( (x2 + i*y2) * (x1 - i*y1) ) / (x1^2 + y1^2)
         = ( (x1*x2 + y1*y2) + i*(x1*y2 - x2*y1) ) / (x1^2 + y1^2)
&nbsp;
 Since we are only interested in the angle and not the enlargement, we
 can find this as the angle of the vector (x1*x2 + y1*y2, x1*y2 - x2*y1)
 from the origin.  This also save us from having to perform complicated
 calculations to determine whether either of PA or PB is zero; PA or PB is
 zero if both the real part (x1*x2 + y1*y2) and the imaginary part
 (x1*y2 - x2*y1) are zero, and the angle is pi if the imaginary part is
 zero and the real part is negative.
&nbsp;
 We thus compute this for each pair of adjacent vertices, and return a pair
 (hit, angle), with hit==True if the point p lies on the side AB and False
 otherwise, and angle is the required angle.
&nbsp;
 We use the Standard Prelude function atan2 y x which returns the angle
 from the origin to the point (x,y), measured anticlockwise from the x-axis
 and lying in the range -pi &lt;= atan2 y x &lt;= pi.  Note the order of the
 arguments of atan2!!
&nbsp;
 Finally, if any hit is True, the point is contained within the polygon.
 Otherwise, we add up all the angles, divide the answer by 2*pi, and round
 to the nearest integer (to overcome rounding errors).  If the final answer
 is 0, then the point is outside the polygon, otherwise it is inside.
 (If the final answer is 2, it means that the polygon winds twice around this
 point, and the polygon is self-intersecting.)
-}</span>
&nbsp;
winding <span style="color: #339933; font-weight: bold;">::</span> Coordinate <span style="color: #339933; font-weight: bold;">-&gt;</span> Ray <span style="color: #339933; font-weight: bold;">-&gt;</span> <span style="color: green;">&#40;</span><span style="color: #cccc00; font-weight: bold;">Bool</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: #cccc00; font-weight: bold;">Float</span><span style="color: green;">&#41;</span>
winding <span style="color: green;">&#40;</span>px<span style="color: #339933; font-weight: bold;">,</span>py<span style="color: green;">&#41;</span> <span style="color: green;">&#40;</span><span style="color: green;">&#40;</span>ax<span style="color: #339933; font-weight: bold;">,</span>ay<span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span>bx<span style="color: #339933; font-weight: bold;">,</span>by<span style="color: green;">&#41;</span><span style="color: green;">&#41;</span>
  <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">let</span> x1 <span style="color: #339933; font-weight: bold;">=</span> ax <span style="color: #339933; font-weight: bold;">-</span> px
        y1 <span style="color: #339933; font-weight: bold;">=</span> ay <span style="color: #339933; font-weight: bold;">-</span> py
        x2 <span style="color: #339933; font-weight: bold;">=</span> bx <span style="color: #339933; font-weight: bold;">-</span> px
        y2 <span style="color: #339933; font-weight: bold;">=</span> by <span style="color: #339933; font-weight: bold;">-</span> py
        re <span style="color: #339933; font-weight: bold;">=</span> x1<span style="color: #339933; font-weight: bold;">*</span>x2 <span style="color: #339933; font-weight: bold;">+</span> y1<span style="color: #339933; font-weight: bold;">*</span>y2
        im <span style="color: #339933; font-weight: bold;">=</span> x1<span style="color: #339933; font-weight: bold;">*</span>y2 <span style="color: #339933; font-weight: bold;">-</span> x2<span style="color: #339933; font-weight: bold;">*</span>y1
    <span style="color: #06c; font-weight: bold;">in</span> aux re im
       <span style="color: #06c; font-weight: bold;">where</span> aux r i
               <span style="color: #339933; font-weight: bold;">|</span> r <span style="color: #339933; font-weight: bold;">&lt;=</span> <span style="color: red;">0</span> <span style="color: #339933; font-weight: bold;">&amp;&amp;</span> i <span style="color: #339933; font-weight: bold;">==</span> <span style="color: red;">0</span>  <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#40;</span>True<span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">0</span><span style="color: green;">&#41;</span>
               <span style="color: #339933; font-weight: bold;">|</span> <span style="font-weight: bold;">otherwise</span>         <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#40;</span>False<span style="color: #339933; font-weight: bold;">,</span> <span style="font-weight: bold;">atan2</span> i r<span style="color: green;">&#41;</span>
&nbsp;
containsS <span style="color: #339933; font-weight: bold;">::</span> Shape <span style="color: #339933; font-weight: bold;">-&gt;</span> Coordinate <span style="color: #339933; font-weight: bold;">-&gt;</span> <span style="color: #cccc00; font-weight: bold;">Bool</span>
<span style="color: green;">&#40;</span>Rectangle s1 s2<span style="color: green;">&#41;</span> `containsS` <span style="color: green;">&#40;</span>x<span style="color: #339933; font-weight: bold;">,</span>y<span style="color: green;">&#41;</span>
   <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">let</span> t1 <span style="color: #339933; font-weight: bold;">=</span> s1<span style="color: #339933; font-weight: bold;">/</span><span style="color: red;">2</span>; t2 <span style="color: #339933; font-weight: bold;">=</span> s2<span style="color: #339933; font-weight: bold;">/</span><span style="color: red;">2</span>
     <span style="color: #06c; font-weight: bold;">in</span> <span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span>t1<span style="color: #339933; font-weight: bold;">&lt;=</span>x<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">&amp;&amp;</span> <span style="color: green;">&#40;</span>x<span style="color: #339933; font-weight: bold;">&lt;=</span>t1<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">&amp;&amp;</span> <span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span>t2<span style="color: #339933; font-weight: bold;">&lt;=</span>y<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">&amp;&amp;</span> <span style="color: green;">&#40;</span>y<span style="color: #339933; font-weight: bold;">&lt;=</span>t2<span style="color: green;">&#41;</span>
<span style="color: green;">&#40;</span>Ellipse r1 r2<span style="color: green;">&#41;</span> `containsS` <span style="color: green;">&#40;</span>x<span style="color: #339933; font-weight: bold;">,</span>y<span style="color: green;">&#41;</span>
   <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#40;</span>x<span style="color: #339933; font-weight: bold;">/</span>r1<span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">^</span><span style="color: red;">2</span> <span style="color: #339933; font-weight: bold;">+</span> <span style="color: green;">&#40;</span>y<span style="color: #339933; font-weight: bold;">/</span>r2<span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">^</span><span style="color: red;">2</span> <span style="color: #339933; font-weight: bold;">&lt;=</span> <span style="color: red;">1</span>
<span style="color: green;">&#40;</span>Polygon pts<span style="color: green;">&#41;</span> `containsS` p
   <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">let</span> windings       <span style="color: #339933; font-weight: bold;">=</span> <span style="font-weight: bold;">map</span> <span style="color: green;">&#40;</span>winding p<span style="color: green;">&#41;</span> <span style="color: green;">&#40;</span><span style="font-weight: bold;">zip</span> pts <span style="color: green;">&#40;</span><span style="font-weight: bold;">tail</span> pts <span style="color: #339933; font-weight: bold;">++</span> <span style="color: green;">&#91;</span><span style="font-weight: bold;">head</span> pts<span style="color: green;">&#93;</span><span style="color: green;">&#41;</span><span style="color: green;">&#41;</span>
         <span style="color: green;">&#40;</span>hits<span style="color: #339933; font-weight: bold;">,</span> angles<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span> <span style="font-weight: bold;">unzip</span> windings
     <span style="color: #06c; font-weight: bold;">in</span> <span style="font-weight: bold;">or</span> hits <span style="color: #339933; font-weight: bold;">||</span> <span style="font-weight: bold;">round</span> <span style="color: green;">&#40;</span><span style="font-weight: bold;">sum</span> angles <span style="color: #339933; font-weight: bold;">/</span> <span style="color: green;">&#40;</span><span style="color: red;">2</span> <span style="color: #339933; font-weight: bold;">*</span> <span style="font-weight: bold;">pi</span><span style="color: green;">&#41;</span><span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">/=</span> <span style="color: red;">0</span>
<span style="color: green;">&#40;</span>RtTriangle s1 s2<span style="color: green;">&#41;</span> `containsS` p
   <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#40;</span>Polygon <span style="color: green;">&#91;</span><span style="color: green;">&#40;</span><span style="color: red;">0</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">0</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span>s1<span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">0</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: red;">0</span><span style="color: #339933; font-weight: bold;">,</span>s2<span style="color: green;">&#41;</span><span style="color: green;">&#93;</span><span style="color: green;">&#41;</span> `containsS` p
&nbsp;
shs <span style="color: #339933; font-weight: bold;">::</span> <span style="color: green;">&#91;</span>Shape<span style="color: green;">&#93;</span>
shs <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#91;</span>
  Polygon <span style="color: green;">&#91;</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: green;">&#93;</span><span style="color: #339933; font-weight: bold;">,</span>
  Polygon <span style="color: green;">&#91;</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: green;">&#93;</span><span style="color: #339933; font-weight: bold;">,</span>
  Polygon <span style="color: green;">&#91;</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: red;">0</span><span style="color: #339933; font-weight: bold;">,-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: red;">0</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: green;">&#93;</span><span style="color: #339933; font-weight: bold;">,</span>
  Polygon <span style="color: green;">&#91;</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: green;">&#93;</span><span style="color: #339933; font-weight: bold;">,</span>  
  Polygon <span style="color: green;">&#91;</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: green;">&#93;</span><span style="color: #339933; font-weight: bold;">,</span>
  Polygon <span style="color: green;">&#91;</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: red;">0</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">0</span><span style="color: green;">&#41;</span><span style="color: green;">&#93;</span><span style="color: #339933; font-weight: bold;">,</span>
  Polygon <span style="color: green;">&#91;</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: red;">0</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: green;">&#93;</span>
  <span style="color: green;">&#93;</span>
&nbsp;
shcontains <span style="color: #339933; font-weight: bold;">=</span> <span style="font-weight: bold;">map</span> <span style="color: green;">&#40;</span>\x <span style="color: #339933; font-weight: bold;">-&gt;</span> x `containsS` <span style="color: green;">&#40;</span><span style="color: red;">0</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">0</span><span style="color: green;">&#41;</span><span style="color: green;">&#41;</span> shs
&nbsp;
main <span style="color: #339933; font-weight: bold;">::</span> <span style="color: #cccc00; font-weight: bold;">IO</span><span style="color: green;">&#40;</span><span style="color: green;">&#41;</span>
main <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">do</span> <span style="font-weight: bold;">putStrLn</span> <span style="color: green;">&#40;</span><span style="font-weight: bold;">show</span> shcontains<span style="color: green;">&#41;</span></pre></div></div>

]]></content:encoded>
	</item>
	<item>
		<title>Comment on Exercise 8.12 by Julian</title>
		<link>http://www.elbeno.com/haskell_soe_blog/?p=41&#038;cpage=1#comment-114</link>
		<dc:creator>Julian</dc:creator>
		<pubDate>Wed, 14 Apr 2010 08:31:53 +0000</pubDate>
		<guid isPermaLink="false">http://www.elbeno.com/haskell_soe_blog/?p=41#comment-114</guid>
		<description>There&#039;s a more elegant method than maxop, which is to use the Standard Prelude maximum function.

Unfortunately, however, the method shown does not work in this case:

&lt;pre lang=&quot;haskell&quot;&gt;
let poly = Polygon ([(-1,-1),(1,-1),(1,1),(-1,1)])
    p = (0,0)
in poly `containsS&#039;` p
&lt;/pre&gt;

gives a result of False, even though the point (0,0) clearly lies inside the square.

The reason is that the point outside that is chosen is (2,2), and the ray (0,0) to (2,2) passes through the vertex (1,1), and so lies on two edges.

This problem is therefore far subtler than it first appears.

One approach is to use the given idea but to take account of the fixed ray (from chosen point to outside point) passing through vertices, by having each one counting for 0.5.  However, this will also fail if the ray just touches a vertex (if the shape is concave).  A fix for this is to use signed crossings, taking account of the direction in which the rays cross.  But this is getting fairly awkward and difficult.

I&#039;m currently working on an alternative approach which uses winding numbers - we&#039;ll see how it works out ....

Julian</description>
		<content:encoded><![CDATA[<p>There&#8217;s a more elegant method than maxop, which is to use the Standard Prelude maximum function.</p>
<p>Unfortunately, however, the method shown does not work in this case:</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">let</span> poly <span style="color: #339933; font-weight: bold;">=</span> Polygon <span style="color: green;">&#40;</span><span style="color: green;">&#91;</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: green;">&#93;</span><span style="color: green;">&#41;</span>
    p <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#40;</span><span style="color: red;">0</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: red;">0</span><span style="color: green;">&#41;</span>
<span style="color: #06c; font-weight: bold;">in</span> poly `containsS'` p</pre></div></div>

<p>gives a result of False, even though the point (0,0) clearly lies inside the square.</p>
<p>The reason is that the point outside that is chosen is (2,2), and the ray (0,0) to (2,2) passes through the vertex (1,1), and so lies on two edges.</p>
<p>This problem is therefore far subtler than it first appears.</p>
<p>One approach is to use the given idea but to take account of the fixed ray (from chosen point to outside point) passing through vertices, by having each one counting for 0.5.  However, this will also fail if the ray just touches a vertex (if the shape is concave).  A fix for this is to use signed crossings, taking account of the direction in which the rays cross.  But this is getting fairly awkward and difficult.</p>
<p>I&#8217;m currently working on an alternative approach which uses winding numbers &#8211; we&#8217;ll see how it works out &#8230;.</p>
<p>Julian</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Exercise 8.9 by Julian</title>
		<link>http://www.elbeno.com/haskell_soe_blog/?p=38&#038;cpage=1#comment-113</link>
		<dc:creator>Julian</dc:creator>
		<pubDate>Wed, 14 Apr 2010 08:13:18 +0000</pubDate>
		<guid isPermaLink="false">http://www.elbeno.com/haskell_soe_blog/?p=38#comment-113</guid>
		<description>For simplicity and brevity, I will use somthing like standard
set-theoretic notations as abbreviations for Intersection and Union,
writing

r1 u r2    for     r1 `Union` r2

and

r1 n r2    for     r1 `Intersection` r2

Also, I will write r&#039; for Complement r, 0 for Empty and 1 for univ,
and a simple = sign instead of the three-line equivalence notation.

Then the five axioms, together with some simple corollaries, read:

Axiom 1
-------

r1 u (r2 u r3) = (r1 u r2) u r3
r1 n (r2 n r3) = (r1 n r2) n r3

Axiom 2
-------

r1 u r2 = r2 u r1
r1 n r2 = r2 n r1

Axiom 3
-------

r1 n (r2 u r3) = (r1 n r2) u (r1 n r3)
r1 u (r2 n r3) = (r1 u r2) n (r1 u r3)

Corollaries:

(r2 u r3) n r1 = (r2 n r1) u (r3 n r1)
(r2 n r3) u r1 = (r2 u r1) n (r3 u r1)

Proof: Apply Axiom 2 to both sides.

Axiom 4
-------

r u 0 = r
r n 1 = r

Corollaries:

0 u r = r
1 n r = r

Proof: Apply Axiom 2 to the left side.

Axiom 5
-------

r u r&#039; = 1
r n r&#039; = 0

Corollaries:

r&#039; u r = 1
r&#039; n r = 0

Proof: Apply Axiom 2 to the left side.



Now for the exercise at hand...

Lemma 1
-------

r n r = r
r u r = r

Proof:

r = r n 1                   [Axiom 4]
  = r n (r u r&#039;)            [Axiom 5]
  = (r n r) u (r n r&#039;)      [Axiom 3]
  = (r n r) u 0             [Axiom 5]
  = r n r                   [Axiom 4]

The proof of the second statement is essentially identical, swapping
n with u and 1 with 0:

r = r u 0                   [Axiom 4]
  = r u (r n r&#039;)            [Axiom 5]
  = (r u r) n (r u r&#039;)      [Axiom 3]
  = (r u r) n 1             [Axiom 5]
  = r u r                   [Axiom 4]


Lemma 2
-------

r u 1 = 1
r n 0 = 0

Proof:

r u 1 = r u (r u r&#039;)        [Axiom 5]
      = (r u r) u r&#039;        [Axiom 1]
      = r u r&#039;              [Lemma 1]
      = 1                   [Axiom 5]

and again, the other is exactly parallel:

r n 0 = r n (r n r&#039;)        [Axiom 5]
      = (r n r) n r&#039;        [Axiom 1]
      = r n r&#039;              [Lemma 1]
      = 0                   [Axiom 5]

Corollaries:

1 u r = 1
0 n r = 0

Proof: Apply Axiom 2 to the left side.


Lemma 3
-------

r1 u (r1 n r2) = r1
r1 n (r1 u r2) = r1

Proof (the first step is sneaky):

r1 u (r1 n r2) = (r1 n 1) u (r1 n r2)    [Axiom 4]
               = r1 n (1 u r2)           [Axiom 3, in reverse]
               = r1 n 1                  [Lemma 2, corollary]
               = r1                      [Axiom 4]

And again, swapping n with u and 1 with 0 gives the corresponding
result:

r1 n (r1 u r2) = (r1 u 0) n (r1 u r2)    [Axiom 4]
               = r1 u (0 n r2)           [Axiom 3, in reverse]
               = r1 u 0                  [Lemma 2, corollary]
               = r1                      [Axiom 4]

Alternatively, the latter can be deduced from the former as follows:

r1 n (r1 u r2) = (r1 n r1) u (r1 n r2)   [Axiom 3]
               = r1 u (r1 n r2)          [Lemma 1]
               = r1                      [first part of Lemma 3]


Lemma 4
-------

r&#039;&#039; = r, where r&#039;&#039; means (r&#039;)&#039;

Proof:

The idea of this proof is to show that r&#039;&#039; u r = r and also r&#039;&#039; u r = r&#039;&#039;, 
so that r = r&#039;&#039; u r = r&#039;&#039;, or r&#039;&#039; = r.  It could be written in one
long chain, but it is clearer to write it in two halves.

We have

r&#039;&#039; u r = (r&#039;&#039; u r) n 1                 [Axiom 4]
        = (r&#039;&#039; u r) n (r u r&#039;)          [Axiom 5]
        = (r u r&#039;&#039;) n (r u r&#039;)          [Axiom 2]
        = r u (r&#039;&#039; n r&#039;)                [Axiom 3, in reverse]
        = r u (r&#039; n (r&#039;)&#039;)              [Axiom 2, and writing r&#039;&#039;=(r&#039;)&#039;]
        = r u 0                         [Axiom 5]
        = r                             [Axiom 4]

Likewise, but this time writing 1 = r&#039; u (r&#039;)&#039; instead of 1 = r u r&#039;,
we get:

r&#039;&#039; u r = (r&#039;&#039; u r) n 1                 [Axiom 4]
        = (r&#039;&#039; u r) n (r&#039; u (r&#039;)&#039;)      [Axiom 5]
        = (r&#039;&#039; u r) n (r&#039;&#039; u r&#039;)        [Axiom 2, and writing (r&#039;)&#039;=r&#039;&#039;]
        = r&#039;&#039; u (r n r&#039;)                [Axiom 3, in reverse]
        = r&#039;&#039; u 0                       [Axiom 5]
        = r&#039;&#039;                           [Axiom 4]

Therefore r = r&#039;&#039;.


Lemma 5
-------

0&#039; = 1
1&#039; = 0

Well, the first is the definition of univ (as given just before Axiom
3), and the proof the of second is trivial:

1&#039; = (0&#039;)&#039;        [By definition: 1 = 0&#039;]
   = 0            [Lemma 4]


Lemma 6
-------

(r1 u r2)&#039; = r1&#039; n r2&#039;
(r1 n r2)&#039; = r1&#039; u r2&#039;

These are the famous De Morgan&#039;s Theorems, and their proof is tricky
(and not due to me, either!).  We prove a preliminary lemma first.

Lemma 7
-------

If r1&#039; n r2 = 0 and r1&#039; u r2 = 1, then r1 = r2.

Proof:

r1 = r1 u 0                         [Axiom 4]
   = r1 u (r1&#039; n r2)                [Hypothesis]
   = (r1 u r1&#039;) n (r1 u r2)         [Axiom 3]
   = 1 n (r1 u r2)                  [Axiom 5]
   = (r1&#039; u r2) n (r1 u r2)         [Hypothesis]
   = (r2 u r1&#039;) n (r2 u r1)         [Axiom 2]
   = r2 u (r1&#039; n r1)                [Axiom 3, in reverse]
   = r2 u 0                         [Axiom 5, corollary]
   = r2

Proof of Lemma 6
----------------

We want to show first that (r1 u r2)&#039; = r1&#039; n r2&#039;, so we aim to show
that ((r1 u r2)&#039;)&#039; n (r1&#039; n r2&#039;) = 0  and  ((r1 u r2)&#039;)&#039; u (r1&#039; n r2&#039;)
= 1, so that (r1 u r2)&#039; = r1&#039; n r2&#039; by Lemma 7.

We note first that ((r1 u r2)&#039;)&#039; = r1 u r2 by Lemma 4.  We then have

(r1 u r2) n (r1&#039; n r2&#039;)

   = ((r1 u r2) n r1&#039;) n r2&#039;          [Axiom 1]
   = ((r1 n r1&#039;) u (r2 n r1&#039;)) n r2&#039;  [Axiom 3, corollary]
   = (0 u (r2 n r1&#039;)) n r2&#039;           [Axiom 5]
   = (r2 n r1&#039;) n r2&#039;                 [Axiom 4, corollary]
   = (r1&#039; n r2) n r2&#039;                 [Axiom 2]
   = r1&#039; n (r2 n r2&#039;)                 [Axiom 1]
   = r1&#039; n 0                          [Axiom 5]
   = 0                                [Lemma 2]

and

(r1 u r2) u (r1&#039; n r2&#039;)
   = ((r1 u r2) u r1&#039;) n ((r1 u r2) u r2&#039;)  [Axiom 3]
   = ((r2 u r1) u r1&#039;) n ((r1 u r2) u r2&#039;)  [Axiom 2]
   = (r2 u (r1 u r1&#039;)) n (r1 u (r2 u r2&#039;))  [Axiom 1]
   = (r2 u 1 ) n (r1 u 1)                   [Axiom 5]
   = 1 n 1                                  [Lemma 2]
   = 1                                      [Axiom 4]

Thus, by Lemma 7, (r1 u r2)&#039; = r1&#039; n r2&#039;.

For the second part of Lemma 6, we can either argue identically, or as
follows:

We have

(r1 n r2)&#039; = ( (r1&#039;)&#039; n (r2&#039;)&#039; )&#039;    [Lemma 4]
           = ( ((r1&#039;) u (r2&#039;))&#039; )&#039;   [Lemma 6, first part]
           = (r1&#039; u r2&#039;)&#039;&#039;           [rewriting with fewer brackets]
           = r1&#039; u r2&#039;               [Lemma 4]</description>
		<content:encoded><![CDATA[<p>For simplicity and brevity, I will use somthing like standard<br />
set-theoretic notations as abbreviations for Intersection and Union,<br />
writing</p>
<p>r1 u r2    for     r1 `Union` r2</p>
<p>and</p>
<p>r1 n r2    for     r1 `Intersection` r2</p>
<p>Also, I will write r&#8217; for Complement r, 0 for Empty and 1 for univ,<br />
and a simple = sign instead of the three-line equivalence notation.</p>
<p>Then the five axioms, together with some simple corollaries, read:</p>
<p>Axiom 1<br />
&#8212;&#8212;-</p>
<p>r1 u (r2 u r3) = (r1 u r2) u r3<br />
r1 n (r2 n r3) = (r1 n r2) n r3</p>
<p>Axiom 2<br />
&#8212;&#8212;-</p>
<p>r1 u r2 = r2 u r1<br />
r1 n r2 = r2 n r1</p>
<p>Axiom 3<br />
&#8212;&#8212;-</p>
<p>r1 n (r2 u r3) = (r1 n r2) u (r1 n r3)<br />
r1 u (r2 n r3) = (r1 u r2) n (r1 u r3)</p>
<p>Corollaries:</p>
<p>(r2 u r3) n r1 = (r2 n r1) u (r3 n r1)<br />
(r2 n r3) u r1 = (r2 u r1) n (r3 u r1)</p>
<p>Proof: Apply Axiom 2 to both sides.</p>
<p>Axiom 4<br />
&#8212;&#8212;-</p>
<p>r u 0 = r<br />
r n 1 = r</p>
<p>Corollaries:</p>
<p>0 u r = r<br />
1 n r = r</p>
<p>Proof: Apply Axiom 2 to the left side.</p>
<p>Axiom 5<br />
&#8212;&#8212;-</p>
<p>r u r&#8217; = 1<br />
r n r&#8217; = 0</p>
<p>Corollaries:</p>
<p>r&#8217; u r = 1<br />
r&#8217; n r = 0</p>
<p>Proof: Apply Axiom 2 to the left side.</p>
<p>Now for the exercise at hand&#8230;</p>
<p>Lemma 1<br />
&#8212;&#8212;-</p>
<p>r n r = r<br />
r u r = r</p>
<p>Proof:</p>
<p>r = r n 1                   [Axiom 4]<br />
  = r n (r u r&#8217;)            [Axiom 5]<br />
  = (r n r) u (r n r&#8217;)      [Axiom 3]<br />
  = (r n r) u 0             [Axiom 5]<br />
  = r n r                   [Axiom 4]</p>
<p>The proof of the second statement is essentially identical, swapping<br />
n with u and 1 with 0:</p>
<p>r = r u 0                   [Axiom 4]<br />
  = r u (r n r&#8217;)            [Axiom 5]<br />
  = (r u r) n (r u r&#8217;)      [Axiom 3]<br />
  = (r u r) n 1             [Axiom 5]<br />
  = r u r                   [Axiom 4]</p>
<p>Lemma 2<br />
&#8212;&#8212;-</p>
<p>r u 1 = 1<br />
r n 0 = 0</p>
<p>Proof:</p>
<p>r u 1 = r u (r u r&#8217;)        [Axiom 5]<br />
      = (r u r) u r&#8217;        [Axiom 1]<br />
      = r u r&#8217;              [Lemma 1]<br />
      = 1                   [Axiom 5]</p>
<p>and again, the other is exactly parallel:</p>
<p>r n 0 = r n (r n r&#8217;)        [Axiom 5]<br />
      = (r n r) n r&#8217;        [Axiom 1]<br />
      = r n r&#8217;              [Lemma 1]<br />
      = 0                   [Axiom 5]</p>
<p>Corollaries:</p>
<p>1 u r = 1<br />
0 n r = 0</p>
<p>Proof: Apply Axiom 2 to the left side.</p>
<p>Lemma 3<br />
&#8212;&#8212;-</p>
<p>r1 u (r1 n r2) = r1<br />
r1 n (r1 u r2) = r1</p>
<p>Proof (the first step is sneaky):</p>
<p>r1 u (r1 n r2) = (r1 n 1) u (r1 n r2)    [Axiom 4]<br />
               = r1 n (1 u r2)           [Axiom 3, in reverse]<br />
               = r1 n 1                  [Lemma 2, corollary]<br />
               = r1                      [Axiom 4]</p>
<p>And again, swapping n with u and 1 with 0 gives the corresponding<br />
result:</p>
<p>r1 n (r1 u r2) = (r1 u 0) n (r1 u r2)    [Axiom 4]<br />
               = r1 u (0 n r2)           [Axiom 3, in reverse]<br />
               = r1 u 0                  [Lemma 2, corollary]<br />
               = r1                      [Axiom 4]</p>
<p>Alternatively, the latter can be deduced from the former as follows:</p>
<p>r1 n (r1 u r2) = (r1 n r1) u (r1 n r2)   [Axiom 3]<br />
               = r1 u (r1 n r2)          [Lemma 1]<br />
               = r1                      [first part of Lemma 3]</p>
<p>Lemma 4<br />
&#8212;&#8212;-</p>
<p>r&#8221; = r, where r&#8221; means (r&#8217;)&#8217;</p>
<p>Proof:</p>
<p>The idea of this proof is to show that r&#8221; u r = r and also r&#8221; u r = r&#8221;,<br />
so that r = r&#8221; u r = r&#8221;, or r&#8221; = r.  It could be written in one<br />
long chain, but it is clearer to write it in two halves.</p>
<p>We have</p>
<p>r&#8221; u r = (r&#8221; u r) n 1                 [Axiom 4]<br />
        = (r&#8221; u r) n (r u r&#8217;)          [Axiom 5]<br />
        = (r u r&#8221;) n (r u r&#8217;)          [Axiom 2]<br />
        = r u (r&#8221; n r&#8217;)                [Axiom 3, in reverse]<br />
        = r u (r&#8217; n (r&#8217;)')              [Axiom 2, and writing r''=(r')']<br />
        = r u 0                         [Axiom 5]<br />
        = r                             [Axiom 4]</p>
<p>Likewise, but this time writing 1 = r&#8217; u (r&#8217;)&#8217; instead of 1 = r u r&#8217;,<br />
we get:</p>
<p>r&#8221; u r = (r&#8221; u r) n 1                 [Axiom 4]<br />
        = (r&#8221; u r) n (r&#8217; u (r&#8217;)')      [Axiom 5]<br />
        = (r&#8221; u r) n (r&#8221; u r&#8217;)        [Axiom 2, and writing (r')'=r'']<br />
        = r&#8221; u (r n r&#8217;)                [Axiom 3, in reverse]<br />
        = r&#8221; u 0                       [Axiom 5]<br />
        = r&#8221;                           [Axiom 4]</p>
<p>Therefore r = r&#8221;.</p>
<p>Lemma 5<br />
&#8212;&#8212;-</p>
<p>0&#8242; = 1<br />
1&#8242; = 0</p>
<p>Well, the first is the definition of univ (as given just before Axiom<br />
3), and the proof the of second is trivial:</p>
<p>1&#8242; = (0&#8242;)&#8217;        [By definition: 1 = 0']<br />
   = 0            [Lemma 4]</p>
<p>Lemma 6<br />
&#8212;&#8212;-</p>
<p>(r1 u r2)&#8217; = r1&#8242; n r2&#8242;<br />
(r1 n r2)&#8217; = r1&#8242; u r2&#8242;</p>
<p>These are the famous De Morgan&#8217;s Theorems, and their proof is tricky<br />
(and not due to me, either!).  We prove a preliminary lemma first.</p>
<p>Lemma 7<br />
&#8212;&#8212;-</p>
<p>If r1&#8242; n r2 = 0 and r1&#8242; u r2 = 1, then r1 = r2.</p>
<p>Proof:</p>
<p>r1 = r1 u 0                         [Axiom 4]<br />
   = r1 u (r1&#8242; n r2)                [Hypothesis]<br />
   = (r1 u r1&#8242;) n (r1 u r2)         [Axiom 3]<br />
   = 1 n (r1 u r2)                  [Axiom 5]<br />
   = (r1&#8242; u r2) n (r1 u r2)         [Hypothesis]<br />
   = (r2 u r1&#8242;) n (r2 u r1)         [Axiom 2]<br />
   = r2 u (r1&#8242; n r1)                [Axiom 3, in reverse]<br />
   = r2 u 0                         [Axiom 5, corollary]<br />
   = r2</p>
<p>Proof of Lemma 6<br />
&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>We want to show first that (r1 u r2)&#8217; = r1&#8242; n r2&#8242;, so we aim to show<br />
that ((r1 u r2)&#8217;)&#8217; n (r1&#8242; n r2&#8242;) = 0  and  ((r1 u r2)&#8217;)&#8217; u (r1&#8242; n r2&#8242;)<br />
= 1, so that (r1 u r2)&#8217; = r1&#8242; n r2&#8242; by Lemma 7.</p>
<p>We note first that ((r1 u r2)&#8217;)&#8217; = r1 u r2 by Lemma 4.  We then have</p>
<p>(r1 u r2) n (r1&#8242; n r2&#8242;)</p>
<p>   = ((r1 u r2) n r1&#8242;) n r2&#8242;          [Axiom 1]<br />
   = ((r1 n r1&#8242;) u (r2 n r1&#8242;)) n r2&#8242;  [Axiom 3, corollary]<br />
   = (0 u (r2 n r1&#8242;)) n r2&#8242;           [Axiom 5]<br />
   = (r2 n r1&#8242;) n r2&#8242;                 [Axiom 4, corollary]<br />
   = (r1&#8242; n r2) n r2&#8242;                 [Axiom 2]<br />
   = r1&#8242; n (r2 n r2&#8242;)                 [Axiom 1]<br />
   = r1&#8242; n 0                          [Axiom 5]<br />
   = 0                                [Lemma 2]</p>
<p>and</p>
<p>(r1 u r2) u (r1&#8242; n r2&#8242;)<br />
   = ((r1 u r2) u r1&#8242;) n ((r1 u r2) u r2&#8242;)  [Axiom 3]<br />
   = ((r2 u r1) u r1&#8242;) n ((r1 u r2) u r2&#8242;)  [Axiom 2]<br />
   = (r2 u (r1 u r1&#8242;)) n (r1 u (r2 u r2&#8242;))  [Axiom 1]<br />
   = (r2 u 1 ) n (r1 u 1)                   [Axiom 5]<br />
   = 1 n 1                                  [Lemma 2]<br />
   = 1                                      [Axiom 4]</p>
<p>Thus, by Lemma 7, (r1 u r2)&#8217; = r1&#8242; n r2&#8242;.</p>
<p>For the second part of Lemma 6, we can either argue identically, or as<br />
follows:</p>
<p>We have</p>
<p>(r1 n r2)&#8217; = ( (r1&#8242;)&#8217; n (r2&#8242;)&#8217; )&#8217;    [Lemma 4]<br />
           = ( ((r1&#8242;) u (r2&#8242;))&#8217; )&#8217;   [Lemma 6, first part]<br />
           = (r1&#8242; u r2&#8242;)&#8221;           [rewriting with fewer brackets]<br />
           = r1&#8242; u r2&#8242;               [Lemma 4]</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Exercise 5.9 by Julian</title>
		<link>http://www.elbeno.com/haskell_soe_blog/?p=23&#038;cpage=1#comment-112</link>
		<dc:creator>Julian</dc:creator>
		<pubDate>Sun, 11 Apr 2010 12:48:10 +0000</pubDate>
		<guid isPermaLink="false">http://www.elbeno.com/haskell_soe_blog/?p=23#comment-112</guid>
		<description>Here&#039;s one way of solving the problem as described in the technical error, which finds the best way of doing it.  It uses several functions from the Standard Prelude and a little bit of currying.  Hopefully this will be properly formatted - apologies if not!

&lt;pre lang=&quot;haskell&quot; escaped=&quot;true&quot;&gt;
type Coin = (Int,[Int])

{-
 This takes a list of coins and produces a list of Coins, where each coin
 denomination is converted into a pair (value,[0,0,...,0,1,0,...]), where
 the value is the value of the coin, and the 0-1 array has length equal to
 the number of coins and has a 1 in only the ith position, where the coin
 is the ith in the list of coins (0-based), so for example, [10,5,1] will
 be converted to [ (10,[1,0,0]), (5,[0,1,0]), (1,[0,0,1]) ].
 In this way, we are easily able to add one coin to a collection, simply
 by adding the corresponding array termwise to the existing array.
-}
makeCoins :: [Int] -&gt; [Coin]
makeCoins coins = aux coins [0..]
                  where n = length coins
                        aux [] _ = []
                        aux (c:cs) (i:is) =
                          (c,replicate i 0 ++ [1] ++ replicate (n-1-i) 0):
                          aux cs is

{- 
 This takes an amount and a set of coins, and recursively finds the best
 way of producing all amounts up to and including the given amount; this
 is the heart of the solution of the problem.
 We do this by finding all possibilities for making the required amount,
 which is easy: with a coin of value 10, say, we take the best way of making
 10 less (if the amount is at least 10), and add the array corresponding to
 the 10 coin to this best way.
 We then take the possibility which uses the fewest coins, using a variation
 on the Standard Prelude definition of minimum.
-}
best :: Int -&gt; [Coin] -&gt; [[Int]]
best n coins
  &#124; n == 0  = [ replicate (length coins) 0 ]
  &#124; n &gt; 0   = let bests = best (n-1) coins
              in (next n coins bests) : bests
                where next n coins bests
                        = let possibilities = concat (map aux coins)
                              aux (den,coinList)
                                = if den &lt;= n
                                  then [ zipWith (+) (bests!!(den-1)) coinList ]
                                  else []
                          in smallest possibilities
                      smallest = foldr1 aux
                        where aux p1 p2 &#124; (sum p1) &lt;= (sum p2)  = p1
                                        &#124; otherwise             = p2

makeChange :: Int -&gt; [Int] -&gt; [Int]
makeChange amt coins = let cs = makeCoins coins
                           bests = best amt cs
                       in head bests
&lt;/pre&gt;</description>
		<content:encoded><![CDATA[<p>Here&#8217;s one way of solving the problem as described in the technical error, which finds the best way of doing it.  It uses several functions from the Standard Prelude and a little bit of currying.  Hopefully this will be properly formatted &#8211; apologies if not!</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">type</span> Coin <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#40;</span><span style="color: #cccc00; font-weight: bold;">Int</span><span style="color: #339933; font-weight: bold;">,</span><span style="color: green;">&#91;</span><span style="color: #cccc00; font-weight: bold;">Int</span><span style="color: green;">&#93;</span><span style="color: green;">&#41;</span>
&nbsp;
<span style="color: #5d478b; font-style: italic;">{-
 This takes a list of coins and produces a list of Coins, where each coin
 denomination is converted into a pair (value,[0,0,...,0,1,0,...]), where
 the value is the value of the coin, and the 0-1 array has length equal to
 the number of coins and has a 1 in only the ith position, where the coin
 is the ith in the list of coins (0-based), so for example, [10,5,1] will
 be converted to [ (10,[1,0,0]), (5,[0,1,0]), (1,[0,0,1]) ].
 In this way, we are easily able to add one coin to a collection, simply
 by adding the corresponding array termwise to the existing array.
-}</span>
makeCoins <span style="color: #339933; font-weight: bold;">::</span> <span style="color: green;">&#91;</span><span style="color: #cccc00; font-weight: bold;">Int</span><span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">-&gt;</span> <span style="color: green;">&#91;</span>Coin<span style="color: green;">&#93;</span>
makeCoins coins <span style="color: #339933; font-weight: bold;">=</span> aux coins <span style="color: green;">&#91;</span>0<span style="color: #339933; font-weight: bold;">..</span><span style="color: green;">&#93;</span>
                  <span style="color: #06c; font-weight: bold;">where</span> n <span style="color: #339933; font-weight: bold;">=</span> <span style="font-weight: bold;">length</span> coins
                        aux <span style="color: green;">&#91;</span><span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">_</span> <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#91;</span><span style="color: green;">&#93;</span>
                        aux <span style="color: green;">&#40;</span>c:cs<span style="color: green;">&#41;</span> <span style="color: green;">&#40;</span>i:is<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span>
                          <span style="color: green;">&#40;</span>c<span style="color: #339933; font-weight: bold;">,</span>replicate i <span style="color: red;">0</span> <span style="color: #339933; font-weight: bold;">++</span> <span style="color: green;">&#91;</span><span style="color: red;">1</span><span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">++</span> replicate <span style="color: green;">&#40;</span>n<span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">-</span>i<span style="color: green;">&#41;</span> <span style="color: red;">0</span><span style="color: green;">&#41;</span>:
                          aux cs is
&nbsp;
<span style="color: #5d478b; font-style: italic;">{- 
 This takes an amount and a set of coins, and recursively finds the best
 way of producing all amounts up to and including the given amount; this
 is the heart of the solution of the problem.
 We do this by finding all possibilities for making the required amount,
 which is easy: with a coin of value 10, say, we take the best way of making
 10 less (if the amount is at least 10), and add the array corresponding to
 the 10 coin to this best way.
 We then take the possibility which uses the fewest coins, using a variation
 on the Standard Prelude definition of minimum.
-}</span>
best <span style="color: #339933; font-weight: bold;">::</span> <span style="color: #cccc00; font-weight: bold;">Int</span> <span style="color: #339933; font-weight: bold;">-&gt;</span> <span style="color: green;">&#91;</span>Coin<span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">-&gt;</span> <span style="color: green;">&#91;</span><span style="color: green;">&#91;</span><span style="color: #cccc00; font-weight: bold;">Int</span><span style="color: green;">&#93;</span><span style="color: green;">&#93;</span>
best n coins
  <span style="color: #339933; font-weight: bold;">|</span> n <span style="color: #339933; font-weight: bold;">==</span> <span style="color: red;">0</span>  <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#91;</span> replicate <span style="color: green;">&#40;</span><span style="font-weight: bold;">length</span> coins<span style="color: green;">&#41;</span> <span style="color: red;">0</span> <span style="color: green;">&#93;</span>
  <span style="color: #339933; font-weight: bold;">|</span> n <span style="color: #339933; font-weight: bold;">&gt;</span> <span style="color: red;">0</span>   <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">let</span> bests <span style="color: #339933; font-weight: bold;">=</span> best <span style="color: green;">&#40;</span>n<span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span> coins
              <span style="color: #06c; font-weight: bold;">in</span> <span style="color: green;">&#40;</span>next n coins bests<span style="color: green;">&#41;</span> : bests
                <span style="color: #06c; font-weight: bold;">where</span> next n coins bests
                        <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">let</span> possibilities <span style="color: #339933; font-weight: bold;">=</span> <span style="font-weight: bold;">concat</span> <span style="color: green;">&#40;</span><span style="font-weight: bold;">map</span> aux coins<span style="color: green;">&#41;</span>
                              aux <span style="color: green;">&#40;</span>den<span style="color: #339933; font-weight: bold;">,</span>coinList<span style="color: green;">&#41;</span>
                                <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">if</span> den <span style="color: #339933; font-weight: bold;">&lt;=</span> n
                                  <span style="color: #06c; font-weight: bold;">then</span> <span style="color: green;">&#91;</span> <span style="font-weight: bold;">zipWith</span> <span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">+</span><span style="color: green;">&#41;</span> <span style="color: green;">&#40;</span>bests<span style="color: #339933; font-weight: bold;">!!</span><span style="color: green;">&#40;</span>den<span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: green;">&#41;</span><span style="color: green;">&#41;</span> coinList <span style="color: green;">&#93;</span>
                                  <span style="color: #06c; font-weight: bold;">else</span> <span style="color: green;">&#91;</span><span style="color: green;">&#93;</span>
                          <span style="color: #06c; font-weight: bold;">in</span> smallest possibilities
                      smallest <span style="color: #339933; font-weight: bold;">=</span> <span style="font-weight: bold;">foldr1</span> aux
                        <span style="color: #06c; font-weight: bold;">where</span> aux p1 p2 <span style="color: #339933; font-weight: bold;">|</span> <span style="color: green;">&#40;</span><span style="font-weight: bold;">sum</span> p1<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">&lt;=</span> <span style="color: green;">&#40;</span><span style="font-weight: bold;">sum</span> p2<span style="color: green;">&#41;</span>  <span style="color: #339933; font-weight: bold;">=</span> p1
                                        <span style="color: #339933; font-weight: bold;">|</span> <span style="font-weight: bold;">otherwise</span>             <span style="color: #339933; font-weight: bold;">=</span> p2
&nbsp;
makeChange <span style="color: #339933; font-weight: bold;">::</span> <span style="color: #cccc00; font-weight: bold;">Int</span> <span style="color: #339933; font-weight: bold;">-&gt;</span> <span style="color: green;">&#91;</span><span style="color: #cccc00; font-weight: bold;">Int</span><span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">-&gt;</span> <span style="color: green;">&#91;</span><span style="color: #cccc00; font-weight: bold;">Int</span><span style="color: green;">&#93;</span>
makeChange amt coins <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">let</span> cs <span style="color: #339933; font-weight: bold;">=</span> makeCoins coins
                           bests <span style="color: #339933; font-weight: bold;">=</span> best amt cs
                       <span style="color: #06c; font-weight: bold;">in</span> <span style="font-weight: bold;">head</span> bests</pre></div></div>

]]></content:encoded>
	</item>
	<item>
		<title>Comment on Exercise 2.4 by Julian</title>
		<link>http://www.elbeno.com/haskell_soe_blog/?p=9&#038;cpage=1#comment-111</link>
		<dc:creator>Julian</dc:creator>
		<pubDate>Sun, 04 Apr 2010 10:13:39 +0000</pubDate>
		<guid isPermaLink="false">http://www.elbeno.com/haskell_soe_blog/?p=9#comment-111</guid>
		<description>(Oops - the &gt; and &lt; signs got garbled :-( )</description>
		<content:encoded><![CDATA[<p>(Oops &#8211; the &gt; and &lt; signs got garbled <img src='http://www.elbeno.com/haskell_soe_blog/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' />  )</p>
]]></content:encoded>
	</item>
</channel>
</rss>

<!-- Dynamic Page Served (once) in 3.599 seconds -->
