<?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-37577615</id><updated>2012-02-16T14:50:42.445+01:00</updated><title type='text'>Haskell and Web</title><subtitle type='html'>&lt;center&gt; weblog about the Haskell programming language &amp;amp; the Web.&lt;/center&gt;</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://haskell-web.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://haskell-web.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Alberto</name><uri>http://www.blogger.com/profile/11962281728014883353</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>14</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-37577615.post-1890284313740538245</id><published>2012-02-06T09:52:00.000+01:00</published><updated>2012-02-07T11:55:22.574+01:00</updated><title type='text'>MFlow: A Web application server with stateful server processes and simple typed widget combinators.</title><content type='html'>&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;I Just released MFlow, a simple application server with stateful request-response flows, persistent&amp;nbsp;and transparent session handling. server process management, combinators for the definition of widgets&amp;nbsp;and formlets that can be mixed freely with HTML formatting and produce statically&amp;nbsp;&amp;nbsp;typed web applications. Adopt and extend the best formlet/applicative Haskell traditions.&amp;nbsp;Console and window oriented apps are possible.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;a href="http://hackage.haskell.org/package/MFlow-0.0.2"&gt;http://hackage.haskell.org/package/MFlow&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .&lt;/div&gt;&lt;div style="text-align: justify;"&gt;MFlow (MessageFlow) was created initially as the user interface for the Workflow package.&amp;nbsp;Currently is an alpha version. It has&amp;nbsp;only basic authentication but I plan to inprove it for serious applications.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&amp;nbsp;It includes Application Server features such is resource an process management&amp;nbsp;and automatic recovery&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&amp;nbsp; Resource management: The user can define process and session timeout. The&amp;nbsp;&amp;nbsp;process is automatically rerun after timeout if a new request arrive with transparent&amp;nbsp;&amp;nbsp;recovery of state, at the point of the interrupted dialog &amp;nbsp;even after server crash.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The backend operation relies on the Workflow package&lt;br /&gt;&lt;br /&gt;&lt;a href="http://hackage.haskell.org/package/Workflow"&gt;http://hackage.haskell.org/package/Workflow&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Workflow gives transparent sessión persistence and recovery, all of this&amp;nbsp;&amp;nbsp;is supported by&amp;nbsp;&amp;nbsp;TCache:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://hackage.haskell.org/package/TCache"&gt;http://hackage.haskell.org/package/TCache&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;TCache gives backend-independent transactions and can be used&amp;nbsp;directly by the programmer. Persistence in files &amp;nbsp;for session and data out of the box enables&amp;nbsp;&amp;nbsp;very fast prototyping.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;All the plumbing is hidden to the programmer, There is no methods for&amp;nbsp;session management, database query, recovery and so on. All of this is&amp;nbsp;&amp;nbsp;transparent So the surface exposed to the programmer is minimal.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Includes generalized formlets that permits the mix of active widgets&amp;nbsp;&amp;nbsp;in the same page while remaining statically typed and, thus the programs&amp;nbsp;can verify correctness at compilation time.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Includes combinators for seamless inclusion of these widgets within&amp;nbsp;&amp;nbsp;user defined HTML formatting. Bindings for Text.XHtml. The widget generation may be easy&amp;nbsp;for user with familiarity with formlets/digestive functors and Text.XHtml formatting.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Currently it has bindings for the Hack &amp;nbsp;interface&amp;nbsp;This module defines an integrated way to interact with the user. `ask` isa single method of user interaction. it send user interfaces and return statically&amp;nbsp;typed responses. The user interface definitions are &amp;nbsp;based on the formLets interface&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;But additionally, unlike formLets in its current form, it permits the&amp;nbsp;definition of widgets. A widget is data that, when renderized&amp;nbsp;and interact with the user, return data, just like a formlet, but it hasn&amp;nbsp;to be an HTML form. it can contain JavaScript, or additional Html decoration or&amp;nbsp;it can use Ajax istead of form post for the interaction.&amp;nbsp;There is an example of widget defined (`Selection`)&amp;nbsp;widgets (and formlets) can be combined in a sigle Html page.Here is a ready-to-run example that combines a Widget (Selection) and&amp;nbsp;a HTML decorated formLet in the same page.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;This example show a widtget and a formlet togeter in a statically typed page defined in a declarative style. The server process has 10-15 lines. But it transparently manages user state, session timeout, shutdown the server process and restart it even after intended or unintended server shutdown.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;table class="amelie-code" style="background-color: white; color: black; font-family: 'DejaVu Sans', sans-serif; font-size: 13px; text-align: justify;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="amelie-line-nums" style="vertical-align: top;"&gt;&lt;pre style="margin-right: 1em; text-align: right;"&gt;&lt;a href="http://hpaste.org/57517#line1" id="line1" name="line1" style="color: #555555; text-decoration: none;"&gt;1&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line2" id="line2" name="line2" style="color: #555555; text-decoration: none;"&gt;2&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line3" id="line3" name="line3" style="color: #555555; text-decoration: none;"&gt;3&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line4" id="line4" name="line4" style="color: #555555; text-decoration: none;"&gt;4&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line5" id="line5" name="line5" style="color: #555555; text-decoration: none;"&gt;5&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line6" id="line6" name="line6" style="color: #555555; text-decoration: none;"&gt;6&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line7" id="line7" name="line7" style="color: #555555; text-decoration: none;"&gt;7&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line8" id="line8" name="line8" style="color: #555555; text-decoration: none;"&gt;8&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line9" id="line9" name="line9" style="color: #555555; text-decoration: none;"&gt;9&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line10" id="line10" name="line10" style="color: #555555; text-decoration: none;"&gt;10&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line11" id="line11" name="line11" style="color: #555555; text-decoration: none;"&gt;11&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line12" id="line12" name="line12" style="color: #555555; text-decoration: none;"&gt;12&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line13" id="line13" name="line13" style="color: #555555; text-decoration: none;"&gt;13&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line14" id="line14" name="line14" style="color: #555555; text-decoration: none;"&gt;14&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line15" id="line15" name="line15" style="color: #555555; text-decoration: none;"&gt;15&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line16" id="line16" name="line16" style="color: #555555; text-decoration: none;"&gt;16&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line17" id="line17" name="line17" style="color: #555555; text-decoration: none;"&gt;17&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line18" id="line18" name="line18" style="color: #555555; text-decoration: none;"&gt;18&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line19" id="line19" name="line19" style="color: #555555; text-decoration: none;"&gt;19&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line20" id="line20" name="line20" style="color: #555555; text-decoration: none;"&gt;20&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line21" id="line21" name="line21" style="color: #555555; text-decoration: none;"&gt;21&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line22" id="line22" name="line22" style="color: #555555; text-decoration: none;"&gt;22&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line23" id="line23" name="line23" style="color: #555555; text-decoration: none;"&gt;23&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line24" id="line24" name="line24" style="color: #555555; text-decoration: none;"&gt;24&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line25" id="line25" name="line25" style="color: #555555; text-decoration: none;"&gt;25&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line26" id="line26" name="line26" style="color: #555555; text-decoration: none;"&gt;26&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line27" id="line27" name="line27" style="color: #555555; text-decoration: none;"&gt;27&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line28" id="line28" name="line28" style="color: #555555; text-decoration: none;"&gt;28&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line29" id="line29" name="line29" style="color: #555555; text-decoration: none;"&gt;29&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line30" id="line30" name="line30" style="color: #555555; text-decoration: none;"&gt;30&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line31" id="line31" name="line31" style="color: #555555; text-decoration: none;"&gt;31&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line32" id="line32" name="line32" style="color: #555555; text-decoration: none;"&gt;32&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line33" id="line33" name="line33" style="color: #555555; text-decoration: none;"&gt;33&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line34" id="line34" name="line34" style="color: #555555; text-decoration: none;"&gt;34&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line35" id="line35" name="line35" style="color: #555555; text-decoration: none;"&gt;35&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line36" id="line36" name="line36" style="color: #555555; text-decoration: none;"&gt;36&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line37" id="line37" name="line37" style="color: #555555; text-decoration: none;"&gt;37&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line38" id="line38" name="line38" style="color: #555555; text-decoration: none;"&gt;38&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line39" id="line39" name="line39" style="color: #555555; text-decoration: none;"&gt;39&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line40" id="line40" name="line40" style="color: #555555; text-decoration: none;"&gt;40&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line41" id="line41" name="line41" style="color: #555555; text-decoration: none;"&gt;41&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line42" id="line42" name="line42" style="color: #555555; text-decoration: none;"&gt;42&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line43" id="line43" name="line43" style="color: #555555; text-decoration: none;"&gt;43&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line44" id="line44" name="line44" style="color: #555555; text-decoration: none;"&gt;44&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line45" id="line45" name="line45" style="color: #555555; text-decoration: none;"&gt;45&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line46" id="line46" name="line46" style="color: #555555; text-decoration: none;"&gt;46&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line47" id="line47" name="line47" style="color: #555555; text-decoration: none;"&gt;47&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line48" id="line48" name="line48" style="color: #555555; text-decoration: none;"&gt;48&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line49" id="line49" name="line49" style="color: #555555; text-decoration: none;"&gt;49&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line50" id="line50" name="line50" style="color: #555555; text-decoration: none;"&gt;50&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line51" id="line51" name="line51" style="color: #555555; text-decoration: none;"&gt;51&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line52" id="line52" name="line52" style="color: #555555; text-decoration: none;"&gt;52&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line53" id="line53" name="line53" style="color: #555555; text-decoration: none;"&gt;53&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line54" id="line54" name="line54" style="color: #555555; text-decoration: none;"&gt;54&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line55" id="line55" name="line55" style="color: #555555; text-decoration: none;"&gt;55&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line56" id="line56" name="line56" style="color: #555555; text-decoration: none;"&gt;56&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line57" id="line57" name="line57" style="color: #555555; text-decoration: none;"&gt;57&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line58" id="line58" name="line58" style="color: #555555; text-decoration: none;"&gt;58&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line59" id="line59" name="line59" style="color: #555555; text-decoration: none;"&gt;59&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line60" id="line60" name="line60" style="color: #555555; text-decoration: none;"&gt;60&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line61" id="line61" name="line61" style="color: #555555; text-decoration: none;"&gt;61&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line62" id="line62" name="line62" style="color: #555555; text-decoration: none;"&gt;62&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line63" id="line63" name="line63" style="color: #555555; text-decoration: none;"&gt;63&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line64" id="line64" name="line64" style="color: #555555; text-decoration: none;"&gt;64&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line65" id="line65" name="line65" style="color: #555555; text-decoration: none;"&gt;65&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line66" id="line66" name="line66" style="color: #555555; text-decoration: none;"&gt;66&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line67" id="line67" name="line67" style="color: #555555; text-decoration: none;"&gt;67&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line68" id="line68" name="line68" style="color: #555555; text-decoration: none;"&gt;68&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line69" id="line69" name="line69" style="color: #555555; text-decoration: none;"&gt;69&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line70" id="line70" name="line70" style="color: #555555; text-decoration: none;"&gt;70&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line71" id="line71" name="line71" style="color: #555555; text-decoration: none;"&gt;71&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line72" id="line72" name="line72" style="color: #555555; text-decoration: none;"&gt;72&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line73" id="line73" name="line73" style="color: #555555; text-decoration: none;"&gt;73&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line74" id="line74" name="line74" style="color: #555555; text-decoration: none;"&gt;74&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line75" id="line75" name="line75" style="color: #555555; text-decoration: none;"&gt;75&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line76" id="line76" name="line76" style="color: #555555; text-decoration: none;"&gt;76&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line77" id="line77" name="line77" style="color: #555555; text-decoration: none;"&gt;77&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line78" id="line78" name="line78" style="color: #555555; text-decoration: none;"&gt;78&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line79" id="line79" name="line79" style="color: #555555; text-decoration: none;"&gt;79&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line80" id="line80" name="line80" style="color: #555555; text-decoration: none;"&gt;80&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line81" id="line81" name="line81" style="color: #555555; text-decoration: none;"&gt;81&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line82" id="line82" name="line82" style="color: #555555; text-decoration: none;"&gt;82&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line83" id="line83" name="line83" style="color: #555555; text-decoration: none;"&gt;83&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line84" id="line84" name="line84" style="color: #555555; text-decoration: none;"&gt;84&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line85" id="line85" name="line85" style="color: #555555; text-decoration: none;"&gt;85&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line86" id="line86" name="line86" style="color: #555555; text-decoration: none;"&gt;86&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line87" id="line87" name="line87" style="color: #555555; text-decoration: none;"&gt;87&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line88" id="line88" name="line88" style="color: #555555; text-decoration: none;"&gt;88&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line89" id="line89" name="line89" style="color: #555555; text-decoration: none;"&gt;89&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line90" id="line90" name="line90" style="color: #555555; text-decoration: none;"&gt;90&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line91" id="line91" name="line91" style="color: #555555; text-decoration: none;"&gt;91&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line92" id="line92" name="line92" style="color: #555555; text-decoration: none;"&gt;92&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line93" id="line93" name="line93" style="color: #555555; text-decoration: none;"&gt;93&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line94" id="line94" name="line94" style="color: #555555; text-decoration: none;"&gt;94&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line95" id="line95" name="line95" style="color: #555555; text-decoration: none;"&gt;95&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line96" id="line96" name="line96" style="color: #555555; text-decoration: none;"&gt;96&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line97" id="line97" name="line97" style="color: #555555; text-decoration: none;"&gt;97&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line98" id="line98" name="line98" style="color: #555555; text-decoration: none;"&gt;98&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line99" id="line99" name="line99" style="color: #555555; text-decoration: none;"&gt;99&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line100" id="line100" name="line100" style="color: #555555; text-decoration: none;"&gt;100&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line101" id="line101" name="line101" style="color: #555555; text-decoration: none;"&gt;101&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line102" id="line102" name="line102" style="color: #555555; text-decoration: none;"&gt;102&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line103" id="line103" name="line103" style="color: #555555; text-decoration: none;"&gt;103&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line104" id="line104" name="line104" style="color: #555555; text-decoration: none;"&gt;104&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line105" id="line105" name="line105" style="color: #555555; text-decoration: none;"&gt;105&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line106" id="line106" name="line106" style="color: #555555; text-decoration: none;"&gt;106&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line107" id="line107" name="line107" style="color: #555555; text-decoration: none;"&gt;107&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line108" id="line108" name="line108" style="color: #555555; text-decoration: none;"&gt;108&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line109" id="line109" name="line109" style="color: #555555; text-decoration: none;"&gt;109&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line110" id="line110" name="line110" style="color: #555555; text-decoration: none;"&gt;110&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line111" id="line111" name="line111" style="color: #555555; text-decoration: none;"&gt;111&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line112" id="line112" name="line112" style="color: #555555; text-decoration: none;"&gt;112&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line113" id="line113" name="line113" style="color: #555555; text-decoration: none;"&gt;113&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line114" id="line114" name="line114" style="color: #555555; text-decoration: none;"&gt;114&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line115" id="line115" name="line115" style="color: #555555; text-decoration: none;"&gt;115&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line116" id="line116" name="line116" style="color: #555555; text-decoration: none;"&gt;116&lt;/a&gt;&lt;br /&gt;&lt;a href="http://hpaste.org/57517#line117" id="line117" name="line117" style="color: #555555; text-decoration: none;"&gt;117&lt;/a&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td style="vertical-align: top;"&gt;&lt;pre&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;{-# OPTIONS -XDeriveDataTypeable&lt;br /&gt;            -XMultiParamTypeClasses -XRecordWildCards&lt;br /&gt;&lt;br /&gt;            #-}&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-keyword" style="color: #397460;"&gt;module&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Test&lt;/span&gt; &lt;span class="hs-keyword" style="color: #397460;"&gt;where&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-keyword" style="color: #397460;"&gt;import&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;MFlow&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;.&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Hack&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;.&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;XHtml&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;.&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;All&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="hs-keyword" style="color: #397460;"&gt;import&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Data&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;.&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Typeable&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-keyword" style="color: #397460;"&gt;import&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Control&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;.&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Monad&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;.&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Trans&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-keyword" style="color: #397460;"&gt;import&lt;/span&gt; &lt;span class="hs-keyword" style="color: #397460;"&gt;qualified&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Data&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;.&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Vector&lt;/span&gt; &lt;span class="hs-keyword" style="color: #397460;"&gt;as&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;V&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="hs-keyword" style="color: #397460;"&gt;import&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Data&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;.&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;TCache&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-definition"&gt;main&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;=&lt;/span&gt; &lt;span class="hs-keyword" style="color: #397460;"&gt;do&lt;/span&gt;&lt;br /&gt;   &lt;span class="hs-varid" style="color: #333333;"&gt;userRegister&lt;/span&gt;  &lt;span class="hs-str" style="color: #366354;"&gt;"pepe"&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"pepe"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   &lt;span class="hs-varid" style="color: #333333;"&gt;putStrLn&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;$&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;options&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;messageFlows&lt;/span&gt;&lt;br /&gt;   &lt;span class="hs-varid" style="color: #333333;"&gt;run&lt;/span&gt; &lt;span class="hs-num" style="color: #4f4371;"&gt;80&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;$&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;hackMessageFlow&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;messageFlows&lt;/span&gt;&lt;br /&gt;   &lt;span class="hs-keyword" style="color: #397460;"&gt;where&lt;/span&gt;&lt;br /&gt;   &lt;span class="hs-varid" style="color: #333333;"&gt;messageFlows&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;=&lt;/span&gt;  &lt;span class="hs-keyglyph"&gt;[&lt;/span&gt;&lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-str" style="color: #366354;"&gt;"main"&lt;/span&gt;&lt;span class="hs-layout"&gt;,&lt;/span&gt;  &lt;span class="hs-varid" style="color: #333333;"&gt;runFlow&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;mainProds&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;br /&gt;                  &lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-str" style="color: #366354;"&gt;"hello"&lt;/span&gt;&lt;span class="hs-layout"&gt;,&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;stateless&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;hello&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   &lt;span class="hs-varid" style="color: #333333;"&gt;options&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;msgs&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;=&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"in the browser choose\n\n"&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;++&lt;/span&gt;&lt;br /&gt;     &lt;span class="hs-varid" style="color: #333333;"&gt;concat&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;[&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"http://server/"&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;++&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;i&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;++&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"\n"&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;|&lt;/span&gt; &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;i&lt;/span&gt;&lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;span class="hs-keyword" style="color: #397460;"&gt;_&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;msgs&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;-- an stateless procedure, as an example&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-definition"&gt;hello&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;::&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Env&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;IO&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;String&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-definition"&gt;hello&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;env&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;=&lt;/span&gt;  &lt;span class="hs-varid" style="color: #333333;"&gt;return&lt;/span&gt;  &lt;span class="hs-str" style="color: #366354;"&gt;"hello, this is a stateless response"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="hs-keyword" style="color: #397460;"&gt;data&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Prod&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;=&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Prod&lt;/span&gt;&lt;span class="hs-layout"&gt;{&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;pname&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;::&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;String&lt;/span&gt;&lt;span class="hs-layout"&gt;,&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;pprice&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;::&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Int&lt;/span&gt;&lt;span class="hs-layout"&gt;}&lt;/span&gt; &lt;span class="hs-keyword" style="color: #397460;"&gt;deriving&lt;/span&gt; &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Typeable&lt;/span&gt;&lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Read&lt;/span&gt;&lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Show&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;-- formLets can have Html formatting&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-keyword" style="color: #397460;"&gt;instance&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;FormLet&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Prod&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;IO&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Html&lt;/span&gt; &lt;span class="hs-keyword" style="color: #397460;"&gt;where&lt;/span&gt;&lt;br /&gt;   &lt;span class="hs-varid" style="color: #333333;"&gt;digest&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;mp&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;=&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;table&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;br /&gt;      &lt;span class="hs-conid" style="color: #4f4371;"&gt;Prod&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;tr&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;td&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"enter the name"&lt;/span&gt;  &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;++&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;td&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;getString&lt;/span&gt; &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;pname&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;mp&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;br /&gt;           &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;tr&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;td&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"enter the price"&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;++&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;td&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;getInt&lt;/span&gt; &lt;span class="hs-layout"&gt;(&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;pprice&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;mp&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;-- Here an example of predefined widget (`Selection`) that return an Int, combined in the same&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;-- page with the fromLet for the introduction of a product.&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;-- The result is a 2-tuple of Maybes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="hs-definition"&gt;shopProds&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;::&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;V&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;.&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Vector&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Int&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;[&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Prod&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;]&lt;/span&gt;&lt;br /&gt;          &lt;span class="hs-keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;View&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Html&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;IO&lt;/span&gt;  &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Either&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Int&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Prod&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-definition"&gt;shopProds&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;cart&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;products&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;=&lt;/span&gt;&lt;br /&gt;  &lt;span class="hs-varid" style="color: #333333;"&gt;br&lt;/span&gt;&lt;br /&gt;  &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;++&lt;/span&gt;                    &lt;span class="hs-comment" style="color: #555555;"&gt;-- add Html to the first widget&lt;/span&gt;&lt;br /&gt;  &lt;span class="hs-varid" style="color: #333333;"&gt;p&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"-----Shopping List-----"&lt;/span&gt;&lt;br /&gt;  &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;++&lt;/span&gt;&lt;br /&gt;  &lt;span class="hs-varid" style="color: #333333;"&gt;widget&lt;/span&gt;&lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Selection&lt;/span&gt;&lt;span class="hs-layout"&gt;{&lt;/span&gt;&lt;br /&gt;       &lt;span class="hs-varid" style="color: #333333;"&gt;stitle&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;=&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;bold&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"choose an item"&lt;/span&gt;&lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;br /&gt;       &lt;span class="hs-varid" style="color: #333333;"&gt;sheader&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;=&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;[&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;bold&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"item"&lt;/span&gt;   &lt;span class="hs-layout"&gt;,&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;bold&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"price"&lt;/span&gt;&lt;span class="hs-layout"&gt;,&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;bold&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"times chosen"&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;]&lt;/span&gt;&lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;br /&gt;       &lt;span class="hs-varid" style="color: #333333;"&gt;sbody&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;=&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;[&lt;/span&gt;&lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;[&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;toHtml&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;pname&lt;/span&gt;&lt;span class="hs-layout"&gt;,&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;toHtml&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;$&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;show&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;pprice&lt;/span&gt;&lt;span class="hs-layout"&gt;,&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;toHtml&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;$&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;show&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;$&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;cart&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;V&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;.!&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;i&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;]&lt;/span&gt;&lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;i&lt;/span&gt; &lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;br /&gt;              &lt;span class="hs-keyglyph"&gt;|&lt;/span&gt; &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Prod&lt;/span&gt;&lt;span class="hs-layout"&gt;{&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;..&lt;/span&gt;&lt;span class="hs-layout"&gt;}&lt;/span&gt;&lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;i&lt;/span&gt; &lt;span class="hs-layout"&gt;)&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;zip&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;products&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;[&lt;/span&gt;&lt;span class="hs-num" style="color: #4f4371;"&gt;1&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;..&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;]&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;]&lt;/span&gt;&lt;span class="hs-layout"&gt;}&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;+&amp;gt;&lt;/span&gt;                    &lt;span class="hs-comment" style="color: #555555;"&gt;-- operator to mix two wdigets&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="hs-varid" style="color: #333333;"&gt;br&lt;/span&gt;&lt;br /&gt;  &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;++&lt;/span&gt;                    &lt;span class="hs-comment" style="color: #555555;"&gt;-- add Html to the second widget&lt;/span&gt;&lt;br /&gt;  &lt;span class="hs-varid" style="color: #333333;"&gt;p&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"---Add a new product---"&lt;/span&gt;&lt;br /&gt;  &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;++&lt;/span&gt;&lt;br /&gt;  &lt;span class="hs-varid" style="color: #333333;"&gt;table&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;              &lt;span class="hs-comment" style="color: #555555;"&gt;-- &amp;lt;&amp;lt;&amp;lt; encloses a widget in HTML tags&lt;/span&gt;&lt;br /&gt;            &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;tr&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;td&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;!&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;[&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;valign&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"top"&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;]&lt;/span&gt;&lt;br /&gt;                          &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;widget&lt;/span&gt; &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Form&lt;/span&gt; &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Nothing&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;::&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Maybe&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Prod&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt; &lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;             &lt;span class="hs-varop" style="color: #333333;"&gt;++&amp;gt;&lt;/span&gt;         &lt;span class="hs-comment" style="color: #555555;"&gt;-- append Html after the widget&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;             &lt;span class="hs-varid" style="color: #333333;"&gt;tr&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;td&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;!&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;[&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;align&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"center"&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;]&lt;/span&gt;&lt;br /&gt;                          &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;hotlink&lt;/span&gt;  &lt;span class="hs-str" style="color: #366354;"&gt;"hello"&lt;/span&gt;&lt;br /&gt;                                      &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;bold&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"Hello World"&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;-- the header&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="hs-definition"&gt;appheader&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;user&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;forms&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;=&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;thehtml&lt;/span&gt;&lt;br /&gt;         &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;body&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;dlist&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;concatHtml&lt;/span&gt;&lt;br /&gt;            &lt;span class="hs-keyglyph"&gt;[&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;dterm&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-str" style="color: #366354;"&gt;"Hi "&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;++&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;user&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;dterm&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"This example contains two forms enclosed within user defined HTML formatting"&lt;/span&gt;&lt;br /&gt;            &lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;dterm&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"The first one is defined as a Widget, the second is a formlet formatted within a table"&lt;/span&gt;&lt;br /&gt;            &lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;dterm&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"both are defined using an extension of the FormLets concept"&lt;/span&gt;&lt;br /&gt;            &lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;dterm&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"the form results are statically typed"&lt;/span&gt;&lt;br /&gt;            &lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;dterm&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"The state is implicitly logged. No explicit handling of state"&lt;/span&gt;&lt;br /&gt;            &lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;dterm&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"The program logic is written as a procedure. Not    in request-response form. But request response is possible"&lt;/span&gt;&lt;br /&gt;            &lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;dterm&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"lifespan of the serving process and the execution state defined by the programmer"&lt;/span&gt;&lt;br /&gt;            &lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;dterm&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"user state is  automatically recovered after cold re-start"&lt;/span&gt;&lt;br /&gt;            &lt;span class="hs-layout"&gt;,&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;dterm&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="hs-str" style="color: #366354;"&gt;"transient, non persistent states possible."&lt;/span&gt;&lt;br /&gt;            &lt;span class="hs-keyglyph"&gt;]&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class="hs-varop" style="color: #333333;"&gt;+++&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;forms&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;-- Here the procedure. It ask for either entering a new product&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;-- or to "buy" one of the entered products.&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;-- There is a timeout of ten minutes before the process is stopped&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;-- There is a timeout of one day for the whole session so after this, the&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;-- user will see the list  or prudicts erased.&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;-- In a real application the product list should be stored out of the session&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;-- using TCache's writeDBRef for example&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;-- The state is user specific.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="hs-definition"&gt;mainProds&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;::&lt;/span&gt;  &lt;span class="hs-conid" style="color: #4f4371;"&gt;FlowM&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;Html&lt;/span&gt; &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;Workflow&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;IO&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-definition"&gt;mainProds&lt;/span&gt;   &lt;span class="hs-keyglyph"&gt;=&lt;/span&gt; &lt;span class="hs-keyword" style="color: #397460;"&gt;do&lt;/span&gt;&lt;br /&gt;   &lt;span class="hs-varid" style="color: #333333;"&gt;setTimeouts&lt;/span&gt; &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-num" style="color: #4f4371;"&gt;10&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;*&lt;/span&gt;&lt;span class="hs-num" style="color: #4f4371;"&gt;60&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt; &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-num" style="color: #4f4371;"&gt;24&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;*&lt;/span&gt;&lt;span class="hs-num" style="color: #4f4371;"&gt;60&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;*&lt;/span&gt;&lt;span class="hs-num" style="color: #4f4371;"&gt;60&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;--   setHeader $ \w -&amp;gt; bold &amp;lt;&amp;lt; "Please enter user/password (pepe/pepe)" +++ br +++ w&lt;/span&gt;&lt;br /&gt;&lt;span class="hs-comment" style="color: #555555;"&gt;--   us &amp;lt;-  getUser&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   &lt;span class="hs-varid" style="color: #333333;"&gt;setHeader&lt;/span&gt;  &lt;span class="hs-varop" style="color: #333333;"&gt;$&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;appheader&lt;/span&gt;  &lt;span class="hs-str" style="color: #366354;"&gt;"user"&lt;/span&gt;&lt;br /&gt;   &lt;span class="hs-varid" style="color: #333333;"&gt;mainProds1&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;[]&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;$&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;V&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;.&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;fromList&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;[&lt;/span&gt;&lt;span class="hs-num" style="color: #4f4371;"&gt;0&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;]&lt;/span&gt;&lt;br /&gt;   &lt;span class="hs-keyword" style="color: #397460;"&gt;where&lt;/span&gt;&lt;br /&gt;   &lt;span class="hs-varid" style="color: #333333;"&gt;mainProds1&lt;/span&gt;  &lt;span class="hs-varid" style="color: #333333;"&gt;prods&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;cart&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;=&lt;/span&gt;  &lt;span class="hs-keyword" style="color: #397460;"&gt;do&lt;/span&gt;&lt;br /&gt;     &lt;span class="hs-varid" style="color: #333333;"&gt;mr&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;step&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;.&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;ask&lt;/span&gt;  &lt;span class="hs-varop" style="color: #333333;"&gt;$&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;shopProds&lt;/span&gt;  &lt;span class="hs-varid" style="color: #333333;"&gt;cart&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;prods&lt;/span&gt;&lt;br /&gt;     &lt;span class="hs-keyword" style="color: #397460;"&gt;case&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;mr&lt;/span&gt; &lt;span class="hs-keyword" style="color: #397460;"&gt;of&lt;/span&gt;&lt;br /&gt;      &lt;span class="hs-conid" style="color: #4f4371;"&gt;Right&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;prod&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;mainProds1&lt;/span&gt;  &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;prod&lt;/span&gt;&lt;span class="hs-conop"&gt;:&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;prods&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt; &lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-conid" style="color: #4f4371;"&gt;V&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;.&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;snoc&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;cart&lt;/span&gt; &lt;span class="hs-num" style="color: #4f4371;"&gt;0&lt;/span&gt;&lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class="hs-conid" style="color: #4f4371;"&gt;Left&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;i&lt;/span&gt;   &lt;span class="hs-keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="hs-keyword" style="color: #397460;"&gt;do&lt;/span&gt;&lt;br /&gt;         &lt;span class="hs-keyword" style="color: #397460;"&gt;let&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;newCart&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;=&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;cart&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;V&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;.//&lt;/span&gt; &lt;span class="hs-keyglyph"&gt;[&lt;/span&gt;&lt;span class="hs-layout"&gt;(&lt;/span&gt;&lt;span class="hs-varid" style="color: #333333;"&gt;i&lt;/span&gt;&lt;span class="hs-layout"&gt;,&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;cart&lt;/span&gt; &lt;span class="hs-conid" style="color: #4f4371;"&gt;V&lt;/span&gt;&lt;span class="hs-varop" style="color: #333333;"&gt;.!&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;i&lt;/span&gt; &lt;span class="hs-varop" style="color: #333333;"&gt;+&lt;/span&gt; &lt;span class="hs-num" style="color: #4f4371;"&gt;1&lt;/span&gt; &lt;span class="hs-layout"&gt;)&lt;/span&gt;&lt;span class="hs-keyglyph"&gt;]&lt;/span&gt;&lt;br /&gt;         &lt;span class="hs-varid" style="color: #333333;"&gt;mainProds1&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;prods&lt;/span&gt; &lt;span class="hs-varid" style="color: #333333;"&gt;newCart&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37577615-1890284313740538245?l=haskell-web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://haskell-web.blogspot.com/feeds/1890284313740538245/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37577615&amp;postID=1890284313740538245' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/1890284313740538245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/1890284313740538245'/><link rel='alternate' type='text/html' href='http://haskell-web.blogspot.com/2012/02/web-application-server-with-stateful.html' title='MFlow: A Web application server with stateful server processes and simple typed widget combinators.'/><author><name>Alberto</name><uri>http://www.blogger.com/profile/11962281728014883353</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-37577615.post-3274270202641447884</id><published>2011-11-07T08:03:00.000+01:00</published><updated>2011-11-07T08:04:51.690+01:00</updated><title type='text'>New version of the package Workflow</title><content type='html'>A new version of Workflow is coming. I will have a surgery now, so I uploaded it to my public folder in dropbox. Just in case.&lt;br /&gt;&lt;br /&gt;&lt;a href="https://www.dropbox.com/home#/Public:::"&gt;http://dl.dropbox.com/u/23415684/Workflow-0.5.8.rar&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;See the documentation and the demos (in &amp;nbsp;Demos directory) &amp;nbsp;included. &amp;nbsp;It admits Binary and RefSerialize serialization . This is an intermediate step to allow user-defined serializations. &amp;nbsp;RefSerialize mode does not work still. I hope to fix it soon.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; font: normal normal normal 13px/1.4 sans-serif; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; min-height: 100%; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; position: relative; text-align: left;"&gt;&lt;div id="package-header" style="background-attachment: initial; background-clip: initial; background-color: #293845; background-image: initial; background-origin: initial; border-top-color: rgb(78, 98, 114); border-top-style: solid; border-top-width: 5px; color: #dddddd; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.2em; padding-left: 0.2em; padding-right: 0.2em; padding-top: 0.2em; position: relative;"&gt;&lt;ul class="links" id="page-menu" style="display: inline-table; float: right; font-size: 11px; list-style-image: initial; list-style-position: initial; list-style-type: none; margin-bottom: 0px; margin-left: 1em; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;li style="border-left-color: rgb(213, 213, 213); border-left-style: solid; border-left-width: 1px; display: inline; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; white-space: nowrap;"&gt;&lt;a href="file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/index.html" style="color: white; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.2em; padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.2em; text-decoration: none;"&gt;Contents&lt;/a&gt;&lt;/li&gt;&lt;li style="border-left-color: rgb(213, 213, 213); border-left-style: solid; border-left-width: 1px; display: inline; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; white-space: nowrap;"&gt;&lt;a href="file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/doc-index.html" style="color: white; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.2em; padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.2em; text-decoration: none;"&gt;Index&lt;/a&gt;&lt;/li&gt;&lt;li style="border-left-color: rgb(213, 213, 213); border-left-style: solid; border-left-width: 1px; display: inline; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; white-space: nowrap;"&gt;&lt;a href="file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/index.html#" style="color: white; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.2em; padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.2em; text-decoration: none;"&gt;Frames&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="caption" style="background-attachment: initial; background-clip: initial; background-color: initial; background-image: url(file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/hslogo-16.png); background-origin: initial; background-position: 0em 50%; background-repeat: no-repeat no-repeat; color: white; margin-left: 2em; margin-right: 2em; padding-bottom: 0px; padding-left: 2em; padding-right: 0px; padding-top: 0px;"&gt;Workflow-0.5.8: library for transparent execution of interruptible computations&lt;/div&gt;&lt;/div&gt;&lt;div id="content" style="margin-bottom: 0px; margin-left: auto; margin-right: auto; margin-top: 0px; padding-bottom: 6em; padding-left: 2em; padding-right: 2em; padding-top: 0px;"&gt;&lt;div class="doc" id="description" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 2em; padding-right: 0px; padding-top: 0px;"&gt;&lt;h1 style="color: #4e6272; font-size: 19px; margin-bottom: 0.4em; margin-left: 0px; margin-right: 0px; margin-top: 0.8em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;Workflow-0.5.8: library for transparent execution of interruptible computations&lt;/h1&gt;&lt;div style="margin-bottom: 0.8em; margin-top: 0.8em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;Transparent support for interruptible computations. A workflow can be seen as a persistent thread that executes any monadic computation. Therefore, it can be used in very time consuming computations such are CPU intensive calculations or procedures that are most of the time waiting for the action of a process or an user, that are prone to comunication failures, timeouts or shutdowns.&lt;/div&gt;&lt;div style="margin-bottom: 0.8em; margin-top: 0.8em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;The computantion can be restarted at the interrupted point because the computation is encapsulated inside a state monad transformer that transparently checkpoint the computation state. Besides that, the package also provides other services associated to workflows&lt;/div&gt;&lt;div style="margin-bottom: 0.8em; margin-top: 0.8em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;New in this release, * registerType is no longer needed (made possible by the use of TCache 0.9 usage)&lt;/div&gt;&lt;ul style="margin-bottom: 0.8em; margin-left: 2em; margin-right: 0px; margin-top: 0.8em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;configurable state persistence (for example, in databases) (made possible by the use of TCache 0.9 usage)&lt;/li&gt;&lt;li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;optional binary serialization of state&lt;/li&gt;&lt;li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;new simpler and more ituitive workflow start(int) primitives&lt;/li&gt;&lt;li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;instances of classes in Control.Concurrent.MonadIO, MonadCatchIO etc&lt;/li&gt;&lt;li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;Patterns, an EDSL of workflow patterns. To express workflows as sequences and concurrency of actions&lt;/li&gt;&lt;/ul&gt;&lt;div style="margin-bottom: 0.8em; margin-top: 0.8em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;The main features are:&lt;/div&gt;&lt;ul style="margin-bottom: 0.8em; margin-left: 2em; margin-right: 0px; margin-top: 0.8em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;logging of each intermediate action results in disk.&lt;/li&gt;&lt;li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;resume the monadic computation at the last checkpoint after soft or hard interruption.&lt;/li&gt;&lt;li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;suspend a computation until the input object meet certain conditions. Useful for inter-workflow comunications.-&lt;/li&gt;&lt;li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;Persisten communications facilities trough persistent data objects, inspection of workflow states , persistent queues, persistent timeouts, to avoid data lost due to shutdowns&lt;/li&gt;&lt;li style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;workflow management and monitoriing, view workflow history and intermediate results.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div id="module-list" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;div class="caption" style="color: #4e6272; font-size: 17px; font-weight: bold; margin-bottom: 0.4em; margin-top: 0.8em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;Modules&lt;/div&gt;&lt;ul style="list-style-image: initial; list-style-position: initial; list-style-type: none; margin-bottom: 0px; margin-left: 2em; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;li style="clear: right; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="module collapser" id="control.n.1" style="background-image: url(file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/minus.gif); background-position: 0px 0.3em; background-repeat: no-repeat no-repeat; cursor: pointer; margin-bottom: 0px; margin-left: -14px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 14px; padding-right: 0px; padding-top: 0px;"&gt;Control&lt;/span&gt;&lt;ul class="show" id="section.n.1" style="display: inherit; list-style-image: initial; list-style-position: initial; list-style-type: none; margin-bottom: 0px; margin-left: 2em; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;li style="clear: right; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="module collapser" id="control.n.1.1" style="background-image: url(file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/minus.gif); background-position: 0px 0.3em; background-repeat: no-repeat no-repeat; cursor: pointer; margin-bottom: 0px; margin-left: -14px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 14px; padding-right: 0px; padding-top: 0px;"&gt;Workflow&lt;/span&gt;&lt;ul class="show" id="section.n.1.1" style="display: inherit; list-style-image: initial; list-style-position: initial; list-style-type: none; margin-bottom: 0px; margin-left: 2em; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;li style="clear: right; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="module" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="collapser" id="control.n.1.1.1" style="background-image: url(file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/minus.gif); background-position: 0px 0.3em; background-repeat: no-repeat no-repeat; cursor: pointer; margin-bottom: 0px; margin-left: -14px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 14px; padding-right: 0px; padding-top: 0px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/Control-Workflow-Binary.html" style="color: #c4451d; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;Control.Workflow.Binary&lt;/a&gt;&lt;/span&gt;&lt;ul class="show" id="section.n.1.1.1" style="display: inherit; list-style-image: initial; list-style-position: initial; list-style-type: none; margin-bottom: 0px; margin-left: 2em; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;li style="clear: right; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="module" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;a href="file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/Control-Workflow-Binary-BinDefs.html" style="color: #c4451d; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;Control.Workflow.Binary.BinDefs&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="clear: right; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="module" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;a href="file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/Control-Workflow-Binary-Patterns.html" style="color: #c4451d; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;Control.Workflow.Binary.Patterns&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="clear: right; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="module" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;a href="file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/Control-Workflow-Binary-Queue.html" style="color: #c4451d; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;Control.Workflow.Binary.Queue&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li style="clear: right; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="module" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;a href="file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/Control-Workflow-GenSerializer.html" style="color: #c4451d; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;Control.Workflow.GenSerializer&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="clear: right; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="module" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;a href="file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/Control-Workflow-IDynamic.html" style="color: #c4451d; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;Control.Workflow.IDynamic&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="clear: right; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="module" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;a href="file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/Control-Workflow-Stat.html" style="color: #c4451d; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;Control.Workflow.Stat&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="clear: right; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="module" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="collapser" id="control.n.1.1.5" style="background-image: url(file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/minus.gif); background-position: 0px 0.3em; background-repeat: no-repeat no-repeat; cursor: pointer; margin-bottom: 0px; margin-left: -14px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 14px; padding-right: 0px; padding-top: 0px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/Control-Workflow-Text.html" style="color: #c4451d; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;Control.Workflow.Text&lt;/a&gt;&lt;/span&gt;&lt;ul class="show" id="section.n.1.1.5" style="display: inherit; list-style-image: initial; list-style-position: initial; list-style-type: none; margin-bottom: 0px; margin-left: 2em; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;li style="clear: right; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="module" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;a href="file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/Control-Workflow-Text-Patterns.html" style="color: #c4451d; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;Control.Workflow.Text.Patterns&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="clear: right; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="module" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;a href="file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/Control-Workflow-Text-Queue.html" style="color: #c4451d; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;Control.Workflow.Text.Queue&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="clear: right; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;span class="module" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;a href="file:///C:/Users/magocoal/Documents/Dropbox/haskell/devel/Workflow-0.5.8/dist/doc/html/Workflow/Control-Workflow-Text-TextDefs.html" style="color: #c4451d; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;Control.Workflow.Text.TextDefs&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div id="footer" style="background-attachment: initial; background-clip: initial; background-color: #dddddd; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-top-color: rgb(170, 170, 170); border-top-style: solid; border-top-width: 1px; bottom: 0px; color: #666666; height: 3em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0.5em; position: absolute; text-align: center; width: 1007px;"&gt;&lt;div style="margin-bottom: 0.8em; margin-top: 0.8em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;Produced by&amp;nbsp;&lt;a href="http://www.haskell.org/haddock/" style="color: #c4451d; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;Haddock&lt;/a&gt;&amp;nbsp;version 2.9.2&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37577615-3274270202641447884?l=haskell-web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://haskell-web.blogspot.com/feeds/3274270202641447884/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37577615&amp;postID=3274270202641447884' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/3274270202641447884'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/3274270202641447884'/><link rel='alternate' type='text/html' href='http://haskell-web.blogspot.com/2011/11/new-version-of-package-workflow.html' title='New version of the package Workflow'/><author><name>Alberto</name><uri>http://www.blogger.com/profile/11962281728014883353</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-37577615.post-1978543272593969164</id><published>2009-12-08T13:46:00.004+01:00</published><updated>2009-12-09T14:10:07.877+01:00</updated><title type='text'>The Transient monad</title><content type='html'>Concerning Stable Names&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.haskell.org/ghc/docs/6.10.4/html/libraries/base/System-Mem-StableName.html"&gt;http://www.haskell.org/ghc/docs/6.10.4/html/libraries/base/System-Mem-StableName.html&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;I did not test fully my proposal, and I´m thinking aloud, Just to inspire others and fish some ideas: look at the type:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;i&gt;makeStableName :: a -&gt; IO (StableName a)&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The IO in &lt;i&gt;makeStableName &lt;/i&gt;suggest more side effects than the call really do. But still it isn't pure. For calls such are makeStableName that gives a different result the FIRST time they are called but return the same result every time in the same session, I suggest to use a Transient monad:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;makeStableName :: a -&gt; &lt;b&gt;Transient &lt;/b&gt;(StableName a)&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;The key here is to maintain the programmer aware that it is not pure, but there are no IO and that the results have no meaning from session to session.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Instance Monad Transient where&lt;br /&gt;  Transient x ↠ f = f x&lt;br /&gt;  return x = Transient x&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;We can Transient`ize IO calls by means of an implicit memoization:&lt;br /&gt;&lt;br /&gt;liftT:: IO a -&gt; Transient a&lt;br /&gt;liftT= &lt;whatever&gt;&lt;br /&gt;liftT2=....&lt;br /&gt;liftT3=....&lt;br /&gt;&lt;br /&gt;Memorization then is embedded in the monad transformation.&lt;/whatever&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;This may be more elegant than IO plus unsafePerformIO and is more informative for the programmer.&lt;br /&gt;&lt;br /&gt;Instead of unsafePerformIO, we can use:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;unsafePurifyTransient :: Transient a -&gt; a&lt;br /&gt;unsafePurifyTransient (Transient x) = x&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;for the inherently transient calls&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The transition form IO to pure can be done in two steps trough Transient: A safer version of unsafePerformIO using implicit memoization could be:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;i&gt;unsafePerformIOT :: IO a -&gt; a&lt;br /&gt;unsafePerformIOT = unsafePurifyTransient . liftT&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;unsafePerformIOT &lt;/i&gt;guarantee that it returns the same value in the same session&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Twan van Laarhoven objected that makeStableName return different values before  and after evaluation of an expression. True, makeStableName does not return the same value ever. This is the second time that I forget that. Still I think that Transient or something similar is worth the pain for making a less unsafe transition from IO to pure trough memoization, That was my goal. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For this reason, I want something more narrow than IO to make the programmer aware of the higuer  level of safety, rather than something more general. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Stable names are good for memoization however, since memoization of IO procedures can be implemente by hashing their stable names. I think that it is possible to force the evaluation of an expression, then it is possible to have a Transient version of makeStableName.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Transient means that something has been cached and fixed. This can be generalized also for temporary valid computations:&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;data Time= Session | Time Integer &lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;data Transient a= Trans (Time, a)&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;instance Monad  Transient where&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;     Trans( t,x) ↠ f = &lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;                  let Trans (t2, y)    =  f  x&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;                  in  Trans ((min1 t t2) , y)&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;     return x = Trans (Session, x)&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;min1 :: Time →  Time →  Time&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;min1 Session x= x&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;min1 x Session= x&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;min1 (Time x) (Time y)=Time $  min x y&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This monad will calculate the time that the result remain valid given the time validity of each computation involved. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, more fine  calculation is needed since the computation takes time too. Perhaps the bind operation can abort the compuitation and send an error when the time is zero. this can be catched to restart the computation again or whatever else.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37577615-1978543272593969164?l=haskell-web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://haskell-web.blogspot.com/feeds/1978543272593969164/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37577615&amp;postID=1978543272593969164' title='42 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/1978543272593969164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/1978543272593969164'/><link rel='alternate' type='text/html' href='http://haskell-web.blogspot.com/2009/12/transient-monad.html' title='The Transient monad'/><author><name>Alberto</name><uri>http://www.blogger.com/profile/11962281728014883353</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>42</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37577615.post-2473054584006324061</id><published>2009-11-21T00:48:00.012+01:00</published><updated>2009-12-07T18:56:27.972+01:00</updated><title type='text'>Workflow: an Haskell package for transparent support of interruptible computations</title><content type='html'>&lt;div style="TEXT-ALIGN: justify; WIDTH: 90%"&gt;A month ago i uploaded the package &lt;a href="http://hackage.haskell.org/packages/archive/Workflow/0.5.6/doc/html/Control-Workflow.html"&gt;Workflow &lt;/a&gt;to hackage, the repository of Haskell libraries. I added an hopefully self suficient documentations and examples. &lt;/div&gt;&lt;div style="TEXT-ALIGN: justify; WIDTH: 90%"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="TEXT-ALIGN: justify; WIDTH: 90%"&gt;Here follows a few remarks, a simple example and a more sophsticated example:&lt;ple)&gt; &lt;div style="TEXT-ALIGN: justify; WIDTH: 90%"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span class="Apple-style-span"  style="font-family:-webkit-sans-serif;"&gt; &lt;table style="TEXT-ALIGN: justify; BORDER-RIGHT-WIDTH: 0px; WIDTH: 991px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" class="vanilla" cellspacing="0" cellpadding="0"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="BORDER-RIGHT-WIDTH: 0px; PADDING-LEFT: 10px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 2px" class="doc"&gt;&lt;p&gt;The main features are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Transparent state logging trough a monad transformer: step :: m a -&gt; Workflow m a.&lt;/li&gt;&lt;li&gt;Resume the computation state after an accidental o planned program shutdown (restartWorkflows).&lt;/li&gt;&lt;li&gt;Event handling (waithFor, waitForData).&lt;/li&gt;&lt;li&gt;Monitoring of workflows with state change display and other auxiliary features.&lt;/li&gt;&lt;li&gt;Communications with other processes including other workflows trough persistent data objects, inspecttion of intermediate workflow results , Queues so that no data is lost due to shutdowns&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Here is a complete example: &lt;/p&gt;&lt;p&gt;This is a counter that shows a sequence of numbers, one a second:&lt;/p&gt;&lt;pre style="FONT-SIZE: 13px"&gt;module Main where &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;import Control.Concurrent(threadDelay) &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;import System.IO (hFlush,stdout)  &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;count n= putStr (show n ++ &lt;a style="COLOR: rgb(0,0,224); TEXT-DECORATION: none" href="http://hackage.haskell.org/packages/archive/Workflow/0.5.6/doc/html/.html"&gt; &lt;/a&gt;) &gt;&gt; hFlush stdout &gt;&gt; threadDelay 1000000 &gt;&gt; count (n+1) &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;main= count 0&lt;/pre&gt;&lt;p&gt;This is the same program, with the added feature of remembering the last count after interrupted:&lt;/p&gt;&lt;pre style="FONT-SIZE: 13px"&gt;module Main where &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;import Control.Workflow &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;import Control.Concurrent(threadDelay) &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;import System.IO (hFlush,stdout)  &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;mcount n= &lt;tt style="FONT-SIZE: 13px"&gt;&lt;a style="COLOR: rgb(0,0,224); TEXT-DECORATION: none" href="http://hackage.haskell.org/packages/archive/Workflow/0.5.6/doc/html/Control-Workflow.html#v%3Astep"&gt;step&lt;/a&gt;&lt;/tt&gt; $  putStr (show n ++ &lt;a style="COLOR: rgb(0,0,224); TEXT-DECORATION: none" href="http://hackage.haskell.org/packages/archive/Workflow/0.5.6/doc/html/.html"&gt; &lt;/a&gt;) &gt;&gt; hFlush stdout &gt;&gt; threadDelay 1000000 &gt;&gt; mcount (n+1)  &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;main= do    &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;   registerType :: IO ()    &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;   registerType :: IO Int    &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;   let start= 0 :: Int    &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;   startWF  &lt;a style="COLOR: rgb(0,0,224); TEXT-DECORATION: none" href="http://hackage.haskell.org/packages/archive/Workflow/0.5.6/doc/html/count.html"&gt;count&lt;/a&gt;  start   [(&lt;a style="COLOR: rgb(0,0,224); TEXT-DECORATION: none" href="http://hackage.haskell.org/packages/archive/Workflow/0.5.6/doc/html/count.html"&gt;count&lt;/a&gt;, mcount)] :: IO ()&lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This is the execution log:&lt;/p&gt;&lt;pre style="FONT-SIZE: 13px"&gt;Worflow-0.5.5demos&gt;runghc sequence.hs &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;0 1 2 3 4 5 6 7 sequence.hs: win32ConsoleHandler sequence.hs: sequence.hs: interrupted &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;Worflow-0.5.5demos&gt; &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;Worflow-0.5.5demos&gt;runghc sequence.hs &lt;/pre&gt;&lt;pre style="FONT-SIZE: 13px"&gt;7 8 9 10 11 ....&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="TEXT-ALIGN: justify; WIDTH: 90%"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="TEXT-ALIGN: justify; WIDTH: 90%"&gt;&lt;span class="Apple-style-span"  style="font-family:-webkit-sans-serif;"&gt;Here is the &lt;a href="http://hackage.haskell.org/packages/archive/Workflow/0.5.6/doc/html/Control-Workflow.html"&gt;complete documentation&lt;/a&gt; iof the package&lt;/span&gt;&lt;/div&gt;&lt;div style="TEXT-ALIGN: justify; WIDTH: 90%"&gt;&lt;span class="Apple-style-span"  style="font-family:-webkit-sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="TEXT-ALIGN: justify; WIDTH: 90%"&gt;&lt;span class="Apple-style-span"  style="font-family:-webkit-sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="TEXT-ALIGN: justify; WIDTH: 90%"&gt;&lt;span class="Apple-style-span"  style="font-family:-webkit-sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="TEXT-ALIGN: justify; WIDTH: 90%"&gt;&lt;span class="Apple-style-span"  style="font-family:-webkit-sans-serif;"&gt;And here is a more sophisticated example, at &lt;a href="http://paste.org/pastebin/view/12049"&gt;pastebin.org&lt;/a&gt;. The code is also documented.&lt;/span&gt;&lt;/div&gt;&lt;/PLE)&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37577615-2473054584006324061?l=haskell-web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://haskell-web.blogspot.com/feeds/2473054584006324061/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37577615&amp;postID=2473054584006324061' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/2473054584006324061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/2473054584006324061'/><link rel='alternate' type='text/html' href='http://haskell-web.blogspot.com/2009/11/workflow-haskell-package-for-ransparent.html' title='Workflow: an Haskell package for transparent support of interruptible computations'/><author><name>Alberto</name><uri>http://www.blogger.com/profile/11962281728014883353</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37577615.post-6301418212388677966</id><published>2009-09-29T12:23:00.004+01:00</published><updated>2009-09-29T12:34:41.550+01:00</updated><title type='text'>The future of Haskell</title><content type='html'>&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Most successful languages spread because they are part of a platform which solves an IT problem. C was part of Unix, both brougth CPU independence when this was necessary. Java is part of the Java platform, that brougth OS independence and interoperability at the right time. Download-execution on the client was also a reason for the initial success of Java in the Internet era.  Javascript is part of the web browser. The .NET languages are part of NET.  Rubi and Pyton came with libraries targeted to Rapid development of Internet applications.&lt;br/&gt;&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;What is the vehicle that haskell can use to enter the mainstream?. I think that the mere interest of the ideas in the language is not enough.  Many people will play with Haskell in the spare time, and many of them will be permitted to develop some non critical applications at work. But that is all.  Java was not designed for the Internet but it was re-targeted to it because some needed features where already implemented in Java. Maybe something like that will happen to Haskell.&lt;br/&gt;&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;I think that all the current niches are filled, but new niches  are coming. specially with higher level programming that is made on top of current software infrastructure such are BPM, workflows, more flexible scientific applicatins, creation of  models in business intelligence, as part of ERPs,.Data mining too.  And higuer levels of netwrok communications( for example, Google Wave robots) etc.&lt;br/&gt;&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;About the last point, sometimes a basically identical infrastructure is re-engineered to a higher level, and a new language takes over. For example, the  architecture of many Internet applications in the 80s was client-server based, where C, C++ was the king. This was substituted by  the web architecture with Java because Java was involved in the gradual change by filling the holes of the new architecture.  It could be that in a few years, instead of Web sites people could develop interoperable gadgets for aggregators such are netvibes or IGoogle or, even more radical, robots and gadgets in google Wave. Anyway, for sure, people will think and develop at a higher level.&lt;br/&gt;&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;Financial applications are an example of higher level programming where tasks usually performed by humans are now automatized and there is no or few traditions about that. The need to think at a higher level without being worried by side effects and other details are specially needed in such kind of areas. That's where haskell could have its own niche.&lt;br/&gt;&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;Regards&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37577615-6301418212388677966?l=haskell-web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://haskell-web.blogspot.com/feeds/6301418212388677966/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37577615&amp;postID=6301418212388677966' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/6301418212388677966'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/6301418212388677966'/><link rel='alternate' type='text/html' href='http://haskell-web.blogspot.com/2009/09/future-of-haskell.html' title='The future of Haskell'/><author><name>Alberto</name><uri>http://www.blogger.com/profile/11962281728014883353</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-37577615.post-9163392152340924633</id><published>2009-01-17T23:31:00.002+01:00</published><updated>2012-02-07T21:08:28.919+01:00</updated><title type='text'>Declarative vs imperative: Math, Algoritms, the universe and everything</title><content type='html'>&amp;nbsp;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial; font-size: 13px;"&gt;The question of imperative versus pure declarative coding has brought&amp;nbsp;to my mind some may be off-topic speculations. &amp;nbsp;(so please don´t read it if you have no time to waste): &amp;nbsp;I´m interested in the misterious relation bentween mathematics, algoritms and reality (&lt;a href="http://arxiv.org/pdf/0704.0646" style="color: #2a5db0;" target="_blank"&gt;see this&lt;/a&gt;&amp;nbsp;for example). &amp;nbsp;Functional programming is declarative, you can model the entire world functionally&amp;nbsp;with no concern for the order&amp;nbsp;of calculations. The world is mathematical. The laws of physics have no concern for sequencing.&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial; font-size: 13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial; font-size: 13px;"&gt;But CPUs and communications are basically sequential. &amp;nbsp;Life is sequential, and programs run along the time coordinate. Whenever&amp;nbsp;you have to run a program, &amp;nbsp;you or your compiler must sequence it. &amp;nbsp;The sequentiation &amp;nbsp;must be done by you or your compiler or both. The functional declarative code can be sequenced on-the-run by the compiler in the CPU by the runtime. but IO is different.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial; font-size: 13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial; font-size: 13px;"&gt;You have to create, explicitly or implicitly the sequence of IO actions because the external events in the external world &amp;nbsp;are not controlled by you or the compiler. So you, the programmer are the responsible of sequencing effects in coordination with the external world. so every language must give you ways to express &amp;nbsp;sequencing of actions. that is why, to interact with the external world you must think in terms of algorithms, that is , imperatively, no matter if you make the imperative-sequence &amp;nbsp;(relatively) explicit with monads or if you make it trough pairs (state, value) or unsafePerformIO or whatever. You have to think imperatively either way, because yo HAVE TO construct a sequence. I think that the elegant option is to recognize this different algorithmic nature of IO by using the IO monad.&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial; font-size: 13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial; font-size: 13px;"&gt;In other terms, the appearance of input-output in a problem means that you modelize just a part of the whole system. the interaction with the part of the system that the program do not control appears as input output. if the program includes the model of the environment that give the input output (including perhaps a model of yourself), then, all the code may be side effects free and unobservable. Thus, input output is a measure of the lack of &amp;nbsp;a priori information. &amp;nbsp;Because this information is given and demanded at precide points in the time dimension with a quantitative (real time) or ordered (sequential) measure, then these impure considerations must be taken into account in the program. However, the above is nonsensical, because if you know everithing a priory, then you don´t have a problem, so you don´t need a program. Because problem solving is to cope with unknow data that appears AFTER the program has been created, in oder to produce output at the corrrect time, then the program must have timing on it. has an algoritmic nature, is not pure mathemathical. This applies indeed to all living beings, that respond to the environment, and this creates the notion of time.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial; font-size: 13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial; font-size: 13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial; font-size: 13px;"&gt;Concerning monadic code with no side effects, In mathematical terms, &amp;nbsp;sequenced (monadic) code are mathematically different from declarative code: A &amp;nbsp;function describes what in mathematics is called a &amp;nbsp;"manifold" with a number of dimensions equal to the number of parameters. &amp;nbsp;In the other side, a sequence describe a particular &amp;nbsp;trayectory in a manifold, a ordered set of points in a wider&amp;nbsp;manyfold surface. For this reason the latter must be described algorithmically. The former can be said that include all possible trajectories, and can be expressed declaratively. The latter is a sequence &amp;nbsp;. You can use the former to construct the later, but you must &amp;nbsp; express the sequence because you are defining the concrete trajectory in the general manifold that solve your concrete problem, not other infinite sets of related problems. This essentially applies also to IO.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial; font-size: 13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial; font-size: 13px;"&gt;&amp;nbsp;Well this does not imply that you must use monads for it. For example, a way to express a sequence is a list where each element is a function of the previous. &amp;nbsp;The complier is forced to sequence it in the way you whant, but this happens also with monad evaluation. &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial; font-size: 13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial; font-size: 13px;"&gt;This can be exemplified with the laws of Newton: they are declarative. Like any phisical formula. has no concern for sequencing. But when you need to simulate the behaviour of a ballistic weapon, you must use a sequence of instructions( that include the l newton laws). (well, in this case the trajectory is continuous integrable and can be expressed in a single function. In this case, the manifold includes a unique trajectory, but &amp;nbsp;this is not the case in ordinary discrete problems,) . So any language need declarative as well as imperative elements to program mathematical models as well as algorithms.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37577615-9163392152340924633?l=haskell-web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://haskell-web.blogspot.com/feeds/9163392152340924633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37577615&amp;postID=9163392152340924633' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/9163392152340924633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/9163392152340924633'/><link rel='alternate' type='text/html' href='http://haskell-web.blogspot.com/2009/01/declarative-vs-imperative-matrh.html' title='Declarative vs imperative: Math, Algoritms, the universe and everything'/><author><name>Alberto</name><uri>http://www.blogger.com/profile/11962281728014883353</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-37577615.post-7696853371495149945</id><published>2009-01-11T14:13:00.000+01:00</published><updated>2009-01-11T14:14:24.297+01:00</updated><title type='text'>About programming and design</title><content type='html'>&lt;div style="text-align: justify;"&gt;As a physicist, I think that programming, like any design in general, is all about making as little use of brain resources as possible at the time of solving problems and to transmit the solution to others. This is the reason why it is pervasive in all kinds of engineering the concepts of modularity, isolation, clean interfacing (for which referential transparency is part of) etc. To decompose a problem in parts each one with simple solutions and with as little uncontrolled interaction with other parts is a rule of good design simply  because we can not think in nothing  but around seven concepts at the same time (By the way, an evolutionary psychologist would say that the beatifulness of simplicity is related with this release of brain resources). As a matter of fact,  these rules of "good" design do not apply to the design of living beings simply because the process of Natural Selection has not these limitations. that is indeed the reason because natural designs are so difficult for reverse engineering. &lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Because such kid of human brain limitations and our lack of knowledge, design has a lot of trial and error. The danger of this is to get lost in the explosion of unfruitful alternatives due to low level issues outside of our high level problem, because the limitation of the tools we are using for it. In this sense, things like the strong type inference is superb for cutting the explosion of erroneous paths that the process of software development can generate. If designing solutions is sculpting order from chaos and against chaos, intelligent tools are the thing needed  to keep us concentrated in fruitful courses of action. A physicist would say that design is to lower the entropic balance by progressively lowering the number of microstates until the only ones permitted correspond with the desired outcomes, called "solutions" and a few bugs, of course.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;For me, syntactic sugar is one more of this features that make haskell so great. Once we discover that a solution  general enough has a correspondence with something already know, such are monads for imperative languages, then, why not make this similarity explicit ,with the do notation, in order to communicate it better with other people making use of this common knowledge?. &lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;I have to say also that, without Haskell, I never dream to have the confidence to play simultaneously with concurrence, transactions, internet communications, parsing and, at the time, keeping the code clean enough to understand it after a month of inactivity.  This is for me the big picture that matters for real programming.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37577615-7696853371495149945?l=haskell-web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://haskell-web.blogspot.com/feeds/7696853371495149945/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37577615&amp;postID=7696853371495149945' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/7696853371495149945'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/7696853371495149945'/><link rel='alternate' type='text/html' href='http://haskell-web.blogspot.com/2009/01/about-programming-and-design.html' title='About programming and design'/><author><name>Alberto</name><uri>http://www.blogger.com/profile/11962281728014883353</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37577615.post-6261021186179818092</id><published>2009-01-09T20:51:00.005+01:00</published><updated>2009-01-09T22:46:01.811+01:00</updated><title type='text'>A new version of TCache (0.5.5)</title><content type='html'>has been uploaded to hackage. &lt;br /&gt;&lt;a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/TCache"&gt;http://hackage.haskell.org/cgi-bin/hackage-scripts/package/TCache&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The main addition of this versión is the capablity to safely handle transact, and serialize to permanent storage many datatypes simultaneously in the same piece of code and incrementally. &lt;br /&gt;&lt;br /&gt;Just register each new datatype (with registerType :: &lt;Type&gt;). So it is not necessary to glue all types in advance in a single algebraic datatype. I suppose taht "enhanced composablility" applies to this feature.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        In this release:&lt;br /&gt;           Added a Data.TCache.Dynamic.  (SEE dynamicsample.hs)&lt;br /&gt;             - Can handle, transact, and serialize to disk many datatypes simultaneously and incrementally&lt;br /&gt;             - Dynamic uses the same interface than TCache and add *DResource(s) calls for handling many &lt;br /&gt;               datatypes simultaneously&lt;br /&gt;             - Safe dynamic data handling trough a lighter, indexable and serializable version of Data.Dynamic&lt;br /&gt;             - Added KEY object for retrieving any object of any type.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        Data.Tcache is a transactional cache with configurable persistence. It tries to simulate Hibernate &lt;br /&gt;        for Java or Rails for Ruby. The main difference is that transactions are done in memory trough STM. &lt;br /&gt;        There are transactional cache implementations for some J2EE servers like JBOSS.&lt;br /&gt;&lt;br /&gt;        TCache uses STM. It can  atomically apply a function to a list of cached objects. The resulting &lt;br /&gt;        objects go back to the cache (withResources). It also can retrieve these objects (getResources).  &lt;br /&gt;        Persistence can be syncronous (syncCache)  or asyncronous, wtih configurable time between cache &lt;br /&gt;        writes and configurable cache clearance strategy. the size of the cache can be configured too . &lt;br /&gt;        All of this can be done trough clearSyncCacheProc. Even the TVar variables can be accessed &lt;br /&gt;        directly (getTVar) to acceess all the semantic of atomic blocks while maintaining the persistence of the &lt;br /&gt;        TVar updates.&lt;br /&gt;&lt;br /&gt;        Persistence can be defined for each object: Each object must have a defined key, a default filename&lt;br /&gt;        path (if applicable). Persistence is pre-defined in files, but the readResource writeResource and &lt;br /&gt;        delResource methods can be redefined to persist in databases or whatever.&lt;br /&gt;&lt;br /&gt;        There are  Samples in the package that explain the main features.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37577615-6261021186179818092?l=haskell-web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://haskell-web.blogspot.com/feeds/6261021186179818092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37577615&amp;postID=6261021186179818092' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/6261021186179818092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/6261021186179818092'/><link rel='alternate' type='text/html' href='http://haskell-web.blogspot.com/2009/01/new-version-of-tcache-055.html' title='A new version of TCache (0.5.5)'/><author><name>Alberto</name><uri>http://www.blogger.com/profile/11962281728014883353</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-37577615.post-3251503680293372723</id><published>2008-10-23T22:01:00.001+01:00</published><updated>2008-10-24T22:13:36.437+01:00</updated><title type='text'>axioms-properties for haskell classes</title><content type='html'>&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt; &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;&lt;div class="pasteEntry" id="a0"&gt;&lt;div style="text-align: center;"&gt;&lt;div style="text-align: center;"&gt;&lt;font size="5"&gt;&lt;span class="entryLabel"&gt;Axioms and properties for haskell classes&lt;/span&gt;&lt;/font&gt;&lt;br&gt;&lt;/div&gt;&lt;font size="5"&gt;&lt;span class="entryLabel"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;font size="5"&gt;&lt;span class="entryLabel"&gt;&lt;font size="2"&gt;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;div style="text-align: center;"&gt;&lt;div style="text-align: center;"&gt;&lt;font size="5"&gt;&lt;span class="entryLabel"&gt;&lt;font size="2"&gt;Alberto Gómez Corona&amp;nbsp; agocorona (at) gmail.com&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;br&gt;&lt;/div&gt;&lt;font size="5"&gt;&lt;span class="entryLabel"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;font size="5"&gt;&lt;span class="entryLabel"&gt;&lt;font size="2"&gt;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;div&gt;NOTE: added changes to avoid error due to duplicated instances. See code below.&lt;br&gt;&lt;br&gt;&lt;br&gt;Eureka!!!&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;. I found someting interesting that have something in the middle&lt;br /&gt;of the heaven of universal algebras and the&amp;nbsp;firm ground of&amp;nbsp;quickcheck:&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;This is a way to express axioms in pure Haskell and make practical&amp;nbsp;use of them at the same time:&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;First, I start by &amp;nbsp;defining &amp;nbsp;a special class called Axioms that contains list of different properties with different arities. &lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;data Axiom a= Axiom String a&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;b&gt;class Axioms a where&lt;br&gt;&amp;nbsp; unaryAxioms&amp;nbsp; :: [Axiom (a -&amp;gt; Bool)]&lt;br&gt;&amp;nbsp; unaryAxioms = []&lt;br&gt;&amp;nbsp; &lt;br&gt;&amp;nbsp; binaryAxioms :: [Axiom ((a,a) -&amp;gt; Bool)]&lt;br&gt;&amp;nbsp; binaryAxioms = []&lt;br&gt;&amp;nbsp; &lt;br&gt;&amp;nbsp; ternaryAxioms :: [Axiom ((a,a,a) -&amp;gt; Bool)]&lt;br&gt;&lt;br /&gt;&amp;nbsp; ternaryAxioms = []&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;For&amp;nbsp;properties involving relations between two or many classes, a similar&amp;nbsp;multiparameter type class is also possible (see code below).&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;If&amp;nbsp;I need to define axioms/properties for the the methods of a&lt;br /&gt;class, I just make the class a instance of Axioms:. For example, for a&lt;br /&gt;Ring:&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;pre&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="conid"&gt;Eq&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="keyglyph"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="conid"&gt;Ring&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;  &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;op1&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;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;op2&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;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;zero&lt;/span&gt; &lt;span class="keyglyph"&gt;::&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;inverse&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;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;You see that the kind of both op1 and op2 say very little about the structure of the ring.&amp;nbsp; Anyone can instantiate a Num class without respecting the nature of * and + operations.&lt;br&gt;&lt;b&gt;&amp;nbsp;What gives a Class the meaning and structure of the Class for which he was designed are the axioms.&lt;/b&gt;&lt;br&gt;&lt;br&gt; &lt;br /&gt;&lt;div&gt;&lt;i&gt;I want to express that whenever a Ring a is defined,&amp;nbsp;it&lt;br /&gt;must&amp;nbsp;agree with&amp;nbsp;some Axioms. I think that this way of defining&lt;br /&gt;properties&amp;nbsp; is fairly meaningful to say in haskell:&lt;br&gt;&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br&gt;&lt;br&gt;&lt;pre&gt;&lt;span class="keyword"&gt;instance&lt;/span&gt;  &lt;span class="conid"&gt;Ring&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="keyglyph"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="conid"&gt;Axioms&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;unaryAxioms&lt;/span&gt;   &lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="keyglyph"&gt;[&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="str"&gt;"identity"&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="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;zero&lt;/span&gt; &lt;span class="varop"&gt;`op2`&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;==&lt;/span&gt; &lt;span class="varid"&gt;zero&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;                  &lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="str"&gt;"inverse element"&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="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;`op1`&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;inverse&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="varop"&gt;==&lt;/span&gt; &lt;span class="varid"&gt;zero&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;                  &lt;span class="keyglyph"&gt;]&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class="varid"&gt;binaryAxioms&lt;/span&gt;  &lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="keyglyph"&gt;[&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="str"&gt;"commutative"&lt;/span&gt;   &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="keyglyph"&gt;\&lt;/span&gt;&lt;span class="layout"&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="layout"&gt;)&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;`op1`&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt; &lt;span class="varop"&gt;==&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt; &lt;span class="varop"&gt;`op1`&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;]&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class="varid"&gt;ternaryAxioms&lt;/span&gt; &lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="keyglyph"&gt;[&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="str"&gt;"associative `op1`"&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="keyglyph"&gt;\&lt;/span&gt;&lt;span class="layout"&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="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;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;`op1`&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;`op1`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="varop"&gt;==&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;`op1`&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;y&lt;/span&gt; &lt;span class="varop"&gt;`op1`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;                  &lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="str"&gt;"associative `op2`"&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="keyglyph"&gt;\&lt;/span&gt;&lt;span class="layout"&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="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;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;`op2`&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;`op2`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="varop"&gt;==&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;`op2`&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;y&lt;/span&gt; &lt;span class="varop"&gt;`op2`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;                  &lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="str"&gt;"distributive"&lt;/span&gt;  &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="keyglyph"&gt;\&lt;/span&gt;&lt;span class="layout"&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="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;`op2`&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;y&lt;/span&gt; &lt;span class="varop"&gt;`op1`&lt;/span&gt; &lt;span class="varid"&gt;z&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="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;`op2`&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;`op1`&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;`op2`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;                  &lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="str"&gt;"distributive2"&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="keyglyph"&gt;\&lt;/span&gt;&lt;span class="layout"&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="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;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;`op1`&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;`op2`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="varop"&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;`op2`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="varop"&gt;`op1`&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;y&lt;/span&gt; &lt;span class="varop"&gt;`op2`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;                  &lt;span class="keyglyph"&gt;]&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;/pre&gt;&lt;div&gt;What practical use can I extract from this stuff?&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Lets define any object of the class Num as a Ring&amp;nbsp; &lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;pre&gt;&lt;span class="keyword"&gt;instance&lt;/span&gt;  &lt;span class="conid"&gt;Num&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;  &lt;span class="keyglyph"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="conid"&gt;Ring&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;op1&lt;/span&gt;&lt;span class="keyglyph"&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;br&gt;  &lt;span class="varid"&gt;op2&lt;/span&gt;&lt;span class="keyglyph"&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;br&gt;  &lt;span class="varid"&gt;zero&lt;/span&gt; &lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="num"&gt;0&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;inverse&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="varid"&gt;negate&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;br&gt;Now we will see te return of all of this stuff. We have Num, We have the operators of Num and we have the &lt;b&gt;meaning, the semantic that glue all pieces togeter&amp;nbsp;&lt;/b&gt; captured in the Ring axioms. Now, in a Galaxy far away, someone define a new data type as member of the class Num.&amp;nbsp; Because Num is a Ring , It can&amp;nbsp; test the compliance with the axioms of this new Ring candidate:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;pre&gt;&lt;span class="keyword"&gt;instance&lt;/span&gt; &lt;span class="conid"&gt;Num&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br&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;N&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&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;+&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;`verify`&lt;/span&gt;  &lt;span class="varid"&gt;binaryAxioms&lt;/span&gt; &lt;span class="varop"&gt;`with`&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&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;N&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;br&gt;  &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="comment"&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;N&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="comment"&gt;-&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&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;N&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&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;*&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;negate&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="comment"&gt;-&lt;/span&gt;&lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;abs&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;abs&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;signum&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;signum&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;fromInteger&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;N&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;fromInteger&lt;/span&gt; &lt;span class="varid"&gt;i&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span class="varid"&gt;main&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class="keyword"&gt;let&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="num"&gt;5&lt;/span&gt;&lt;br&gt;  &lt;span class="keyword"&gt;let&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="num"&gt;3&lt;/span&gt;           &lt;span class="varop"&gt;`verify`&lt;/span&gt;  &lt;span class="varid"&gt;unaryAxioms&lt;/span&gt; &lt;span class="varop"&gt;`with`&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;br&gt;  &lt;span class="keyword"&gt;let&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;+&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;print&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;br&gt;  &lt;span class="keyword"&gt;let&lt;/span&gt; &lt;span class="varid"&gt;t&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="num"&gt;7&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;print&lt;/span&gt; &lt;span class="varid"&gt;t&lt;/span&gt;              &lt;span class="varop"&gt;`verify`&lt;/span&gt;  &lt;span class="varid"&gt;ternaryAxioms&lt;/span&gt; &lt;span class="varop"&gt;`with`&lt;/span&gt; &lt;span class="layout"&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="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Here I show&amp;nbsp; two different ways to test axioms/ properties: Either in the instance definition or in the middle of the code&amp;nbsp;&amp;nbsp; &lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;With "verify&amp;nbsp; axiom&amp;nbsp;data"&amp;nbsp;&amp;nbsp;&amp;nbsp;inserted&amp;nbsp;in strategic&amp;nbsp;parts of the&lt;br /&gt;code i have a cheap quickcheck&amp;nbsp;with the advantage that I can test the&lt;br /&gt;real data of my aplication. you can play with the class definitions and see the violated axioms.&lt;br&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Note that with the Ring properties I can define&amp;nbsp; subtractions in a counterintuitive way, since the ring properties say nothing practical&lt;br /&gt;about substraction.&amp;nbsp; Here we can see the difference between axiom and&lt;br /&gt;the more practical concept of&amp;nbsp;"property". although both can have the&lt;br /&gt;same shape.&amp;nbsp;&amp;nbsp; &lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Note that for this ring is fairly straighforward to realize that&lt;br /&gt;it is a ring since it is a small modification of Number.&amp;nbsp; This would be&lt;br /&gt;not so obvous for more complicated datatypes, maybe this is a way to add confidence for&lt;br /&gt;managing complicated pieces of code with unsafe IO operations and other beasts&amp;nbsp; as Rings or other mathematical structures!.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;This can be applied of course for anything you may think that may have a property to check.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;I´m excited!&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br&gt;&lt;b&gt;&lt;i&gt;NOTE : I had to eliminate the separate Axioms class and put the properties directly inside the class definitions due to some limitations. that makes thigs a little less flexible. Here is the code:&lt;/i&gt;&lt;/b&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;The complete code:&lt;br&gt;&lt;/div&gt;&lt;pre&gt;&lt;br&gt;&lt;span class="conid"&gt;Copyright&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;c&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="conid"&gt;Alberto&lt;/span&gt; &lt;span class="conid"&gt;Gómez&lt;/span&gt; &lt;span class="conid"&gt;Corona&lt;/span&gt; &lt;span class="num"&gt;2008&lt;/span&gt; &lt;span class="varid"&gt;agocorona&lt;/span&gt;&lt;span class="keyglyph"&gt;@&lt;/span&gt;&lt;span class="varid"&gt;gmail&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt;&lt;span class="varid"&gt;com&lt;/span&gt;&lt;br&gt;&lt;span class="varid"&gt;see&lt;/span&gt; &lt;span class="varid"&gt;http&lt;/span&gt;&lt;span class="conop"&gt;://&lt;/span&gt;&lt;span class="varid"&gt;docs&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt;&lt;span class="varid"&gt;google&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt;&lt;span class="varid"&gt;com&lt;/span&gt;&lt;span class="varop"&gt;/&lt;/span&gt;&lt;span class="conid"&gt;Doc&lt;/span&gt;&lt;span class="varop"&gt;?&lt;/span&gt;&lt;span class="varid"&gt;id&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt;&lt;span class="varid"&gt;dd5rm7qq_165rshp74gf&lt;/span&gt;&lt;span class="varop"&gt;&amp;amp;&lt;/span&gt;&lt;span class="varid"&gt;hl&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt;&lt;span class="varid"&gt;en&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="varid"&gt;version&lt;/span&gt; &lt;span class="num"&gt;2.0&lt;/span&gt;&lt;br&gt;&lt;span class="varid"&gt;corrected&lt;/span&gt; &lt;span class="varid"&gt;some&lt;/span&gt; &lt;span class="varid"&gt;instantiation&lt;/span&gt; &lt;span class="varid"&gt;problems&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="conid"&gt;All&lt;/span&gt; &lt;span class="varid"&gt;rights&lt;/span&gt; &lt;span class="varid"&gt;reserved&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="conid"&gt;Redistribution&lt;/span&gt; &lt;span class="varid"&gt;and&lt;/span&gt; &lt;span class="varid"&gt;use&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="varid"&gt;source&lt;/span&gt; &lt;span class="varid"&gt;and&lt;/span&gt; &lt;span class="varid"&gt;binary&lt;/span&gt; &lt;span class="varid"&gt;forms&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="varid"&gt;with&lt;/span&gt; &lt;span class="varid"&gt;or&lt;/span&gt; &lt;span class="varid"&gt;without&lt;/span&gt;&lt;br&gt;&lt;span class="varid"&gt;modification&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="varid"&gt;are&lt;/span&gt; &lt;span class="varid"&gt;permitted&lt;/span&gt; &lt;span class="varid"&gt;provided&lt;/span&gt; &lt;span class="varid"&gt;that&lt;/span&gt; &lt;span class="varid"&gt;the&lt;/span&gt; &lt;span class="varid"&gt;following&lt;/span&gt; &lt;span class="varid"&gt;conditions&lt;/span&gt;&lt;br&gt;&lt;span class="varid"&gt;are&lt;/span&gt; &lt;span class="varid"&gt;met&lt;/span&gt;&lt;span class="conop"&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class="num"&gt;1&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt; &lt;span class="conid"&gt;Redistributions&lt;/span&gt; &lt;span class="keyword"&gt;of&lt;/span&gt; &lt;span class="varid"&gt;source&lt;/span&gt; &lt;span class="varid"&gt;code&lt;/span&gt; &lt;span class="varid"&gt;must&lt;/span&gt; &lt;span class="varid"&gt;retain&lt;/span&gt; &lt;span class="varid"&gt;the&lt;/span&gt; &lt;span class="varid"&gt;above&lt;/span&gt; &lt;span class="varid"&gt;copyright&lt;/span&gt;&lt;br&gt;   &lt;span class="varid"&gt;notice&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="varid"&gt;this&lt;/span&gt; &lt;span class="varid"&gt;list&lt;/span&gt; &lt;span class="keyword"&gt;of&lt;/span&gt; &lt;span class="varid"&gt;conditions&lt;/span&gt; &lt;span class="varid"&gt;and&lt;/span&gt; &lt;span class="varid"&gt;the&lt;/span&gt; &lt;span class="varid"&gt;following&lt;/span&gt; &lt;span class="varid"&gt;disclaimer&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt;&lt;br&gt;&lt;span class="num"&gt;2&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt; &lt;span class="conid"&gt;Redistributions&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="varid"&gt;binary&lt;/span&gt; &lt;span class="varid"&gt;form&lt;/span&gt; &lt;span class="varid"&gt;must&lt;/span&gt; &lt;span class="varid"&gt;reproduce&lt;/span&gt; &lt;span class="varid"&gt;the&lt;/span&gt; &lt;span class="varid"&gt;above&lt;/span&gt; &lt;span class="varid"&gt;copyright&lt;/span&gt;&lt;br&gt;   &lt;span class="varid"&gt;notice&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="varid"&gt;this&lt;/span&gt; &lt;span class="varid"&gt;list&lt;/span&gt; &lt;span class="keyword"&gt;of&lt;/span&gt; &lt;span class="varid"&gt;conditions&lt;/span&gt; &lt;span class="varid"&gt;and&lt;/span&gt; &lt;span class="varid"&gt;the&lt;/span&gt; &lt;span class="varid"&gt;following&lt;/span&gt; &lt;span class="varid"&gt;disclaimer&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="varid"&gt;the&lt;/span&gt;&lt;br&gt;   &lt;span class="varid"&gt;documentation&lt;/span&gt; &lt;span class="varid"&gt;and&lt;/span&gt;&lt;span class="varop"&gt;/&lt;/span&gt;&lt;span class="varid"&gt;or&lt;/span&gt; &lt;span class="varid"&gt;other&lt;/span&gt; &lt;span class="varid"&gt;materials&lt;/span&gt; &lt;span class="varid"&gt;provided&lt;/span&gt; &lt;span class="varid"&gt;with&lt;/span&gt; &lt;span class="varid"&gt;the&lt;/span&gt; &lt;span class="varid"&gt;distribution&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt;&lt;br&gt;&lt;span class="num"&gt;3&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt; &lt;span class="conid"&gt;Neither&lt;/span&gt; &lt;span class="varid"&gt;the&lt;/span&gt; &lt;span class="varid"&gt;name&lt;/span&gt; &lt;span class="keyword"&gt;of&lt;/span&gt; &lt;span class="varid"&gt;the&lt;/span&gt; &lt;span class="varid"&gt;author&lt;/span&gt; &lt;span class="varid"&gt;nor&lt;/span&gt; &lt;span class="varid"&gt;the&lt;/span&gt; &lt;span class="varid"&gt;names&lt;/span&gt; &lt;span class="keyword"&gt;of&lt;/span&gt; &lt;span class="varid"&gt;his&lt;/span&gt; &lt;span class="varid"&gt;contributors&lt;/span&gt;&lt;br&gt;   &lt;span class="varid"&gt;may&lt;/span&gt; &lt;span class="varid"&gt;be&lt;/span&gt; &lt;span class="varid"&gt;used&lt;/span&gt; &lt;span class="varid"&gt;to&lt;/span&gt; &lt;span class="varid"&gt;endorse&lt;/span&gt; &lt;span class="varid"&gt;or&lt;/span&gt; &lt;span class="varid"&gt;promote&lt;/span&gt; &lt;span class="varid"&gt;products&lt;/span&gt; &lt;span class="varid"&gt;derived&lt;/span&gt; &lt;span class="varid"&gt;from&lt;/span&gt; &lt;span class="varid"&gt;this&lt;/span&gt; &lt;span class="varid"&gt;software&lt;/span&gt;&lt;br&gt;   &lt;span class="varid"&gt;without&lt;/span&gt; &lt;span class="varid"&gt;specific&lt;/span&gt; &lt;span class="varid"&gt;prior&lt;/span&gt; &lt;span class="varid"&gt;written&lt;/span&gt; &lt;span class="varid"&gt;permission&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="conid"&gt;THIS&lt;/span&gt; &lt;span class="conid"&gt;SOFTWARE&lt;/span&gt; &lt;span class="conid"&gt;IS&lt;/span&gt; &lt;span class="conid"&gt;PROVIDED&lt;/span&gt; &lt;span class="conid"&gt;BY&lt;/span&gt; &lt;span class="conid"&gt;THE&lt;/span&gt; &lt;span class="conid"&gt;REGENTS&lt;/span&gt; &lt;span class="conid"&gt;AND&lt;/span&gt; &lt;span class="conid"&gt;CONTRIBUTORS&lt;/span&gt; &lt;span class="varop"&gt;`&lt;/span&gt;&lt;span class="varop"&gt;`&lt;/span&gt;&lt;span class="conid"&gt;AS&lt;/span&gt; &lt;span class="conid"&gt;IS''&lt;/span&gt; &lt;span class="conid"&gt;AND&lt;/span&gt;&lt;br&gt;&lt;span class="conid"&gt;ANY&lt;/span&gt; &lt;span class="conid"&gt;EXPRESS&lt;/span&gt; &lt;span class="conid"&gt;OR&lt;/span&gt; &lt;span class="conid"&gt;IMPLIED&lt;/span&gt; &lt;span class="conid"&gt;WARRANTIES&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;INCLUDING&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;BUT&lt;/span&gt; &lt;span class="conid"&gt;NOT&lt;/span&gt; &lt;span class="conid"&gt;LIMITED&lt;/span&gt; &lt;span class="conid"&gt;TO&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;THE&lt;/span&gt;&lt;br&gt;&lt;span class="conid"&gt;IMPLIED&lt;/span&gt; &lt;span class="conid"&gt;WARRANTIES&lt;/span&gt; &lt;span class="conid"&gt;OF&lt;/span&gt; &lt;span class="conid"&gt;MERCHANTABILITY&lt;/span&gt; &lt;span class="conid"&gt;AND&lt;/span&gt; &lt;span class="conid"&gt;FITNESS&lt;/span&gt; &lt;span class="conid"&gt;FOR&lt;/span&gt; &lt;span class="conid"&gt;A&lt;/span&gt; &lt;span class="conid"&gt;PARTICULAR&lt;/span&gt; &lt;span class="conid"&gt;PURPOSE&lt;/span&gt;&lt;br&gt;&lt;span class="conid"&gt;ARE&lt;/span&gt; &lt;span class="conid"&gt;DISCLAIMED&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt;  &lt;span class="conid"&gt;IN&lt;/span&gt; &lt;span class="conid"&gt;NO&lt;/span&gt; &lt;span class="conid"&gt;EVENT&lt;/span&gt; &lt;span class="conid"&gt;SHALL&lt;/span&gt; &lt;span class="conid"&gt;THE&lt;/span&gt; &lt;span class="conid"&gt;AUTHORS&lt;/span&gt; &lt;span class="conid"&gt;OR&lt;/span&gt; &lt;span class="conid"&gt;CONTRIBUTORS&lt;/span&gt; &lt;span class="conid"&gt;BE&lt;/span&gt; &lt;span class="conid"&gt;LIABLE&lt;/span&gt;&lt;br&gt;&lt;span class="conid"&gt;FOR&lt;/span&gt; &lt;span class="conid"&gt;ANY&lt;/span&gt; &lt;span class="conid"&gt;DIRECT&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;INDIRECT&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;INCIDENTAL&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;SPECIAL&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;EXEMPLARY&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;OR&lt;/span&gt; &lt;span class="conid"&gt;CONSEQUENTIAL&lt;/span&gt;&lt;br&gt;&lt;span class="conid"&gt;DAMAGES&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;INCLUDING&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;BUT&lt;/span&gt; &lt;span class="conid"&gt;NOT&lt;/span&gt; &lt;span class="conid"&gt;LIMITED&lt;/span&gt; &lt;span class="conid"&gt;TO&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;PROCUREMENT&lt;/span&gt; &lt;span class="conid"&gt;OF&lt;/span&gt; &lt;span class="conid"&gt;SUBSTITUTE&lt;/span&gt; &lt;span class="conid"&gt;GOODS&lt;/span&gt;&lt;br&gt;&lt;span class="conid"&gt;OR&lt;/span&gt; &lt;span class="conid"&gt;SERVICES&lt;/span&gt;&lt;span class="layout"&gt;;&lt;/span&gt; &lt;span class="conid"&gt;LOSS&lt;/span&gt; &lt;span class="conid"&gt;OF&lt;/span&gt; &lt;span class="conid"&gt;USE&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;DATA&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;OR&lt;/span&gt; &lt;span class="conid"&gt;PROFITS&lt;/span&gt;&lt;span class="layout"&gt;;&lt;/span&gt; &lt;span class="conid"&gt;OR&lt;/span&gt; &lt;span class="conid"&gt;BUSINESS&lt;/span&gt; &lt;span class="conid"&gt;INTERRUPTION&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class="conid"&gt;HOWEVER&lt;/span&gt; &lt;span class="conid"&gt;CAUSED&lt;/span&gt; &lt;span class="conid"&gt;AND&lt;/span&gt; &lt;span class="conid"&gt;ON&lt;/span&gt; &lt;span class="conid"&gt;ANY&lt;/span&gt; &lt;span class="conid"&gt;THEORY&lt;/span&gt; &lt;span class="conid"&gt;OF&lt;/span&gt; &lt;span class="conid"&gt;LIABILITY&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;WHETHER&lt;/span&gt; &lt;span class="conid"&gt;IN&lt;/span&gt; &lt;span class="conid"&gt;CONTRACT&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;STRICT&lt;/span&gt;&lt;br&gt;&lt;span class="conid"&gt;LIABILITY&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;OR&lt;/span&gt; &lt;span class="conid"&gt;TORT&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;INCLUDING&lt;/span&gt; &lt;span class="conid"&gt;NEGLIGENCE&lt;/span&gt; &lt;span class="conid"&gt;OR&lt;/span&gt; &lt;span class="conid"&gt;OTHERWISE&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="conid"&gt;ARISING&lt;/span&gt; &lt;span class="conid"&gt;IN&lt;/span&gt; &lt;span class="conid"&gt;ANY&lt;/span&gt; &lt;span class="conid"&gt;WAY&lt;/span&gt;&lt;br&gt;&lt;span class="conid"&gt;OUT&lt;/span&gt; &lt;span class="conid"&gt;OF&lt;/span&gt; &lt;span class="conid"&gt;THE&lt;/span&gt; &lt;span class="conid"&gt;USE&lt;/span&gt; &lt;span class="conid"&gt;OF&lt;/span&gt; &lt;span class="conid"&gt;THIS&lt;/span&gt; &lt;span class="conid"&gt;SOFTWARE&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;EVEN&lt;/span&gt; &lt;span class="conid"&gt;IF&lt;/span&gt; &lt;span class="conid"&gt;ADVISED&lt;/span&gt; &lt;span class="conid"&gt;OF&lt;/span&gt; &lt;span class="conid"&gt;THE&lt;/span&gt; &lt;span class="conid"&gt;POSSIBILITY&lt;/span&gt; &lt;span class="conid"&gt;OF&lt;/span&gt;&lt;br&gt;&lt;span class="conid"&gt;SUCH&lt;/span&gt; &lt;span class="conid"&gt;DAMAGE&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="comment"&gt;{-# OPTIONS -fglasgow-exts  -fallow-undecidable-instances  #-}&lt;/span&gt;&lt;br&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; &lt;span class="conid"&gt;Debug&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt;&lt;span class="conid"&gt;Trace&lt;/span&gt;&lt;br&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;Concurrent&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt;&lt;span class="conid"&gt;MVar&lt;/span&gt;&lt;br&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; &lt;span class="conid"&gt;System&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt;&lt;span class="conid"&gt;IO&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt;&lt;span class="conid"&gt;Unsafe&lt;/span&gt;&lt;br&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;Exception&lt;/span&gt;&lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;evaluate&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&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;Maybe&lt;/span&gt;&lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;catMaybes&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&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="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;when&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; &lt;span class="conid"&gt;Debug&lt;/span&gt;&lt;span class="varop"&gt;.&lt;/span&gt;&lt;span class="conid"&gt;Trace&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="varid"&gt;debug&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="varid"&gt;b&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="varid"&gt;trace&lt;/span&gt; &lt;span class="varid"&gt;b&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;&lt;br&gt;&lt;span class="keyword"&gt;data&lt;/span&gt; &lt;span class="conid"&gt;Axiom&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;Axiom&lt;/span&gt; &lt;span class="conid"&gt;String&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span class="keyword"&gt;data&lt;/span&gt; &lt;span class="conid"&gt;Axioms&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;br&gt; &lt;span class="conid"&gt;Axioms&lt;/span&gt;&lt;span class="layout"&gt;{&lt;/span&gt;&lt;span class="varid"&gt;unary&lt;/span&gt;   &lt;span class="keyglyph"&gt;::&lt;/span&gt; &lt;span class="keyglyph"&gt;[&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="conid"&gt;Bool&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;]&lt;/span&gt;&lt;br&gt;       &lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;binary&lt;/span&gt;  &lt;span class="keyglyph"&gt;::&lt;/span&gt; &lt;span class="keyglyph"&gt;[&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;a&lt;/span&gt;&lt;span class="layout"&gt;,&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="conid"&gt;Bool&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;]&lt;/span&gt;&lt;br&gt;       &lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;ternary&lt;/span&gt; &lt;span class="keyglyph"&gt;::&lt;/span&gt; &lt;span class="keyglyph"&gt;[&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;a&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;a&lt;/span&gt;&lt;span class="layout"&gt;,&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="conid"&gt;Bool&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;]&lt;/span&gt;&lt;br&gt;&lt;br&gt; &lt;span class="layout"&gt;}&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="varid"&gt;axioms&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;Axioms&lt;/span&gt; &lt;span class="conid"&gt;[]&lt;/span&gt; &lt;span class="conid"&gt;[]&lt;/span&gt; &lt;span class="conid"&gt;[]&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="keyword"&gt;type&lt;/span&gt; &lt;span class="conid"&gt;Relations&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="varid"&gt;b&lt;/span&gt; &lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="keyglyph"&gt;[&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;a&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;b&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="conid"&gt;Bool&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;]&lt;/span&gt;&lt;br&gt;  &lt;br&gt;&lt;span class="keyword"&gt;type&lt;/span&gt; &lt;span class="conid"&gt;TermaryRelation&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="varid"&gt;b&lt;/span&gt; &lt;span class="varid"&gt;c&lt;/span&gt; &lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="keyglyph"&gt;[&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;a&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;b&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;c&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="conid"&gt;Bool&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;]&lt;/span&gt; &lt;br&gt;&lt;br&gt;&lt;span class="varid"&gt;inTest&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="varid"&gt;unsafePerformIO&lt;/span&gt; &lt;span class="varop"&gt;$&lt;/span&gt; &lt;span class="varid"&gt;newMVar&lt;/span&gt; &lt;span class="conid"&gt;True&lt;/span&gt;  &lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span class="varid"&gt;with&lt;/span&gt;&lt;span class="keyglyph"&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;br&gt;&lt;br&gt;&lt;br&gt;&lt;span class="varid"&gt;verify&lt;/span&gt; &lt;span class="keyglyph"&gt;::&lt;/span&gt; &lt;span class="conid"&gt;Show&lt;/span&gt; &lt;span class="varid"&gt;b&lt;/span&gt; &lt;span class="keyglyph"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;a&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;Axiom&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;b&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="conid"&gt;Bool&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;]&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;b&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;&lt;br&gt;&lt;span class="varid"&gt;verify&lt;/span&gt; &lt;span class="varid"&gt;res&lt;/span&gt; &lt;span class="varid"&gt;axioms&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;check&lt;/span&gt; &lt;span class="varop"&gt;`seq`&lt;/span&gt;&lt;span class="varid"&gt;res&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br&gt; &lt;span class="varid"&gt;check&lt;/span&gt; &lt;span class="keyglyph"&gt;=&lt;/span&gt;&lt;span class="varid"&gt;unsafePerformIO&lt;/span&gt; &lt;span class="varop"&gt;$&lt;/span&gt;  &lt;br&gt;    &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br&gt;        &lt;span class="varid"&gt;int&lt;/span&gt; &lt;span class="keyglyph"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="varid"&gt;tryTakeMVar&lt;/span&gt; &lt;span class="varid"&gt;inTest&lt;/span&gt;&lt;br&gt;        &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="varid"&gt;int&lt;/span&gt; &lt;span class="varop"&gt;==&lt;/span&gt; &lt;span class="conid"&gt;Nothing&lt;/span&gt; &lt;span class="keyword"&gt;then&lt;/span&gt; &lt;span class="varid"&gt;return&lt;/span&gt; &lt;span class="conid"&gt;()&lt;/span&gt;&lt;br&gt;         &lt;span class="keyword"&gt;else&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br&gt;         &lt;span class="varid"&gt;errors&lt;/span&gt; &lt;span class="keyglyph"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="varid"&gt;evaluate&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;catMaybes&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;test&lt;/span&gt;  &lt;span class="varid"&gt;v&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="varid"&gt;axioms&lt;/span&gt; &lt;br&gt;         &lt;span class="varid"&gt;when&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;not&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;errors&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt; &lt;span class="varid"&gt;putTraceMsg&lt;/span&gt; &lt;span class="varid"&gt;errors&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;br&gt;         &lt;span class="varid"&gt;putMVar&lt;/span&gt; &lt;span class="varid"&gt;inTest&lt;/span&gt; &lt;span class="conid"&gt;False&lt;/span&gt;&lt;br&gt;         &lt;span class="varid"&gt;return&lt;/span&gt; &lt;span class="conid"&gt;()&lt;/span&gt;    &lt;br&gt;   &lt;span class="keyword"&gt;where&lt;/span&gt; &lt;br&gt;   &lt;span class="varid"&gt;test&lt;/span&gt; &lt;span class="varid"&gt;v&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="varid"&gt;n&lt;/span&gt; &lt;span class="varid"&gt;f&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt;  &lt;span class="varid"&gt;f&lt;/span&gt; &lt;span class="varid"&gt;v&lt;/span&gt; &lt;span class="keyword"&gt;then&lt;/span&gt;  &lt;span class="conid"&gt;Nothing&lt;/span&gt;&lt;br&gt;                       &lt;span class="keyword"&gt;else&lt;/span&gt;  &lt;span class="conid"&gt;Just&lt;/span&gt; &lt;span class="varop"&gt;$&lt;/span&gt; &lt;span class="str"&gt;"violated axiom "&lt;/span&gt;&lt;span class="varop"&gt;++&lt;/span&gt;&lt;span class="varid"&gt;n&lt;/span&gt; &lt;span class="varop"&gt;++&lt;/span&gt; &lt;span class="str"&gt;" with value/s: "&lt;/span&gt; &lt;span class="varop"&gt;++&lt;/span&gt; &lt;span class="varid"&gt;show&lt;/span&gt; &lt;span class="varid"&gt;v&lt;/span&gt; &lt;br&gt;    &lt;br&gt;    &lt;br&gt;    &lt;br&gt;&lt;span class="comment"&gt;--------------------------- Example for a Ring  -------    &lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;br&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="conid"&gt;Eq&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="keyglyph"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="conid"&gt;Ring&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;  &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;op1&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;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;op2&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;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;zero&lt;/span&gt; &lt;span class="keyglyph"&gt;::&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;inverse&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;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;&lt;br&gt;  &lt;br&gt;  &lt;span class="varid"&gt;ringAxioms&lt;/span&gt; &lt;span class="keyglyph"&gt;::&lt;/span&gt; &lt;span class="conid"&gt;Axioms&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;ringAxioms&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="varid"&gt;axioms&lt;/span&gt;&lt;span class="layout"&gt;{&lt;/span&gt;&lt;br&gt; &lt;br&gt;     &lt;span class="varid"&gt;unary&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt;   &lt;span class="keyglyph"&gt;[&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="str"&gt;"identity"&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="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;zero&lt;/span&gt; &lt;span class="varop"&gt;`op2`&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;==&lt;/span&gt; &lt;span class="varid"&gt;zero&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;              &lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="str"&gt;"inverse element"&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="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;`op1`&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;inverse&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="varop"&gt;==&lt;/span&gt; &lt;span class="varid"&gt;zero&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;]&lt;/span&gt;&lt;br&gt;                  &lt;br&gt;&lt;br&gt;&lt;br&gt;     &lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;binary&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt;  &lt;span class="keyglyph"&gt;[&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="str"&gt;"commutative"&lt;/span&gt;       &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="keyglyph"&gt;\&lt;/span&gt;&lt;span class="layout"&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="layout"&gt;)&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;`op1`&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt; &lt;span class="varop"&gt;==&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt; &lt;span class="varop"&gt;`op1`&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;]&lt;/span&gt;&lt;br&gt;  &lt;br&gt;&lt;br&gt;&lt;br&gt;     &lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;ternary&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="keyglyph"&gt;[&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="str"&gt;"associative `op1`"&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="keyglyph"&gt;\&lt;/span&gt;&lt;span class="layout"&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="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;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;`op1`&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;`op1`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="varop"&gt;==&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;`op1`&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;y&lt;/span&gt; &lt;span class="varop"&gt;`op1`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;              &lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="str"&gt;"associative `op2`"&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="keyglyph"&gt;\&lt;/span&gt;&lt;span class="layout"&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="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;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;`op2`&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;`op2`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="varop"&gt;==&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;`op2`&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;y&lt;/span&gt; &lt;span class="varop"&gt;`op2`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;              &lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="str"&gt;"distributive"&lt;/span&gt;      &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="keyglyph"&gt;\&lt;/span&gt;&lt;span class="layout"&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="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;`op2`&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;y&lt;/span&gt; &lt;span class="varop"&gt;`op1`&lt;/span&gt; &lt;span class="varid"&gt;z&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="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;`op2`&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;`op1`&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;`op2`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;              &lt;span class="layout"&gt;,&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="str"&gt;"distributive2"&lt;/span&gt;     &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="keyglyph"&gt;\&lt;/span&gt;&lt;span class="layout"&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="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;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;`op1`&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;`op2`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="varop"&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;`op2`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="varop"&gt;`op1`&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;y&lt;/span&gt; &lt;span class="varop"&gt;`op2`&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;              &lt;span class="keyglyph"&gt;]&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class="layout"&gt;}&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="comment"&gt;----------------Define a simple Ring set --------------&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="keyword"&gt;instance&lt;/span&gt;  &lt;span class="conid"&gt;Num&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;  &lt;span class="keyglyph"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="conid"&gt;Ring&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;op1&lt;/span&gt;&lt;span class="keyglyph"&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;br&gt;  &lt;span class="varid"&gt;op2&lt;/span&gt;&lt;span class="keyglyph"&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;br&gt;  &lt;span class="varid"&gt;zero&lt;/span&gt; &lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="num"&gt;0&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;inverse&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="varid"&gt;negate&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span class="keyword"&gt;data&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="conid"&gt;Int&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;Eq&lt;/span&gt;&lt;span class="layout"&gt;,&lt;/span&gt; &lt;span class="conid"&gt;Show&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span class="keyword"&gt;instance&lt;/span&gt; &lt;span class="conid"&gt;Show&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="keyglyph"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="conid"&gt;Num&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br&gt;&lt;br&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;N&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&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;+&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;`verify`&lt;/span&gt;  &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;binary&lt;/span&gt; &lt;span class="varid"&gt;ringAxioms&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="varop"&gt;`with`&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&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;N&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;br&gt;&lt;br&gt;  &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="comment"&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;N&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="comment"&gt;-&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&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;N&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&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;*&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;negate&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="comment"&gt;-&lt;/span&gt;&lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;abs&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;abs&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;signum&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;signum&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;fromInteger&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;N&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;fromInteger&lt;/span&gt; &lt;span class="varid"&gt;i&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;Eq&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="conid"&gt;String1&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br&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="keyglyph"&gt;::&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt; &lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;len&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;-&amp;gt;&lt;/span&gt; &lt;span class="conid"&gt;Int&lt;/span&gt;&lt;br&gt;  &lt;br&gt;  &lt;span class="varid"&gt;stringAxioms&lt;/span&gt; &lt;span class="keyglyph"&gt;::&lt;/span&gt; &lt;span class="conid"&gt;Axioms&lt;/span&gt; &lt;span class="varid"&gt;a&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;stringAxioms&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;br&gt;    &lt;span class="varid"&gt;axioms&lt;/span&gt; &lt;span class="layout"&gt;{&lt;/span&gt;&lt;span class="varid"&gt;binary&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt;&lt;span class="keyglyph"&gt;[&lt;/span&gt;&lt;span class="conid"&gt;Axiom&lt;/span&gt; &lt;span class="str"&gt;"length"&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="keyglyph"&gt;\&lt;/span&gt;&lt;span class="layout"&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="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;len&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;+++&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="varop"&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;len&lt;/span&gt; &lt;span class="varid"&gt;x&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="varid"&gt;len&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="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;]&lt;/span&gt;&lt;span class="layout"&gt;}&lt;/span&gt;&lt;br&gt;  &lt;br&gt;&lt;span class="keyword"&gt;data&lt;/span&gt; &lt;span class="conid"&gt;A&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;A&lt;/span&gt; &lt;span class="conid"&gt;String&lt;/span&gt; &lt;span class="keyword"&gt;deriving&lt;/span&gt; &lt;span class="conid"&gt;Eq&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span class="keyword"&gt;instance&lt;/span&gt; &lt;span class="conid"&gt;String1&lt;/span&gt; &lt;span class="conid"&gt;A&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br&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;A&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;A&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;A&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;++&lt;/span&gt;&lt;span class="varid"&gt;y&lt;/span&gt;&lt;span class="varop"&gt;++&lt;/span&gt;&lt;span class="str"&gt;"hola"&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;len&lt;/span&gt; &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="conid"&gt;A&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="varid"&gt;length&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;br&gt;&lt;br&gt;&lt;span class="varid"&gt;main&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;  &lt;span class="keyword"&gt;let&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="num"&gt;5&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class="keyword"&gt;let&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="num"&gt;3&lt;/span&gt;                                &lt;span class="varop"&gt;`verify`&lt;/span&gt;  &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;unary&lt;/span&gt; &lt;span class="varid"&gt;ringAxioms&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="varop"&gt;`with`&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class="keyword"&gt;let&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt; &lt;span class="varop"&gt;+&lt;/span&gt; &lt;span class="varid"&gt;y&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class="varid"&gt;print&lt;/span&gt; &lt;span class="varid"&gt;z&lt;/span&gt;&lt;br&gt;  &lt;span class="keyword"&gt;let&lt;/span&gt; &lt;span class="varid"&gt;t&lt;/span&gt;&lt;span class="keyglyph"&gt;=&lt;/span&gt; &lt;span class="conid"&gt;N&lt;/span&gt; &lt;span class="num"&gt;7&lt;/span&gt;&lt;br&gt;  &lt;span class="varid"&gt;print&lt;/span&gt; &lt;span class="varid"&gt;t&lt;/span&gt;                                   &lt;span class="varop"&gt;`verify`&lt;/span&gt;  &lt;span class="layout"&gt;(&lt;/span&gt;&lt;span class="varid"&gt;ternary&lt;/span&gt; &lt;span class="varid"&gt;ringAxioms&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt; &lt;span class="varop"&gt;`with`&lt;/span&gt; &lt;span class="layout"&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="layout"&gt;,&lt;/span&gt;&lt;span class="varid"&gt;z&lt;/span&gt;&lt;span class="layout"&gt;)&lt;/span&gt;&lt;br&gt;  &lt;span class="keyword"&gt;let&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;span class="varid"&gt;print&lt;/span&gt; &lt;span class="varid"&gt;x&lt;/span&gt;&lt;br&gt;&lt;br&gt;  &lt;br&gt;&lt;br&gt;  &lt;br&gt;&lt;br&gt;  &lt;br&gt;&lt;br&gt;  &lt;br&gt;&lt;br&gt;  &lt;br&gt;&lt;/pre&gt;&lt;div class="pasteforms"&gt;&lt;form action="/11427" method="get"&gt;&lt;fieldset class="left"&gt;&lt;label for="lines"&gt;number lines:&lt;/label&gt;format&lt;/fieldset&gt;&lt;/form&gt;&lt;div class="clear"&gt;&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37577615-3251503680293372723?l=haskell-web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://haskell-web.blogspot.com/feeds/3251503680293372723/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37577615&amp;postID=3251503680293372723' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/3251503680293372723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/3251503680293372723'/><link rel='alternate' type='text/html' href='http://haskell-web.blogspot.com/2008/10/axioms-properties-for-haskell-classes.html' title='axioms-properties for haskell classes'/><author><name>Alberto</name><uri>http://www.blogger.com/profile/11962281728014883353</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37577615.post-8241735978829005058</id><published>2007-11-17T22:26:00.001+01:00</published><updated>2009-01-09T20:57:28.718+01:00</updated><title type='text'>New version of the Transactiona Cache (not tested)</title><content type='html'>NOTE: last version download at: &lt;a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/TCache"&gt;http://hackage.haskell.org/cgi-bin/hackage-scripts/package/TCache&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I created a new version of the Transactional Cache&amp;nbsp; &lt;a title="Transactional Cache" href="http://haskell-web.blogspot.com/2006/11/transactional-cache-for-haskell.html" id="gjtx"&gt;See the original post&lt;/a&gt;&amp;nbsp; where I describe the idea. (&lt;a title="download" href="http://www.box.net/shared/dkvap78d4d" id="zf3c"&gt;download this version&lt;/a&gt; ). Some interesting additions are: &lt;br&gt;&lt;ul&gt;&lt;li&gt;Default persistence in files (both strict file reads and fail safe reads/writes are needed, because reads and writes can collide). &lt;/li&gt;&lt;li&gt;Direct handling of TVars with full atomic semantic without loosing transparent persistence (getTVars)&lt;br&gt;&lt;/li&gt;&lt;li&gt;No repeated hashtable lookups in case of atomic rollbacks&lt;/li&gt;&lt;li&gt;insertResources&lt;/li&gt;&lt;li&gt;readFileStrict - to be used for instantiate custom persistence in files.&lt;br&gt;&lt;/li&gt;&lt;li&gt;Not only addings but also deletes of objects within single atomic operations. (withResourcesID)&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;Also, a minimal description of existing primitives has been added.&lt;br&gt;&lt;br&gt;This is the header:&lt;br&gt;&lt;tt&gt;&lt;/tt&gt;&lt;br&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;table class="paste-area" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td colspan="2" bgcolor="#f4f4f4" width="100%"&gt;&lt;tt&gt;module TCache (&lt;br&gt;&lt;br&gt;IResource(..) &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- class interface to be instantiated by the user&lt;br&gt;,DefaultPersistResource(..) --instance of IResource with default definitions, except defkeyResource&lt;br&gt;,Serializable(..) &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--instances of DefaultPersistResource must be instances of Serializable as well&lt;br&gt;,Operation (Insert,Delete) -- data definition used to communicate object Inserts and Deletes to the cache&lt;br&gt;&lt;br&gt;,Cache &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- :: IORef (Ht a,Int, Integer) &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--The cache definition&lt;br&gt;&lt;br&gt;,withResourcesID &amp;nbsp;-- :: (IResource a)=&amp;gt; [a]-&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--list of resources to be extracted for the user function&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- &amp;nbsp;&amp;nbsp;&amp;nbsp;([Maybe a]-&amp;gt;[Operation a]) &amp;nbsp;&amp;nbsp;&amp;nbsp;--user function that get the retrieved resources&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- &amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;gt;IO () &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--and return a list of &amp;nbsp;objects to be inserted/modified or deleted&lt;br&gt;&lt;br&gt;,withResources &amp;nbsp;&amp;nbsp;-- :: (IResource a)=&amp;gt; [a] &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--list of resources to be retrieve&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- &amp;nbsp;&amp;nbsp;-&amp;gt;([Maybe a]-&amp;gt;[a]) &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;----function that get the retrieved resources&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- &amp;nbsp;&amp;nbsp;-&amp;gt;IO () &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--and return a list of &amp;nbsp;objects to be inserted/modified&lt;br&gt;&lt;br&gt;,withResource &amp;nbsp;&amp;nbsp;&amp;nbsp;-- :: (IResource a)=&amp;gt; a &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--same as withResources , but for one only object&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- &amp;nbsp;&amp;nbsp;-&amp;gt;([Maybe a]-&amp;gt;a) &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- &amp;nbsp;&amp;nbsp;-&amp;gt;IO () &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--&lt;br&gt;&lt;br&gt;,insertResources &amp;nbsp;-- :: (IResource a)=&amp;gt; [a] -&amp;gt;IO () &amp;nbsp;&amp;nbsp;-- create resources in the cache. if there are resources with&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- the same key, they will be updated.&lt;br&gt;&lt;br&gt;-- getMVars give &amp;nbsp;the transactional variables (TVar´s) to be handled directly by the user. This allows &amp;nbsp;the full&lt;br&gt;-- semantics of "atomic" blocks. Because the TVars are referenced also by the hashtable, the resources inside these TVars&lt;br&gt;-- are saved to disk,transparently for the user, on every sync. Also, they are not deleted from the cache until released.&lt;br&gt;-- getMVars put a high value in the access time an modif. time to avoid the swap process to &amp;nbsp;delete from memory&lt;br&gt;-- getMVars is also useful when the same resources are frequently accessed. This avoid frequent hashtable lookups.&lt;br&gt;&lt;br&gt;,getTVars &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- :: (IResource a)=&amp;gt; [a] &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- the list of resources to be retrieved&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- &amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;gt; IO [Maybe (TVar a)] &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- The Transactional variables (See Data.TVar documentation)&lt;br&gt;&lt;br&gt;-- releaseMVars allows the release of the resources taken by takeMVars so that them can be swapped to disk if needed.&lt;br&gt;,releaseTVars &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- :: (IResource a)=&amp;gt; [a]-&amp;gt; IO()&lt;br&gt;&lt;br&gt;,getResources &amp;nbsp;&amp;nbsp;&amp;nbsp;-- :: (IResource a)=&amp;gt;[a] &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--resources [a] are read from cache and returned&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- &amp;nbsp;&amp;nbsp;-&amp;gt; IO [Maybe a] &amp;nbsp;&amp;nbsp;&lt;br&gt;&lt;br&gt;,getResource &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- :: :: (IResource a)=&amp;gt;a &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--to retrieve one object instead of a list&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- &amp;nbsp;&amp;nbsp;-&amp;gt; IO [Maybe a] &amp;nbsp;&amp;nbsp;&lt;br&gt;&lt;br&gt;,deleteResources -- :: (IResource a)=&amp;gt;[a]-&amp;gt; IO() &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- delete the list of resources from cache and from persistent storage&lt;br&gt;,deleteResource &amp;nbsp;-- :: (IResource a)=&amp;gt;a-&amp;gt; IO() &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- delete the &amp;nbsp;resource from cache and from persistent storage&lt;br&gt;--cache handling&lt;br&gt;&lt;br&gt;,refcache &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- :: Cache a &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--the reference to the cache (see data definition below)&lt;br&gt;&lt;br&gt;,syncCache &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- :: (IResource a) =&amp;gt;Cache a -&amp;gt; IO() --force the atomic write of all the cache objects into permanent storage&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--useful for termination&lt;br&gt;&lt;br&gt;--start the thread that clean and writes on the persistent storage trough syncCache&lt;br&gt;,clearSyncCacheProc &amp;nbsp;-- :: (IResource a) =&amp;gt;Cache a &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--The cache reference &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- &amp;nbsp;&amp;nbsp;-&amp;gt; Int &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--number of seconds betwen checks&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- &amp;nbsp;&amp;nbsp;-&amp;gt; (Integer-&amp;gt;Integer-&amp;gt; Bool) &amp;nbsp;&amp;nbsp;--The user-defined check-for-cleanup-from-cache for each object&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--(when True, the object is removed from cache)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- &amp;nbsp;&amp;nbsp;-&amp;gt; Int &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--The max number of objects in the cache, if more, the cleanup start&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- &amp;nbsp;&amp;nbsp;-&amp;gt; &amp;gt;IO ThreadId &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--Identifier of the thread created&lt;br&gt;&lt;br&gt;-- the default check procedure&lt;br&gt;,defaultCheck &amp;nbsp;&amp;nbsp;&amp;nbsp;-- :: Integer &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--last access time for a given object&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- &amp;nbsp;&amp;nbsp;-&amp;gt;Integer &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--last cache syncronization (with the persisten storage)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- &amp;nbsp;&amp;nbsp;-&amp;gt;Bool &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--return true for all the elems not accesed since &amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--half the time between now and the last sync&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;-- auxiliary&lt;br&gt;,readFileStrict &amp;nbsp;-- :: String -&amp;gt; IO String &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- Strict file read, needed for persistence trough files &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/tt&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class="bottom-links"&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37577615-8241735978829005058?l=haskell-web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://haskell-web.blogspot.com/feeds/8241735978829005058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37577615&amp;postID=8241735978829005058' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/8241735978829005058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/8241735978829005058'/><link rel='alternate' type='text/html' href='http://haskell-web.blogspot.com/2007/11/new-version-of-transactiona-cache-not.html' title='New version of the Transactiona Cache (not tested)'/><author><name>Alberto</name><uri>http://www.blogger.com/profile/11962281728014883353</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37577615.post-516194176145972309</id><published>2006-12-13T01:31:00.001+01:00</published><updated>2006-12-13T12:42:05.824+01:00</updated><title type='text'>Some ideas in progress</title><content type='html'>&lt;div style="text-align: justify;"&gt;I´m wondering about how the search engine and the transactional cache can be used together in new ways. The transactional cache has only access by unique index, there is no freedom to access objects by arbitrary expressións with boolean conditions and field values &lt;span style="font-style: italic;"&gt;a la&lt;/span&gt; SQL.&lt;br /&gt;&lt;br /&gt;In the other side, the search engine has no relevance and is not enough flexible for some needs.  Can I inprove the search engine to provide both functionalities?.&lt;br /&gt;&lt;br /&gt;I found that it is possible:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;To improve the relevance of the search engine results&lt;/li&gt;&lt;li&gt;Search queries with arbitrary boolean expressions&lt;/li&gt;&lt;li&gt;Query for haskell objects with certain field values.&lt;/li&gt;&lt;li&gt;To use the query language to retrieve sets of haskell registers and perform atomic operations with these registers.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;a href="http://docs.google.com/View?docid=dd5rm7qq_27gk3vd6"&gt;&lt;br /&gt;                              more&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37577615-516194176145972309?l=haskell-web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://haskell-web.blogspot.com/feeds/516194176145972309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37577615&amp;postID=516194176145972309' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/516194176145972309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/516194176145972309'/><link rel='alternate' type='text/html' href='http://haskell-web.blogspot.com/2006/12/some-ideas-in-progress_13.html' title='Some ideas in progress'/><author><name>Alberto</name><uri>http://www.blogger.com/profile/11962281728014883353</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37577615.post-8458032154384065235</id><published>2006-11-24T03:07:00.002+01:00</published><updated>2006-11-24T13:09:42.623+01:00</updated><title type='text'>A search engine written in Haskell. Part two</title><content type='html'>&lt;p align="justify"&gt;&lt;br /&gt;  I&lt;a href="http://haskell-web.blogspot.com/2006/11/search-engine-written-in-haskell.html" title="in the first post"&gt;n&lt;br /&gt;  the first post&lt;/a&gt;&amp;nbsp; of this Blog&amp;nbsp;, I described what would be the&lt;br /&gt;  core or a search engine. Now it´s time to extend it a little more. Up to now,&lt;br /&gt;  the search return a list of URI strings (unique keys in the case of database&lt;br /&gt;  records, file-names in the case of&amp;nbsp;files on a&amp;nbsp;file-system, URL´s in&lt;br /&gt;  the case of Web pages.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  But it is meaningless to present this list to the user.&amp;nbsp;An excerpt of&lt;br /&gt;  each object, with the paragraphs that contains the keywords searched&lt;br /&gt;  for&amp;nbsp;may be&amp;nbsp;something very valuable. At the end, if I take a little&lt;br /&gt;  more effort and runtime resources to present something with meaning, it is&lt;br /&gt;  probable that the user will not repeat the search many times and browse many&lt;br /&gt;  files.&amp;nbsp; This is something&amp;nbsp;that, no doubt,&amp;nbsp;would be far more&lt;br /&gt;  costly in every aspect.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  &amp;nbsp;So the purpose is to extract an excerpt from the list of URIs returned&lt;br /&gt;  by the core search procedure.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &lt;table class="paste-area" width="100%"&gt;&lt;br /&gt;    &lt;tbody&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td bgcolor="#f4f4f4" colspan="2" width="100%"&gt;&lt;br /&gt;        &lt;p&gt;&lt;br /&gt;          &lt;tt&gt;&lt;span class="function"&gt;showExcerpts&lt;/span&gt;&lt;span class="keyword"&gt;::&lt;/span&gt; &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;span class="variable"&gt;String&lt;/span&gt;&lt;/span&gt;]&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="variable"&gt;String&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;span class="paren2"&gt;(&lt;span class="paste"&gt;&lt;span class="variable"&gt;String,Int&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;]&lt;/span&gt;&lt;br/&gt;&lt;span class="function"&gt;showExcerpts&lt;/span&gt; xs r&lt;span class="keyword"&gt;=&lt;/span&gt; &amp;nbsp;se xs text &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt; 0 &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;where&lt;/span&gt; &lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;text&lt;span class="keyword"&gt;=&lt;/span&gt; show r&lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;se&lt;span class="keyword"&gt;::&lt;/span&gt; &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;span class="variable"&gt;String&lt;/span&gt;&lt;/span&gt;]&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="variable"&gt;String&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="variable"&gt;String&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="variable"&gt;Int&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;span class="paren2"&gt;(&lt;span class="paste"&gt;&lt;span class="variable"&gt;String,Int&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;]&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;span class="paren2"&gt;(&lt;span class="paste"&gt;&lt;span class="variable"&gt;String,Int&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;]&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;se _ &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt; _ _ fr&lt;span class="keyword"&gt;=&lt;/span&gt; fr&lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;se qs t&lt;span class="atom"&gt;@&lt;/span&gt;&lt;span class="paren1"&gt;(&lt;span class="paste"&gt;x&lt;span class="variable"&gt;:&lt;/span&gt;xs&lt;/span&gt;)&lt;/span&gt; f hasKeys fr&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span class="keyword"&gt;|&lt;/span&gt; &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;not&lt;span class="atom"&gt;.&lt;/span&gt;null&lt;/span&gt;)&lt;/span&gt; &lt;span class="atom"&gt;$&lt;/span&gt; filter &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="atom"&gt;==&lt;/span&gt;&lt;span class="variable"&gt;True&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;span class="atom"&gt;$&lt;/span&gt; map &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="paren2"&gt;(&lt;span class="paste"&gt;flip &amp;nbsp;isPrefixOf&lt;/span&gt;)&lt;/span&gt; t&lt;/span&gt;)&lt;/span&gt; qs&lt;span class="keyword"&gt;=&lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;se qs xs &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;append f &amp;nbsp;x&lt;/span&gt;)&lt;/span&gt; &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;hasKeys&lt;span class="atom"&gt;+&lt;/span&gt;1&lt;/span&gt;)&lt;/span&gt; fr &lt;span class="comment"&gt;--some word found&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;|&lt;/span&gt; x &lt;span class="atom"&gt;`elem`&lt;/span&gt; &lt;span class="string"&gt;".,"&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt; &amp;nbsp;&lt;span class="comment"&gt;-- limit of fragment&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;case&lt;/span&gt; hasKeys &lt;span class="keyword"&gt;of&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 &lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt; se qs xs &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt; 0 fr&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;--the previous fragment was &lt;/span&gt;&lt;/tt&gt;&lt;br /&gt;        &lt;/p&gt;&lt;br /&gt;        &lt;p&gt;&lt;br /&gt;          &lt;tt&gt;&lt;span class="comment"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; --void of keys&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _ &lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt; se qs xs &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt; 0 &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="paren2"&gt;(&lt;span class="paste"&gt;f,hasKeys&lt;/span&gt;)&lt;/span&gt;&lt;span class="variable"&gt;:&lt;/span&gt;fr&lt;/span&gt;)&lt;/span&gt; &lt;span class="comment"&gt;--added the old, &lt;/span&gt;&lt;/tt&gt;&lt;br /&gt;        &lt;/p&gt;&lt;br /&gt;        &lt;p&gt;&lt;br /&gt;          &lt;tt&gt;&lt;span class="comment"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--new fragment starts&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span class="keyword"&gt;|&lt;/span&gt; otherwise&lt;span class="keyword"&gt;=&lt;/span&gt; se qs xs &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;append f x&lt;/span&gt;)&lt;/span&gt; hasKeys fr&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;append l c&lt;span class="keyword"&gt;=&lt;/span&gt; l &lt;span class="atom"&gt;++&lt;/span&gt; &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;c&lt;/span&gt;]&lt;/span&gt;&lt;/tt&gt;&lt;br /&gt;        &lt;/p&gt;&lt;br /&gt;      &lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td bgcolor="#f4f4f4" colspan="2" width="100%"&gt;&lt;br /&gt;      &lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td bgcolor="#f4f4f4" colspan="2" width="100%"&gt;&lt;br /&gt;      &lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td bgcolor="#f4f4f4" colspan="2" width="100%"&gt;&lt;br /&gt;      &lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;    &lt;/tbody&gt;&lt;br /&gt;  &lt;/table&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  &lt;em&gt;ShowExcerpts&lt;/em&gt; take a set of keywords, a Show-able something and return&lt;br /&gt;  the&amp;nbsp;paragraphs&amp;nbsp;that contains&amp;nbsp;at least one of the&lt;br /&gt;  keywords&amp;nbsp;and the number of keywords found in each paragraphs.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  for example,&amp;nbsp; In this test I use text from&lt;br /&gt;  &lt;a href="http://www.paulgraham.com/gap.html" title="Paul Graham"&gt;Paul&lt;br /&gt;  Graham&lt;/a&gt; the genius :&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;  &lt;table class="paste-header"&gt;&lt;br /&gt;    &lt;tbody&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td align="left" nowrap="" valign="top"&gt;&lt;br /&gt;      &lt;/td&gt;&lt;br /&gt;      &lt;td width="100%"&gt;&lt;br /&gt;        &amp;nbsp;&lt;br /&gt;      &lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;    &lt;/tbody&gt;&lt;br /&gt;  &lt;/table&gt;&lt;br /&gt;  &lt;table class="paste-area" width="100%"&gt;&lt;br /&gt;    &lt;tbody&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td bgcolor="#f4f4f4" colspan="2" width="100%"&gt;&lt;br /&gt;        &lt;tt&gt;&lt;span class="function"&gt;main&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print &lt;span class="atom"&gt;$&lt;/span&gt; showExcerpts &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;span class="string"&gt;"Daddy"&lt;/span&gt;,&lt;span class="string"&gt;"model"&lt;/span&gt;&lt;/span&gt;]&lt;/span&gt; text&lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;where&lt;/span&gt; text&lt;span class="keyword"&gt;=&lt;/span&gt; &amp;nbsp;&lt;span class="string"&gt;"When people care enough about something to do it well, those who do it best tend to be far better than everyone else. There's a huge gap between Leonardo and second-rate contemporaries like Borgognone. You see the same gap between Raymond Chandler and the average writer of detective novels. A top-ranked professional chess player could play ten thousand games against an ordinary club player without losing once.Like chess or painting or writing novels, making money is a very specialized skill. But for some reason we treat this skill differently. No one complains when a few people surpass all the rest at playing chess or writing novels, but when a few people make more money than the rest, we get editorials saying this is wrong.Why? The pattern of variation seems no different than for any other skill. What causes people to react so strongly when the skill is making money?I think there are three reasons we treat making money as different: the misleading model of wealth we learn as children; the disreputable way in which, till recently, most fortunes were accumulated; and the worry that great variations in income are somehow bad for society. As far as I can tell, the first is mistaken, the second outdated, and the third empirically false. Could it be that, in a modern democracy, variation in income is actually a sign of health?The Daddy Model of WealthBecause kids are unable to create wealth, whatever they have has to be given to them. And when wealth is something you're given, then of course it seems that it should be distributed equally. [2] As in most families it is. The kids see to that. \"Unfair,\" they cry, when one sibling gets more than another.In the real world, you can't keep living off your parents. If you want something, you either have to make it, or do something of equivalent value for someone else, in order to get them to give you enough money to buy it. In the real world, wealth is (except for a few specialists like thieves and speculators) something you have to create, not something that's distributed by Daddy. And since the ability and desire to create it vary from person to person, it's not made equally.It may seem unlikely in principle that one individual could really generate so much more wealth than another. The key to this mystery is to revisit that question, are they really worth 100 of us? Would a basketball team trade one of their players for 100 random people? What would Apple's next product look like if you replaced Steve Jobs with a committee of 100 random people? [6] These things don't scale linearly. Perhaps the CEO or the professional athlete has only ten times (whatever that means) the skill and determination of an ordinary person. But it makes all the difference that it's concentrated in one individual. When we say that one kind of work is overpaid and another underpaid, what are we really saying? In a free market, prices are determined by what buyers want. People like baseball more than poetry, so baseball players make more than poets. To say that a certain kind of work is &lt;/span&gt;&lt;/tt&gt;&lt;br /&gt;      &lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;    &lt;/tbody&gt;&lt;br /&gt;  &lt;/table&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;the results are:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &lt;strong&gt;C:\Documents and Settings\Propietario\Escritorio\haskell&amp;gt;main&lt;br /&gt;  &lt;/strong&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &lt;br/&gt;&lt;br /&gt;  &lt;strong&gt;[(" Why else would this idea occur in this odd context? Whereas if the&lt;br /&gt;  speaker were still operating on the Daddy Model",2),(" The appearance of the&lt;br /&gt;  word &lt;/strong&gt;&lt;strong&gt;unjust&lt;/strong&gt;&lt;strong&gt; here is the unmistakable&lt;br /&gt;  spectral signature of the Daddy Model",2),(" not something that's distributed&lt;br /&gt;  by Daddy",1),(" variation in income is actually a sign of health?The Daddy&lt;br /&gt;  Model of Wealth Because kids are unable to create wealth",2)]&lt;/strong&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  &amp;nbsp;Things to note:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;&lt;br /&gt;    &lt;div align="justify"&gt;&lt;br /&gt;      The paragraphs are not sorted by relevance, but&amp;nbsp;the relevance is&lt;br /&gt;      calculated&amp;nbsp;(the numbers attached to each paragraph).&lt;br /&gt;    &lt;/div&gt;&lt;br /&gt;    &lt;li&gt;&lt;br /&gt;      &lt;div align="justify"&gt;&lt;br /&gt;        There is no limit in the number of paragraphs to return&lt;br /&gt;      &lt;/div&gt;&lt;br /&gt;    &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  This is&amp;nbsp;by design. It is&amp;nbsp;a task of the consumer to decide either to&lt;br /&gt;  sort&amp;nbsp;it,&amp;nbsp;limit the number of paragraphs or whatever.&amp;nbsp;That is so&lt;br /&gt;  because &lt;em&gt;this algorithm&amp;nbsp;do it all in one single pass,&lt;/em&gt; so that the&lt;br /&gt;  lazy nature of Haskell permit &lt;em&gt;getExcerpts &lt;/em&gt;stop wasting resources when&lt;br /&gt;  the consumer decides that there are enough paragraphs extracted. Great!.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  &amp;nbsp;there are&amp;nbsp;many&amp;nbsp;many cases like this in web programming where&lt;br /&gt;  laziness pays a lot: HTML Pagination for example. This&amp;nbsp;is something that&lt;br /&gt;  happens too in the presentation of search results.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  Note that&amp;nbsp;there are&amp;nbsp;hard coded thinks, for example,&amp;nbsp;I take&lt;br /&gt;  the&amp;nbsp;dot and the comma as the only&amp;nbsp;separators of paragraphs.&amp;nbsp;By&lt;br /&gt;  the way, How the&amp;nbsp;object can be&amp;nbsp;obtained realistically&amp;nbsp;?. This&lt;br /&gt;  is a mook-up.&amp;nbsp;it is&amp;nbsp;certainly not general and hardly reusable.&amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  For that matter&amp;nbsp;I have enhanced&lt;br /&gt;  the&amp;nbsp;Type&amp;nbsp;class&amp;nbsp;Indexable&amp;nbsp; for retrieving, convert to&lt;br /&gt;  string and give the separators to split the text in words and paragraphs.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &lt;table class="paste-area" width="100%"&gt;&lt;br /&gt;    &lt;tbody&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td bgcolor="#f4f4f4" colspan="2" width="100%"&gt;&lt;br /&gt;        &lt;tt&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="variable"&gt;Indexable&lt;/span&gt; a &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;listIze &amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;::&lt;/span&gt; a &lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;span class="variable"&gt;String&lt;/span&gt;&lt;/span&gt;]&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;getFromURI&lt;span class="keyword"&gt;::&lt;/span&gt; &lt;span class="variable"&gt;String&lt;/span&gt; &lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="variable"&gt;IO&lt;/span&gt; a &lt;span class="comment"&gt;--get the object as s String&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;toString &lt;span class="keyword"&gt;::&lt;/span&gt; a&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="variable"&gt;String&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;expSeparators &lt;span class="keyword"&gt;::&lt;/span&gt; &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;span class="variable"&gt;Char&lt;/span&gt;&lt;/span&gt;]&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wordSeparators&lt;span class="keyword"&gt;::&lt;/span&gt; &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;span class="variable"&gt;Char&lt;/span&gt;&lt;/span&gt;]&lt;/span&gt;&lt;/tt&gt;&lt;br /&gt;      &lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;    &lt;/tbody&gt;&lt;br /&gt;  &lt;/table&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  The&amp;nbsp;additions are not&amp;nbsp;orthogonal&amp;nbsp;with &lt;em&gt;listIze&lt;/em&gt;, but at&lt;br /&gt;  this moment, it&amp;nbsp;is enough&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  So how looks like the integration of this stuff with the previous&amp;nbsp;search&lt;br /&gt;  engine described in&lt;br /&gt;  &lt;a href="http://haskell-web.blogspot.com/2006/11/search-engine-written-in-haskell.html" title="the first post"&gt;the&lt;br /&gt;  first post&lt;/a&gt; ?&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;  &lt;table class="paste-area" width="100%"&gt;&lt;br /&gt;    &lt;tbody&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td bgcolor="#f4f4f4" colspan="2" width="100%"&gt;&lt;br /&gt;        &lt;p&gt;&lt;br /&gt;          &lt;tt&gt;&lt;span class="comment"&gt;-- return a list of URIs and excerpts for each document that match the search criteria&lt;/span&gt;&lt;br/&gt;&lt;span class="function"&gt;&lt;/span&gt;&lt;/tt&gt;&lt;br /&gt;        &lt;/p&gt;&lt;br /&gt;        &lt;p&gt;&lt;br /&gt;          &lt;tt&gt;&lt;span class="function"&gt;searchResults&lt;/span&gt; keys&lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;let&lt;/span&gt; xs&lt;span class="keyword"&gt;=&lt;/span&gt;listIze &lt;span class="atom"&gt;$&lt;/span&gt; &lt;span class="variable"&gt;Words&lt;/span&gt; str&lt;br/&gt;&amp;nbsp;&amp;nbsp;uris&lt;span class="keyword"&gt;&amp;lt;-&lt;/span&gt; search xs&lt;br/&gt;&amp;nbsp;&amp;nbsp;rs &amp;nbsp;&lt;span class="keyword"&gt;&amp;lt;-&lt;/span&gt; map getFromURI uris&lt;br/&gt;&amp;nbsp;&amp;nbsp;&lt;br/&gt;&amp;nbsp;&amp;nbsp;return &lt;span class="atom"&gt;$&lt;/span&gt; zip uris &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;map &lt;span class="paren2"&gt;(&lt;span class="paste"&gt;showExcerpts xs&lt;/span&gt;)&lt;/span&gt; rs&lt;/span&gt;)&lt;/span&gt;&lt;br/&gt;&lt;/p&gt;&lt;/tt&gt;&lt;br /&gt;      &lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;    &lt;/tbody&gt;&lt;br /&gt;  &lt;/table&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  &lt;em&gt;searchResults&lt;/em&gt;&amp;nbsp;is, basically, a map to call &lt;em&gt;showExcerpts&lt;/em&gt;&lt;br /&gt;  for each&amp;nbsp;URI returned by&amp;nbsp;search.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  Again, there is no limit&amp;nbsp;in the&amp;nbsp;number of the results&lt;br /&gt;  returned.&amp;nbsp;The lazy nature of Haskell permits me to&amp;nbsp;give to the&lt;br /&gt;  consumer total freedom and responsibility,&lt;br /&gt;  without&amp;nbsp;complicating&amp;nbsp;the&amp;nbsp;code with clumsy parameters&amp;nbsp;and&lt;br /&gt;  buffering.&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p align="justify"&gt;&lt;br /&gt;  The caching of document content for extracting excerpts is not the search&lt;br /&gt;  engine responsibility up to now.&amp;nbsp;Google do it, so&amp;nbsp;it&amp;nbsp;may&lt;br /&gt;  be&amp;nbsp;a good idea to cache the content if possible.&lt;br /&gt;  &lt;a href="http://haskell-web.blogspot.com/2006/11/transactional-cache-for-haskell.html" title="The transactional cache&amp;amp;nbsp;"&gt;The&lt;br /&gt;  transactional cache&amp;nbsp;&lt;/a&gt; can be a good&amp;nbsp;candidate&amp;nbsp;for this role.&lt;br /&gt;  Specially when the objects&amp;nbsp;indexed&amp;nbsp;are&amp;nbsp;being updated&lt;br /&gt;  transactionally and the&amp;nbsp;index engine has to take care of the changes. I´m&lt;br /&gt;  working on it.&amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37577615-8458032154384065235?l=haskell-web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://haskell-web.blogspot.com/feeds/8458032154384065235/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37577615&amp;postID=8458032154384065235' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/8458032154384065235'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/8458032154384065235'/><link rel='alternate' type='text/html' href='http://haskell-web.blogspot.com/2006/11/search-engine-written-in-haskell-part_24.html' title='A search engine written in Haskell. Part two'/><author><name>Alberto</name><uri>http://www.blogger.com/profile/11962281728014883353</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37577615.post-3016508305601059012</id><published>2006-11-16T17:21:00.001+01:00</published><updated>2012-02-07T21:10:53.974+01:00</updated><title type='text'>Haskell Transactional Cache</title><content type='html'>NOTE: last version download at: &lt;a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/TCache"&gt;http://hackage.haskell.org/cgi-bin/hackage-scripts/package/TCache&lt;/a&gt;&lt;br /&gt;&lt;div align="justify"&gt;&lt;br /&gt;  I was impressed by Haskell since I started to learn it a year ago. I was&amp;nbsp;looking for a language that can be used for genetic programming, and haskell&amp;nbsp;eases the&amp;nbsp;creation custom languages such is the one I needed.&lt;/div&gt;&lt;div align="justify"&gt;&lt;br /&gt;  Soon I was fascinated by the pure functional approach. I was also attracted by&amp;nbsp;the concept of referential transparency, that&amp;nbsp;makes life easier for code&amp;nbsp;clarity and maintainability. The smart type system also was impressive on  avoiding common errors at compilation time that plagued other languages. For&amp;nbsp;these reason and a lot more&amp;nbsp;I though that Haskell&amp;nbsp;has&amp;nbsp;reasonable&amp;nbsp;perspectives to be the future Java. Concerning Web&lt;br /&gt;  programming, despite the&amp;nbsp;timid effort done up to now,&amp;nbsp;surprisingly,&amp;nbsp;&lt;a href="http://www.w3.org/2001/tag/doc/leastPower.html"&gt;Haskell is  in the best track&lt;/a&gt;&amp;nbsp;to win the race for the best Web engine. Haskell Server Pages has a&amp;nbsp;quite good web framework with unique capabilities. HSP Client-side has the&amp;nbsp;best approach&amp;nbsp;for Ajax programming.&lt;/div&gt;&lt;div align="justify"&gt;&lt;br /&gt;  But Haskell still has many holes for rapid application development, something&amp;nbsp;that is vital for escalating Haskell from naive, fun driven web projects to&amp;nbsp;industrial acceptance. It lacks a MVC (Model View Controller) framework.&amp;nbsp;Haskell has not something like Rails for Rubi or Hibernate for Java.&lt;/div&gt;&lt;div align="justify"&gt;&lt;br /&gt;  One of the&amp;nbsp;problems of Web development is the three tier programming&amp;nbsp;problems. It is about how to&amp;nbsp;keep low&amp;nbsp;the&amp;nbsp;impedance between&amp;nbsp;layers&amp;nbsp;when&amp;nbsp;each layer has his own&amp;nbsp;architectural requirements&amp;nbsp;so that they&amp;nbsp;are designed around different&amp;nbsp;paradigms. With impedance&amp;nbsp;I refer to the additional problems introduced within each layer, at every&amp;nbsp;stage of the software life-cycle,&amp;nbsp;produced&amp;nbsp;by the mismatch with&amp;nbsp;other layers.&lt;/div&gt;&lt;br /&gt;&lt;div align="justify"&gt;  Typically,&amp;nbsp;the data layer is constructed around a database and a&amp;nbsp;relational language. The business layer&amp;nbsp;uses a object oriented&amp;nbsp;language,&amp;nbsp;while the presentation layer uses HTML, Javascript and some&amp;nbsp;other web technologies.&amp;nbsp;Depending on the framework chosen, more often&amp;nbsp;than not, the middle layer end&amp;nbsp;with a mess of relational, business and&amp;nbsp;presentation code.&lt;/div&gt;&lt;br /&gt;&lt;div align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div align="justify"&gt;&lt;br /&gt;  That happens even when the framework explicitly forbid that, unless&amp;nbsp;some&lt;br /&gt;  clear configurable interfaces are&amp;nbsp;defined to isolate them. By using the&lt;br /&gt;  natural data on each layer and providing&amp;nbsp; mapping mechanisms between&lt;br /&gt;  the&amp;nbsp;idiosyncrasies of the respective layers&amp;nbsp;avoids the middle layer&lt;br /&gt;  contamination. This&amp;nbsp;keep the&amp;nbsp;impedance low not only at the design&lt;br /&gt;  and development&amp;nbsp;time but also in &amp;nbsp;test, integration&amp;nbsp;and&lt;br /&gt;  maintenance. Each layer expert&amp;nbsp; can perform his work with little care&lt;br /&gt;  about the technologies configurations, design decisions&lt;br /&gt;  and&amp;nbsp;changes&amp;nbsp;in the other layers. Such kind of mappings are&lt;br /&gt;  exemplified, in the case of the Business-Data layer boundary, by&lt;br /&gt;  storage-independent data persistence mechanisms, such is &lt;em&gt;Hibernate&lt;/em&gt;&lt;br /&gt;  for Java and &lt;em&gt;Rails&lt;/em&gt; for Rubi.&amp;nbsp; In the case of the&lt;br /&gt;  Business-Presentation Layer boundary, something like the &lt;em&gt;Custom Tags&lt;/em&gt;&lt;br /&gt;  of JSP and ASP.NET do the same role into isolating the presentation from&lt;br /&gt;  the&amp;nbsp; logic of the business layer . They are also mapping mechanisms. XSLT&lt;br /&gt;  also play this role.&lt;/div&gt;&lt;br /&gt;&lt;div align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div align="justify"&gt;&lt;br /&gt;  In the other side, I HATE designing and programming databases (database record&lt;br /&gt;  and field access is so low level that it can ruin the readability and elegance&lt;br /&gt;  of any algorithm). I want to use my own defined objects, not the&amp;nbsp;pieces&lt;br /&gt;  of information defined to accomplish with low level data requirements. I want&lt;br /&gt;  not to take care about on every single access to the data I need.&lt;/div&gt;&lt;br /&gt;&lt;div align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div align="justify"&gt;&lt;br /&gt;  So i need to:&lt;/div&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;&lt;br /&gt;    &lt;div align="justify"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Abstract myself from the physical data structure&lt;br /&gt;and rather use the data definitions that fit with the nature of the&lt;br /&gt;problem to solve&lt;/div&gt;&lt;br /&gt;    &lt;/li&gt;&lt;li&gt;&lt;br /&gt;      &lt;div align="justify"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; I need Transaction-aware data objects, because in the&lt;br /&gt;multi-threaded world of Internet servers, two clients may want to buy&lt;br /&gt;the same Item at the same time and I want to decrease the stock of this&lt;br /&gt;item&amp;nbsp;two times instead of one, for example (if there are two items&lt;br /&gt;at least).&lt;/div&gt;&lt;br /&gt;      &lt;/li&gt;&lt;li&gt;&lt;br /&gt;        &lt;div align="justify"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; I also need a way to define mappings between the&lt;br /&gt;objects I use and the physical storage, no matter that it is a&lt;br /&gt;file-system or a Database.&lt;/div&gt;&lt;br /&gt;        &lt;/li&gt;&lt;li&gt;&lt;br /&gt;          &lt;div align="justify"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; should be abstract to&amp;nbsp;work with&amp;nbsp;any&lt;br /&gt;kind of data definitions.&lt;/div&gt;&lt;br /&gt;        &lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;div align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div align="justify"&gt;&lt;br /&gt;  Once the database is just a persistence mechanism for a web application the&lt;br /&gt;  transactionality can not be provided by the database because the updates do&lt;br /&gt;  not go directly to the database. The data has to be transactional in memory.&lt;br /&gt;  It is very important to have a general mechanism of transactions for this&lt;br /&gt;  reason.&lt;/div&gt;&lt;br /&gt;&lt;div align="justify"&gt;&lt;br /&gt;  &amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div align="justify"&gt;&lt;br /&gt;  &amp;nbsp;I created &lt;span style="color: #330099;"&gt;TCache.hs&lt;/span&gt;&lt;br /&gt;  (&lt;a href="http://www.box.net/public/dedpysnsud" title="download"&gt;download&lt;/a&gt;&lt;br /&gt;  ), a transactional cache that abstract the user from physical data and&lt;br /&gt;  transactional plumbing. The data access uses a very simple semantics: to&lt;br /&gt;  access a&amp;nbsp;data object&amp;nbsp;I&amp;nbsp;use just&amp;nbsp;the data&lt;br /&gt;  object&amp;nbsp;itself updated with just the fields necessary for composing a&lt;br /&gt;  unique key.&lt;br /&gt;  &lt;/div&gt;&lt;div align="justify"&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;/div&gt;&lt;div align="justify"&gt;&lt;br /&gt;      The transactional cache takes care of transactions,&amp;nbsp;synchronization&lt;br /&gt;      with the physical data ( one way, from the cache to the&amp;nbsp;PD&amp;nbsp;up to&lt;br /&gt;      now) and&amp;nbsp;maintenance of the cache size by dropping the data&amp;nbsp;with&lt;br /&gt;      older&amp;nbsp;access.&lt;br /&gt;      &lt;/div&gt;&lt;div align="justify"&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;/div&gt;&lt;div align="justify"&gt;&lt;br /&gt;          The transaction uses STM (Software Transactional Memory) so that no&lt;br /&gt;          blocking is used, and the resulting application is faster at doing&lt;br /&gt;          transactions. For this reason it only compiles in&amp;nbsp;GHC.&lt;br /&gt;          &lt;/div&gt;&lt;div align="justify"&gt;&lt;br /&gt;            &lt;br /&gt;            &lt;/div&gt;&lt;div align="justify"&gt;&lt;br /&gt;              The cache is implemented in a Hash Table&lt;br /&gt;              (&lt;em&gt;Data.HashTable&lt;/em&gt;)&amp;nbsp;so that many thread may be doing&lt;br /&gt;              transactions at the same time.&lt;br /&gt;              &lt;/div&gt;&lt;div align="justify"&gt;&lt;br /&gt;                &lt;br /&gt;                &lt;/div&gt;&lt;div align="justify"&gt;&lt;br /&gt;                  Below you can find an example of use:&lt;br /&gt;                  &lt;/div&gt;&lt;div align="justify"&gt;&lt;br /&gt;                    &lt;br /&gt;                    &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;table border="1" bordercolor="#ccffff" cellpadding="1" cellspacing="2" class="paste-area"&gt;                        &lt;tbody&gt;&lt;tr&gt;                          &lt;td bgcolor="#f4f4f4" colspan="2" width="100%"&gt;&lt;br /&gt;&lt;br /&gt;                              &lt;tt&gt;&lt;span class="keyword"&gt;module&lt;/span&gt; &lt;span class="variable"&gt;Main&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;br /&gt;-------------------------------------------------&lt;br /&gt;-- A example of&amp;nbsp;Transactional cache usage (TCache.hs)&lt;br /&gt;-- (Something like the Java Hibernate)&lt;br /&gt;-- Author: Alberto Gómez Corona Nov 2006&lt;br /&gt;-- Language: Haskell&lt;br /&gt;-- Terms of use: you can do whatever you want&lt;br /&gt;-- with this code as long as you keep this notice&lt;br /&gt;------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; &lt;span class="variable"&gt;TCache&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; &lt;span class="variable"&gt;Control&lt;/span&gt;&lt;span class="atom"&gt;.&lt;/span&gt;&lt;span class="variable"&gt;Concurrent&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; &lt;span class="variable"&gt;System&lt;/span&gt;&lt;span class="atom"&gt;.&lt;/span&gt;&lt;span class="variable"&gt;Directory&lt;/span&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                              &lt;tt&gt;--1 and 4:&amp;nbsp;The data elements to be used in the example: A&amp;nbsp;user will repeatedly buy Items.&lt;br /&gt;&lt;br /&gt;&lt;span class="keyword"&gt;data&lt;/span&gt; &amp;nbsp;&lt;span class="variable"&gt;Data&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt; &amp;nbsp;&amp;nbsp;&lt;span class="variable"&gt;User&lt;/span&gt;&lt;span class="paren1"&gt;{&lt;span class="paste"&gt;uname&lt;span class="keyword"&gt;::&lt;/span&gt;&lt;span class="variable"&gt;String,&lt;/span&gt; uid&lt;span class="keyword"&gt;::&lt;/span&gt;&lt;span class="variable"&gt;String,&lt;/span&gt; spent&lt;span class="keyword"&gt;::&lt;/span&gt; &lt;span class="variable"&gt;Int&lt;/span&gt;&lt;/span&gt;} |&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="variable"&gt;Item&lt;/span&gt;&lt;span class="paren1"&gt;{&lt;span class="paste"&gt;iname&lt;span class="keyword"&gt;::&lt;/span&gt;&lt;span class="variable"&gt;String,&lt;/span&gt; iid&lt;span class="keyword"&gt;::&lt;/span&gt;&lt;span class="variable"&gt;String,&lt;/span&gt; price&lt;span class="keyword"&gt;::&lt;/span&gt;&lt;span class="variable"&gt;Int,&lt;/span&gt; stock&lt;span class="keyword"&gt;::&lt;/span&gt;&lt;span class="variable"&gt;Int&lt;/span&gt;&lt;/span&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;deriving&lt;/span&gt; &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="variable"&gt;Read,&lt;/span&gt; &lt;span class="variable"&gt;Show&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;--3 The mappings&amp;nbsp;between the cache&amp;nbsp;and the&amp;nbsp;phisical storage are defined by the interface IResource &lt;/tt&gt;&lt;br /&gt;                            &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                              &lt;tt&gt;--&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; to extract the resource unique key, &lt;/tt&gt;&lt;br /&gt;                            &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                              &lt;tt&gt;--&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; to read the resource from the physical storage, &lt;/tt&gt;&lt;br /&gt;                            &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                              &lt;tt&gt;--&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; to store it and &lt;/tt&gt;&lt;br /&gt;                            &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                              &lt;tt&gt;--&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;to delete the resource from the physical storage.&lt;/tt&gt;&lt;br /&gt;                            &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                              &lt;tt&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;&lt;span class="keyword"&gt;instance&lt;/span&gt; &lt;span class="variable"&gt;IResource&lt;/span&gt; &lt;span class="variable"&gt;Data&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;keyResource &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="variable"&gt;User&lt;/span&gt;&lt;span class="paren1"&gt;{&lt;span class="paste"&gt;uid&lt;span class="keyword"&gt;=&lt;/span&gt;id&lt;/span&gt;}&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt; id&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;keyResource &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="variable"&gt;Item&lt;/span&gt;&lt;span class="paren1"&gt;{&lt;span class="paste"&gt;iid&lt;span class="keyword"&gt;=&lt;/span&gt;id&lt;/span&gt;}&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt; id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;readResource &amp;nbsp;&amp;nbsp;&amp;nbsp;e&lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; s&lt;span class="keyword"&gt;&amp;lt;-&lt;/span&gt; readFile&lt;span class="atom"&gt;$&lt;/span&gt; keyResource e&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&lt;span class="atom"&gt;$&lt;/span&gt; &lt;span class="variable"&gt;Just&lt;/span&gt; &lt;span class="atom"&gt;$&lt;/span&gt; read s&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;writeResource &amp;nbsp;&amp;nbsp;e&lt;span class="keyword"&gt;=&lt;/span&gt; writeFile &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;keyResource e&lt;/span&gt;)&lt;/span&gt; &lt;span class="atom"&gt;$&lt;/span&gt; show e&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;delResource &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;e&lt;span class="keyword"&gt;=&lt;/span&gt; removeFile &lt;span class="atom"&gt;$&lt;/span&gt; keyResource e&lt;br /&gt;&lt;br /&gt;-- buy is the operation to be performed in the example&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;--4 &lt;em&gt;withResources&lt;/em&gt; gets a partial definition of each resource necessary for extracting the key, fill all the rest of the data structures (if found ) and return a list of Maybe Data. BuyIt is part of the domain problem. it receive this list and generates a new list of dat objects that are updated in the cache. buyIt is executed atomically. &lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;&lt;span class="function"&gt;user&lt;/span&gt; &lt;span class="atom"&gt;`buy`&lt;/span&gt; item&lt;span class="keyword"&gt;=&lt;/span&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;withResources&lt;/span&gt;&lt;span class="paren1"&gt;[&lt;span class="paste"&gt;user,item&lt;/span&gt;]&lt;/span&gt; buyIt &lt;br /&gt;&lt;br /&gt;&lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;buyIt&lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;span class="variable"&gt;Just&lt;/span&gt; us,Just it&lt;/span&gt;]&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;|&lt;/span&gt; stock it &lt;span class="atom"&gt;&amp;gt;&lt;/span&gt; 0&lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="paren1"&gt;[us',it']&lt;/span&gt; &lt;span class="atom"&gt;`debug1`&lt;/span&gt; &lt;span class="string"&gt;"john buy a PC"&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;|&lt;/span&gt; otherwise &amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; error &lt;span class="string"&gt;"stock is empty for this product"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;buyIt&lt;span class="paren1"&gt;[&lt;span class="paste"&gt;_,_&lt;/span&gt;]&lt;/span&gt; &lt;span class="keyword"&gt;=&lt;/span&gt; error &lt;span class="string"&gt;"either the user or the item does not exist"&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; us'= &lt;span class="paste"&gt;us&lt;span class="paren2"&gt;{&lt;span class="paste"&gt;spent&lt;span class="keyword"&gt;=&lt;/span&gt;spent us &lt;span class="atom"&gt;+&lt;/span&gt; price it&lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;it'= it&lt;span class="paren2"&gt;{&lt;span class="paste"&gt;stock&lt;span class="keyword"&gt;=&lt;/span&gt; stock it&lt;span class="atom"&gt;-&lt;/span&gt;1&lt;/span&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="function"&gt;main&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;-- create resources (acces no resources and return two new Data objects defined in items)&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;withResources&lt;/span&gt;&lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt;items &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;--11 PCs are charged &amp;nbsp;to the John´s account in paralel, to show transactionality&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;--because there are only 10 PCs in stock, the last thread must return an error&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for 11 &lt;span class="atom"&gt;$&lt;/span&gt; forkIO &lt;span class="atom"&gt;$&lt;/span&gt; &lt;span class="variable"&gt;User&lt;/span&gt;&lt;span class="paren1"&gt;{&lt;span class="paste"&gt;uid&lt;span class="keyword"&gt;=&lt;/span&gt;&lt;span class="string"&gt;"U12345"&lt;/span&gt;&lt;/span&gt;}&lt;/span&gt; &lt;span class="atom"&gt;`buy`&lt;/span&gt; &lt;span class="variable"&gt;Item&lt;/span&gt;&lt;span class="paren1"&gt;{&lt;span class="paste"&gt;iid&lt;span class="keyword"&gt;=&lt;/span&gt;&lt;span class="string"&gt;"I54321"&lt;/span&gt;&lt;/span&gt;}&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;--wait 5 seconds&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;threadDelay 5000000&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;-- write the cache content in a persistent store (invoque writeResource for each resource)&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;-- in a real application clearSyncCache can be used instead to adjust size and write the cache periodically&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;syncCache &lt;/span&gt;&lt;span class="paren1"&gt;(&lt;span class="paste"&gt;refcache &lt;span class="keyword"&gt;::&lt;/span&gt; &lt;span class="variable"&gt;Cache&lt;/span&gt; &lt;span class="variable"&gt;Data&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;-- the files have been created. the files U12345 and I54321 must contain the result of the 11 iterations&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;items _&lt;span class="keyword"&gt;=&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;span class="variable"&gt;User&lt;/span&gt; &lt;span class="string"&gt;"John"&lt;/span&gt; &lt;span class="string"&gt;"U12345"&lt;/span&gt; 0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;,&lt;span class="variable"&gt;Item&lt;/span&gt; &lt;span class="string"&gt;"PC"&lt;/span&gt; &lt;span class="string"&gt;"I54321"&lt;/span&gt; 6000 10&lt;/span&gt;]&lt;/span&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Here follows&amp;nbsp;is a typical output. I&amp;nbsp;&amp;nbsp;printed a trace with the text &lt;em&gt;atomic try&lt;/em&gt;&amp;nbsp;as the first statement of the atomic transaction. You can se how the first transaction initiated blocks the rest and even some retry. That is so because all the updates go to the same registers. Overall, STM is faster&amp;nbsp;than blocking and far easier. My first version used&amp;nbsp; blocking and the code were far more complicated.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;"atomic try"&lt;br /&gt;"atomic try"&lt;br /&gt;&lt;strong&gt;john buy a PC&lt;/strong&gt;&lt;br /&gt;"atomic try""atomic try""atomic try""atomic try""atomic try""atomic try""atomic&lt;br /&gt;try""atomic try""atomic try""atomic try"&lt;br /&gt;&lt;strong&gt;john buy a PC&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;john buy a PC&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;john buy a PC&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;john buy a PC&lt;br /&gt;john buy a PC&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;john buy a PC&lt;br /&gt;john buy a PC&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;john buy a PC&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;john buy a PC&lt;br /&gt;john buy a PC&lt;/strong&gt;&lt;br /&gt;"atomic try""atomic try"&lt;br /&gt;&lt;strong&gt;john buy a PC&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;john buy a PC&lt;/strong&gt;&lt;br /&gt;"atomic try"&lt;br /&gt;&lt;strong&gt;john buy a PC&lt;/strong&gt;"atomic try"&lt;br /&gt;&lt;strong&gt;main: stock is empty for this product&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The final content of the files are:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;U12345: &amp;nbsp;User {uname = "John", uid = "U12345", spent = 60000}&lt;br /&gt;&lt;br /&gt;I54321: &amp;nbsp;Item {iname = "PC", iid = "I54321", price = 6000, stock = 0}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The amount spent by John is the sum of th prices of the ten PCs in stock and the stock is 0, so the transactions have been managed correcly.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div align="justify"&gt;There are other operations; &lt;em&gt;getResources&lt;/em&gt; that simply return the data requested withour doing any transaction.&amp;nbsp;&amp;nbsp; &lt;em&gt;clearSyncCacheProc&amp;nbsp;&lt;/em&gt;start the process for&amp;nbsp;cache maintenance and syncronization according with&amp;nbsp;his&amp;nbsp;passed parameters: time between checks, cache size and filtering criteria.&amp;nbsp;&lt;em&gt;getResourcesID&lt;/em&gt;&amp;nbsp;permits not only update but also delete cache elements in the course of a transaction.&lt;/div&gt;&lt;br /&gt;&lt;div align="justify"&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div align="justify"&gt;The module is far from finised. The syncronization mechanism must be refined for example with cache invalidation machanisms. I welcome anyone interested in to improve it.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div align="justify" style="color: red;"&gt;NOTES:&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div align="justify"&gt;I just realized that my transactional cache has been used in this excelent paper: &lt;a href="http://www.cs.rochester.edu/meetings/TRANSACT07/papers/perfumo.pdf"&gt;Dissecting Transactional Executions in Haskell&lt;/a&gt;.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div align="justify"&gt;The test case used in the study is more or less the same example described above. Since all the parallel treads update the same two objects all the time, this is the worst case. TCache uses in-memory non blocking transactions .  Each transaction do not block, but instead he try to perform the task and rollback at the very end if things have been changed by other thread in the meantime. Just like databases. The bad thing is that the more CPU cores are executing the example, the more work being rolled back is done.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div align="justify"&gt;Fortunately this is not the case in real life. TCache and the STM transactions are designed with the assumption that the application manages many objects and the threads update simultaneously different objects most of the time. A user does not buy eleven times simultaneously the same product. And non blocking transactions scale better than blocking ones in real life scenarios, just because they don´t block.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37577615-3016508305601059012?l=haskell-web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://haskell-web.blogspot.com/feeds/3016508305601059012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37577615&amp;postID=3016508305601059012' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/3016508305601059012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/3016508305601059012'/><link rel='alternate' type='text/html' href='http://haskell-web.blogspot.com/2006/11/transactional-cache-for-haskell.html' title='Haskell Transactional Cache'/><author><name>Alberto</name><uri>http://www.blogger.com/profile/11962281728014883353</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>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37577615.post-7671485339545859183</id><published>2006-11-14T17:30:00.000+01:00</published><updated>2006-11-24T21:50:16.248+01:00</updated><title type='text'>A search engine written in Haskell</title><content type='html'>&lt;p&gt;&lt;br /&gt;  It is so easy to transform ideas into programs using Haskell.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  I was bored in a conference.&amp;nbsp;The conferences excite my&lt;br /&gt;  imagination&amp;nbsp;in the same way than&amp;nbsp;walking fast.&amp;nbsp;I started to&lt;br /&gt;  think about how the core of a search engine would look like. I also need one&lt;br /&gt;  for my portal&lt;br /&gt;  &lt;a href="http://www.freechooser.com/"&gt;http://www.FreeChooser.com&lt;/a&gt; (more on&lt;br /&gt;  this portal coming soon). I needed to index not only web pages, but also&lt;br /&gt;  Haskell data records.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  My&amp;nbsp;search engine needed a compact index database, well designed so that&lt;br /&gt;  the&amp;nbsp;the search should be fast, even when searching for many words at the&lt;br /&gt;  same time, it would return a short set of documents that contains all the&lt;br /&gt;  words requested. This is the way to achieve a compromise between simplicity,&lt;br /&gt;  speed, ease of use and resource waste.&amp;nbsp; I didn't realize that the core&lt;br /&gt;  idea&amp;nbsp;could have been achieved in less than 50 lines of Haskell code!!!&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  I heard time ago about a search engine&lt;br /&gt;  &lt;a href="http://www.alltheweb.com"&gt;www.alltheweb.com&lt;/a&gt;&amp;nbsp;that&lt;br /&gt;  used bit maps to achieve the fastest search results six years ago.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  During the conference, I figured out a way to use bitmaps. For each word, the&lt;br /&gt;  index must store a set of bits. each bit correspond to a document identified&lt;br /&gt;  by the position in the bitmap (an Inte(ger)) and the association of this&lt;br /&gt;  Int(eger) with the URL of the document. the bit will have a 1 when the&lt;br /&gt;  document has this word and 0 when not. Very simple.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  To search for the documents that contain &lt;em&gt;term1 AND term2 ... AND&lt;br /&gt;  TermN&lt;/em&gt; is just&amp;nbsp; a bitwise AND of the respective bitmap terms.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  So I started to code it as soon as I returned home. Here is the code:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;  &lt;table class="paste-header"&gt;&lt;br /&gt;    &lt;tbody&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td align="left" nowrap="" valign="top"&gt;&lt;br /&gt;        :&lt;br /&gt;      &lt;/td&gt;&lt;br /&gt;      &lt;td width="100%"&gt;&lt;br /&gt;      &lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;    &lt;/tbody&gt;&lt;br /&gt;  &lt;/table&gt;&lt;br /&gt;  &lt;div&gt;&lt;br /&gt;    &lt;table bgcolor="#ccffff" border="0" cellpadding="1" cellspacing="2" width="100%"&gt;&lt;br /&gt;      &lt;tbody&gt;&lt;br /&gt;      &lt;tr&gt;&lt;br /&gt;        &lt;td bgcolor="#f4f4f4" colspan="2" width="100%"&gt;&lt;br /&gt;          &lt;p&gt;&lt;br /&gt;            &lt;tt&gt;&lt;span class="comment"&gt;Module Search where&lt;br/&gt;&lt;font face="Verdana"&gt;-------------------------------------------------&lt;br/&gt;-- The Core of a Search Engine&lt;br/&gt;-- Author: Alberto Gómez Corona&lt;br/&gt;-- Language: Haskell&lt;br/&gt;-- Terms of use: you can do whatever you want&lt;br/&gt;-- with this code as long as you keep this notice&lt;br/&gt;------------------------------------------------&lt;/font&gt;&lt;br/&gt;&lt;/span&gt;&lt;/tt&gt;&lt;br /&gt;          &lt;/p&gt;&lt;br /&gt;          &lt;p&gt;&lt;br /&gt;            &lt;tt&gt;&lt;span class="comment"&gt;&lt;/span&gt;&lt;/tt&gt;&lt;br /&gt;          &lt;/p&gt;&lt;br /&gt;          &lt;p&gt;&lt;br /&gt;            &lt;tt&gt;&lt;span class="comment"&gt;--store the URI list of indexed objects (reverse to intKey)&lt;/span&gt;&lt;br/&gt;&lt;span class="function"&gt;keyInt&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt; unsafePerformIO &lt;span class="atom"&gt;$&lt;/span&gt; new &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="atom"&gt;==&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt; hashString &lt;span class="keyword"&gt;::&lt;/span&gt; &lt;span class="variable"&gt;HashTable&lt;/span&gt; &lt;span class="variable"&gt;String&lt;/span&gt; &lt;span class="variable"&gt;Int&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span class="comment"&gt;--store the bitmaps for each word&lt;/span&gt;&lt;br/&gt;&lt;span class="function"&gt;hs&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt; unsafePerformIO &lt;span class="atom"&gt;$&lt;/span&gt; new &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="atom"&gt;==&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt; hashString &lt;span class="keyword"&gt;::&lt;/span&gt; &lt;span class="variable"&gt;HashTable&lt;/span&gt; &lt;span class="variable"&gt;String&lt;/span&gt; &lt;span class="variable"&gt;Integer&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span class="comment"&gt;--store the URN for each bit position&lt;/span&gt;&lt;br/&gt;&lt;span class="function"&gt;intKey&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt; unsafePerformIO &lt;span class="atom"&gt;$&lt;/span&gt; new &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="atom"&gt;==&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt; hashInt&lt;span class="keyword"&gt;::&lt;/span&gt; &lt;span class="variable"&gt;HashTable&lt;/span&gt; &lt;span class="variable"&gt;Int&lt;/span&gt; &lt;span class="variable"&gt;String&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span class="comment"&gt;--store the last bit position/las int id of the last object indexed&lt;/span&gt;&lt;br/&gt;&lt;span class="function"&gt;indexRef&lt;/span&gt; &lt;span class="keyword"&gt;=&lt;/span&gt;unsafePerformIO &lt;span class="atom"&gt;$&lt;/span&gt; newMVar 0 &lt;span class="keyword"&gt;::&lt;/span&gt; &lt;span class="variable"&gt;MVar&lt;/span&gt; &lt;span class="variable"&gt;Int&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;span class="comment"&gt;-- add the content of an object, identified by the uri string:&lt;/span&gt;&lt;br/&gt;&lt;span class="function"&gt;addObject&lt;/span&gt;&lt;span class="keyword"&gt;::&lt;/span&gt; (Indexable a)=&amp;gt; &lt;span class="variable"&gt;String&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;a&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="variable"&gt;IO&lt;/span&gt;&lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;/span&gt;)&lt;/span&gt;&lt;br/&gt;&lt;span class="function"&gt;addObject&lt;/span&gt; uri content&lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;mk&lt;span class="keyword"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="variable"&gt;HT&lt;/span&gt;&lt;span class="atom"&gt;.&lt;/span&gt;lookup keyInt uri &lt;br/&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;case&lt;/span&gt; mk &lt;span class="keyword"&gt;of&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="variable"&gt;Just&lt;/span&gt; k &lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt; return &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;/span&gt;)&lt;/span&gt; &lt;span class="comment"&gt;--to avoid repeated indexing of documents&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="variable"&gt;Nothing&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt; addObject1 uri content&lt;br/&gt;&amp;nbsp;&lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br/&gt;&amp;nbsp;addObject1 &amp;nbsp;uri content&lt;span class="keyword"&gt;=&lt;/span&gt;&lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;n &lt;span class="keyword"&gt;&amp;lt;-&lt;/span&gt; takeMVar indexRef&lt;br/&gt;&amp;nbsp;&amp;nbsp;add n &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;k n&lt;/span&gt;)&lt;/span&gt; &lt;span class="atom"&gt;$&lt;/span&gt; listIze content&lt;br/&gt;&amp;nbsp;&amp;nbsp;update keyInt uri n&lt;br/&gt;&amp;nbsp;&amp;nbsp;update intKey n uri&lt;br/&gt;&amp;nbsp;&amp;nbsp;putMVar indexRef &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;n&lt;span class="atom"&gt;+&lt;/span&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;add n k &amp;nbsp;&lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt; return &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;/span&gt;)&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;add n k &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;x&lt;span class="variable"&gt;:&lt;/span&gt;xs&lt;/span&gt;)&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mv&lt;span class="keyword"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="variable"&gt;HT&lt;/span&gt;&lt;span class="atom"&gt;.&lt;/span&gt;lookup hs x&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;case&lt;/span&gt; mv &lt;span class="keyword"&gt;of&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="variable"&gt;Just&lt;/span&gt; v &lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt; update hs x &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;v &lt;span class="atom"&gt;.|.&lt;/span&gt; k&lt;/span&gt;)&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="variable"&gt;Nothing&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt; update hs x k&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;add n k xs&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;k n&lt;span class="keyword"&gt;=&lt;/span&gt; shiftL 1 n &lt;br/&gt;&lt;br/&gt;&lt;span class="comment"&gt;-- search for a set of ANDed keywords and return the list of URIs That contain all of them &lt;/span&gt;&lt;br/&gt;&lt;span class="function"&gt;search&lt;/span&gt; xs &lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;n &lt;span class="keyword"&gt;&amp;lt;-&lt;/span&gt; readMVar indexRef&lt;br/&gt;&amp;nbsp;&amp;nbsp;print n&lt;br/&gt;&amp;nbsp;&amp;nbsp;mbi&lt;span class="keyword"&gt;&amp;lt;-&lt;/span&gt; mapM &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="variable"&gt;HT&lt;/span&gt;&lt;span class="atom"&gt;.&lt;/span&gt;lookup hs&lt;/span&gt;)&lt;/span&gt;xs &lt;br/&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;let&lt;/span&gt; bi &lt;span class="keyword"&gt;=&lt;/span&gt; catMaybes mbi&lt;br/&gt;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;-- if a word has not been found then return empty results&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt; length bi&lt;span class="atom"&gt;/=&lt;/span&gt; length mbi &lt;span class="keyword"&gt;then&lt;/span&gt; return &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt; &lt;span class="keyword"&gt;else&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;let&lt;/span&gt; r&lt;span class="keyword"&gt;=&lt;/span&gt; foldr &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="atom"&gt;.&amp;amp;.&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt; &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;head bi&lt;/span&gt;)&lt;/span&gt; &amp;nbsp;bi &lt;span class="comment"&gt;-- select te doc bits that have all the words &amp;nbsp;&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;--r has the bits of the objects that match&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;print r&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;getObjecURIs n 0 r &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;getObjecURIs &lt;span class="keyword"&gt;::&lt;/span&gt; &lt;span class="variable"&gt;Int&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="variable"&gt;Int&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="variable"&gt;Integer&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;span class="variable"&gt;String&lt;/span&gt;&lt;/span&gt;]&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="variable"&gt;IO&lt;/span&gt; &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;span class="variable"&gt;String&lt;/span&gt;&lt;/span&gt;]&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;getObjecURIs 0 _ _ rs&lt;span class="keyword"&gt;=&lt;/span&gt; return rs&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;getObjecURIs n i r rs&lt;span class="keyword"&gt;=&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;testBit r 0&lt;/span&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;of&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span class="variable"&gt;True&lt;/span&gt; &lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;urn &lt;span class="keyword"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="variable"&gt;HT&lt;/span&gt;&lt;span class="atom"&gt;.&lt;/span&gt;lookup intKey i&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;getObjecURIs &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;n&lt;span class="atom"&gt;-&lt;/span&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;span class="paren1"&gt;(&lt;span class="paste"&gt;i&lt;span class="atom"&gt;+&lt;/span&gt;1&lt;/span&gt;)&lt;/span&gt; &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;shiftR r 1&lt;/span&gt;)&lt;/span&gt; &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;fromJust urn&lt;span class="variable"&gt;:&lt;/span&gt;rs&lt;/span&gt;)&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span class="variable"&gt;False&lt;/span&gt;&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt; getObjecURIs &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;n&lt;span class="atom"&gt;-&lt;/span&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;span class="paren1"&gt;(&lt;span class="paste"&gt;i&lt;span class="atom"&gt;+&lt;/span&gt;1&lt;/span&gt;)&lt;/span&gt; &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;shiftR r 1&lt;/span&gt;)&lt;/span&gt; rs&lt;/tt&gt;&lt;br /&gt;          &lt;/p&gt;&lt;br /&gt;        &lt;/td&gt;&lt;br /&gt;      &lt;/tr&gt;&lt;br /&gt;      &lt;/tbody&gt;&lt;br /&gt;    &lt;/table&gt;&lt;br /&gt;  &lt;/div&gt;&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;    &amp;nbsp;&lt;br /&gt;  &lt;/p&gt;&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;    &amp;nbsp;&amp;nbsp;&lt;br /&gt;  &lt;/p&gt;&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;    Of course, it is necessary to add persistence for the index database&lt;br /&gt;    &lt;em&gt;hs&lt;/em&gt; and the rest of the associated HashTables and so on.&lt;br /&gt;  &lt;/p&gt;&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;    There are two procedures&lt;br /&gt;    &lt;font style="BACKGROUND-COLOR:#ffffff"&gt;&lt;font color="#3333ff"&gt;&lt;em&gt;addObject&lt;/em&gt;&lt;br /&gt;    &lt;/font&gt;&lt;/font&gt;(to add a new object URI and his string content) to the index&lt;br /&gt;    database. The other method is &lt;em&gt;&lt;font color="#3333ff"&gt;Search&lt;/font&gt;.&lt;br /&gt;    &lt;/em&gt;It takes a list of words as arguments and return the list of documents&lt;br /&gt;    that have all the words.&lt;br /&gt;  &lt;/p&gt;&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;    &amp;nbsp;&lt;br /&gt;  &lt;/p&gt;&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;    To feed addObject, &amp;nbsp;I also started to define&amp;nbsp;&amp;nbsp;filters for&lt;br /&gt;    special kind of objects: (text files, Haskell registers, XML/HTML files).&lt;br /&gt;    The code below shows an early attemp to do so. Note the type signature of&lt;br /&gt;    adObject.&lt;br /&gt;  &lt;/p&gt;&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;    &amp;nbsp;&lt;br /&gt;  &lt;/p&gt;&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;    I have defined a Class &lt;em&gt;Indexable&lt;/em&gt; that has a function that convert&lt;br /&gt;    the object into a list of strings:&lt;br /&gt;  &lt;/p&gt;&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;    &amp;nbsp;&lt;br /&gt;  &lt;/p&gt;&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;    &amp;nbsp;&lt;br /&gt;    &lt;div&gt;&lt;br /&gt;      &lt;table bgcolor="#ccffff" border="0" cellpadding="1" cellspacing="2" width="100%"&gt;&lt;br /&gt;        &lt;tbody&gt;&lt;br /&gt;        &lt;tr&gt;&lt;br /&gt;          &lt;td bgcolor="#f4f4f4" colspan="2" width="100%"&gt;&lt;br /&gt;            &lt;tt&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;span class="comment"&gt;--a is indexable if it can be serialized into a list of word strings &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="variable"&gt;Indexable&lt;/span&gt; a &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;listIze&lt;span class="keyword"&gt;::&lt;/span&gt; a&lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;span class="variable"&gt;String&lt;/span&gt;&lt;/span&gt;]&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br/&gt;&lt;br/&gt;&lt;span class="keyword"&gt;data&lt;/span&gt; &lt;span class="variable"&gt;Words&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="variable"&gt;Words&lt;/span&gt; &lt;span class="variable"&gt;String&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span class="keyword"&gt;instance&lt;/span&gt; &lt;span class="variable"&gt;Indexable&lt;/span&gt; &lt;span class="variable"&gt;Words&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;listIze &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="variable"&gt;Words&lt;/span&gt; s&lt;/span&gt;)&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt; str2List s &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="keyword"&gt;\&lt;/span&gt;c &lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt;isAlphaNum c &lt;span class="atom"&gt;||&lt;/span&gt; c&lt;span class="atom"&gt;==&lt;/span&gt;&lt;span class="character"&gt;'@'&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;/span&gt; &lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;str2List &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt; _&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;str2List s &amp;nbsp;f&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; h&lt;span class="variable"&gt;:&lt;/span&gt;r &lt;span class="keyword"&gt;where&lt;/span&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="paren1"&gt;(&lt;span class="paste"&gt;h,t&lt;/span&gt;)&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; myreads2 s f&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;r&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; str2List t f&lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;myreads2 &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt; _&lt;span class="keyword"&gt;=&lt;/span&gt;&lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="paren2"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt;,&lt;span class="paren2"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;myreads2 &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;c&lt;span class="variable"&gt;:&lt;/span&gt;rest&lt;/span&gt;)&lt;/span&gt; f &lt;span class="keyword"&gt;|&lt;/span&gt; not&lt;span class="paren1"&gt;(&lt;span class="paste"&gt;f c&lt;/span&gt;)&lt;/span&gt; &amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="paren2"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt;, rest&lt;/span&gt;)&lt;/span&gt; &lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;|&lt;/span&gt; otherwise &lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;c&lt;span class="variable"&gt;:&lt;/span&gt;r, skipspaces s f&lt;/span&gt;)&lt;/span&gt; &lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;where&lt;/span&gt; &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;r,s&lt;/span&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;=&lt;/span&gt; myreads2 rest f&lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;skipspaces &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt; _ &lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;skipspaces &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;c&lt;span class="variable"&gt;:&lt;/span&gt;rest&lt;/span&gt;)&lt;/span&gt; f &amp;nbsp;&lt;span class="keyword"&gt;|&lt;/span&gt; not&lt;span class="paren1"&gt;(&lt;span class="paste"&gt;f c&lt;/span&gt;)&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; skipspaces rest f&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;|&lt;/span&gt; otherwise&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; c&lt;span class="variable"&gt;:&lt;/span&gt;rest&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;span class="keyword"&gt;data&lt;/span&gt; &lt;span class="variable"&gt;XMLText&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="variable"&gt;XMLText&lt;/span&gt; &lt;span class="variable"&gt;String&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span class="keyword"&gt;instance&lt;/span&gt; &lt;span class="variable"&gt;Indexable&lt;/span&gt; &lt;span class="variable"&gt;XMLText&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;listIze &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="variable"&gt;XMLText&lt;/span&gt; s&lt;/span&gt;)&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt; str2List s &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="keyword"&gt;\&lt;/span&gt;c &lt;span class="keyword"&gt;-&amp;gt;&lt;/span&gt;isAlphaNum c &lt;span class="atom"&gt;||&lt;/span&gt; c&lt;span class="atom"&gt;==&lt;/span&gt;&lt;span class="character"&gt;'@'&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;/span&gt; &lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;str2List &lt;span class="string"&gt;""&lt;/span&gt; _&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;str2List &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="character"&gt;'&amp;lt;'&lt;/span&gt;&lt;span class="variable"&gt;:&lt;/span&gt;rs&lt;/span&gt;)&lt;/span&gt; f &amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; str2List &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;tail &lt;span class="atom"&gt;$&lt;/span&gt; dropWhile&lt;span class="paren2"&gt;(&lt;span class="paste"&gt;&lt;span class="atom"&gt;/=&lt;/span&gt;&lt;span class="character"&gt;'&amp;gt;'&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt; rs&lt;/span&gt;)&lt;/span&gt; f&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;str2List s &amp;nbsp;f&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; h&lt;span class="variable"&gt;:&lt;/span&gt;r &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="paren1"&gt;(&lt;span class="paste"&gt;h,t&lt;/span&gt;)&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; myreads2 s f&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;r&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; str2List t f&lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;myreads2 &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt; _&lt;span class="keyword"&gt;=&lt;/span&gt;&lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="paren2"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt;,&lt;span class="paren2"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;myreads2 &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;c&lt;span class="variable"&gt;:&lt;/span&gt;rest&lt;/span&gt;)&lt;/span&gt; f &lt;span class="keyword"&gt;|&lt;/span&gt; not&lt;span class="paren1"&gt;(&lt;span class="paste"&gt;f c&lt;/span&gt;)&lt;/span&gt; &amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="paren2"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt;, rest&lt;/span&gt;)&lt;/span&gt; &lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;|&lt;/span&gt; otherwise &lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;c&lt;span class="variable"&gt;:&lt;/span&gt;r, skipspaces s f&lt;/span&gt;)&lt;/span&gt; &lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;where&lt;/span&gt; &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;r,s&lt;/span&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;=&lt;/span&gt; myreads2 rest f&lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;skipspaces &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt; _ &lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;/span&gt;]&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;skipspaces &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="character"&gt;'&amp;lt;'&lt;/span&gt;&lt;span class="variable"&gt;:&lt;/span&gt;rs&lt;/span&gt;)&lt;/span&gt; f &lt;span class="keyword"&gt;=&lt;/span&gt; skipspaces &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;tail &lt;span class="atom"&gt;$&lt;/span&gt; dropWhile&lt;span class="paren2"&gt;(&lt;span class="paste"&gt;&lt;span class="atom"&gt;/=&lt;/span&gt;&lt;span class="character"&gt;'&amp;gt;'&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt; rs&lt;/span&gt;)&lt;/span&gt; f&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;skipspaces &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;c&lt;span class="variable"&gt;:&lt;/span&gt;rest&lt;/span&gt;)&lt;/span&gt; f &amp;nbsp;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;|&lt;/span&gt; not&lt;span class="paren1"&gt;(&lt;span class="paste"&gt;f c&lt;/span&gt;)&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; skipspaces rest f&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;|&lt;/span&gt; otherwise&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;=&lt;/span&gt; c&lt;span class="variable"&gt;:&lt;/span&gt;rest&lt;br/&gt;&lt;br/&gt;&lt;span class="keyword"&gt;data&lt;/span&gt; &lt;span class="variable"&gt;Idx&lt;/span&gt; a&lt;span class="keyword"&gt;=&lt;/span&gt; &lt;span class="variable"&gt;Idx&lt;/span&gt; a&lt;br/&gt;&lt;span class="keyword"&gt;instance&lt;/span&gt; &lt;span class="variable"&gt;Show&lt;/span&gt; a &lt;span class="atom"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="variable"&gt;Indexable&lt;/span&gt; &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="variable"&gt;Idx&lt;/span&gt; a&lt;/span&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;listIze &amp;nbsp;a &lt;span class="keyword"&gt;=&lt;/span&gt; listIze &lt;span class="atom"&gt;$&lt;/span&gt; &lt;span class="variable"&gt;Words&lt;/span&gt; &lt;span class="atom"&gt;$&lt;/span&gt; show a&lt;br/&gt;&lt;br/&gt;&lt;span class="keyword"&gt;instance&lt;/span&gt; &lt;span class="variable"&gt;Show&lt;/span&gt; a&lt;span class="atom"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="variable"&gt;Show&lt;/span&gt;&lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="variable"&gt;Idx&lt;/span&gt; a&lt;/span&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;where&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;show &lt;span class="paren1"&gt;(&lt;span class="paste"&gt;&lt;span class="variable"&gt;Idx&lt;/span&gt; a&lt;/span&gt;)&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt; show a&lt;/tt&gt;&lt;br /&gt;          &lt;/td&gt;&lt;br /&gt;        &lt;/tr&gt;&lt;br /&gt;        &lt;/tbody&gt;&lt;br /&gt;      &lt;/table&gt;&lt;br /&gt;    &lt;/div&gt;&lt;br /&gt;    &amp;nbsp;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;      &amp;nbsp;&lt;br /&gt;    &lt;/p&gt;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;      With this quick and dirty filter definitions for Text, XML/HTML and&lt;br /&gt;      Haskell registers, we can do this:&lt;br /&gt;    &lt;/p&gt;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;      &amp;nbsp;&lt;br /&gt;    &lt;/p&gt;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;      &lt;table class="paste-header"&gt;&lt;br /&gt;        &lt;tbody&gt;&lt;br /&gt;        &lt;tr&gt;&lt;br /&gt;          &lt;td align="left" nowrap="" valign="top"&gt;&lt;br /&gt;          &lt;/td&gt;&lt;br /&gt;          &lt;td width="100%"&gt;&lt;br /&gt;            &amp;nbsp;&lt;br /&gt;          &lt;/td&gt;&lt;br /&gt;        &lt;/tr&gt;&lt;br /&gt;        &lt;/tbody&gt;&lt;br /&gt;      &lt;/table&gt;&lt;br /&gt;      &lt;div&gt;&lt;br /&gt;        &lt;table bgcolor="#ccffff" border="0" cellpadding="1" cellspacing="2" width="100%"&gt;&lt;br /&gt;          &lt;tbody&gt;&lt;br /&gt;          &lt;tr&gt;&lt;br /&gt;            &lt;td bgcolor="#f4f4f4" colspan="2" width="100%"&gt;&lt;br /&gt;              &lt;tt&gt;&lt;span class="keyword"&gt;data&lt;/span&gt; &lt;span class="variable"&gt;Register&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt;&lt;span class="variable"&gt;Reg&lt;/span&gt; &lt;span class="variable"&gt;String&lt;/span&gt; &lt;span class="variable"&gt;Integer&lt;/span&gt; &lt;span class="keyword"&gt;deriving&lt;/span&gt; &lt;span class="variable"&gt;Show&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;span class="function"&gt;main&lt;/span&gt;&lt;span class="keyword"&gt;=&lt;/span&gt;&lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&lt;br/&gt;&amp;nbsp;&amp;nbsp;addObject &lt;span class="string"&gt;"input1.txt"&lt;/span&gt; &lt;span class="atom"&gt;$&lt;/span&gt; &lt;span class="variable"&gt;Words&lt;/span&gt; &lt;span class="string"&gt;"John, 18"&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&lt;br/&gt;&amp;nbsp;&amp;nbsp;addObject &lt;span class="string"&gt;"input2.html"&lt;/span&gt; &lt;span class="atom"&gt;$&lt;/span&gt; &lt;span class="variable"&gt;XMLText&lt;/span&gt; &lt;span class="string"&gt;"&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;p&amp;gt;John&amp;lt;/p&amp;gt;&amp;lt;body&amp;gt;18&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;"&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&lt;br/&gt;&amp;nbsp;&amp;nbsp;addObject &lt;span class="string"&gt;"HaskelReg.hs"&lt;/span&gt; &lt;span class="atom"&gt;$&lt;/span&gt; &lt;span class="variable"&gt;Idx&lt;/span&gt; &lt;span class="atom"&gt;$&lt;/span&gt; &lt;span class="variable"&gt;Reg&lt;/span&gt; &lt;span class="string"&gt;"John"&lt;/span&gt; 18&lt;br/&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;r&lt;span class="keyword"&gt;&amp;lt;-&lt;/span&gt; search &lt;span class="paren1"&gt;[&lt;span class="paste"&gt;&lt;span class="string"&gt;"John"&lt;/span&gt;,&lt;span class="string"&gt;"18"&lt;/span&gt;&lt;/span&gt;]&lt;/span&gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;print r&lt;br/&gt;&lt;/tt&gt;&lt;br /&gt;            &lt;/td&gt;&lt;br /&gt;          &lt;/tr&gt;&lt;br /&gt;          &lt;/tbody&gt;&lt;br /&gt;        &lt;/table&gt;&lt;br /&gt;      &lt;/div&gt;&lt;br /&gt;      &lt;p&gt;&lt;br /&gt;        &amp;nbsp;&lt;br /&gt;      &lt;/p&gt;&lt;br /&gt;      &lt;font face="Courier New"&gt;&lt;span class="keyword"&gt;&lt;br /&gt;      &lt;div&gt;&lt;br /&gt;        &lt;p&gt;&lt;br /&gt;          The source of &lt;font color="#6666cc"&gt;Search.hs &lt;/font&gt;can be found&lt;br /&gt;          &lt;a href="http://www.box.net/public/fdkami7jbk"&gt;&lt;font color="#999999"&gt;here&lt;/font&gt;&lt;/a&gt;&lt;br /&gt;        &lt;/p&gt;&lt;br /&gt;        &lt;p&gt;&lt;br /&gt;          &amp;nbsp;&lt;br /&gt;        &lt;/p&gt;&lt;br /&gt;        &lt;p&gt;&lt;br /&gt;          See&lt;br /&gt;          &lt;a href="http://haskell-web.blogspot.com/2006/11/search-engine-written-in-haskell-part_24.html" title="part 2"&gt;part&lt;br /&gt;          2&lt;/a&gt;&amp;nbsp; of the search engine&lt;br /&gt;        &lt;/p&gt;&lt;br /&gt;      &lt;/div&gt;&lt;br /&gt;      &lt;/span&gt;&lt;/font&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37577615-7671485339545859183?l=haskell-web.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://haskell-web.blogspot.com/feeds/7671485339545859183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37577615&amp;postID=7671485339545859183' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/7671485339545859183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37577615/posts/default/7671485339545859183'/><link rel='alternate' type='text/html' href='http://haskell-web.blogspot.com/2006/11/search-engine-written-in-haskell.html' title='A search engine written in Haskell'/><author><name>Alberto</name><uri>http://www.blogger.com/profile/11962281728014883353</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></feed>
