<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1254792667029254313</id><updated>2011-07-29T08:06:25.130+10:00</updated><category term='constraints'/><category term='sudoku'/><category term='monads'/><category term='logic'/><category term='photography'/><category term='haskell'/><category term='programming'/><title type='text'>David's Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://overtond.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1254792667029254313/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://overtond.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>David Overton</name><uri>http://www.blogger.com/profile/02945248194158818964</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>5</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1254792667029254313.post-1540047010124464856</id><published>2008-07-04T21:27:00.001+10:00</published><updated>2008-07-04T21:29:41.044+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='monads'/><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='sudoku'/><category scheme='http://www.blogger.com/atom/ns#' term='constraints'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='logic'/><title type='text'>A Haskell Sudoku Solver using Finite Domain Constraints</title><content type='html'>&lt;p&gt;In a
&lt;a href="http://overtond.blogspot.com/2008/07/pre.html"&gt;previous post&lt;/a&gt;
we looked at how to write a finite domain constraint solver in Haskell.
Now we're going to look at how to use this solver to solve
&lt;a href="http://en.wikipedia.org/wiki/Sudoku"&gt;Sudoku&lt;/a&gt; puzzles.
First we give the module header and define a useful type:&lt;/p&gt;
&lt;pre class=haskell&gt;&lt;span class='keyword'&gt;module&lt;/span&gt; &lt;span class='conid'&gt;Sudoku&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Puzzle&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;printSudoku&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;displayPuzzle&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;sudoku&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyword'&gt;where&lt;/span&gt;

&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;Control&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Monad&lt;/span&gt;
&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;Data&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;List&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;transpose&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt;

&lt;span class='keyword'&gt;type&lt;/span&gt; &lt;span class='conid'&gt;Puzzle&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;Int&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;We represent both unsolved and solved puzzles as a list of 81
&lt;samp class=haskell&gt;&lt;span class='conid'&gt;Int&lt;/span&gt;&lt;/samp&gt;s.
In an unsolved puzzle, we use 0 to represent a blank square.
The numbers 1 to 9 represent squares with known values.
Here is an example of an unsolved puzzle that I copied from the local newspaper:
&lt;/p&gt;
&lt;pre class=haskell&gt;
&lt;span class='varid'&gt;test&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Puzzle&lt;/span&gt;
&lt;span class='varid'&gt;test&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;
    &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;
    &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;6&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;7&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;
    &lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;7&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;
    &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;
    &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;
    &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;9&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;7&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;
    &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;6&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;
    &lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;
    &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;6&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt; &lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The function &lt;samp&gt;displayPuzzle&lt;/samp&gt; displays a puzzle for us in
rows and columns.  The function &lt;samp&gt;printSudoku&lt;/samp&gt; will solve a puzzle
by calling &lt;samp&gt;sudoku&lt;/samp&gt;, which we will define below.
It then prints each solution.
&lt;/p&gt;
&lt;pre class=haskell&gt;
&lt;span class='varid'&gt;displayPuzzle&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Puzzle&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt;
&lt;span class='varid'&gt;displayPuzzle&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;unlines&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;map&lt;/span&gt; &lt;span class='varid'&gt;show&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;chunk&lt;/span&gt; &lt;span class='num'&gt;9&lt;/span&gt;

&lt;span class='varid'&gt;printSudoku&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Puzzle&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='conid'&gt;()&lt;/span&gt;
&lt;span class='varid'&gt;printSudoku&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;putStr&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;unlines&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;map&lt;/span&gt; &lt;span class='varid'&gt;displayPuzzle&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;sudoku&lt;/span&gt;

&lt;span class='varid'&gt;chunk&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Int&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='varid'&gt;chunk&lt;/span&gt; &lt;span class='keyword'&gt;_&lt;/span&gt; &lt;span class='conid'&gt;[]&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;[]&lt;/span&gt;
&lt;span class='varid'&gt;chunk&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varid'&gt;xs&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;ys&lt;/span&gt; &lt;span class='conop'&gt;:&lt;/span&gt; &lt;span class='varid'&gt;chunk&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varid'&gt;zs&lt;/span&gt; &lt;span class='keyword'&gt;where&lt;/span&gt;
    &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;ys&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;zs&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;splitAt&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varid'&gt;xs&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;We now present the code to actually solve the puzzle:&lt;/p&gt;
&lt;pre class=haskell&gt;
&lt;span class='varid'&gt;sudoku&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Puzzle&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;Puzzle&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='varid'&gt;sudoku&lt;/span&gt; &lt;span class='varid'&gt;puzzle&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;runFD&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;vars&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;newVars&lt;/span&gt; &lt;span class='num'&gt;81&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='keyglyph'&gt;..&lt;/span&gt;&lt;span class='num'&gt;9&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
    &lt;span class='varid'&gt;zipWithM_&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='keyglyph'&gt;\&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;when&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varop'&gt;`hasValue`&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;vars&lt;/span&gt; &lt;span class='varid'&gt;puzzle&lt;/span&gt;
    &lt;span class='varid'&gt;mapM_&lt;/span&gt; &lt;span class='varid'&gt;allDifferent&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;rows&lt;/span&gt; &lt;span class='varid'&gt;vars&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='varid'&gt;mapM_&lt;/span&gt; &lt;span class='varid'&gt;allDifferent&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;columns&lt;/span&gt; &lt;span class='varid'&gt;vars&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='varid'&gt;mapM_&lt;/span&gt; &lt;span class='varid'&gt;allDifferent&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;boxes&lt;/span&gt; &lt;span class='varid'&gt;vars&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='varid'&gt;labelling&lt;/span&gt; &lt;span class='varid'&gt;vars&lt;/span&gt;

&lt;span class='varid'&gt;rows&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;columns&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;boxes&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='varid'&gt;rows&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;chunk&lt;/span&gt; &lt;span class='num'&gt;9&lt;/span&gt;
&lt;span class='varid'&gt;columns&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;transpose&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;rows&lt;/span&gt;
&lt;span class='varid'&gt;boxes&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;concat&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;map&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;map&lt;/span&gt; &lt;span class='varid'&gt;concat&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;transpose&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;chunk&lt;/span&gt; &lt;span class='num'&gt;3&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;chunk&lt;/span&gt; &lt;span class='num'&gt;3&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;chunk&lt;/span&gt; &lt;span class='num'&gt;3&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;We start by initialising 81 new solver variables, one for each square in
the puzzle.
Next, we constrain each known square in the puzzle to its given value.
The next three lines create the Sudoku constraints: each number 1 to 9 may
occur only once in each row, column and 3x3 box.  The functions for
grouping the variables into rows, columns and boxes are given below the main
function.  Finally, we call &lt;samp&gt;labelling&lt;/samp&gt; to search for solutions.&lt;/p&gt;

&lt;p&gt;Let's see how this performs with our &lt;samp&gt;test&lt;/samp&gt; puzzle, running
on a 2.4GHz Intel Core 2 Duo with 4GB RAM:
&lt;pre&gt;
&gt; ghc --make -O2 test
[1 of 3] Compiling FD               ( FD.hs, FD.o )
[2 of 3] Compiling Sudoku           ( Sudoku.hs, Sudoku.o )
[3 of 3] Compiling Main             ( test.hs, test.o )
Linking test ...
&gt; time ./test
[5,6,7,4,8,3,2,9,1]
[9,3,8,1,2,6,5,4,7]
[4,1,2,7,9,5,3,6,8]
[6,8,9,3,7,2,1,5,4]
[7,4,3,6,5,1,8,2,9]
[1,2,5,8,4,9,6,7,3]
[2,5,4,9,3,8,7,1,6]
[3,7,1,2,6,4,9,8,5]
[8,9,6,5,1,7,4,3,2]


real 0m6.518s
user 0m6.480s
sys 0m0.032s
&lt;/pre&gt;
&lt;p&gt;So it takes around 6.5 seconds to find all solutions to this puzzle (of
which there is exactly one, as expected).  Can we do any better than that?
Yes we can, actually.  Recall our earlier definition of the function
&lt;samp&gt;different&lt;/samp&gt; which constrains two variables to have
different values, and is used by the &lt;samp&gt;allDifferent&lt;/samp&gt; function
which features prominently in our Sudoku solving code:
&lt;pre class=haskell&gt;
&lt;span class='varid'&gt;different&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='conid'&gt;()&lt;/span&gt;
&lt;span class='varid'&gt;different&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;addBinaryConstraint&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='keyglyph'&gt;\&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;lookup&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt;
    &lt;span class='varid'&gt;yv&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;lookup&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt;
    &lt;span class='varid'&gt;guard&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;size&lt;/span&gt; &lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt; &lt;span class='varop'&gt;||&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;size&lt;/span&gt; &lt;span class='varid'&gt;yv&lt;/span&gt; &lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt; &lt;span class='varop'&gt;||&lt;/span&gt; &lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='varop'&gt;/=&lt;/span&gt; &lt;span class='varid'&gt;yv&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt; Notice how this function doesn't try to constrain the domains of the
variables or do any constraint propagation.
That's because, in the general case, we don't have enough information
to do this, we just have to store the
constraint and retest it each time the domains are changed.
This means that in our Sudoku solver, the labelling step will effectively
try each value 1 to 9 in turn for each blank square and then test
whether the &lt;samp&gt;allDifferent&lt;/samp&gt; constraints still hold.
This is almost a brute force algorithm.  &lt;/p&gt;

&lt;p&gt;However, we have overlooked one case where we &lt;em&gt;can&lt;/em&gt; 
further constrain the
variables: if the domain of one variable is a singleton set, then we can
remove that value from the domain of the other variable.  This should
drastically reduce the number of tests we need to do during labelling.
Here's the modified function:&lt;/p&gt;
&lt;pre class=haskell&gt;
&lt;span class='varid'&gt;different&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;addBinaryConstraint&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='keyglyph'&gt;\&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;lookup&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt;
    &lt;span class='varid'&gt;yv&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;lookup&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt;
    &lt;span class='varid'&gt;guard&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;size&lt;/span&gt; &lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt; &lt;span class='varop'&gt;||&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;size&lt;/span&gt; &lt;span class='varid'&gt;yv&lt;/span&gt; &lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt; &lt;span class='varop'&gt;||&lt;/span&gt; &lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='varop'&gt;/=&lt;/span&gt; &lt;span class='varid'&gt;yv&lt;/span&gt;
    &lt;span class='varid'&gt;when&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;size&lt;/span&gt; &lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='varop'&gt;==&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt; &lt;span class='varop'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='varop'&gt;`&lt;/span&gt;&lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;isProperSubsetOf&lt;/span&gt;&lt;span class='varop'&gt;`&lt;/span&gt; &lt;span class='varid'&gt;yv&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt;
        &lt;span class='varid'&gt;update&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;yv&lt;/span&gt; &lt;span class='varop'&gt;`&lt;/span&gt;&lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;difference&lt;/span&gt;&lt;span class='varop'&gt;`&lt;/span&gt; &lt;span class='varid'&gt;xv&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='varid'&gt;when&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;size&lt;/span&gt; &lt;span class='varid'&gt;yv&lt;/span&gt; &lt;span class='varop'&gt;==&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt; &lt;span class='varop'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='varid'&gt;yv&lt;/span&gt; &lt;span class='varop'&gt;`&lt;/span&gt;&lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;isProperSubsetOf&lt;/span&gt;&lt;span class='varop'&gt;`&lt;/span&gt; &lt;span class='varid'&gt;xv&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt;
        &lt;span class='varid'&gt;update&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='varop'&gt;`&lt;/span&gt;&lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;difference&lt;/span&gt;&lt;span class='varop'&gt;`&lt;/span&gt; &lt;span class='varid'&gt;yv&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Here are the times with the modified funtion:&lt;/p&gt;
&lt;pre&gt;
&gt; time ./test
[5,6,7,4,8,3,2,9,1]
[9,3,8,1,2,6,5,4,7]
[4,1,2,7,9,5,3,6,8]
[6,8,9,3,7,2,1,5,4]
[7,4,3,6,5,1,8,2,9]
[1,2,5,8,4,9,6,7,3]
[2,5,4,9,3,8,7,1,6]
[3,7,1,2,6,4,9,8,5]
[8,9,6,5,1,7,4,3,2]


real 0m0.180s
user 0m0.160s
sys 0m0.020s
&lt;/pre&gt;
That's a 36-fold improvement.  Not bad for adding four lines of code!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1254792667029254313-1540047010124464856?l=overtond.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://overtond.blogspot.com/feeds/1540047010124464856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1254792667029254313&amp;postID=1540047010124464856' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1254792667029254313/posts/default/1540047010124464856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1254792667029254313/posts/default/1540047010124464856'/><link rel='alternate' type='text/html' href='http://overtond.blogspot.com/2008/07/haskell-sudoku-solver-using-finite.html' title='A Haskell Sudoku Solver using Finite Domain Constraints'/><author><name>David Overton</name><uri>http://www.blogger.com/profile/02945248194158818964</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1254792667029254313.post-1151843562812398686</id><published>2008-07-03T21:54:00.010+10:00</published><updated>2008-07-08T08:35:23.957+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='monads'/><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='constraints'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='logic'/><title type='text'>Constraint Programming in Haskell</title><content type='html'>&lt;p&gt;Having had a bit of free time in the evenings lately, I've finally got
around to starting one of the things on my list of cool Haskell projects I'd
like to get around to one day.  Since my time working on
&lt;a href="http://www.cs.mu.oz.au/research/mercury/"&gt;Mercury&lt;/a&gt; and
&lt;a href="http://www.csse.monash.edu.au/~mbanda/hal/"&gt;HAL&lt;/a&gt;, I've been interested
in logic programming and constraint logic programming and I've been wanting to
find out how close I can get to something that looks like a constraint logic
programming system in Haskell.  &lt;/p&gt;

&lt;p&gt;The Haskell list monad already allows a style of programming that feels
somewhat like non-deterministic logic programming, with backtracking to do a
depth-first left-to-right search.  I'm going to build a monad on top of the
list monad to do finite domain constraint programming.  I'm aiming for a nice
clean interface and a simple implementation, so this is not going to be as
efficient as it could be, but that's ok for a proof of concept.  If I get time
later, I'll go back and try to make it more efficient.&lt;/p&gt;

&lt;p&gt;In a finite domain solver the variables represent a finite set of (usually
integer) values to which the programmer can add various constraints.
They are particularly useful for scheduling and timetabling problems.
They are also good for solving puzzles such as Sudoku, which I will detail in a later post.&lt;/p&gt;

&lt;p&gt;An example of the kind of constraint program we're aiming to be able to write is
&lt;pre class=haskell&gt;
&lt;span class='varid'&gt;runTest&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;runFD&lt;/span&gt; &lt;span class='varid'&gt;test&lt;/span&gt;

&lt;span class='varid'&gt;test&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;newVar&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='keyglyph'&gt;..&lt;/span&gt;&lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
    &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;newVar&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='keyglyph'&gt;..&lt;/span&gt;&lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
    &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='layout'&gt;(&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varop'&gt;.&amp;lt;.&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;`mplus`&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varop'&gt;`same`&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varop'&gt;`hasValue`&lt;/span&gt; &lt;span class='num'&gt;2&lt;/span&gt;
    &lt;span class='varid'&gt;labelling&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;/pre&gt;
Here we create two finite domain variables &lt;samp&gt;x&lt;/samp&gt; and &lt;samp&gt;y&lt;/samp&gt;, each with an initial
domain of &lt;samp&gt;{0, 1, 2, 3}&lt;/samp&gt;.
We then add a constraint that says either &lt;samp&gt;x&lt;/samp&gt; is less than &lt;samp&gt;y&lt;/samp&gt; or
&lt;samp&gt;x&lt;/samp&gt; is the same as &lt;samp&gt;y&lt;/samp&gt;.
We then further constrain &lt;samp&gt;x&lt;/samp&gt; to have the value &lt;samp&gt;2&lt;/samp&gt;.
Finally, the call to &lt;samp&gt;labelling&lt;/samp&gt; will search for all possible solutions that satisfy the
given constraints.
When we evaluate &lt;samp&gt;runTest&lt;/samp&gt; we get the result &lt;samp&gt;[[2,3],[2,2]]&lt;/samp&gt; which
represents the two possible solutions &lt;samp&gt;{x = 2, y = 3}&lt;/samp&gt; and &lt;samp&gt;{x = 2, y = 2}&lt;/samp&gt;.
&lt;/p&gt;

&lt;p&gt;Finite domain solvers also allow constraints to contain arithmetic
expressions involving constraint variables and integers.
To keep things simple, we'll leave them out for now.
The interface we are going to implement is shown below.
&lt;/p&gt;

&lt;pre class=haskell&gt;
&lt;span class='comment'&gt;{-# LANGUAGE GeneralizedNewtypeDeriving #-}&lt;/span&gt;
&lt;span class='comment'&gt;{-# LANGUAGE RankNTypes #-}&lt;/span&gt;
&lt;span class='keyword'&gt;module&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;
    &lt;span class='comment'&gt;-- Types&lt;/span&gt;
    &lt;span class='conid'&gt;FD&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;           &lt;span class='comment'&gt;-- Monad for finite domain constraint solver&lt;/span&gt;
    &lt;span class='conid'&gt;FDVar&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;        &lt;span class='comment'&gt;-- Finite domain solver variable&lt;/span&gt;

    &lt;span class='comment'&gt;-- Functions&lt;/span&gt;
    &lt;span class='varid'&gt;runFD&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;        &lt;span class='comment'&gt;-- Run the monad and return a list of solutions.&lt;/span&gt;
    &lt;span class='varid'&gt;newVar&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;       &lt;span class='comment'&gt;-- Create a new FDVar&lt;/span&gt;
    &lt;span class='varid'&gt;newVars&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;      &lt;span class='comment'&gt;-- Create multiple FDVars&lt;/span&gt;
    &lt;span class='varid'&gt;hasValue&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;     &lt;span class='comment'&gt;-- Constrain a FDVar to a specific value&lt;/span&gt;
    &lt;span class='varid'&gt;same&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;         &lt;span class='comment'&gt;-- Constrain two FDVars to be the same&lt;/span&gt;
    &lt;span class='varid'&gt;different&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;    &lt;span class='comment'&gt;-- Constrain two FDVars to be different&lt;/span&gt;
    &lt;span class='varid'&gt;allDifferent&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='comment'&gt;-- Constrain a list of FDVars to be different&lt;/span&gt;
    &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varop'&gt;.&amp;lt;.&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;        &lt;span class='comment'&gt;-- Constrain one FDVar to be less than another&lt;/span&gt;
    &lt;span class='varid'&gt;labelling&lt;/span&gt;     &lt;span class='comment'&gt;-- Backtracking search for all solutions&lt;/span&gt;
    &lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyword'&gt;where&lt;/span&gt;
&lt;/pre&gt;
Modules we need to import:
&lt;pre class=haskell&gt;
&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;Prelude&lt;/span&gt; &lt;span class='varid'&gt;hiding&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;lookup&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;Control&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Monad&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;State&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Lazy&lt;/span&gt;
&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;Control&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Monad&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Trans&lt;/span&gt;
&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='keyword'&gt;qualified&lt;/span&gt; &lt;span class='conid'&gt;Data&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Map&lt;/span&gt; &lt;span class='keyword'&gt;as&lt;/span&gt; &lt;span class='conid'&gt;Map&lt;/span&gt;
&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;Data&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Map&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varop'&gt;!&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;Map&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='keyword'&gt;qualified&lt;/span&gt; &lt;span class='conid'&gt;Data&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;IntSet&lt;/span&gt; &lt;span class='keyword'&gt;as&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;
&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;Data&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;IntSet&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/pre&gt;

Below we define the types for the solver.
&lt;pre class=haskell&gt;
&lt;span class='comment'&gt;-- The FD monad&lt;/span&gt;
&lt;span class='keyword'&gt;newtype&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='layout'&gt;{&lt;/span&gt; &lt;span class='varid'&gt;unFD&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;StateT&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;FDState&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='conid'&gt;[]&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='layout'&gt;}&lt;/span&gt;
    &lt;span class='keyword'&gt;deriving&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Monad&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;MonadPlus&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;MonadState&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;FDState&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;

&lt;span class='comment'&gt;-- FD variables&lt;/span&gt;
&lt;span class='keyword'&gt;newtype&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='layout'&gt;{&lt;/span&gt; &lt;span class='varid'&gt;unFDVar&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Int&lt;/span&gt; &lt;span class='layout'&gt;}&lt;/span&gt; &lt;span class='keyword'&gt;deriving&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Ord&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;Eq&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;

&lt;span class='keyword'&gt;type&lt;/span&gt; &lt;span class='conid'&gt;VarSupply&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;
&lt;span class='keyword'&gt;data&lt;/span&gt; &lt;span class='conid'&gt;VarInfo&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;VarInfo&lt;/span&gt;
     &lt;span class='layout'&gt;{&lt;/span&gt; &lt;span class='varid'&gt;delayedConstraints&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='conid'&gt;()&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;values&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt; &lt;span class='layout'&gt;}&lt;/span&gt;
&lt;span class='keyword'&gt;type&lt;/span&gt; &lt;span class='conid'&gt;VarMap&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;Map&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;VarInfo&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='keyword'&gt;data&lt;/span&gt; &lt;span class='conid'&gt;FDState&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;FDState&lt;/span&gt;
     &lt;span class='layout'&gt;{&lt;/span&gt; &lt;span class='varid'&gt;varSupply&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;VarSupply&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;varMap&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;VarMap&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='layout'&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt; The type &lt;samp class=haskell&gt;&lt;span class='conid'&gt;FD&lt;/span&gt; s a&lt;/samp&gt; is
our constraint solver monad.  It contains a list monad to provide the search
capability.
This is wrapped in a &lt;samp class=haskell&gt;&lt;span class='conid'&gt;StateT&lt;/span&gt;&lt;/samp&gt; monad transformer
which threads through the &lt;em&gt;constraint store&lt;/em&gt;
&lt;samp class=haskell&gt;&lt;span class=conid&gt;FDState&lt;/span&gt; s&lt;/samp&gt;.
The type variable &lt;samp&gt;s&lt;/samp&gt; is a &lt;em&gt;phantom type&lt;/em&gt;.  We will see later how this can be
used to prevent any of the implementation detail "leaking out" of the monad.  &lt;/p&gt;

&lt;p&gt;Our constraint store &lt;samp class=haskell&gt;&lt;span class=conid&gt;FDState&lt;/span&gt; s&lt;/samp&gt; contains
a supply of fresh constraint variables and also keeps track of the information we need to know
about existing variables.
For each existing variable we record its set of possible values (its &lt;em&gt;domain&lt;/em&gt;)
and a set of constraints on it.
Whenever the domain of a variable changes, we need to execute its constraints to check that they
are still satisfied.
This, in turn, may further constrain the domain of other variables.  This is known as
&lt;em&gt;constraint propagation&lt;/em&gt;.&lt;/p&gt;

&lt;pre class=haskell&gt;
&lt;span class='comment'&gt;-- Run the FD monad and produce a lazy list of possible solutions.&lt;/span&gt;
&lt;span class='varid'&gt;runFD&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='keyword'&gt;forall&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='varid'&gt;runFD&lt;/span&gt; &lt;span class='varid'&gt;fd&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;evalStateT&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;unFD&lt;/span&gt; &lt;span class='varid'&gt;fd&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;initState&lt;/span&gt;

&lt;span class='varid'&gt;initState&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;FDState&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;
&lt;span class='varid'&gt;initState&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;FDState&lt;/span&gt; &lt;span class='layout'&gt;{&lt;/span&gt; &lt;span class='varid'&gt;varSupply&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;varMap&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;Map&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;empty&lt;/span&gt; &lt;span class='layout'&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The function &lt;samp&gt;runFD&lt;/samp&gt; runs a constraint solver, starting with an
initially empty constraint store, and return a list of all possible solutions.
The type &lt;samp class=haskell&gt;&lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='keyword'&gt;forall&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;/samp&gt;
ensures that any values of a type containing the phantom type variable &lt;samp&gt;s&lt;/samp&gt;
can't "escape" from the monad.
This means that we can't take a constraint variable from one monad and use it inside another one,
thus ensuring, through the type system, that the monad is used safely.

&lt;pre class=haskell&gt;
&lt;span class='comment'&gt;-- Get a new FDVar&lt;/span&gt;
&lt;span class='varid'&gt;newVar&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;Int&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='varid'&gt;newVar&lt;/span&gt; &lt;span class='varid'&gt;domain&lt;/span&gt;&lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;v&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;nextVar&lt;/span&gt;
    &lt;span class='varid'&gt;v&lt;/span&gt; &lt;span class='varop'&gt;`isOneOf`&lt;/span&gt; &lt;span class='varid'&gt;domain&lt;/span&gt;
    &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='varid'&gt;v&lt;/span&gt;
    &lt;span class='keyword'&gt;where&lt;/span&gt;
        &lt;span class='varid'&gt;nextVar&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
        &lt;span class='varid'&gt;nextVar&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
            &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;get&lt;/span&gt;
            &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;v&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;varSupply&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;
            &lt;span class='varid'&gt;put&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='layout'&gt;{&lt;/span&gt; &lt;span class='varid'&gt;varSupply&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;unFDVar&lt;/span&gt; &lt;span class='varid'&gt;v&lt;/span&gt; &lt;span class='varop'&gt;+&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='layout'&gt;}&lt;/span&gt;
            &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='varid'&gt;v&lt;/span&gt;
        &lt;span class='varid'&gt;isOneOf&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;Int&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='conid'&gt;()&lt;/span&gt;
        &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varop'&gt;`isOneOf`&lt;/span&gt; &lt;span class='varid'&gt;domain&lt;/span&gt;&lt;span class='keyglyph'&gt;=&lt;/span&gt;
            &lt;span class='varid'&gt;modify&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='keyglyph'&gt;\&lt;/span&gt;&lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;vm&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;varMap&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;
                    &lt;span class='varid'&gt;vi&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;VarInfo&lt;/span&gt; &lt;span class='layout'&gt;{&lt;/span&gt;
                        &lt;span class='varid'&gt;delayedConstraints&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='conid'&gt;()&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;
                        &lt;span class='varid'&gt;values&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;fromList&lt;/span&gt; &lt;span class='varid'&gt;domain&lt;/span&gt;&lt;span class='layout'&gt;}&lt;/span&gt;
                &lt;span class='keyword'&gt;in&lt;/span&gt;
                &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='layout'&gt;{&lt;/span&gt; &lt;span class='varid'&gt;varMap&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;Map&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;insert&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varid'&gt;vi&lt;/span&gt; &lt;span class='varid'&gt;vm&lt;/span&gt; &lt;span class='layout'&gt;}&lt;/span&gt;

&lt;span class='varid'&gt;newVars&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Int&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;Int&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='varid'&gt;newVars&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varid'&gt;domain&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;replicateM&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;newVar&lt;/span&gt; &lt;span class='varid'&gt;domain&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The function &lt;samp&gt;newVar domain&lt;/samp&gt; creates a new constraint variable constrained to
values in &lt;samp&gt;domain&lt;/samp&gt;.
The function &lt;samp&gt;newVars n domain&lt;/samp&gt; is a convenient way of creating multiple variables
with the same domain.&lt;/p&gt;

&lt;p&gt;Some helper functions which are not exported, but are used when we define the constraint functions:
&lt;/p&gt;
&lt;pre class=haskell&gt;
&lt;span class='comment'&gt;-- Lookup the current domain of a variable.&lt;/span&gt;
&lt;span class='varid'&gt;lookup&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;
&lt;span class='varid'&gt;lookup&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;get&lt;/span&gt;
    &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;values&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;varMap&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='varop'&gt;!&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt;

&lt;span class='comment'&gt;-- Update the domain of a variable and fire all delayed constraints&lt;/span&gt;
&lt;span class='comment'&gt;-- associated with that variable.&lt;/span&gt;
&lt;span class='varid'&gt;update&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='conid'&gt;()&lt;/span&gt;
&lt;span class='varid'&gt;update&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;get&lt;/span&gt;
    &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;vm&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;varMap&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;
    &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;vi&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;vm&lt;/span&gt; &lt;span class='varop'&gt;!&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt;
    &lt;span class='varid'&gt;put&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='layout'&gt;{&lt;/span&gt; &lt;span class='varid'&gt;varMap&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;Map&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;insert&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;vi&lt;/span&gt; &lt;span class='layout'&gt;{&lt;/span&gt; &lt;span class='varid'&gt;values&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt;&lt;span class='layout'&gt;}&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;vm&lt;/span&gt; &lt;span class='layout'&gt;}&lt;/span&gt;
    &lt;span class='varid'&gt;delayedConstraints&lt;/span&gt; &lt;span class='varid'&gt;vi&lt;/span&gt;

&lt;span class='comment'&gt;-- Add a new constraint for a variable to the constraint store.&lt;/span&gt;
&lt;span class='varid'&gt;addConstraint&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='conid'&gt;()&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='conid'&gt;()&lt;/span&gt;
&lt;span class='varid'&gt;addConstraint&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varid'&gt;constraint&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;get&lt;/span&gt;
    &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;vm&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;varMap&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;
    &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;vi&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;vm&lt;/span&gt; &lt;span class='varop'&gt;!&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt;
    &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;cs&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;delayedConstraints&lt;/span&gt; &lt;span class='varid'&gt;vi&lt;/span&gt;
    &lt;span class='varid'&gt;put&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='layout'&gt;{&lt;/span&gt; &lt;span class='varid'&gt;varMap&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt;
        &lt;span class='conid'&gt;Map&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;insert&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;vi&lt;/span&gt; &lt;span class='layout'&gt;{&lt;/span&gt; &lt;span class='varid'&gt;delayedConstraints&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;cs&lt;/span&gt; &lt;span class='varop'&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;constraint&lt;/span&gt; &lt;span class='layout'&gt;}&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;vm&lt;/span&gt; &lt;span class='layout'&gt;}&lt;/span&gt;
 
&lt;span class='comment'&gt;-- Useful helper function for adding binary constraints between FDVars.&lt;/span&gt;
&lt;span class='keyword'&gt;type&lt;/span&gt; &lt;span class='conid'&gt;BinaryConstraint&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='conid'&gt;()&lt;/span&gt;
&lt;span class='varid'&gt;addBinaryConstraint&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;BinaryConstraint&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;BinaryConstraint&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;
&lt;span class='varid'&gt;addBinaryConstraint&lt;/span&gt; &lt;span class='varid'&gt;f&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;constraint&lt;/span&gt;  &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;f&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt;
    &lt;span class='varid'&gt;constraint&lt;/span&gt;
    &lt;span class='varid'&gt;addConstraint&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varid'&gt;constraint&lt;/span&gt;
    &lt;span class='varid'&gt;addConstraint&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='varid'&gt;constraint&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The function &lt;samp&gt;lookup&lt;/samp&gt; returns the current domain for a variable;
&lt;samp&gt;update&lt;/samp&gt; updates the domain for a variable and propagates the change into all constraints
on that variable;
&lt;samp&gt;addConstraint&lt;/samp&gt; inserts a constraint into the constraint store;
&lt;samp&gt;addBinaryConstraint&lt;/samp&gt; tests a constraint on two variable and then adds it to the constraint
store for each variable.&lt;/p&gt;

&lt;p&gt;Now we can define the actual constraint functions:&lt;/p&gt;
&lt;pre class=haskell&gt;
&lt;span class='comment'&gt;-- Constrain a variable to a particular value.&lt;/span&gt;
&lt;span class='varid'&gt;hasValue&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;Int&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='conid'&gt;()&lt;/span&gt;
&lt;span class='varid'&gt;var&lt;/span&gt; &lt;span class='varop'&gt;`hasValue`&lt;/span&gt; &lt;span class='varid'&gt;val&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;vals&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;lookup&lt;/span&gt; &lt;span class='varid'&gt;var&lt;/span&gt;
    &lt;span class='varid'&gt;guard&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;val&lt;/span&gt; &lt;span class='varop'&gt;`&lt;/span&gt;&lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;member&lt;/span&gt;&lt;span class='varop'&gt;`&lt;/span&gt; &lt;span class='varid'&gt;vals&lt;/span&gt;
    &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;singleton&lt;/span&gt; &lt;span class='varid'&gt;val&lt;/span&gt;
    &lt;span class='varid'&gt;when&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='varop'&gt;/=&lt;/span&gt; &lt;span class='varid'&gt;vals&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;update&lt;/span&gt; &lt;span class='varid'&gt;var&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt;
&lt;/pre&gt;
In &lt;samp&gt;hasValue&lt;/samp&gt; we lookup the current domain of the variable and test that
the value to be set is within the domain.
If the domain has changed, we update the constraint store and propagate the change.
The other constraints are defined similarly:
&lt;pre class=haskell&gt;
&lt;span class='comment'&gt;-- Constrain two variables to have the same value.&lt;/span&gt;
&lt;span class='varid'&gt;same&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='conid'&gt;()&lt;/span&gt;
&lt;span class='varid'&gt;same&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;addBinaryConstraint&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='keyglyph'&gt;\&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;lookup&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt;
    &lt;span class='varid'&gt;yv&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;lookup&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt;
    &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;intersection&lt;/span&gt; &lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='varid'&gt;yv&lt;/span&gt;
    &lt;span class='varid'&gt;guard&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;not&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;null&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt;
    &lt;span class='varid'&gt;when&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='varop'&gt;/=&lt;/span&gt; &lt;span class='varid'&gt;xv&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;update&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt;
    &lt;span class='varid'&gt;when&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;i&lt;/span&gt; &lt;span class='varop'&gt;/=&lt;/span&gt; &lt;span class='varid'&gt;yv&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;update&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='varid'&gt;i&lt;/span&gt;

&lt;span class='comment'&gt;-- Constrain two variables to have different values.&lt;/span&gt;
&lt;span class='varid'&gt;different&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='conid'&gt;()&lt;/span&gt;
&lt;span class='varid'&gt;different&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;addBinaryConstraint&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='keyglyph'&gt;\&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;lookup&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt;
    &lt;span class='varid'&gt;yv&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;lookup&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt;
    &lt;span class='varid'&gt;guard&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;size&lt;/span&gt; &lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt; &lt;span class='varop'&gt;||&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;size&lt;/span&gt; &lt;span class='varid'&gt;yv&lt;/span&gt; &lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt; &lt;span class='varop'&gt;||&lt;/span&gt; &lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='varop'&gt;/=&lt;/span&gt; &lt;span class='varid'&gt;yv&lt;/span&gt;

&lt;span class='comment'&gt;-- Constrain a list of variables to all have different values.&lt;/span&gt;
&lt;span class='varid'&gt;allDifferent&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='conid'&gt;()&lt;/span&gt;
&lt;span class='varid'&gt;allDifferent&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;xs&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;mapM_&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;different&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;xs&lt;/span&gt;
    &lt;span class='varid'&gt;allDifferent&lt;/span&gt; &lt;span class='varid'&gt;xs&lt;/span&gt;
&lt;span class='varid'&gt;allDifferent&lt;/span&gt; &lt;span class='keyword'&gt;_&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='conid'&gt;()&lt;/span&gt;

&lt;span class='comment'&gt;-- Constrain one variable to have a value less than the value of another&lt;/span&gt;
&lt;span class='comment'&gt;-- variable.&lt;/span&gt;
&lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varop'&gt;.&amp;lt;.&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='conid'&gt;()&lt;/span&gt;
&lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varop'&gt;.&amp;lt;.&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;addBinaryConstraint&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='keyglyph'&gt;\&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;lookup&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt;
    &lt;span class='varid'&gt;yv&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;lookup&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt;
    &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;xv'&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;filter&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varop'&gt;&amp;lt;&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;findMax&lt;/span&gt; &lt;span class='varid'&gt;yv&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;xv&lt;/span&gt;
    &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;yv'&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;filter&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;findMin&lt;/span&gt; &lt;span class='varid'&gt;xv&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;yv&lt;/span&gt;
    &lt;span class='varid'&gt;guard&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;not&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;null&lt;/span&gt; &lt;span class='varid'&gt;xv'&lt;/span&gt;
    &lt;span class='varid'&gt;guard&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;not&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;null&lt;/span&gt; &lt;span class='varid'&gt;yv'&lt;/span&gt;
    &lt;span class='varid'&gt;when&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;xv&lt;/span&gt; &lt;span class='varop'&gt;/=&lt;/span&gt; &lt;span class='varid'&gt;xv'&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;update&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varid'&gt;xv'&lt;/span&gt;
    &lt;span class='varid'&gt;when&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;yv&lt;/span&gt; &lt;span class='varop'&gt;/=&lt;/span&gt; &lt;span class='varid'&gt;yv'&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;update&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='varid'&gt;yv'&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Finally, in the &lt;samp&gt;labelling&lt;/samp&gt; function we make use of the underlying list monad
to search for all solutions for the given set of variables.&lt;/p&gt;
&lt;pre class=haskell&gt;
&lt;span class='comment'&gt;-- Label variables using a depth-first left-to-right search.&lt;/span&gt;
&lt;span class='varid'&gt;labelling&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;FDVar&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;Int&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='varid'&gt;labelling&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;mapM&lt;/span&gt; &lt;span class='varid'&gt;label&lt;/span&gt; &lt;span class='keyword'&gt;where&lt;/span&gt;
    &lt;span class='varid'&gt;label&lt;/span&gt; &lt;span class='varid'&gt;var&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
        &lt;span class='varid'&gt;vals&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;lookup&lt;/span&gt; &lt;span class='varid'&gt;var&lt;/span&gt;
        &lt;span class='varid'&gt;val&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='conid'&gt;FD&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;lift&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='conid'&gt;IntSet&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;toList&lt;/span&gt; &lt;span class='varid'&gt;vals&lt;/span&gt;
        &lt;span class='varid'&gt;var&lt;/span&gt; &lt;span class='varop'&gt;`hasValue`&lt;/span&gt; &lt;span class='varid'&gt;val&lt;/span&gt;
        &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='varid'&gt;val&lt;/span&gt;
&lt;/pre&gt;

In a later posts I plan to show how to use this finite domain solver monad to
write a solver for Sudoku puzzles, and extend the monad to support arithmetic
expressions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1254792667029254313-1151843562812398686?l=overtond.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://overtond.blogspot.com/feeds/1151843562812398686/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1254792667029254313&amp;postID=1151843562812398686' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1254792667029254313/posts/default/1151843562812398686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1254792667029254313/posts/default/1151843562812398686'/><link rel='alternate' type='text/html' href='http://overtond.blogspot.com/2008/07/pre.html' title='Constraint Programming in Haskell'/><author><name>David Overton</name><uri>http://www.blogger.com/profile/02945248194158818964</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1254792667029254313.post-1436439661131783763</id><published>2008-06-25T23:26:00.003+10:00</published><updated>2008-06-25T23:44:32.297+10:00</updated><title type='text'>Off to Kiwiland</title><content type='html'>&lt;p&gt;Yes, the rumours you may have been hearing are true.  Just when you thought we'd finally decided which country to live in, we've gone and (temporarily) changed our minds again.  We'll be spending most of the next six months in Auckland, courtesy of Deloitte.
&lt;/p&gt;
&lt;p&gt;Moana left today (via Sydney and Christchurch, but that's another story) and I'll be following her in about a month.  Of course we have to be back in Melbourne when Christine comes to visit from Wellington in July and when Peter and Lynne come over from Dunedin in October.  I'll also be back a couple more times so that the people I work for don't forget that I exist.  Apparently things weren't complicated enough already.
&lt;/p&gt;
&lt;p&gt;This has all happened very suddenly and I think we are both still feeling a bit shell-shocked.  We were just getting used to our new house, and staying in the one place.  But hey, it's a good opportunity for Moana work-wise, and NZ is a great place to take photographs, so I'm happy.  Now I just have to brush up on my accent and learn a bit about rugby and under-arm bowling....&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1254792667029254313-1436439661131783763?l=overtond.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://overtond.blogspot.com/feeds/1436439661131783763/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1254792667029254313&amp;postID=1436439661131783763' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1254792667029254313/posts/default/1436439661131783763'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1254792667029254313/posts/default/1436439661131783763'/><link rel='alternate' type='text/html' href='http://overtond.blogspot.com/2008/06/off-to-kiwiland.html' title='Off to Kiwiland'/><author><name>David Overton</name><uri>http://www.blogger.com/profile/02945248194158818964</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1254792667029254313.post-4790313952370207286</id><published>2008-05-30T17:13:00.003+10:00</published><updated>2008-05-30T17:52:45.687+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='photography'/><title type='text'>Misty Water</title><content type='html'>&lt;div style="float: right; margin-left: 10px; margin-bottom: 10px;"&gt;&lt;a href="http://www.flickr.com/photos/overton/2530403413/" title="photo sharing"&gt;&lt;img src="http://farm3.static.flickr.com/2387/2530403413_5394832be8_m.jpg" alt="" style="border: solid 2px #000000;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size: 0.9em; margin-top: 0px;"&gt;&lt;a href="http://www.flickr.com/photos/overton/2530403413/"&gt;dsc_2219n&lt;/a&gt;&lt;br /&gt;Originally uploaded by &lt;a href="http://www.flickr.com/people/overton/"&gt;David Overton&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;I've already mentioned my recent &lt;a href="http://overtond.blogspot.com/2008/05/sunset-at-cape-schanck.html"&gt;trip to Cape Schanck&lt;/a&gt;.  I'm particularly pleased with how this photo turned out.  It was already about half an hour after sunset by this stage, making the lighting perfect for a long exposure (30 seconds) that would blur the water into an eerie-looking mist.  I've tried to get shots like this before, but they've never turned out this well.&lt;br clear="all" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1254792667029254313-4790313952370207286?l=overtond.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://overtond.blogspot.com/feeds/4790313952370207286/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1254792667029254313&amp;postID=4790313952370207286' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1254792667029254313/posts/default/4790313952370207286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1254792667029254313/posts/default/4790313952370207286'/><link rel='alternate' type='text/html' href='http://overtond.blogspot.com/2008/05/misty-water.html' title='Misty Water'/><author><name>David Overton</name><uri>http://www.blogger.com/profile/02945248194158818964</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm3.static.flickr.com/2387/2530403413_5394832be8_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1254792667029254313.post-2872701708292881122</id><published>2008-05-30T16:53:00.004+10:00</published><updated>2008-05-30T17:08:41.126+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='photography'/><title type='text'>Sunset at Cape Schanck</title><content type='html'>&lt;p&gt;&lt;div style="float: right; margin-left: 10px; margin-bottom: 10px;"&gt;&lt;a href="http://www.flickr.com/photos/overton/2531135706/" title="photo sharing"&gt;&lt;img src="http://farm3.static.flickr.com/2155/2531135706_d6244770ef_m.jpg" alt="" style="border: 2px solid rgb(0, 0, 0);" /&gt;&lt;/a&gt;
&lt;span style="margin-top: 0px;font-size:0;" &gt;&lt;a href="http://www.flickr.com/photos/overton/2531135706/"&gt;dsc_2128n&lt;/a&gt;
Originally uploaded by &lt;a href="http://www.flickr.com/people/overton/"&gt;David Overton&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;My mother moved down to the Mornington Peninsula, south-east of Melbourne, a few years ago.  Since we moved back to Australia in December we've been visiting her regularly on the weekend and I've been meaning to get out and photograph the local scenery.&lt;/p&gt;

&lt;p&gt;I finally got around to doing this last Saturday night.  I headed down to Cape Schanck, at the southern tip of the Peninsula.  The rugged cliffs overlooking Bass Strait make this a particularly spectacular area.  The lighthouse also adds to the scene, although access to it closed half an hour before sunset, so this is as close as I could get.&lt;/p&gt;

&lt;p&gt;You can see the rest of the photos from this trip at &lt;a href="http://www.flickr.com/photos/overton/sets/72157605293985217/"&gt;flickr&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1254792667029254313-2872701708292881122?l=overtond.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://overtond.blogspot.com/feeds/2872701708292881122/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1254792667029254313&amp;postID=2872701708292881122' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1254792667029254313/posts/default/2872701708292881122'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1254792667029254313/posts/default/2872701708292881122'/><link rel='alternate' type='text/html' href='http://overtond.blogspot.com/2008/05/sunset-at-cape-schanck.html' title='Sunset at Cape Schanck'/><author><name>David Overton</name><uri>http://www.blogger.com/profile/02945248194158818964</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm3.static.flickr.com/2155/2531135706_d6244770ef_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
