| CARVIEW |
Select Language
HTTP/2 200
cross-origin-resource-policy: cross-origin
etag: W/"b260a1e0df2eed55c8e9609ce6c2cc735df3254fb239b990e3b15fad213bfdeb"
date: Sat, 17 Jan 2026 06:48:02 GMT
content-type: application/atom+xml; charset=UTF-8
server: blogger-renderd
expires: Sat, 17 Jan 2026 06:48:03 GMT
cache-control: public, must-revalidate, proxy-revalidate, max-age=1
x-content-type-options: nosniff
x-xss-protection: 0
last-modified: Fri, 09 Jan 2026 15:32:05 GMT
content-encoding: gzip
content-length: 33201
x-frame-options: SAMEORIGIN
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
tag:blogger.com,1999:blog-8387731529560364137 2026-01-09T16:32:05.577+01:00 A dose of logic A blag containing my current adventures in logic, haskell and agents. Nebasuke https://www.blogger.com/profile/00690086652715846121 noreply@blogger.com Blogger 13 1 25 tag:blogger.com,1999:blog-8387731529560364137.post-4575254415978870584 2011-05-01T13:57:00.004+02:00 2011-05-04T17:17:49.595+02:00 Slides about Martin-Löf type theory It's been a while since my last update. Anyway, last year, I participated in the seminar Dependently typed programming given by Andres Löh and Doaitse Swierstra. I gave a presentation, or more of a lecture really, about Martin-Löf type theory, the Curry-Howard correspondence and some of its connections with Agda. <br /><br />Since I thought it would still be useful to share, here are the slides:<br /><a title="View Type Systems on Scribd" href="https://www.scribd.com/doc/54313539/Type-Systems" style="margin: 12px auto 6px auto; font-family: Helvetica,Arial,Sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 14px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none; display: block; text-decoration: underline;">Type Systems</a><iframe class="scribd_iframe_embed" src="https://www.scribd.com/embeds/54313539/content?start_page=1&view_mode=slideshow&access_key=key-28q3ghwna8b0fbsszx24" data-auto-height="true" data-aspect-ratio="1.33115468409586" scrolling="no" id="doc_58782" width="100%" height="600" frameborder="0"></iframe><script type="text/javascript">(function() { var scribd = document.createElement("script"); scribd.type = "text/javascript"; scribd.async = true; scribd.src = "https://www.scribd.com/javascripts/embed_code/inject.js"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(scribd, s); })();</script><br /><br />Download the slides <a href="https://www.students.science.uu.nl/~3448584/TypeSystems.pdf">here</a>. Nebasuke https://www.blogger.com/profile/00690086652715846121 noreply@blogger.com 6 tag:blogger.com,1999:blog-8387731529560364137.post-2150646011075297725 2010-06-28T14:36:00.005+02:00 2010-06-28T14:43:46.148+02:00 Linking Interaction Nets and Post Canonical Systems And one more update due to a <a href="https://www.students.science.uu.nl/~3448584/paper_MoC.pdf">paper</a> I wrote for the Models of Computation course. I'd like to attend you all to a very beautiful model of computation called interaction nets. One application this model is used for is to optimally implement lambda calculus in a certain theoretical sense.<br /><br />The paper I wrote connects the Post correspondence problem (PCP) to interaction nets, by reducing PCP in a number of steps to an interaction net and giving some suggestions for the other way around. (Thereby proving interaction nets at least Turing complete, and leaving the suggestion for Turing equivalence.) <br /><br />The reverse proof is much more involved, needing multiple reduction steps, possibly through the chemical abstract machine I referenced. <br /><br />I hope some of you will be inspired by interaction nets. <br /><br /><br />You can find the paper <a href="https://www.students.science.uu.nl/~3448584/paper_MoC.pdf">here</a>. Nebasuke https://www.blogger.com/profile/00690086652715846121 noreply@blogger.com 0 tag:blogger.com,1999:blog-8387731529560364137.post-7411017981315567335 2010-06-28T14:16:00.004+02:00 2010-06-28T15:22:58.794+02:00 Slides Church-Turing Thesis and Gödels Incompleteness Theorems A pair of slides this time. Again for Models of Computation I held a presentation, this time about the Church-Turing Thesis and some interesting variants of it. As a computer scientist one should really know the general ideas surrounding it.<br /><br />And finally slides for a Philosophy of AI course about Gödel's Incompleteness Theorems (mostly the first theorem). In the slides I tackle some possible misconceptions when interpreting the theorem and try to convince you that Gödel's Incompleteness Theorems, although very interesting, are not very usable <span style="font-weight:bold;">in</span> a philosophical argument, but can be used as a starting point for devising new philosophical theories.<br /><br /><br />I hope you'll find it interesting and comments are always welcome.<br /><br />The slides for the Church-Turing Thesis can be downloaded <a href="https://www.students.science.uu.nl/~3448584/slides_MoC_CT.pdf">here</a>.<br />The slides for Gödel's Incompleteness Theorems can be downloaded <a href="https://www.students.science.uu.nl/~3448584/slides_WBFAI.pdf">here</a>.<br /><br /><a title="View Slides Church-Turing Thesis (MoC) on Scribd" href="https://www.scribd.com/doc/33655854/Slides-Church-Turing-Thesis-MoC" style="margin: 12px auto 6px auto; font-family: Helvetica,Arial,Sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 14px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none; display: block; text-decoration: underline;">Slides Church-Turing Thesis (MoC)</a> <object id="doc_249935967890226" name="doc_249935967890226" height="600" width="100%" type="application/x-shockwave-flash" data="https://d1.scribdassets.com/ScribdViewer.swf" style="outline:none;" > <param name="movie" value="https://d1.scribdassets.com/ScribdViewer.swf"> <param name="wmode" value="opaque"> <param name="bgcolor" value="#ffffff"> <param name="allowFullScreen" value="true"> <param name="allowScriptAccess" value="always"> <param name="FlashVars" value="document_id=33655854&access_key=key-2l8rb2go88226hwqavxe&page=1&viewMode=slideshow"> <embed id="doc_249935967890226" name="doc_249935967890226" src="https://d1.scribdassets.com/ScribdViewer.swf?document_id=33655854&access_key=key-2l8rb2go88226hwqavxe&page=1&viewMode=slideshow" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="600" width="100%" wmode="opaque" bgcolor="#ffffff"></embed> </object><br /><br /><br /><a title="View Slides Gödels Incompleteness Theorems on Scribd" href="https://www.scribd.com/doc/33655856/Slides-Godels-Incompleteness-Theorems" style="margin: 12px auto 6px auto; font-family: Helvetica,Arial,Sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 14px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none; display: block; text-decoration: underline;">Slides Gödels Incompleteness Theorems</a> <object id="doc_982873126743058" name="doc_982873126743058" height="600" width="100%" type="application/x-shockwave-flash" data="https://d1.scribdassets.com/ScribdViewer.swf" style="outline:none;" > <param name="movie" value="https://d1.scribdassets.com/ScribdViewer.swf"> <param name="wmode" value="opaque"> <param name="bgcolor" value="#ffffff"> <param name="allowFullScreen" value="true"> <param name="allowScriptAccess" value="always"> <param name="FlashVars" value="document_id=33655856&access_key=key-pnhqvhh4efiuvharp2j&page=1&viewMode=slideshow"> <embed id="doc_982873126743058" name="doc_982873126743058" src="https://d1.scribdassets.com/ScribdViewer.swf?document_id=33655856&access_key=key-pnhqvhh4efiuvharp2j&page=1&viewMode=slideshow" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="600" width="100%" wmode="opaque" bgcolor="#ffffff"></embed> </object><br /><br /><br />The slides for the Church-Turing Thesis can be downloaded <a href="https://www.students.science.uu.nl/~3448584/slides_MoC_CT.pdf">here</a>.<br />The slides for Gödel's Incompleteness Theorems can be downloaded <a href="https://www.students.science.uu.nl/~3448584/slides_WBFAI.pdf">here</a>. Nebasuke https://www.blogger.com/profile/00690086652715846121 noreply@blogger.com 0 tag:blogger.com,1999:blog-8387731529560364137.post-1011291794467585488 2010-05-18T19:49:00.006+02:00 2010-06-28T14:31:36.156+02:00 Post's Correspondence Problem So I held a presentation for my course Models of Computation and I thought I'd share the slides with you. <br /><br />The presentation is about the classic recursively unsolvable problem called Post's Correspondence Problem. I hope you find it interesting.<br /><br /><br /><a title="View Slides MoC on Scribd" href="https://www.scribd.com/doc/31558322/Slides-MoC" style="margin: 12px auto 6px auto; font-family: Helvetica,Arial,Sans-serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 14px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none; display: block; text-decoration: underline;">Slides MoC</a> <object id="doc_520844192933651" name="doc_520844192933651" height="500" width="100%" type="application/x-shockwave-flash" data="https://d1.scribdassets.com/ScribdViewer.swf" style="outline:none;" rel="media:presentation" resource="https://d1.scribdassets.com/ScribdViewer.swf?document_id=31558322&access_key=key-7ylwvxfyhouh1hyju47&page=1&viewMode=slideshow" xmlns:media="https://search.yahoo.com/searchmonkey/media/" xmlns:dc="https://purl.org/dc/terms/" > <param name="movie" value="https://d1.scribdassets.com/ScribdViewer.swf"> <param name="wmode" value="opaque"> <param name="bgcolor" value="#ffffff"> <param name="allowFullScreen" value="true"> <param name="allowScriptAccess" value="always"> <param name="FlashVars" value="document_id=31558322&access_key=key-7ylwvxfyhouh1hyju47&page=1&viewMode=slideshow"> <embed id="doc_520844192933651" name="doc_520844192933651" src="https://d1.scribdassets.com/ScribdViewer.swf?document_id=31558322&access_key=key-7ylwvxfyhouh1hyju47&page=1&viewMode=slideshow" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="500" width="100%" wmode="opaque" bgcolor="#ffffff"></embed> </object><br /><br /><span style="font-weight:bold;">Updated:</span><br />You can get the slides <a href="https://www.students.science.uu.nl/~3448584/slides_MoC_PCP.pdf">here</a>.<br />I now completed the course and completed a paper related to this presentation. You can find that <a href="https://www.students.science.uu.nl/~3448584/paper_MoC.pdf">here</a>. Nebasuke https://www.blogger.com/profile/00690086652715846121 noreply@blogger.com 0 tag:blogger.com,1999:blog-8387731529560364137.post-6456941282743189956 2010-04-07T20:02:00.011+02:00 2011-05-04T17:26:59.230+02:00 A small handout on TTTAS (Typed Transformations of Typed Abstract Syntax) This period I did the course Advanced Functional Programming and I had to choose a subject from a set list of subjects to present. I chose typed transformations of typed abstract syntax (TTTAS). (See <a href="https://www.cs.uu.nl/wiki/Center/TTTAS">this webpage</a> for the technical report and associated library by Arthur Baars, Doaitse Swierstra and Marcos Viera.)<br /><br />I already expected the subject to be one of the harder ones and I also had a restriction for the presentation due to practical issues, namely we could only use handouts (or your own laptop) and not a beamer because of multiple presenters. <br /><br />Thus I made some handouts in a tutorial like fashion. It might save you some typing of the code found in the paper and hopefully get you interested in the subject. You might also find it useful to get some motivation for the use of GADTs and transformations of EDSLs in general. <br /><br /><span style="font-weight:bold;">The handouts:</span><br />The PDF file is <a href="https://www.students.science.uu.nl/~3448584/Blog/TTTAS/AFPPresentation.pdf">here</a>.<br />The lhs can be found <a href="https://www.students.science.uu.nl/~3448584/Blog/TTTAS/AFPPresentation.lhs">here</a>. Nebasuke https://www.blogger.com/profile/00690086652715846121 noreply@blogger.com 2 tag:blogger.com,1999:blog-8387731529560364137.post-1137961342570882071 2010-01-10T12:01:00.017+01:00 2010-01-11T12:02:36.229+01:00 Using LaTeX for homework exercises Last period I had a course about development of knowledge systems for which I had to do weekly (and quite large) assignments. The assignments were more suited for information science majors and therefore easier on the technical side. So I found this a good opportunity to invest some time in learning some more LaTeX by doing (most of) the exercises in LaTeX.<br /><br />Anyway, one of the problems I had while working with LaTeX was the lack of larger examples. The documentation for LaTeX and the packages I used was pretty good most of the times, but larger examples still help a lot when you're just starting out. So hoping some people will get use out of it, I've uploaded the sources of my solutions to the exercises. (Of course these solutions are not 100% correct.) <br /><br /><br />Some of the packages I used were amsmath and amssymb. These really helped a lot to do the proofs. (Some documentation can be found <a href="ftp://ftp.ams.org/pub/tex/doc/amsmath/amsldoc.pdf">here</a> and <a href="ftp://ftp.ams.org/pub/tex/doc/amsmath/short-math-guide.pdf">here</a>.)<br /><br />For Assignment 2 I also learned to use <a href="https://www.graphviz.org/">graphviz</a> to draw my graphs. So some example DOT files are included in the extras. (The guide I used was <a href="https://www.graphviz.org/pdf/dotguide.pdf">here</a>.)<br /><br /><br />I split the assignments into the original problem description (the part I had to deliver was the hand-in part), the LaTeX source and other sources such as pictures, the final outputted PDF and possibly additional sources such as the solutions in the tools. <br /><br /><br />Assignment 1 (Logic): <br /><a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_1/Problem_Description/as1.pdf">Problem description</a> | <a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_1/Sources.zip">LaTeX + other source files</a> | <a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_1/PDF_Output/Assignment1.pdf">Outputted PDF</a> | <a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_1/Extras.zip">Extra files</a><br />(Extra files include the python files I used and edited to generate the truth tables in LaTeX, thanks to <a href="https://www.siafoo.net/snippet/249">midorikid</a>)<br /><br /><br />Assignment 2 (CLIPS): <br /><a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_2/Problem_Description/assignment2.pdf">Problem description</a> | <a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_2/Sources.zip">LaTeX + other source files</a> | <a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_2/PDF_Output/as2-vanGijzel-3448584.pdf">Outputted PDF</a> | <a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_2/Extras.zip">Extra files</a> | <a href="https://clipsrules.sourceforge.net/">CLIPS</a><br />(Extra files include the DOT files I used for graphviz, Microsoft Visio Drawing of the family tree and the CLIPS files I made.)<br /><br />Assignment 3 (Protégé):<br />This was not done in LaTeX because I did not have access to my own computer. If you're interested, tell me, and I'll find the sources from Protégé and Microsoft Word anyway.<br /><br />Assignment 4 (Hugin/Probability Theory):<br /><a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_4/Problem_Description/assignment4.pdf">Problem description</a> | <a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_4/Sources.zip">LaTeX + other source files</a> | <a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_4/PDF_Output/as4-vanGijzel-3448584.pdf">Outputted PDF</a> | <a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_4/Extras.zip">Extra files</a> | <a href="https://www.hugin.com/productsservices/demo/hugin-lite">Hugin</a><br />(Extra files include the multiple probabilistic networks.)<br /><br />Assignment 5 (Fuzzy Logic/Systems):<br /><a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_5/Problem_Description/assignment5.pdf">Problem description</a> | <a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_5/Sources.zip">LaTeX + other source files</a> | <a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_5/PDF_Output/as5-vanGijzel-3448584.pdf">Outputted PDF</a> | <a href="https://www.students.cs.uu.nl/~bmgijzel/Blog/Assignment_5/Extras.zip">Extra files</a> <br />(Extra files include the Maple 13 file to model the functions.) Nebasuke https://www.blogger.com/profile/00690086652715846121 noreply@blogger.com 4 tag:blogger.com,1999:blog-8387731529560364137.post-7724825278751979106 2009-11-04T22:01:00.003+01:00 2009-11-04T22:15:37.693+01:00 Comparing Parser Construction Techniques Already a few months ago I completed my Bachelor computer science by writing a small paper and attending and presenting at a student conference. Well anyway, the topic I wrote about is parser construction techniques. The paper talks about parser generators (ANTLR in specific), parser combinators (Parsec 2) and a nice novel combination of the two (Tinadic Parsing, still to published somewhere in the future). <br /><br />Anyway I hope this paper might be interesting to some people reading my blog. The paper comes with quite some code examples and it's probably not a very hard read. So you might consider it a small tutorial on parser construction techniques (or even learn some Parsec while you're at it :) ). <br /><br />My paper can be found <a href="https://referaat.cs.utwente.nl/new/paper.php?paperID=504">here at the website of the University of Twente</a>. <br /><br />The accompanying code examples can be found <a href="https://wwwhome.cs.utwente.nl/~michaelw/projects/vgijzel/parsercode.zip">here</a>. If someone would really appreciate it, I might consider writing some more documentation. <br /><br /><br /><br />As you might have noticed blog posts were a bit scarce the last weeks, because of my silly ambition of taking 3 instead of 2 courses :P. Anyway, I'm liking the pace but my side activities suffer a bit, so I'll probably switch back after next period. <br />(People waiting for the extended state monad implementation: I haven't given up yet!) Nebasuke https://www.blogger.com/profile/00690086652715846121 noreply@blogger.com 6 tag:blogger.com,1999:blog-8387731529560364137.post-6543357804698898260 2009-09-11T18:51:00.019+02:00 2009-09-15T17:27:16.239+02:00 Breaking GHC and the monad laws So the summer school Applied Functional Programming at the University of Utrecht ended a few weeks ago. I really had a lot of fun and learned even more than I had fun ;). Anyway during the summer school we received a lot of extra exercises you could do out of your own interests. So I picked up one of the exercises I didn't do during course. Namely an extension of the state monad. <br /><br />In this exercise you should extend the state monad in such a way it keeps track of the number of binds, returns and some other capabilities. One can read the full exercise <a href="https://www.cs.uu.nl/wiki/pub/USCS2009/ComputerLab/StateMonad.pdf">here.</a> In short if you have a computation like this: <br /><pre><font color=Green><u>do</u></font> return <font color=Magenta>3</font> <font color=Cyan>>></font> return <font color=Magenta>4</font><br /> return <font color=Magenta>5</font><br /> diagnostics</pre><br />After running this computation in the state monad one should have a result that somewhat looks like this:<br /><pre> "[bind=3, diagnostics=1, return=3]"</pre><br /><br />That looks doable, but is a lot more tedious than you except at first. Anyway, a very important point you should catch is that after implementing this functionality we now do NOT abide to the monad laws anymore. <br /><br />Remember the monad laws (stolen from <a href="https://www.haskell.org/haskellwiki/Monad_Laws">here</a>):<br /><pre> <br /> 1. "Left identity": return a >>= f ≡ f a<br /> 2. "Right identity": m >>= return ≡ m<br /> 3. "Associativity": (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g) <br /></pre><br />As you can see all three laws can transform an expression on the left side to an expression that contains one bind less. Therefore if we perform a computation in our state monad we would have a different number of binds after transforming and could therefore give a different result when getting out our number of binds and returns.<br /><br /><br />But let's first return to the implementation of this extension. I chose a Map with strings to int that can keep track of the number of binds and annotations. So we now have a State Monad with some extra functionality: <br /><pre><font color=Green><u>data</u></font> StateMonadPlus s a <font color=Red>=</font> StateMonadPlus <font color=Cyan>{</font>runStateMonadPlus<font color=Red>::</font> <font color=Cyan>(</font>s<font color=Cyan>,</font>Map String Int<font color=Cyan>)</font> <font color=Red>-></font> <font color=Cyan>(</font>a<font color=Cyan>,</font> s<font color=Cyan>,</font> Map String Int<font color=Cyan>)</font><font color=Cyan>}</font><br /></pre><br />This is very similar to the original definition of the State Monad. (If you forgot some parts of it you can read a part of my State Monad tutorial <a href="https://adoseoflogic.blogspot.com/2009/07/cannibals-missionaries-and-state-monad_21.html">here</a>. <br /><br />Anyway, before defining the Monad instance we define a useful helper function for updating the Map that keeps track of the number of binds and annotations and another function that puts the diagnostics as the result of the computation. <br />diagnostics :: StateMonadPlus s String<br />diagnostics = StateMonadPlus $ \(s,m) -> <br /> let m2 = updateMap "diagnostics" m <br /> in ((show m2 ), s, m2)<br /><pre><font color=Blue>updateMap</font> <font color=Red>::</font> Ord k <font color=Red>=></font> k <font color=Red>-></font> Map k Int <font color=Red>-></font> Map k Int<br /><font color=Blue>updateMap</font> k <font color=Red>=</font> M<font color=Cyan>.</font>insertWith <font color=Cyan>(</font><font color=Cyan>+</font><font color=Cyan>)</font> k <font color=Magenta>1</font></pre><br /><br />And now for the Monad instance:<pre><font color=Blue>test1</font> <font color=Red>=</font> <font color=Green><u>do</u></font> diagnostics<br /> return <font color=Magenta>4</font> <br /> return <font color=Magenta>5</font><br /> mget<br /><br /><font color=Blue>diag</font> <font color=Red>=</font> diagStateMonadPlus test1 undefined<br /><font color=Blue>eval</font> <font color=Red>=</font> evalStateMonadPlus test1 undefined<br /><font color=Blue>diageval</font> <font color=Red>=</font> <font color=Cyan>(</font>diag<font color=Cyan>,</font> eval<font color=Cyan>)</font></pre><br /><br />Anyway, halfway during the implementation I got stuck on something that seemed like a bug in my program, but before spoiling everything I will first show the functions I defined for running and evaluating our freshly made State Monad.<br /><pre><font color=Blue>evalStateMonadPlus</font> <font color=Red>::</font> StateMonadPlus s a <font color=Red>-></font> s <font color=Red>-></font> a<br /><font color=Blue>evalStateMonadPlus</font> <font color=Cyan>(</font>StateMonadPlus s<font color=Cyan>)</font> st <font color=Red>=</font> <font color=Green><u>let</u></font> <font color=Cyan>(</font>a<font color=Cyan>,</font>b<font color=Cyan>,</font>c<font color=Cyan>)</font> <font color=Red>=</font> s <font color=Cyan>(</font>st<font color=Cyan>,</font> M<font color=Cyan>.</font>empty<font color=Cyan>)</font> <font color=Green><u>in</u></font> a<br /><br /><font color=Blue>execStateMonadPlus</font> <font color=Red>::</font> StateMonadPlus s a <font color=Red>-></font> s <font color=Red>-></font> s <br /><font color=Blue>execStateMonadPlus</font> <font color=Cyan>(</font>StateMonadPlus s<font color=Cyan>)</font> st <font color=Red>=</font> <font color=Green><u>let</u></font> <font color=Cyan>(</font>a<font color=Cyan>,</font>b<font color=Cyan>,</font>c<font color=Cyan>)</font> <font color=Red>=</font> s <font color=Cyan>(</font>st<font color=Cyan>,</font> M<font color=Cyan>.</font>empty<font color=Cyan>)</font> <font color=Green><u>in</u></font> b<br /><br /><font color=Blue>diagStateMonadPlus</font> <font color=Red>::</font> StateMonadPlus s a <font color=Red>-></font> s <font color=Red>-></font> Map String Int<br /><font color=Blue>diagStateMonadPlus</font> <font color=Cyan>(</font>StateMonadPlus s<font color=Cyan>)</font> st <font color=Red>=</font> <font color=Green><u>let</u></font> <font color=Cyan>(</font>a<font color=Cyan>,</font>b<font color=Cyan>,</font>c<font color=Cyan>)</font> <font color=Red>=</font> s <font color=Cyan>(</font>st<font color=Cyan>,</font> M<font color=Cyan>.</font>empty<font color=Cyan>)</font> <font color=Green><u>in</u></font> c<br /><br /><font color=Green><u>instance</u></font> MonadState s <font color=Cyan>(</font>StateMonadPlus s<font color=Cyan>)</font> <font color=Green><u>where</u></font><br /> get <font color=Red>=</font> StateMonadPlus <font color=Cyan>$</font> <font color=Red>\</font><font color=Cyan>(</font>s<font color=Cyan>,</font>m<font color=Cyan>)</font> <font color=Red>-></font> <font color=Cyan>(</font>s<font color=Cyan>,</font> s<font color=Cyan>,</font> m<font color=Cyan>)</font><br /> put a <font color=Red>=</font> StateMonadPlus <font color=Cyan>$</font> <font color=Red>\</font><font color=Cyan>(</font><font color=Green><u>_</u></font><font color=Cyan>,</font> m<font color=Cyan>)</font> <font color=Red>-></font> <font color=Cyan>(</font>()<font color=Cyan>,</font>a<font color=Cyan>,</font> m<font color=Cyan>)</font><br /><br /><font color=Blue>mget</font><font color=Red>::</font> StateMonadPlus s <font color=Cyan>(</font>Map String Int<font color=Cyan>)</font><br /><font color=Blue>mget</font> <font color=Red>=</font> StateMonadPlus <font color=Cyan>$</font> <font color=Red>\</font><font color=Cyan>(</font>s<font color=Cyan>,</font>m<font color=Cyan>)</font> <font color=Red>-></font> <font color=Cyan>(</font>m<font color=Cyan>,</font> s<font color=Cyan>,</font> m<font color=Cyan>)</font></pre><br /><br />Here the get and put functions are the familiar functions in the original state monad, and mget does something similar to diagnostics, by putting our map into the result. <br /><br />Because I defined a multi parameter type class, and a flexible instance too, we will have to add some compiler pragma's to be able to use them. And we furthermore used some imports. So just add this to the start of the module:<br /><pre><font color=Blue><i>{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}</i></font><br /><font color=Green><u>module</u></font> StateMonadExercise <font color=Green><u>where</u></font><br /><font color=Green><u>import</u></font> Control<font color=Cyan>.</font>Monad<font color=Cyan>.</font>State<br /><font color=Green><u>import</u></font> <font color=Green><u>qualified</u></font> Data<font color=Cyan>.</font>Map <font color=Green><u>as</u></font> M<br /><font color=Green><u>import</u></font> Data<font color=Cyan>.</font>Map<font color=Cyan>(</font>Map<font color=Cyan>)</font></pre><br /><br />So the only part left to test this functionality is to define some tests:<br /><pre><font color=Blue>test1</font> <font color=Red>=</font> <font color=Green><u>do</u></font> return <font color=Magenta>4</font> <br /> return <font color=Magenta>5</font><br /> mget<br /><br /><font color=Blue>diag</font> <font color=Red>=</font> diagStateMonadPlus test1 undefined<br /><font color=Blue>eval</font> <font color=Red>=</font> evalStateMonadPlus test1 undefined<br /><font color=Blue>diageval</font> <font color=Red>=</font> <font color=Cyan>(</font>diag<font color=Cyan>,</font> eval<font color=Cyan>)</font></pre><br /><br />So now we're ready to run these test right? (I've enclosed the full test module at the end of this blog post for your convenience, so you could just copy the whole code at once if you'd like.)<br /><br />Anyway, after running these test, (and I think it's not a bug on my part but a (maybe) too enthusiastic optimization of GHC (6.10.4)). We get these results:<br /><pre> <br /><span style="font-weight:bold;">*StateMonadExercise></span> diag<br />fromList [("bind",2),("return",2)]<br /><span style="font-weight:bold;">*StateMonadExercise></span> eval<br />fromList [("return",2)]<br /><span style="font-weight:bold;">*StateMonadExercise></span> diageval<br />(fromList [("bind",2),("return",2)]<br />,fromList [("return",2)])<br /></pre><br /><br />So here GHC just optimized away 2 binds for the result but not from the map. It serves me right though, since I'm breaking the monad laws anyway :-). <span style="font-weight:bold;">So if anyone can confirm this is GHC's "fault" (or doing) and not mine I would be happy.</span><br />One final comment: I will probably post the full implementation later this month.<br /><br /><br /><span style="font-weight:bold;">The full code:</span><br /><pre><font color=Blue><i>{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}</i></font><br /><font color=Green><u>module</u></font> StateMonadExercise <font color=Green><u>where</u></font><br /><font color=Green><u>import</u></font> Control<font color=Cyan>.</font>Monad<font color=Cyan>.</font>State<br /><font color=Green><u>import</u></font> <font color=Green><u>qualified</u></font> Data<font color=Cyan>.</font>Map <font color=Green><u>as</u></font> M<br /><font color=Green><u>import</u></font> Data<font color=Cyan>.</font>Map<font color=Cyan>(</font>Map<font color=Cyan>)</font><br /><br /><font color=Green><u>data</u></font> StateMonadPlus s a <font color=Red>=</font> StateMonadPlus <font color=Cyan>{</font>runStateMonadPlus<font color=Red>::</font> <font color=Cyan>(</font>s<font color=Cyan>,</font>Map String Int<font color=Cyan>)</font> <font color=Red>-></font> <font color=Cyan>(</font>a<font color=Cyan>,</font> s<font color=Cyan>,</font> Map String Int<font color=Cyan>)</font><font color=Cyan>}</font><br /><br /><font color=Green><u>instance</u></font> Monad <font color=Cyan>(</font>StateMonadPlus s<font color=Cyan>)</font> <font color=Green><u>where</u></font> <br /> return a <font color=Red>=</font> StateMonadPlus <font color=Cyan>$</font> <font color=Cyan>(</font><font color=Red>\</font> <font color=Cyan>(</font>s<font color=Cyan>,</font> m<font color=Cyan>)</font> <font color=Red>-></font> <font color=Cyan>(</font>a<font color=Cyan>,</font> s<font color=Cyan>,</font> updateMap <font color=Magenta>"return"</font> m<font color=Cyan>)</font><font color=Cyan>)</font> <br /> <font color=Cyan>(</font>StateMonadPlus s<font color=Cyan>)</font> <font color=Cyan>>>=</font> f <font color=Red>=</font> StateMonadPlus <font color=Cyan>$</font> <font color=Red>\</font><font color=Cyan>(</font>state<font color=Cyan>,</font> m<font color=Cyan>)</font> <font color=Red>-></font> <br /> <font color=Cyan>(</font><font color=Green><u>let</u></font> <font color=Cyan>(</font>a1<font color=Cyan>,</font> st1<font color=Cyan>,</font> m1<font color=Cyan>)</font> <font color=Red>=</font> s <font color=Cyan>(</font>state<font color=Cyan>,</font>m<font color=Cyan>)</font> <font color=Green><u>in</u></font> <br /> <font color=Green><u>let</u></font> <font color=Cyan>(</font>a2<font color=Cyan>,</font> st2<font color=Cyan>,</font> m2<font color=Cyan>)</font> <font color=Red>=</font> runStateMonadPlus <font color=Cyan>(</font>f a1<font color=Cyan>)</font> <font color=Cyan>(</font>st1<font color=Cyan>,</font>m1<font color=Cyan>)</font><br /> <font color=Green><u>in</u></font> <font color=Cyan>(</font>a2<font color=Cyan>,</font> st2<font color=Cyan>,</font> updateMap <font color=Magenta>"bind"</font> m2<font color=Cyan>)</font><br /> <font color=Cyan>)</font><br /><br /><font color=Blue>updateMap</font> <font color=Red>::</font> Ord k <font color=Red>=></font> k <font color=Red>-></font> Map k Int <font color=Red>-></font> Map k Int<br /><font color=Blue>updateMap</font> k <font color=Red>=</font> M<font color=Cyan>.</font>insertWith <font color=Cyan>(</font><font color=Cyan>+</font><font color=Cyan>)</font> k <font color=Magenta>1</font><br /><br /><font color=Blue>diagnostics</font> <font color=Red>::</font> StateMonadPlus s String<br /><font color=Blue>diagnostics</font> <font color=Red>=</font> StateMonadPlus <font color=Cyan>$</font> <font color=Red>\</font><font color=Cyan>(</font>s<font color=Cyan>,</font>m<font color=Cyan>)</font> <font color=Red>-></font> <br /> <font color=Green><u>let</u></font> m2 <font color=Red>=</font> updateMap <font color=Magenta>"diagnostics"</font> m <br /> <font color=Green><u>in</u></font> <font color=Cyan>(</font><font color=Cyan>(</font>show m2 <font color=Cyan>)</font><font color=Cyan>,</font> s<font color=Cyan>,</font> m2<font color=Cyan>)</font><br /><br /><font color=Blue>evalStateMonadPlus</font> <font color=Red>::</font> StateMonadPlus s a <font color=Red>-></font> s <font color=Red>-></font> a<br /><font color=Blue>evalStateMonadPlus</font> <font color=Cyan>(</font>StateMonadPlus s<font color=Cyan>)</font> st <font color=Red>=</font> <font color=Green><u>let</u></font> <font color=Cyan>(</font>a<font color=Cyan>,</font>b<font color=Cyan>,</font>c<font color=Cyan>)</font> <font color=Red>=</font> s <font color=Cyan>(</font>st<font color=Cyan>,</font> M<font color=Cyan>.</font>empty<font color=Cyan>)</font> <font color=Green><u>in</u></font> a<br /><br /><font color=Blue>execStateMonadPlus</font> <font color=Red>::</font> StateMonadPlus s a <font color=Red>-></font> s <font color=Red>-></font> s <br /><font color=Blue>execStateMonadPlus</font> <font color=Cyan>(</font>StateMonadPlus s<font color=Cyan>)</font> st <font color=Red>=</font> <font color=Green><u>let</u></font> <font color=Cyan>(</font>a<font color=Cyan>,</font>b<font color=Cyan>,</font>c<font color=Cyan>)</font> <font color=Red>=</font> s <font color=Cyan>(</font>st<font color=Cyan>,</font> M<font color=Cyan>.</font>empty<font color=Cyan>)</font> <font color=Green><u>in</u></font> b<br /><br /><font color=Blue>diagStateMonadPlus</font> <font color=Red>::</font> StateMonadPlus s a <font color=Red>-></font> s <font color=Red>-></font> Map String Int<br /><font color=Blue>diagStateMonadPlus</font> <font color=Cyan>(</font>StateMonadPlus s<font color=Cyan>)</font> st <font color=Red>=</font> <font color=Green><u>let</u></font> <font color=Cyan>(</font>a<font color=Cyan>,</font>b<font color=Cyan>,</font>c<font color=Cyan>)</font> <font color=Red>=</font> s <font color=Cyan>(</font>st<font color=Cyan>,</font> M<font color=Cyan>.</font>empty<font color=Cyan>)</font> <font color=Green><u>in</u></font> c<br /><br /><font color=Green><u>instance</u></font> MonadState s <font color=Cyan>(</font>StateMonadPlus s<font color=Cyan>)</font> <font color=Green><u>where</u></font><br /> get <font color=Red>=</font> StateMonadPlus <font color=Cyan>$</font> <font color=Red>\</font><font color=Cyan>(</font>s<font color=Cyan>,</font>m<font color=Cyan>)</font> <font color=Red>-></font> <font color=Cyan>(</font>s<font color=Cyan>,</font> s<font color=Cyan>,</font> m<font color=Cyan>)</font><br /> put a <font color=Red>=</font> StateMonadPlus <font color=Cyan>$</font> <font color=Red>\</font><font color=Cyan>(</font><font color=Green><u>_</u></font><font color=Cyan>,</font> m<font color=Cyan>)</font> <font color=Red>-></font> <font color=Cyan>(</font>()<font color=Cyan>,</font>a<font color=Cyan>,</font> m<font color=Cyan>)</font><br /><br /><font color=Blue>mget</font><font color=Red>::</font> StateMonadPlus s <font color=Cyan>(</font>Map String Int<font color=Cyan>)</font><br /><font color=Blue>mget</font> <font color=Red>=</font> StateMonadPlus <font color=Cyan>$</font> <font color=Red>\</font><font color=Cyan>(</font>s<font color=Cyan>,</font>m<font color=Cyan>)</font> <font color=Red>-></font> <font color=Cyan>(</font>m<font color=Cyan>,</font> s<font color=Cyan>,</font> m<font color=Cyan>)</font><br /><br /><font color=Blue>test1</font> <font color=Red>=</font> <font color=Green><u>do</u></font> return <font color=Magenta>4</font> <br /> return <font color=Magenta>5</font><br /> mget<br /><br /><font color=Blue>diag</font> <font color=Red>=</font> diagStateMonadPlus test1 undefined<br /><font color=Blue>eval</font> <font color=Red>=</font> evalStateMonadPlus test1 undefined<br /><font color=Blue>diageval</font> <font color=Red>=</font> <font color=Cyan>(</font>diag<font color=Cyan>,</font> eval<font color=Cyan>)</font><br /><br /><font color=Blue><i>{-<br />*StateMonadExercise> diag<br />fromList [("bind",2),("return",2)]<br />*StateMonadExercise> eval<br />fromList [("return",2)]<br />*StateMonadExercise> diageval<br />(fromList [("bind",2),("return",2)]<br />,fromList [("return",2)])<br />-}</i></font></pre> Nebasuke https://www.blogger.com/profile/00690086652715846121 noreply@blogger.com 8 tag:blogger.com,1999:blog-8387731529560364137.post-7524208834171800778 2009-08-22T12:32:00.021+02:00 2009-08-22T13:08:11.796+02:00 Parsing L-Systems with the uu-parsinglib So I subscribed to the Utrecht Summer School program Applied Functional Programming a few months ago and got accepted. This week the course finally started. I'm really enjoying the nice lectures, new people I meet and the quick pace of new things to learn.<br />One of the parts in this course is to do a project with 3 to 5 people with different levels in Haskell. But of course almost everyone is very motivated so the different levels work quite well :). Anyway, the project we chose after some discussion was: Write an L-systems generator and/or visualizer.<br /><br />So first a small introduction to L-systems. Wikipedia has a really really great page about it <a href="https://en.wikipedia.org/wiki/L-system">here</a>, and it also contains a <a href="https://algorithmicbotany.org/papers/#abop">link to a free book</a> containing even more information. <br /><br />From Wikipedia: "An L-system or Lindenmayer system is a parallel rewriting system, namely a variant of a formal grammar, most famously used to model the growth processes of plant development, but also able to model the morphology of a variety of organisms.[1] L-systems can also be used to generate self-similar fractals such as iterated function systems. L-systems were introduced and developed in 1968 by the Hungarian theoretical biologist and botanist from the University of Utrecht, Aristid Lindenmayer (1925–1989)." <br /><br />So quite fitting to do at a summer school in Utrecht :).<br /><br />If you don't know L-Systems (like I did) just take a short look at the wiki page. They're quite intuitive if you're familiar with something like BNF or grammars in general.<br /><br /><br /><br />Anyway, we split the project in 4 parts. Namely a GUI for visualizing the L-Systems, a GUI for inputting the generating gramamars and following from that are a parser that can parse the inputted grammar, and an algorithm generating the strings of symbols from an L-System.<br /><br />The part I started on was the parser. I already knew some Parsec (2) before coming to the summer school, but I thought it would be more interesting and fitting to use another parser combinator library, namely the newest version from the University of Utrecht themselves. So I started learning the uu-parsinglib. For the package and tutorial see the hackage page <a href="https://hackage.haskell.org/package/uu-parsinglib">here</a>.<br /><br />Anyway before I completely introduce my parser I'll first talk about the datatype we made up. I thought it was a good idea to settle for the most simple kind of L-Systems as a first implementation. And secondly to start with a very basic kind of alphabet to use for drawing the L-Systems. The alphabet will contain symbols directing the drawing, (F means to go forward and draw, f means to go forward without drawing, - means to turn right and + to turn left), the other symbols would only be used to do nothing or to be used in the generating part of the L-Systems. <br />(The drawing part is called <a href="https://en.wikipedia.org/wiki/Turtle_graphics">Turtle Graphics</a> and is very similar to the <a href="https://en.wikipedia.org/wiki/Logo_%28programming_language%29">Logo programming language</a>.)<br /><br /><br />Here is an EBNF I made that might clear up the problem a bit. I make no difference between variables or constants because you can handle that very easily in the generating part. <br /><pre><br />VariableOrConstant := letter | '+' | '-'<br />StartSymbol := VariableOrConstant+<br />Rule := VariableOrConstant "->" VariableOrConstant*<br />Rules := Rule (('\n' | ',') Rule)*<br /></pre><br />So we decided rules can generate a variable number of new symbols (possibly none). Spaces are allow everywhere except in the arrow. And we decided it's very easy to use the generation on a starting symbols rather than just one symbol.<br /><br />So the logical datatype was this:<br /><pre><font color=Green><u>module</u></font> DataType <font color=Green><u>where</u></font><br /><br /><font color=Blue><i>-- we read in the angle and the movement step size</i></font><br /><font color=Blue><i>-- RightAngle = '-', LeftAngle = '+', Forward = 'F', ForwardSkip = 'f', Variable Char = Char</i></font><br /><font color=Green><u>data</u></font> TurtleMove <font color=Red>=</font> RightAngle <font color=Red>|</font> LeftAngle <font color=Red>|</font> Forward <font color=Red>|</font> ForwardSkip <font color=Red>|</font> Variable Char<br /> <font color=Green><u>deriving</u></font> <font color=Cyan>(</font>Show<font color=Cyan>,</font> Eq<font color=Cyan>,</font> Ord<font color=Cyan>)</font><br /><br /><font color=Green><u>type</u></font> Rule <font color=Red>=</font> <font color=Cyan>(</font>TurtleMove<font color=Cyan>,</font> <font color=Red>[</font>TurtleMove<font color=Red>]</font><font color=Cyan>)</font><br /><font color=Green><u>type</u></font> StartSymbol <font color=Red>=</font> <font color=Red>[</font>TurtleMove<font color=Red>]</font><br /></pre><br />The variables are just non movement symbols used in the grammar. The types are some shorthands that will be used in the parser. <br /><br />The parsers I wrote are most importantly for parsing the rules. <br />I wrote increasingly larger parser building blocks with hopefully enough documentation so I will just give the full parser code. If anyone appreciates some explanation beside the exisisting tutorial you're welcome to ask me. <br />To get the example working, before compiling do a cabal update and cabal install uu-parsinglib. (Or install it manually.) The most interesting method is probably runPRules which will take a string and produce a set of rules. Note the cool error correcting and online parsing from the uu-parsinglib if you enter too many symbols or incorrect symbols by using test.<br /><br /><pre><font color=Green><u>module</u></font> LSystemParser <font color=Green><u>where</u></font><br /><font color=Green><u>import</u></font> Text<font color=Cyan>.</font>ParserCombinators<font color=Cyan>.</font>UU<font color=Cyan>.</font>Parsing <br /><font color=Green><u>import</u></font> Text<font color=Cyan>.</font>ParserCombinators<font color=Cyan>.</font>UU<font color=Cyan>.</font>Examples<br /><font color=Green><u>import</u></font> DataType<br /><br /><font color=Blue><i>-- parse one or more</i></font><br /><font color=Blue>pMany</font> p <font color=Red>=</font> <font color=Cyan>(</font><font color=Red><b>:</b></font><font color=Cyan>)</font> <font color=Cyan><$></font> p <font color=Cyan><*></font> pMany p <font color=Cyan><|></font> pReturn []<br /><br /><font color=Blue><i>-- turn a parsed character into a TurtleMove</i></font><br /><font color=Blue><i>-- RightAngle = '-', LeftAngle = '+', Forward = 'F', ForwardSkip = 'f', Variable Char = Char</i></font><br /><font color=Blue>pLetterToDatatype</font> <font color=Red>::</font> Char <font color=Red>-></font> TurtleMove<br /><font color=Blue>pLetterToDatatype</font> l <font color=Red>=</font> <font color=Green><u>case</u></font> l <font color=Green><u>of</u></font> <br /> <font color=Magenta>'-'</font> <font color=Red>-></font> RightAngle<br /> <font color=Magenta>'+'</font> <font color=Red>-></font> LeftAngle<br /> <font color=Magenta>'F'</font> <font color=Red>-></font> Forward<br /> <font color=Magenta>'f'</font> <font color=Red>-></font> ForwardSkip<br /> other <font color=Red>-></font> Variable other<br /><br /><font color=Blue><i>-- parse a number of spaces</i></font><br /><font color=Blue>spaces</font> <font color=Red>::</font> P_m <font color=Cyan>(</font>Str Char<font color=Cyan>)</font> <font color=Red>[</font>Char<font color=Red>]</font><br /><font color=Blue>spaces</font> <font color=Red>=</font> pList <font color=Cyan>$</font> pSym <font color=Magenta>' '</font><br /><br /><font color=Blue><i>-- parse a variable or turtle graphic primitive</i></font><br /><font color=Blue>pLetter'</font> <font color=Red>::</font> P_m <font color=Cyan>(</font>Str Char<font color=Cyan>)</font> Char<br /><font color=Blue>pLetter'</font> <font color=Red>=</font> pLetter <font color=Cyan><|></font> pSym <font color=Magenta>'-'</font> <font color=Cyan><|></font> pSym <font color=Magenta>'+'</font><br /><br /><font color=Blue><i>-- parse a letter that is possibly surrounded by spaces</i></font><br /><font color=Blue>pSimple</font> <font color=Red>::</font> P_m <font color=Cyan>(</font>Str Char<font color=Cyan>)</font> Char<br /><font color=Blue>pSimple</font> <font color=Red>=</font> <font color=Cyan>(</font><font color=Red>\</font> <font color=Green><u>_</u></font> x <font color=Green><u>_</u></font> <font color=Red>-></font> x<font color=Cyan>)</font> <font color=Cyan><$></font> spaces <font color=Cyan><*></font> pLetter' <font color=Cyan><*></font> spaces<br /><br /><font color=Blue><i>-- parse a letter and turn it into a TurtleMove</i></font><br /><font color=Blue>pVariable</font> <font color=Red>::</font> P_m <font color=Cyan>(</font>Str Char<font color=Cyan>)</font> TurtleMove<br /><font color=Blue>pVariable</font> <font color=Red>=</font> pLetterToDatatype <font color=Cyan><$></font> pSimple<br /><br /><font color=Blue><i>-- parse the right hand side of a rule</i></font><br /><font color=Blue>pWord</font> <font color=Red>::</font> P_m <font color=Cyan>(</font>Str Char<font color=Cyan>)</font> <font color=Red>[</font>TurtleMove<font color=Red>]</font><br /><font color=Blue>pWord</font> <font color=Red>=</font> map pLetterToDatatype <font color=Cyan><$></font> pMany pSimple<br /><br /><font color=Blue><i>-- parse a list of variables separated by commas</i></font><br /><font color=Blue>pVariables</font> <font color=Red>::</font> P_m <font color=Cyan>(</font>Str Char<font color=Cyan>)</font> <font color=Red>[</font>TurtleMove<font color=Red>]</font><br /><font color=Blue>pVariables</font> <font color=Red>=</font> map pLetterToDatatype <font color=Cyan><$></font> pListSep <font color=Cyan>(</font>pSym <font color=Magenta>','</font><font color=Cyan>)</font> pSimple<br /><br /><font color=Blue><i>-- *> doesn't work from R to R</i></font><br /><font color=Blue><i>-- parse an arrow and the right hand side of a rule</i></font><br /><font color=Blue>pArrow</font> <font color=Red>::</font> P_m <font color=Cyan>(</font>Str Char<font color=Cyan>)</font> <font color=Red>[</font>TurtleMove<font color=Red>]</font><br /><font color=Blue>pArrow</font> <font color=Red>=</font> pSym <font color=Magenta>'-'</font> <font color=Cyan>*></font> <font color=Cyan>(</font>pSym <font color=Magenta>'>'</font> <font color=Cyan>*></font> pWord<font color=Cyan>)</font><br /><br /><font color=Blue><i>-- parse one production rule</i></font><br /><font color=Blue>pRule</font> <font color=Red>::</font> P_m <font color=Cyan>(</font>Str Char<font color=Cyan>)</font> Rule<br /><font color=Blue>pRule</font> <font color=Red>=</font> <font color=Cyan>(</font><font color=Red>\</font> x y <font color=Red>-></font> <font color=Cyan>(</font>x<font color=Cyan>,</font>y<font color=Cyan>)</font><font color=Cyan>)</font> <font color=Cyan><$></font> pVariable <font color=Cyan><*></font> pArrow <br /><br /><font color=Blue><i>-- parse a sequence of production rules separated by commas or newlines</i></font><br /><font color=Blue>pRules</font> <font color=Red>::</font> P_m <font color=Cyan>(</font>Str Char<font color=Cyan>)</font> <font color=Red>[</font>Rule<font color=Red>]</font><br /><font color=Blue>pRules</font> <font color=Red>=</font> pListSep <font color=Cyan>(</font>pSym <font color=Magenta>'\n'</font> <font color=Cyan><|></font> pSym <font color=Magenta>','</font><font color=Cyan>)</font> pRule<br /><br /><font color=Blue><i>-- parse the rules and take out the results</i></font><br /><font color=Blue>runPRules</font> <font color=Red>::</font> String <font color=Red>-></font> <font color=Red>[</font>Rule<font color=Red>]</font><br /><font color=Blue>runPRules</font> <font color=Red>=</font> fst <font color=Cyan>.</font> test pRules<br /><br /><font color=Blue>main2</font> <font color=Red>=</font> test pRules <font color=Cyan>$</font> <font color=Magenta>"x -> blaF+-blabla\n F->SKF"</font></pre><br /><br />Well that's it for today :). Nebasuke https://www.blogger.com/profile/00690086652715846121 noreply@blogger.com 1 tag:blogger.com,1999:blog-8387731529560364137.post-6370067162389422588 2009-08-10T15:25:00.000+02:00 2009-08-10T15:26:29.728+02:00 Cannibals, Missionaries and the State Monad pt. 3 <a href="https://adoseoflogic.blogspot.com/2009/07/cannibals-missionaries-and-state-monad.html">Part 1: An Explicit State Implementation of Cannibals and Missionaries</a><br /><a href="https://adoseoflogic.blogspot.com/2009/07/cannibals-missionaries-and-state-monad_21.html">Part 2: A State Monad Introduction</a><br /><br />Well this post took a lot longer to materialize due to the a lot of rewriting and extending of part 2. Anyway, I hope you will enjoy it. Comments are very welcome btw.<br /><br /><br /><big><span style="font-weight:bold;">State Monad Implementation of Cannibals and Missionaries</span></big><br />I will start this post by pointing out possible improvements of the example from part 1, the cannibals and missionaries problem solution. Refer to part 1 for the old implementation if you need a refresher.<br /><br /><br />(First we import Control.Monad.State)<br /><br />As we have seen at the first solution of the Cannibal problem we had defined a search function containing the type signature:<br /><pre><font color=Blue>idfs</font> <font color=Red>::</font> PState <font color=Red>-></font> Int <font color=Red>-></font> <font color=Red>[</font>PState<font color=Red>]</font></pre><br /><br />In the idfs function we increase our Int argument for each recursive call. This Int functioned as a counter for the current maximum search depth. <br />We could hide this integer argument instead of having to explicitly pass it every time we call it recursively. <br /><br /><br />The biggest improvement, however, can be gained by using the state monad in our helper function idfs'. Recall the large type signature of idfs':<br /><pre><font color=Blue>idfs'</font> <font color=Red>::</font> Int <font color=Red>-></font> Int <font color=Red>-></font> Bool <font color=Red>-></font> PState <font color=Red>-></font> <font color=Red>[</font>PState<font color=Red>]</font></pre><br /><br />idfs' takes 4 parameters, which respectively are: the current depth, the current max depth, a boolean depicting if the solution is found and finally the current search node (or state).<br /><br />We will hide this arguments by extending our record PState with some new fields. We will then use PState as our state in the state monad. (We won't need a boolean depicting if the solution is found.)<br />Our new PState:<br /><br /><pre><font color=Green><u>data</u></font> PState <font color=Red>=</font> PState <font color=Cyan>{</font><br /> left <font color=Red>::</font> <font color=Red>[</font>Person<font color=Red>]</font><font color=Cyan>,</font> <font color=Blue><i>-- left side of canal</i></font><br /> right <font color=Red>::</font> <font color=Red>[</font>Person<font color=Red>]</font><font color=Cyan>,</font> <font color=Blue><i>-- right side of canal</i></font><br /> boat <font color=Red>::</font> Position<font color=Cyan>,</font> <font color=Blue><i>-- position of boat</i></font><br /> curDepth <font color=Red>::</font> Int<font color=Cyan>,</font> <font color=Blue><i>-- current search depth</i></font><br /> maxDepth <font color=Red>::</font> Int<font color=Cyan>,</font> <font color=Blue><i>-- max search depth</i></font><br /> path <font color=Red>::</font> <font color=Red>[</font>PState<font color=Red>]</font> <font color=Blue><i>-- path found to solution</i></font><br /> <font color=Cyan>}</font> <br /> <font color=Green><u>deriving</u></font> <font color=Cyan>(</font>Eq<font color=Cyan>,</font> Show<font color=Cyan>)</font></pre><br /><br />Defining our new beginState will be straightforward. The starting current and maxdepth should just be 0. Our idfs algorithm will increment the maxdepth with each recursive call, so 0 seems like a good starting point. The path should start empty.<br /><pre><font color=Blue>beginState</font> <font color=Red>::</font> PState <br /><font color=Blue>beginState</font> <font color=Red>=</font> <br /> PState <font color=Cyan>{</font><br /> left <font color=Red>=</font> <font color=Red>[</font>Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Red>]</font><font color=Cyan>,</font><br /> right <font color=Red>=</font> []<font color=Cyan>,</font> <br /> boat <font color=Red>=</font> LeftSide<font color=Cyan>,</font> <br /> curDepth <font color=Red>=</font> <font color=Magenta>0</font><font color=Cyan>,</font> <br /> maxDepth <font color=Red>=</font> <font color=Magenta>0</font><font color=Cyan>,</font><br /> path <font color=Red>=</font> []<br /> <font color=Cyan>}</font></pre><br /><br />Defining the goal state now has a slight quirk. The fields curDepth, maxDepth and path don't have a sensible goal value and I therefore just use undefined. <br />Our new goalState therefore is:<br /><pre><font color=Blue>goalState</font> <font color=Red>=</font> <br /> PState <font color=Cyan>{</font><br /> left <font color=Red>=</font> []<font color=Cyan>,</font><br /> right <font color=Red>=</font> <font color=Red>[</font>Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Red>]</font><font color=Cyan>,</font> <br /> boat <font color=Red>=</font> RightSide<font color=Cyan>,</font> <br /> curDepth <font color=Red>=</font> undefined<font color=Cyan>,</font> <font color=Blue><i>-- arbitrary, to avoid warnings</i></font><br /> maxDepth <font color=Red>=</font> undefined<font color=Cyan>,</font> <font color=Blue><i>-- arbitrary, to avoid warnings </i></font><br /> path <font color=Red>=</font> undefined <font color=Blue><i>-- arbitrary, to avoid warnings</i></font><br /> <font color=Cyan>}</font></pre><br /><br />This new implementation of PState, and corresponding new goal and beginstate, forces almost no changes in the rest of our program. The only necessary change beside our idfs (and idfs') function(s) is the check for a goal state. <br />It is still straightforward though:<br /><pre><font color=Blue><i>-- check if the state is a goal state</i></font><br /><font color=Blue>isGoalState</font> <font color=Red>::</font> PState <font color=Red>-></font> Bool<br /><font color=Blue>isGoalState</font> s <font color=Red>=</font> left s <font color=Cyan>==</font> left goalState <font color=Cyan>&&</font> right s <font color=Cyan>==</font> right goalState <font color=Cyan>&&</font> boat s <font color=Cyan>==</font> boat goalState</pre><br /><br /><br />Before starting with defining our search function and state monad we will define some helper functions to change our PState record more cleanly. We will need to able to increase the current and maxDepth by 1, and we need to be able to build up our path while maneuvering the search space. <br /><pre><font color=Blue><i>-- increase current search depth by 1</i></font><br /><font color=Blue>increaseDepth</font> <font color=Red>::</font> PState <font color=Red>-></font> PState<br /><font color=Blue>increaseDepth</font> s <font color=Red>=</font> <font color=Green><u>let</u></font> depth <font color=Red>=</font> curDepth s <font color=Green><u>in</u></font> s<font color=Cyan>{</font>curDepth <font color=Red>=</font> depth <font color=Cyan>+</font> <font color=Magenta>1</font><font color=Cyan>}</font><br /><br /><font color=Blue><i>-- increase max search depth by 1</i></font><br /><font color=Blue>increaseMaxDepth</font> <font color=Red>::</font> PState <font color=Red>-></font> PState<br /><font color=Blue>increaseMaxDepth</font> s <font color=Red>=</font> <font color=Green><u>let</u></font> depth <font color=Red>=</font> maxDepth s <font color=Green><u>in</u></font> s<font color=Cyan>{</font>maxDepth <font color=Red>=</font> depth <font color=Cyan>+</font> <font color=Magenta>1</font><font color=Cyan>}</font></pre><br />These functions are a straightforward record update, the following addPath function is a bit more dense though. Our current state not only contains the information of the problem, but also the path. When we add the current state to the path, the added state will still contain the older shorter path. This is needless clutter for our solution. We therefore empty the old path in the state that is added to the (possible) solution path.<br /><pre><font color=Blue><i>-- add the current state in front of the the path</i></font><br /><font color=Blue><i>-- before adding the state the path in that state is replaced by [] (to avoid clutter) </i></font><br /><font color=Blue>addPath</font> <font color=Red>::</font> PState <font color=Red>-></font> PState<br /><font color=Blue>addPath</font> s <font color=Red>=</font> s<font color=Cyan>{</font>path <font color=Red>=</font> <font color=Cyan>(</font>s <font color=Cyan>{</font>path <font color=Red>=</font> []<font color=Cyan>}</font><font color=Cyan>)</font> <font color=Red><b>:</b></font> path s<font color=Cyan>}</font></pre><br /><br />Now let's think about a sensible State s a for our solution. We already decided on our state type s, namely PState. A sensible type for our result a, would be the path, and would therefore we be a list of PStates ([PState]).<br />Thus: <span style="font-weight:bold;">State PState [PState]</span><br /><br />We can already change the type signature of idfs' into a much cleaner new one.<br /><pre> idfs' <font color=Red>::</font> State PState <font color=Red>[</font>PState<font color=Red>]</font></pre><br /><br /><br />Before diving in to the definition of idfs' we will first redefine idfs. Because we use a list for our solution path we can use the empty list as our case for failure. So when idfs calls the helper function idfs' and gets an empty list as a result it can increase the current max search depth by 1 and start the process again at the beginstate. <br /><br /><pre><font color=Blue><i>-- State monad implementation</i></font><br /><font color=Blue>idfs</font> <font color=Red>::</font> PState <font color=Red>-></font> <font color=Red>[</font>PState<font color=Red>]</font><br /><font color=Blue>idfs</font> s <font color=Red>=</font> <font color=Green><u>case</u></font> evalState idfs' s <font color=Green><u>of</u></font> <br /> [] <font color=Red>-></font> idfs <font color=Cyan>$</font> increaseMaxDepth s<br /> other <font color=Red>-></font> other</pre><br /><br />The call to idfs' is done by using evalState. Recall that evalState runs the state and pulls out the result. When no solution is found the search depth is increased by 1, otherwise the solution is returned. The first call to our idfs function will be applied with beginState, therefore starting the search at maxDepth 0.<br /><br /><br />Now to define idfs'. The function starts by adding the current node to the path. After that the border cases are handled. <br />The search should end if:<br />1. The current state is a goal state. In this case we can immediately return our current path.<br />2. The current search depth is as large as the maximum search depth, in which case a path of [] should be returned. <br /><br /><pre> idfs' <font color=Red>=</font> <font color=Green><u>do</u></font> modify addPath<br /> s <font color=Red><-</font> get<br /> <font color=Green><u>if</u></font> isGoalState s <br /> <font color=Green><u>then</u></font> return <font color=Cyan>(</font>path s<font color=Cyan>)</font><br /> <font color=Green><u>else</u></font> <font color=Green><u>if</u></font> curDepth s <font color=Cyan>>=</font> maxDepth s <br /> <font color=Green><u>then</u></font> return []</pre><br /><br /><br />If no border cases occur our search will continue by calling idfs' recursively on all successors and taking the first solution that can be found. We will take the first real solution by taking the first non empty list as solution. If no solutions are found we should return the empty list indicating our search failed. <br /><br /><br /><br /><pre> <font color=Green><u>else</u></font> <font color=Green><u>do</u></font> modify increaseDepth<br /> s <font color=Red><-</font> get<br /> <font color=Green><u>let</u></font> states <font color=Red>=</font> map <font color=Cyan>(</font>evalState idfs'<font color=Cyan>)</font> <font color=Cyan>(</font>successors s<font color=Cyan>)</font> <br /> return <font color=Cyan>.</font> safeHead <font color=Cyan>$</font> dropWhile null states<br /><br /><br /><br /><font color=Blue><i>-- returns [] if there are no solutions</i></font><br /><font color=Blue>safeHead</font> <font color=Red>::</font> <font color=Red>[</font><font color=Red>[</font>a<font color=Red>]</font><font color=Red>]</font> <font color=Red>-></font> <font color=Red>[</font>a<font color=Red>]</font><br /><font color=Blue>safeHead</font> [] <font color=Red>=</font> []<br /><font color=Blue>safeHead</font> xs <font color=Red>=</font> head xs</pre><br /><br /><br />Now all that remains is our redefinition of the final solution. All the other functions can remain the same :). <br /><br /><pre><font color=Blue><i>-- State trace of the solution to the cannibal/missionaries problem</i></font><br /><font color=Blue><i>-- The solution is in reverse order</i></font><br /><font color=Blue>solution</font> <font color=Red>::</font> <font color=Red>[</font>PState<font color=Red>]</font><br /><font color=Blue>solution</font> <font color=Red>=</font> reverse <font color=Cyan>$</font> idfs beginState</pre><br /><br /><br />As you can see we also reverse our solution because we always added the last state on the front (for efficiency). <br /><br /><br />I hope you enjoyed this post as much as I did writing it :-). <br /><br /><br />If you have some corrections or comments, please feel free to make them. <br /><br /><br />The final code:<br /><br /><pre><br /><font color=Green><u>module</u></font> AIMAMissionariesStateMonad <font color=Green><u>where</u></font><br /><font color=Green><u>import</u></font> Data<font color=Cyan>.</font>List<font color=Cyan>(</font>sort<font color=Cyan>,</font> nub<font color=Cyan>,</font> <font color=Cyan>(</font><font color=Cyan>\\</font><font color=Cyan>)</font><font color=Cyan>)</font><br /><font color=Green><u>import</u></font> Control<font color=Cyan>.</font>Monad<font color=Cyan>.</font>State<br /><br /><font color=Green><u>data</u></font> Person <font color=Red>=</font> Missionary <font color=Red>|</font> Cannibal<br /> <font color=Green><u>deriving</u></font> <font color=Cyan>(</font>Ord<font color=Cyan>,</font> Eq<font color=Cyan>,</font> Show<font color=Cyan>)</font><br /> <br /><font color=Green><u>data</u></font> Position <font color=Red>=</font> LeftSide <font color=Red>|</font> RightSide<br /> <font color=Green><u>deriving</u></font> <font color=Cyan>(</font>Eq<font color=Cyan>,</font> Show<font color=Cyan>)</font><br /><br /><font color=Green><u>data</u></font> PState <font color=Red>=</font> PState <font color=Cyan>{</font><br /> left <font color=Red>::</font> <font color=Red>[</font>Person<font color=Red>]</font><font color=Cyan>,</font> <font color=Blue><i>-- left side of canal</i></font><br /> right <font color=Red>::</font> <font color=Red>[</font>Person<font color=Red>]</font><font color=Cyan>,</font> <font color=Blue><i>-- right side of canal</i></font><br /> boat <font color=Red>::</font> Position<font color=Cyan>,</font> <font color=Blue><i>-- position of boat</i></font><br /> curDepth <font color=Red>::</font> Int<font color=Cyan>,</font> <font color=Blue><i>-- current search depth</i></font><br /> maxDepth <font color=Red>::</font> Int<font color=Cyan>,</font> <font color=Blue><i>-- max search depth</i></font><br /> path <font color=Red>::</font> <font color=Red>[</font>PState<font color=Red>]</font> <font color=Blue><i>-- path found to solution</i></font><br /> <font color=Cyan>}</font> <br /> <font color=Green><u>deriving</u></font> <font color=Cyan>(</font>Eq<font color=Cyan>,</font> Show<font color=Cyan>)</font><br /> <br /><font color=Blue>beginState</font> <font color=Red>::</font> PState <br /><font color=Blue>beginState</font> <font color=Red>=</font> <br /> PState <font color=Cyan>{</font><br /> left <font color=Red>=</font> <font color=Red>[</font>Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Red>]</font><font color=Cyan>,</font><br /> right <font color=Red>=</font> []<font color=Cyan>,</font> <br /> boat <font color=Red>=</font> LeftSide<font color=Cyan>,</font> <br /> curDepth <font color=Red>=</font> <font color=Magenta>0</font><font color=Cyan>,</font> <br /> maxDepth <font color=Red>=</font> <font color=Magenta>0</font><font color=Cyan>,</font><br /> path <font color=Red>=</font> []<br /> <font color=Cyan>}</font><br /><br /><font color=Blue>goalState</font> <font color=Red>=</font> <br /> PState <font color=Cyan>{</font><br /> left <font color=Red>=</font> []<font color=Cyan>,</font><br /> right <font color=Red>=</font> <font color=Red>[</font>Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Red>]</font><font color=Cyan>,</font> <br /> boat <font color=Red>=</font> RightSide<font color=Cyan>,</font> <br /> curDepth <font color=Red>=</font> undefined<font color=Cyan>,</font> <font color=Blue><i>-- arbitrary, to avoid warnings</i></font><br /> maxDepth <font color=Red>=</font> undefined<font color=Cyan>,</font> <font color=Blue><i>-- arbitrary, to avoid warnings </i></font><br /> path <font color=Red>=</font> undefined <font color=Blue><i>-- arbitrary, to avoid warnings</i></font><br /> <font color=Cyan>}</font><br /><br /><font color=Blue><i>-- State trace of the solution to the cannibal/missionaries problem</i></font><br /><font color=Blue><i>-- The solution is in reverse order</i></font><br /><font color=Blue>solution</font> <font color=Red>::</font> <font color=Red>[</font>PState<font color=Red>]</font><br /><font color=Blue>solution</font> <font color=Red>=</font> reverse <font color=Cyan>$</font> idfs beginState<br /><br /><font color=Blue><i>-- State monad implementation</i></font><br /><font color=Blue>idfs</font> <font color=Red>::</font> PState <font color=Red>-></font> <font color=Red>[</font>PState<font color=Red>]</font><br /><font color=Blue>idfs</font> s <font color=Red>=</font> <font color=Green><u>case</u></font> evalState idfs' s <font color=Green><u>of</u></font> <br /> [] <font color=Red>-></font> idfs <font color=Cyan>$</font> increaseMaxDepth s<br /> other <font color=Red>-></font> other<br /> <font color=Green><u>where</u></font> <br /> idfs' <font color=Red>::</font> State PState <font color=Red>[</font>PState<font color=Red>]</font><br /> idfs' <font color=Red>=</font> <font color=Green><u>do</u></font> modify addPath<br /> s <font color=Red><-</font> get<br /> <font color=Green><u>if</u></font> isGoalState s <br /> <font color=Green><u>then</u></font> return <font color=Cyan>(</font>path s<font color=Cyan>)</font><br /> <font color=Green><u>else</u></font> <font color=Green><u>if</u></font> curDepth s <font color=Cyan>>=</font> maxDepth s <br /> <font color=Green><u>then</u></font> return []<br /> <font color=Green><u>else</u></font> <font color=Green><u>do</u></font> modify increaseDepth<br /> s <font color=Red><-</font> get<br /> <font color=Green><u>let</u></font> states <font color=Red>=</font> map <font color=Cyan>(</font>evalState idfs'<font color=Cyan>)</font> <font color=Cyan>(</font>successors s<font color=Cyan>)</font> <br /> return <font color=Cyan>.</font> safeHead <font color=Cyan>$</font> dropWhile null states<br /><br /><font color=Blue><i>-- returns [] if there are no solutions</i></font><br /><font color=Blue>safeHead</font> <font color=Red>::</font> <font color=Red>[</font><font color=Red>[</font>a<font color=Red>]</font><font color=Red>]</font> <font color=Red>-></font> <font color=Red>[</font>a<font color=Red>]</font><br /><font color=Blue>safeHead</font> [] <font color=Red>=</font> []<br /><font color=Blue>safeHead</font> xs <font color=Red>=</font> head xs<br /><br /><font color=Blue><i>-- increase current search depth by 1</i></font><br /><font color=Blue>increaseDepth</font> <font color=Red>::</font> PState <font color=Red>-></font> PState<br /><font color=Blue>increaseDepth</font> s <font color=Red>=</font> <font color=Green><u>let</u></font> depth <font color=Red>=</font> curDepth s <font color=Green><u>in</u></font> s<font color=Cyan>{</font>curDepth <font color=Red>=</font> depth <font color=Cyan>+</font> <font color=Magenta>1</font><font color=Cyan>}</font><br /><br /><font color=Blue><i>-- increase max search depth by 1</i></font><br /><font color=Blue>increaseMaxDepth</font> <font color=Red>::</font> PState <font color=Red>-></font> PState<br /><font color=Blue>increaseMaxDepth</font> s <font color=Red>=</font> <font color=Green><u>let</u></font> depth <font color=Red>=</font> maxDepth s <font color=Green><u>in</u></font> s<font color=Cyan>{</font>maxDepth <font color=Red>=</font> depth <font color=Cyan>+</font> <font color=Magenta>1</font><font color=Cyan>}</font><br /><br /><font color=Blue><i>-- add the current state in front of the the path</i></font><br /><font color=Blue><i>-- before adding the state the path in that state is replaced by [] (to avoid clutter) </i></font><br /><font color=Blue>addPath</font> <font color=Red>::</font> PState <font color=Red>-></font> PState<br /><font color=Blue>addPath</font> s <font color=Red>=</font> s<font color=Cyan>{</font>path <font color=Red>=</font> <font color=Cyan>(</font>s <font color=Cyan>{</font>path <font color=Red>=</font> []<font color=Cyan>}</font><font color=Cyan>)</font> <font color=Red><b>:</b></font> path s<font color=Cyan>}</font><br /><br /><font color=Blue><i>-- check if the state is a goal state</i></font><br /><font color=Blue>isGoalState</font> <font color=Red>::</font> PState <font color=Red>-></font> Bool<br /><font color=Blue>isGoalState</font> s <font color=Red>=</font> left s <font color=Cyan>==</font> left goalState <font color=Cyan>&&</font> right s <font color=Cyan>==</font> right goalState <font color=Cyan>&&</font> boat s <font color=Cyan>==</font> boat goalState<br /><br /><font color=Blue><i>-- filter legal states</i></font><br /><font color=Blue>successors</font> <font color=Red>::</font> PState <font color=Red>-></font> <font color=Red>[</font>PState<font color=Red>]</font><br /><font color=Blue>successors</font> <font color=Red>=</font> filter isLegalState <font color=Cyan>.</font> allSucc <br /><br /><font color=Blue><i>-- generate all states after applying all possible combinations </i></font><br /><font color=Blue>allSucc</font> <font color=Red>::</font> PState <font color=Red>-></font> <font color=Red>[</font>PState<font color=Red>]</font> <br /><font color=Blue>allSucc</font> s <br /> <font color=Red>|</font> boat s <font color=Cyan>==</font> LeftSide <font color=Red>=</font> map <font color=Cyan>(</font>updatePStateLeft s<font color=Cyan>)</font> <font color=Cyan>(</font>genCombs <font color=Cyan>(</font>left s<font color=Cyan>)</font><font color=Cyan>)</font><br /> <font color=Red>|</font> otherwise <font color=Red>=</font> map <font color=Cyan>(</font>updatePStateRight s<font color=Cyan>)</font> <font color=Cyan>(</font>genCombs <font color=Cyan>(</font>right s<font color=Cyan>)</font><font color=Cyan>)</font><br /><br /><font color=Blue><i>-- move a number of cannibals and missonaries to the right side</i></font><br /><font color=Blue>updatePStateLeft</font> <font color=Red>::</font> PState <font color=Red>-></font> <font color=Red>[</font>Person<font color=Red>]</font> <font color=Red>-></font> PState<br /><font color=Blue>updatePStateLeft</font> s p <font color=Red>=</font> <font color=Green><u>let</u></font> oldLeft <font color=Red>=</font> left s<br /> oldRight <font color=Red>=</font> right s <br /> <font color=Green><u>in</u></font> s <font color=Cyan>{</font><br /> left <font color=Red>=</font> sort <font color=Cyan>$</font> oldLeft <font color=Cyan>\\</font> p<font color=Cyan>,</font><br /> right <font color=Red>=</font> sort <font color=Cyan>$</font> oldRight <font color=Cyan>++</font> p<font color=Cyan>,</font><br /> boat <font color=Red>=</font> RightSide<br /> <font color=Cyan>}</font><br /><br /><font color=Blue><i>-- move a number of cannibals and missonaries to the left side</i></font><br /><font color=Blue>updatePStateRight</font> <font color=Red>::</font> PState <font color=Red>-></font> <font color=Red>[</font>Person<font color=Red>]</font> <font color=Red>-></font> PState<br /><font color=Blue>updatePStateRight</font> s p <font color=Red>=</font> <font color=Green><u>let</u></font> oldLeft <font color=Red>=</font> left s<br /> oldRight <font color=Red>=</font> right s <br /> <font color=Green><u>in</u></font> s <font color=Cyan>{</font><br /> left <font color=Red>=</font> sort <font color=Cyan>$</font> oldLeft <font color=Cyan>++</font> p<font color=Cyan>,</font><br /> right <font color=Red>=</font> sort <font color=Cyan>$</font> oldRight <font color=Cyan>\\</font> p<font color=Cyan>,</font><br /> boat <font color=Red>=</font> LeftSide<br /> <font color=Cyan>}</font><br /> <br /><font color=Blue><i>-- unique combinations</i></font><br /><font color=Blue>genCombs</font> <font color=Red>::</font> Ord a <font color=Red>=></font> <font color=Red>[</font>a<font color=Red>]</font> <font color=Red>-></font> <font color=Red>[</font><font color=Red>[</font>a<font color=Red>]</font><font color=Red>]</font><br /><font color=Blue>genCombs</font> <font color=Red>=</font> nub <font color=Cyan>.</font> map sort <font color=Cyan>.</font> genPerms<br /><br /><font color=Blue><i>-- permutations of length 1 and 2 </i></font><br /><font color=Blue>genPerms</font> <font color=Red>::</font> Eq a <font color=Red>=></font> <font color=Red>[</font>a<font color=Red>]</font> <font color=Red>-></font> <font color=Red>[</font><font color=Red>[</font>a<font color=Red>]</font><font color=Red>]</font><br /><font color=Blue>genPerms</font> [] <font color=Red>=</font> []<br /><font color=Blue>genPerms</font> <font color=Cyan>(</font>x<font color=Red><b>:</b></font>xs<font color=Cyan>)</font> <font color=Red>=</font> <font color=Red>[</font>x<font color=Red>]</font> <font color=Red><b>:</b></font> <font color=Cyan>(</font>map <font color=Cyan>(</font><font color=Red><b>:</b></font> <font color=Red>[</font>x<font color=Red>]</font><font color=Cyan>)</font> xs<font color=Cyan>)</font> <font color=Cyan>++</font> genPerms xs<br /><br /><font color=Blue><i>-- legal states are states with the number of cannibals equal or less </i></font><br /><font color=Blue><i>-- to the number of missionaries on one riverside (or sides with no missionaries)</i></font><br /><font color=Blue>isLegalState</font> <font color=Red>::</font> PState <font color=Red>-></font> Bool<br /><font color=Blue>isLegalState</font> s <font color=Red>=</font> hasNoMoreCannibals <font color=Cyan>(</font>left s<font color=Cyan>)</font> <font color=Cyan>&&</font> hasNoMoreCannibals <font color=Cyan>(</font>right s<font color=Cyan>)</font><br /> <font color=Green><u>where</u></font> hasNoMoreCannibals lst <font color=Red>=</font> <font color=Green><u>let</u></font> lenMiss <font color=Red>=</font> length <font color=Cyan>(</font> filter <font color=Cyan>(</font><font color=Cyan>==</font> Missionary<font color=Cyan>)</font> lst<font color=Cyan>)</font> <br /> lenCann <font color=Red>=</font> length <font color=Cyan>(</font> filter <font color=Cyan>(</font><font color=Cyan>==</font> Cannibal<font color=Cyan>)</font> lst<font color=Cyan>)</font><br /> <font color=Green><u>in</u></font> lenMiss <font color=Cyan>==</font> <font color=Magenta>0</font> <font color=Cyan>||</font> lenMiss <font color=Cyan>>=</font> lenCann</pre> Nebasuke https://www.blogger.com/profile/00690086652715846121 noreply@blogger.com 0 tag:blogger.com,1999:blog-8387731529560364137.post-3166283515222727670 2009-07-21T14:46:00.116+02:00 2009-08-10T15:29:16.182+02:00 Cannibals, Missionaries and the State Monad pt. 2 <a href="https://adoseoflogic.blogspot.com/2009/07/cannibals-missionaries-and-state-monad.html">Part 1: An Explicit State Implementation of Cannibals and Missionaries</a><br /><a href="https://adoseoflogic.blogspot.com/2009/08/cannibals-missionaries-and-state-monad.html">Part 3: State Monad Implementation of Cannibals and Missionaries</a><br /><br /><br />Well here is part 2 of the Cannibals and Missionaries problem. I'll start with a(n) introduction/tutorial of the state monad. Hopefully this will enlighten some readers and myself a bit about how the state monad works. For the next explanations I assume you have seen some monads and now some of the basics such as the bind operator (>>=) and return. But you might learn something too if you've never seen monads before.<br /><br />Readers more comfortable with the state monad could skip to the implementation of the problem (Cannibals, Missionaries and the State Monad pt. 3). <br /><br /><big><span style="font-weight:bold;">Introduction to the State Monad</span></big><br />In this section I will give a motivation for the existence of the state monad by using random generators as an example(thanks to [1]). After that motivation we'll try to define our own state monad. In the section we will again motivate the use of the state monad by trying to renumber trees, define some more helper functions for the state monad and then implement the renumber example with the state monad.<br /><br /><br /><span style="font-weight:bold;">Motivation for implicit state</span><br />Say we would like to implement a random number generator. How would a function that generates a random number look like? In contrast to stateful languages such as C, Haskell can't have a function such as <pre><font color=Blue>randomNumber</font> <font color=Red>::</font> Int</pre> This function would not be referential transparant unless of course randomNumber always returns the same number (possibly chosen by a fair dice roll[2]). <br />Therefore instead we provide an explicit state for our randomNumber function. We can use a pseudorandomgenerator on this state So the function type definition would look like: <pre><font color=Blue>randomNumber</font> <font color=Red>::</font> RandomState <font color=Red>-></font> <font color=Cyan>(</font>Int<font color=Cyan>,</font> RandomState<font color=Cyan>)</font></pre> <br /><br />This function randomNumber takes a RandomState, possibly a seed value, and uses that RandomState to generate a pseudorandom Int and also returns the new seed value or changed RandomState.<br /><br />Let's pretend that randomNumber function already exists, and we wanted to define our own random function that takes a RandomState and returns two random numbers and the new RandomState. <br /><br /><span style="font-weight:bold;">Exercise:</span> Define the function <pre><font color=Blue>twoRandomNumbers</font> <font color=Red>::</font> RandomState <font color=Red>-></font> <font color=Cyan>(</font><font color=Cyan>(</font>Int<font color=Cyan>,</font>Int<font color=Cyan>)</font><font color=Cyan>,</font> RandomState<font color=Cyan>)</font></pre><br /><br /><br /><span style="font-weight:bold;">Try define it yourself first by using the "predefined" function and datatype below.</span><br /><br /><pre><font color=Blue><i>-- to test at least the types check use this:</i></font><br /><font color=Blue><i>-- our predefined function</i></font><br /><font color=Blue>randomNumber</font> <font color=Red>::</font> RandomState <font color=Red>-></font> <font color=Cyan>(</font>Int<font color=Cyan>,</font> RandomState<font color=Cyan>)</font><br /><font color=Blue>randomNumber</font> <font color=Red>=</font> undefined<br /><br /><font color=Blue><i>-- another placeholder </i></font><br /><font color=Green><u>data</u></font> RandomState <font color=Red>=</font> RandomState</pre><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><span style="font-weight:bold;">Solution:</span><br />We would have to explicitly thread the state like this:<br /><pre><font color=Blue><i>-- return two random numbers and the new RandomState</i></font><br /><font color=Blue>twoRandomNumbers</font> <font color=Red>::</font> RandomState <font color=Red>-></font> <font color=Cyan>(</font><font color=Cyan>(</font>Int<font color=Cyan>,</font>Int<font color=Cyan>)</font><font color=Cyan>,</font> RandomState<font color=Cyan>)</font><br /><font color=Blue>twoRandomNumbers</font> s <font color=Red>=</font> <font color=Green><u>let</u></font> <font color=Cyan>(</font>i<font color=Cyan>,</font> s'<font color=Cyan>)</font> <font color=Red>=</font> randomNumber s<br /> <font color=Cyan>(</font>i'<font color=Cyan>,</font> s''<font color=Cyan>)</font> <font color=Red>=</font> randomNumber s'<br /> <font color=Green><u>in</u></font> <font color=Cyan>(</font><font color=Cyan>(</font>i<font color=Cyan>,</font>i'<font color=Cyan>)</font><font color=Cyan>,</font>s''<font color=Cyan>)</font></pre><br />Our function twoRandomNumbers calls randomNumber with it's state, this produces a (pseudo)random Int and the new RandomState, this new state is then threaded in randomNumber again for another Int and newer state. These Int's are tupled and returned with the newest state.<br /><br />It is easy to make mistakes in this threading. We could accidentally thread an older state to our second randomNumber call (and always get the two same numbers) or return and older state as the final result.<br /><br />To avoid these kind of errors we woukd like to avoid this explicit passing of s, s' and s'' by abstracting this state and making it implicit. <br /><br />First we have to see a pattern in our code. The type of randomNumber indicates a common pattern for state passing. Namely, randomNumber takes a state and returns the changed state along with a result. So:<pre><font color=Cyan>(</font>s <font color=Red>-></font> <font color=Cyan>(</font>a<font color=Cyan>,</font> s<font color=Cyan>)</font><font color=Cyan>)</font></pre><br />In this type signature s is the state, and a is the result. We would like to turn this general type signature into a datatype and then somehow use it for implicit state. We will do this by just trying to make this datatype a monad and see how useful it is and how we can improve on it.<br /><br />Now to define our own State Monad!<br />Let's capture this s -> (a, s) pattern and just make it a new data type (you could also use newtype here). <br /><pre><font color=Green><u>data</u></font> State s a <font color=Red>=</font> State <font color=Cyan>(</font>s <font color=Red>-></font> <font color=Cyan>(</font>a<font color=Cyan>,</font> s<font color=Cyan>)</font><font color=Cyan>)</font></pre><br /><br />(By simply following the types our randomFunction would now be of type State RandomState Int.)<br /><br /><br />Now we try to make this datatype into a Monad. Remember that a Monad has a kind of * -> *, this means a monad type can still have a type applied to it. State takes two type parameters, namely s and a, and is therefore of kind * -> * -> * (takes two types and returns one type), so we can only make a Monad out of State s and not out of State or State s a. (See [3] for a small explanation of kinds.)<br /><br /><br />So let's just start with defining our monad instance. The function stubs would look like this:<br /><pre><font color=Green><u>instance</u></font> Monad <font color=Cyan>(</font>State s<font color=Cyan>)</font> <font color=Green><u>where</u></font> <br /> <font color=Blue><i>-- return :: (Monad m) => x -> m x</i></font><br /> return x <font color=Red>=</font> undefined<br /> <font color=Blue><i>--(>>=) :: (Monad m) => m x -> (x -> m y) -> m y</i></font><br /> <font color=Cyan>(</font>State s<font color=Cyan>)</font> <font color=Cyan>>>=</font> f <font color=Red>=</font> undefined</pre><br /><br /><span style="font-weight:bold;">Exercise: Try to define return and bind (>>=). <br /></span><br /><br /><br /><br /><br /><br />Hint: <br />I have used the general type signatures on purpose here, try to specialize this type signatures for the State Monad yourself. The return function should then follow quite easily. The bind operator is quite a bit harder though, so don't worry if you don't get it at once.<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><span style="font-weight:bold;">Solution:</span><br />Let's look at the type of return. It's general type is x -> M x. Think what this <span style="font-style:italic;">x</span> could mean. We can only really touch the second type parameter of our State datatype. Therefore that x must be the type of our result (a), and therefore can't be the type of our first type parameter. So the detailed type of return would be <pre><font color=Blue><i>-- return :: a -> State s a </i></font></pre><br /><br />This reduces our problem to: if we have a value a, how to make it into a State (s -> (a,s))? We will have to make it into a function s -> (a,s) and then wrap it with State. So: <pre><font color=Blue>return</font> a <font color=Red>=</font> State <font color=Cyan>$</font> <font color=Red>\</font>s <font color=Red>-></font> <font color=Cyan>(</font>a<font color=Cyan>,</font> s<font color=Cyan>)</font></pre> There isn't another sensible implementation really.<br /><br />And now the bind operator (>>=). Again specializing types we get: <pre><font color=Blue><i>-- (>>=) :: State s a -> (a -> State s b) -> State s b </i></font></pre><br /><br />Now to reason a bit about what the bind should do. The result of the function is State s b and gives a bit of an intuition of how the final result should look like.<br /><br />State s b is just a function s -> (b, s) with a State wrapper around it, right?. So let's start with that:<pre><font color=Cyan>(</font>State x<font color=Cyan>)</font> <font color=Cyan>>>=</font> f <font color=Red>=</font> State <font color=Cyan>(</font><font color=Red>\</font>s <font color=Red>-></font> <font color=Cyan>(</font><font color=Cyan>...</font><font color=Cyan>,</font> <font color=Cyan>...</font><font color=Cyan>)</font><font color=Cyan>)</font></pre> Now we at least have a result that has a State wrapper and a function in it. But now what?<br /><br />We will need to pass the state to our first argument, State s a, get out the new state and result, and then use that for the next argument. So: <pre><font color=Cyan>(</font>State x<font color=Cyan>)</font> <font color=Cyan>>>=</font> f <font color=Red>=</font> State <font color=Cyan>(</font><font color=Red>\</font>s <font color=Red>-></font> <font color=Cyan>(</font><font color=Green><u>let</u></font> <font color=Cyan>(</font>a<font color=Cyan>,</font> s1<font color=Cyan>)</font> <font color=Red>=</font> x s <font color=Green><u>in</u></font> <font color=Cyan>...</font><font color=Cyan>)</font><font color=Cyan>)</font></pre><br />Great now we've got the result of the first state computation, now to pass it to our function f to generate a State b. <pre><font color=Cyan>(</font>State x<font color=Cyan>)</font> <font color=Cyan>>>=</font> f <font color=Red>=</font> State <font color=Cyan>(</font><font color=Red>\</font>s <font color=Red>-></font> <font color=Cyan>(</font><font color=Green><u>let</u></font> <font color=Cyan>(</font>a<font color=Cyan>,</font> s1<font color=Cyan>)</font> <font color=Red>=</font> x s <font color=Green><u>in</u></font> <font color=Cyan>...</font><font color=Cyan>)</font><font color=Cyan>)</font></pre> Okay that's that, but now we still need to apply our newest state to our State b. Thus: <pre><font color=Cyan>(</font>State x<font color=Cyan>)</font> <font color=Cyan>>>=</font> f <font color=Red>=</font> State <font color=Cyan>(</font><font color=Red>\</font>s <font color=Red>-></font> <font color=Cyan>(</font><font color=Green><u>let</u></font> <font color=Cyan>(</font>a<font color=Cyan>,</font> s1<font color=Cyan>)</font> <font color=Red>=</font> x s<font color=Cyan>;</font> State y <font color=Red>=</font> f a <font color=Green><u>in</u></font> y s1<font color=Cyan>)</font><font color=Cyan>)</font></pre><br /><br />Possibly reread it 2/3 times and let it take some time to sink in. <br /><br /><br /><br /><br /><br />Now to rewrite our randomNumber example. It is still a bit contrived because we haven't really implemented the randomNumber function itself, but forget that for now. We will implement a larger fully working and testable example later. So for now we keep pretending someone has implemented randomNumber for us. and we want to use it with our freshly made State Monad. So instead of randomNumber :: RandomState -> (Int, RandomState) we want: randomNumber' :: State RandomState Int.<br /><br /><br /><span style="font-weight:bold;">Exercise:</span> Define the function:<br /><pre><font color=Blue>randomNumber'</font> <font color=Red>::</font> State RandomState Int</pre><br /><br /><br /><br /><br /><br /><br /><br />Think for a second, it really is quite trivial.<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><span style="font-weight:bold;">Solution:</span><br /><pre><font color=Blue><i>-- our State Monad randomNumber function </i></font><br /><font color=Blue>randomNumber'</font> <font color=Red>::</font> State RandomState Int<br /><font color=Blue>randomNumber'</font> <font color=Red>=</font> State randomNumber</pre><br />Yup that's all it takes. Now to use our randomNumber' function and our monadic functions return and bind (>>=) to implicitly pass the state. <br /><br /><span style="font-weight:bold;">Exercise:</span> Like before, define the function:<br /><pre><font color=Blue>twoRandomNumbers'</font> <font color=Red>::</font> State RandomState <font color=Cyan>(</font>Int<font color=Cyan>,</font>Int<font color=Cyan>)</font></pre><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />Hint:<br />Remember >>= is used for passing the state, and return is used to make a value (or result) into a State monad. You will need lambda abstractions after the bind to be able to use the value as a result.<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><span style="font-weight:bold;">Solution:</span><br /><br /><pre><font color=Blue><i>-- State Monad implementation: return two random numbers and the new RandomState</i></font><br /><font color=Blue>twoRandomNumbers'</font> <font color=Red>::</font> State RandomState <font color=Cyan>(</font>Int<font color=Cyan>,</font>Int<font color=Cyan>)</font><br /><font color=Blue>twoRandomNumbers'</font> <font color=Red>=</font> randomNumber' <font color=Cyan>>>=</font> <font color=Red>\</font> a <font color=Red>-></font> <br /> randomNumber' <font color=Cyan>>>=</font> <font color=Red>\</font> b <font color=Red>-></font> <br /> return <font color=Cyan>(</font>a<font color=Cyan>,</font>b<font color=Cyan>)</font><br /><font color=Blue><i>-- or equivalently:</i></font><br /><font color=Blue><i>-- do a <- randomNumber'</i></font><br /><font color=Blue><i>-- b <- randomNumber' </i></font><br /><font color=Blue><i>-- return (a,b)</i></font></pre><br /><br />That looks a lot cleaner doesn't it :-)? <br /><br />We just call randomNumber' and bind the result to a, then the state is implicitly passed to the other randomNumber' call, we bind that result to b, implicitly pass that state again, and finally use return to make a State Monad out of (a,b). (The state is passed to this monad.)<br /><br />You might have noticed we're now stuck in a state monad. We will define some functions that enable us to peel of the wrapper and run the state in the next section.<br /><br /><br /><br /><br /><span style="font-weight:bold;">Take some deep breaths and then we will continue with another example and define some helpful functions for making the use of the state monad a lot easier.<br /></span><br /><br /><br /><big><span style="font-weight:bold;">Renumbering trees</span></big><br /><br /><br />I hope the previous example already showed some of the uses of the state monad. We will now continue with another example for the movation of use of the state monad by implementing a function that gives a binary tree number labels. We will define this function ourselves to undergo some of the difficulties of explicit state passing. <br /><br /><br />Say we have a binary tree:<br /><br /><pre><font color=Green><u>data</u></font> Tree a <font color=Red>=</font> Leaf a <font color=Red>|</font> Node <font color=Cyan>(</font>Tree a<font color=Cyan>)</font> <font color=Cyan>(</font>Tree a<font color=Cyan>)</font><br /> <font color=Green><u>deriving</u></font> Show</pre><br /><br />And instead of using the elements a, we would like to give all the Leafs a different number. The type signature of our function could therefore be:<br /><br /><pre><font color=Blue>renumberTree</font> <font color=Red>::</font> Tree a <font color=Red>-></font> Tree Int</pre><br /><br />First consider the base case when a Leaf is given a number. The problem is how do we give all Leafs a different number and where do get that number from? We will need to keep the label number with us in the function by keeping it as an explicit argument. So instead we get:<pre><font color=Blue>renumberTree</font> <font color=Red>::</font> <font color=Cyan>(</font>Tree a<font color=Cyan>,</font> Int<font color=Cyan>)</font> <font color=Red>-></font> <font color=Cyan>(</font>Tree Int<font color=Cyan>,</font> Int<font color=Cyan>)</font></pre><br /><br />To keep the Int argument out of the function call we will keep our old renumberTree and define a helper function renumberTreeHelper inside, which will be called by renumberTree.<br /><br /><pre><font color=Blue>renumberHelper</font> <font color=Red>::</font> <font color=Cyan>(</font>Tree a<font color=Cyan>,</font> Int<font color=Cyan>)</font> <font color=Red>-></font> <font color=Cyan>(</font>Tree Int<font color=Cyan>,</font> Int<font color=Cyan>)</font></pre><br /><br />As you can see renumberHelper takes a tuple (Tree a, Int). The Int denotes the current label number. After renumbering a Leaf the relabeled Leaf should be returned along with an incremented integer. <span style="font-weight:bold;">Try to define the rest yourself first!</span><br /><br /><br /><br /><br /><br />The base case for Leafs is quite easy, try that one first. The other case will need some pattern matching on the recursive calls. <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><span style="font-weight:bold;">Solution:</span><br /><br />First we try to solve the base case, namely the case of a Leaf. As said the relabeled Leaf should be returned along with an incremented integer. <br /><br /><pre><font color=Blue>renumberHelper</font> <font color=Cyan>(</font><font color=Cyan>(</font>Leaf x<font color=Cyan>)</font><font color=Cyan>,</font> n<font color=Cyan>)</font> <font color=Red>=</font> <font color=Cyan>(</font>Leaf n<font color=Cyan>,</font> n<font color=Cyan>+</font><font color=Magenta>1</font><font color=Cyan>)</font></pre><br /><br />The Node case is a bit harder though. Because we have to keep track of our current label number and we need to recursively call our two children (left and right) we will have to do some passing of our label number (Int). <br /><br />So first we do a pattern match on the Node as we did we the Leaf:<br /><br /><pre><font color=Blue>renumberHelper</font> <font color=Cyan>(</font><font color=Cyan>(</font>Node l r<font color=Cyan>)</font><font color=Cyan>,</font> n<font color=Cyan>)</font> <font color=Red>=</font> </pre><br /><br />Now we have access to the left and right children of this node, and importantly to the current integer label, n. The right hand side (rhs) can now be defined by applying renumberHelper to the left node, taking the resulting label number, then applying renumberHelper to the right node with the NEW label number from the left node, and then we produce our result by using our Node constructor, the new left and right children, and importantly the new label number returned by the call on the right child. Therefore:<br /><br /><pre> <font color=Green><u>where</u></font> renumberHelper <font color=Red>::</font> <font color=Cyan>(</font>Tree a<font color=Cyan>,</font> Int<font color=Cyan>)</font> <font color=Red>-></font> <font color=Cyan>(</font>Tree Int<font color=Cyan>,</font> Int<font color=Cyan>)</font><br /> renumberHelper <font color=Cyan>(</font><font color=Cyan>(</font>Leaf x<font color=Cyan>)</font><font color=Cyan>,</font> n<font color=Cyan>)</font> <font color=Red>=</font> <font color=Cyan>(</font>Leaf n<font color=Cyan>,</font> n<font color=Cyan>+</font><font color=Magenta>1</font><font color=Cyan>)</font><br /> renumberHelper <font color=Cyan>(</font><font color=Cyan>(</font>Node l r<font color=Cyan>)</font><font color=Cyan>,</font> n<font color=Cyan>)</font> <font color=Red>=</font> <font color=Green><u>let</u></font> <font color=Cyan>(</font>t1<font color=Cyan>,</font> n1<font color=Cyan>)</font> <font color=Red>=</font> renumberHelper <font color=Cyan>(</font>l<font color=Cyan>,</font>n<font color=Cyan>)</font><br /> <font color=Cyan>(</font>t2<font color=Cyan>,</font> n2<font color=Cyan>)</font> <font color=Red>=</font> renumberHelper <font color=Cyan>(</font>r<font color=Cyan>,</font> n1<font color=Cyan>)</font><br /> <font color=Green><u>in</u></font> <font color=Cyan>(</font><font color=Cyan>(</font>Node t1 t2<font color=Cyan>)</font><font color=Cyan>,</font> n2<font color=Cyan>)</font></pre><br /><br />(We have used renumberHelper as a local definition in renumberTree.) Now to define the renumberTree. We only have to call renumberHelper with the tree argument, a starting number (we will take 0) and then take the tree out of the result of renumberHelper.<br /><br />Thus:<br /><br /><pre><font color=Blue><i>-- take a tree and give all leafs a unique number. </i></font><br /><font color=Blue><i>-- I number the leafs in depth first order, any order is fine though</i></font><br /><font color=Blue>renumberTree</font> <font color=Red>::</font> Tree a <font color=Red>-></font> Tree Int<br /><font color=Blue>renumberTree</font> tree <font color=Red>=</font> fst <font color=Cyan>$</font> renumberHelper <font color=Cyan>(</font>tree<font color=Cyan>,</font> <font color=Magenta>0</font><font color=Cyan>)</font></pre><br /><br />And now for an example tree with example run (load it up in GHCi yourself!):<br /><pre><font color=Blue>tree1</font> <font color=Red>=</font> Node <font color=Cyan>(</font>Node <font color=Cyan>(</font>Leaf <font color=Magenta>'a'</font><font color=Cyan>)</font> <font color=Cyan>(</font>Node <font color=Cyan>(</font>Leaf <font color=Magenta>'b'</font><font color=Cyan>)</font> <font color=Cyan>(</font>Leaf <font color=Magenta>'d'</font><font color=Cyan>)</font><font color=Cyan>)</font><font color=Cyan>)</font> <font color=Cyan>(</font>Leaf <font color=Magenta>'c'</font><font color=Cyan>)</font><br /><font color=Blue>tree2</font> <font color=Red>=</font> Node <font color=Cyan>(</font>Leaf <font color=Magenta>'a'</font><font color=Cyan>)</font> <font color=Cyan>(</font>Leaf <font color=Magenta>'b'</font><font color=Cyan>)</font><br /><br /><font color=Cyan>></font> renumberTree tree1<br />Node <font color=Cyan>(</font>Node <font color=Cyan>(</font>Leaf <font color=Magenta>0</font><font color=Cyan>)</font> <font color=Cyan>(</font>Node <font color=Cyan>(</font>Leaf <font color=Magenta>1</font><font color=Cyan>)</font> <font color=Cyan>(</font>Leaf <font color=Magenta>2</font><font color=Cyan>)</font><font color=Cyan>)</font><font color=Cyan>)</font> <font color=Cyan>(</font>Leaf <font color=Magenta>3</font><font color=Cyan>)</font></pre><br /><br />Well that works :)!<br />But as you might have noticed, the let bindings and explicitly passing of our integer argument can be quite susceptible to mistakes. Especially when using names such as n, n' and n''. So instead we would like to have the integer argument passed implicitly. This again can be solved with the state monad.<br /><br />So let's start thinking how to implicitly thread our state. We want to pass our Int argument as the state and will therefore be our s argument in State s a. The result a should be the Tree Int. So a good type for our State Monad would be State Int (Tree Int). This would give us a type of Tree a -> State Int (Tree Int). Now what? We're stuck in a monad! We would like our upper function to have the type:<pre><font color=Blue>renumberTree'</font> <font color=Red>::</font> Tree a <font color=Red>-></font> Tree Int</pre><br /><br /><br />Well that isn't a problem with this monad. We don't have any side effects so pulling of our State wrapper shouldn't give any problems such as launching missiles. We'll define a function that just does this with one simple pattern match:<br /><pre><font color=Blue><i>-- pull of the State wrapper</i></font><br /><font color=Blue>runState</font> <font color=Red>::</font> State s a <font color=Red>-></font> <font color=Cyan>(</font>s <font color=Red>-></font> <font color=Cyan>(</font>a<font color=Cyan>,</font> s<font color=Cyan>)</font><font color=Cyan>)</font><br /><font color=Blue>runState</font> <font color=Cyan>(</font>State s<font color=Cyan>)</font> <font color=Red>=</font> s</pre><br /><br />So now we can pull out the function out of the wrapper. This gives us the opportunity to actually apply some state to this function and get results! So given that we have defined a helper function, this time of type: <pre><font color=Blue>renumberHelper</font> <font color=Red>::</font> Tree a <font color=Red>-></font> State Int <font color=Cyan>(</font>Tree Int<font color=Cyan>)</font></pre><br /><br /><span style="font-weight:bold;">Exercise:</span> Define the function: <br /><pre><font color=Blue>renumberTree'</font> <font color=Red>::</font> Tree a <font color=Red>-></font> Tree Int</pre><br /><br /><br /><br /><br /><br /><br /><br /><br />Hint:<br />Use runState and supply the state.<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><span style="font-weight:bold;">Solution:</span><br />We will need supply the renumberHelper function with the tree (giving us State s a), pull of the State wrapper (giving us s -> (a, s) , supply the state it needs to compute our result, such as 0, (giving (a,s)), and then just pull out the result out of the tuple by using fst. <br /><pre><font color=Blue><i>-- State Monad implementation: take a tree and give all leafs a unique number. </i></font><br /><font color=Blue><i>-- I number the leafs in depth first order, any order is fine though</i></font><br /><font color=Blue>renumberTree'</font> <font color=Red>::</font> Tree a <font color=Red>-></font> Tree Int<br /><font color=Blue>renumberTree'</font> tree <font color=Red>=</font> fst <font color=Cyan>$</font> runState <font color=Cyan>(</font>renumberHelper tree<font color=Cyan>)</font> <font color=Magenta>0</font></pre><br /><br /><br /><br /><br /><span style="font-weight:bold;">Some helper functions:</span><br />One can imagine that calling runState (to pull of the wrapper) and supplying a state and then getting out the result or the new state will be a common use case. We will therefore define some methods that implement these use cases.<br /><br /><pre><font color=Blue><i>-- pull of the State wrapper, supply a state resulting in a (value, newState) pair</i></font><br /><font color=Blue><i>-- and take out the resulting value </i></font><br /><font color=Blue>evalState</font> <font color=Red>::</font> State s a <font color=Red>-></font> s <font color=Red>-></font> a <br /><font color=Blue>evalState</font> m s <font color=Red>=</font> fst <font color=Cyan>(</font>runState m s<font color=Cyan>)</font><br /><br /><font color=Blue><i>-- pull of the State wrapper, supply a state resulting in a (value, newState) pair</i></font><br /><font color=Blue><i>-- and take out the resulting new state</i></font><br /><font color=Blue>execState</font> <font color=Red>::</font> State s a <font color=Red>-></font> s <font color=Red>-></font> s<br /><font color=Blue>execState</font> m s <font color=Red>=</font> snd <font color=Cyan>(</font>runState m s<font color=Cyan>)</font></pre><br /><br />We can therefore rewrite our renumberTree' call to:<br /><pre><font color=Blue>evalState</font> <font color=Cyan>(</font>renumberHelper tree<font color=Cyan>)</font> <font color=Magenta>0</font></pre><br /><br /><br /><br /><big><span style="font-weight:bold;">Explicit implicit state</span></big><br /><br />Before defining the renumberHelper function we will define more functions that will help us use the State Monad. Sometimes we do want to explicitly use the state and we will define some helper functions for that purpose.<br /><br /><br />What if we want to know what the current state is? Remember the datatype of our Monad, data State s a = State (s -> (a, s))<br />So if we're in the middle of a ((State s) >>= \ x -> ...), how do we get the state out? State should most of the times be implicit but if we want to make the state explicit the only way is to return it as a result. So let's define a get function which returns the state as result. So we just replace our type of the result, a, by the type of the state, s. So the only possibly type for our get function is: <pre><font color=Blue>get</font> <font color=Red>::</font> State s s</pre><br />The function itself shouldn't be hard to define now either, give it a try!<br /><span style="font-weight:bold;">Exercise:</span> Define the get function:<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><span style="font-weight:bold;">Solution:</span><br /><pre><font color=Blue><i>-- return the current state by copying it as a value</i></font><br /><font color=Blue>get</font> <font color=Red>::</font> State s s <br /><font color=Blue>get</font> <font color=Red>=</font> State <font color=Cyan>(</font><font color=Red>\</font> c <font color=Red>-></font> <font color=Cyan>(</font>c<font color=Cyan>,</font> c<font color=Cyan>)</font><font color=Cyan>)</font></pre><br /><br /><br />Now for a similar function: put. When we use the get function and get the current state, we sometimes want to change that state and put it back in a state monad.<br />So given a state s, we would like to see a computation that results in that new state s. But what do we do with the result? Because there really isn't a result from putting our new state in the state monad there isn't a sensible value to use for that so we'll just use (). <br /><br /><span style="font-weight:bold;">Exercise:</span> Define put<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />Hint: Again look at the possible types!<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><span style="font-weight:bold;">Solution:</span><br /><pre><font color=Blue><i>-- put the given state s as current state </i></font><br /><font color=Blue>put</font> <font color=Red>::</font> s <font color=Red>-></font> State s ()<br /><font color=Blue>put</font> s <font color=Red>=</font> State <font color=Cyan>(</font><font color=Red>\</font> <font color=Green><u>_</u></font> <font color=Red>-></font> <font color=Cyan>(</font>()<font color=Cyan>,</font> s<font color=Cyan>)</font><font color=Cyan>)</font></pre><br /><br />put takes a state as argument and constructs a State which ignores the next state and puts () as value. <br /><br /><br />Now let's try putting these two functions to use. Let's try to define a function inc, that takes a State Monad with an Int as state, and increases that Int it. <br />You do need to take a State Monad as argument, this can instead be done inside the monad so the type of inc becomes: <pre><font color=Blue>inc</font> <font color=Red>::</font> State Int ()</pre><br /><br /><span style="font-weight:bold;">Exercise:</span> Define inc<br /><br /><br /><br /><br /><br /><br /><br />Hint: <br />Use a combination of get and put and bind.<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><span style="font-weight:bold;">Solution:</span><br /><pre><font color=Blue><i>-- increase the state with 1</i></font><br /><font color=Blue>inc</font> <font color=Red>::</font> State Int ()<br /><font color=Blue>inc</font> <font color=Red>=</font> get <font color=Cyan>>>=</font> <font color=Red>\</font> x <font color=Red>-></font> put <font color=Cyan>(</font>x <font color=Cyan>+</font> <font color=Magenta>1</font><font color=Cyan>)</font><br /><font color=Blue><i>-- or equivalently:</i></font><br /><font color=Blue><i>-- inc = do x <- get</i></font><br /><font color=Blue><i>-- put $ x + 1</i></font></pre><br /><br /><br /><br />As you can see inc uses get to get the current state out as a value and then puts it back after incrementing it by 1.<br /><br />A short sidenote: you can probably imagine that the combination of get and put will often be used when a modification of the state is necessary. Instead of using get and put we can use a convenience function modify which will do the getting and putting for us. The only thing we will need to do is supply modify with our state changing function. Thus modify would look like this:<br /><br /><pre><font color=Blue>modify</font> <font color=Red>::</font> <font color=Cyan>(</font>s <font color=Red>-></font> s<font color=Cyan>)</font> <font color=Red>-></font> State s ()<br /><font color=Blue>modify</font> f <font color=Red>=</font> <font color=Green><u>do</u></font> x <font color=Red><-</font> get<br /> put <font color=Cyan>$</font> f x </pre><br /><br />Defining inc now gets even easier:<br /><pre><font color=Blue>inc</font> <font color=Red>=</font> modify <font color=Cyan>(</font><font color=Cyan>+</font><font color=Magenta>1</font><font color=Cyan>)</font></pre><br /><br /><br />We have now defined all the functions we need for the State Monad version of renumberTree'. Have a go at defining the renumberHelper using our functions inc, get, return and bind. Try to use do notation for a more readable implementation!<br /><br /><br /><span style="font-weight:bold;">Exercise:</span> Define renumberHelper.<br /><br /><br /><br /><br /><br /><br /><br /><br />Hint: <br />Remember the type of the helper function: <pre><font color=Blue>renumberHelper</font> <font color=Red>::</font> Tree a <font color=Red>-></font> State Int <font color=Cyan>(</font>Tree Int<font color=Cyan>)</font></pre><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /><br /><span style="font-weight:bold;">Solution:</span><br /><pre><font color=Blue><i>-- State Monad implementation: take a tree and give all leafs a unique number. </i></font><br /><font color=Blue><i>-- I number the leafs in depth first order, any order is fine though</i></font><br /><font color=Blue>renumberTree'</font> <font color=Red>::</font> Tree a <font color=Red>-></font> Tree Int<br /><font color=Blue>renumberTree'</font> tree <font color=Red>=</font> fst <font color=Cyan>$</font> runState <font color=Cyan>(</font>renumberHelper tree<font color=Cyan>)</font> <font color=Magenta>0</font><br /> <font color=Green><u>where</u></font> renumberHelper <font color=Red>::</font> Tree a <font color=Red>-></font> State Int <font color=Cyan>(</font>Tree Int<font color=Cyan>)</font><br /> renumberHelper <font color=Cyan>(</font>Leaf x<font color=Cyan>)</font> <font color=Red>=</font> <font color=Green><u>do</u></font> n <font color=Red><-</font> get<br /> inc<br /> return <font color=Cyan>(</font>Leaf n<font color=Cyan>)</font><br /> <br /> renumberHelper <font color=Cyan>(</font>Node l r<font color=Cyan>)</font> <font color=Red>=</font> <font color=Green><u>do</u></font> l' <font color=Red><-</font> renumberHelper l<br /> r' <font color=Red><-</font> renumberHelper r<br /> return <font color=Cyan>(</font>Node l' r'<font color=Cyan>)</font></pre><br /><br />Well here's the complete implementation of renumberTree'. renumberTree' is as we defined it earlier, renumberHelper again is splitted in two cases, Leaf and Node cases.<br />The actual changing of the state happens at the Leaf case, we first use get to take out our current counter value, call inc to increment our counter, construct a Leaf with our initial counter value and finally return that Leaf as a State Monad.<br /><br />The Node case has gotten a lot easier and more readable now, we just call renumberHelper two times and use the results in our Node constructor, which we then return as a State Monad. <br /><br />That's all folks!<br /><br /><br /><br /><br />For another simple but sweet example of Fibonacci numbers see <a href="https://calpaterson.blogspot.com/2009/07/state-monad-example-infinite-list-of.html">here</a>. <br /><br />In the next blog post I will finally implement the Cannibals and Missionaries problem by using the State Monad. Try to make an implementation yourself if you think you're capable now!<br /><br />Just import Control.Monad.State and you'll be able to use all the state monad functions defined in this blog post.<br /><br />References: <br />[1] <a href="https://ertes.de/articles/monads.html#section-6 ">https://ertes.de/articles/monads.html#section-6 </a><br />Understanding Haskell Monads by Ertugrul Söylemez<br />Random number generator example and some good explanations of the state monad and monads in general. <br />[2] <a href="https://xkcd.com/221/">https://xkcd.com/221/</a><br />[3] <a href="https://en.wikibooks.org/wiki/Haskell/Kinds">https://en.wikibooks.org/wiki/Haskell/Kinds</a> <br />Explanation of kinds.<br /><br />Acknowledgements:<br />I'd like to thank kosmikus for his help with the state monad.<br /><br /><br /><br />The final code:<br /><pre><br /><font color=Green><u>module</u></font> State <font color=Green><u>where</u></font><br /><br /><font color=Blue><i>-- to test at least the types check use this:</i></font><br /><font color=Blue><i>-- our predefined function</i></font><br /><font color=Blue>randomNumber</font> <font color=Red>::</font> RandomState <font color=Red>-></font> <font color=Cyan>(</font>Int<font color=Cyan>,</font> RandomState<font color=Cyan>)</font><br /><font color=Blue>randomNumber</font> <font color=Red>=</font> undefined<br /><br /><font color=Blue><i>-- another placeholder </i></font><br /><font color=Green><u>data</u></font> RandomState <font color=Red>=</font> RandomState <br /><br /><font color=Blue><i>-- return two random numbers and the new RandomState</i></font><br /><font color=Blue>twoRandomNumbers</font> <font color=Red>::</font> RandomState <font color=Red>-></font> <font color=Cyan>(</font><font color=Cyan>(</font>Int<font color=Cyan>,</font>Int<font color=Cyan>)</font><font color=Cyan>,</font> RandomState<font color=Cyan>)</font><br /><font color=Blue>twoRandomNumbers</font> s <font color=Red>=</font> <font color=Green><u>let</u></font> <font color=Cyan>(</font>i<font color=Cyan>,</font> s'<font color=Cyan>)</font> <font color=Red>=</font> randomNumber s<br /> <font color=Cyan>(</font>i'<font color=Cyan>,</font> s''<font color=Cyan>)</font> <font color=Red>=</font> randomNumber s'<br /> <font color=Green><u>in</u></font> <font color=Cyan>(</font><font color=Cyan>(</font>i<font color=Cyan>,</font>i'<font color=Cyan>)</font><font color=Cyan>,</font>s''<font color=Cyan>)</font><br /><br /><font color=Blue><i>-- our datatype</i></font><br /><font color=Green><u>data</u></font> State s a <font color=Red>=</font> State <font color=Cyan>(</font>s <font color=Red>-></font> <font color=Cyan>(</font>a<font color=Cyan>,</font> s<font color=Cyan>)</font><font color=Cyan>)</font><br /><br /><br /><font color=Green><u>instance</u></font> Monad <font color=Cyan>(</font>State s<font color=Cyan>)</font> <font color=Green><u>where</u></font><br /> <font color=Blue><i>-- return :: (Monad m) => x -> m x</i></font><br /> <font color=Blue><i>-- specialized: return :: a -> State s a</i></font><br /> return x <font color=Red>=</font> State <font color=Cyan>$</font> <font color=Red>\</font>s <font color=Red>-></font> <font color=Cyan>(</font>x<font color=Cyan>,</font> s<font color=Cyan>)</font><br /> <font color=Blue><i>--(>>=) :: (Monad m) => m x -> (x -> m y) -> m y</i></font><br /> <font color=Blue><i>-- specialized: (>>=) :: State s a -> (a -> State s b) -> State s b</i></font><br /> <font color=Cyan>(</font>State x<font color=Cyan>)</font> <font color=Cyan>>>=</font> f <font color=Red>=</font> State <font color=Cyan>(</font><font color=Red>\</font>s <font color=Red>-></font> <font color=Cyan>(</font><font color=Green><u>let</u></font> <font color=Cyan>(</font>a<font color=Cyan>,</font> s1<font color=Cyan>)</font> <font color=Red>=</font> x s<font color=Cyan>;</font> State y <font color=Red>=</font> f a <font color=Green><u>in</u></font> y s1<font color=Cyan>)</font><font color=Cyan>)</font><br /> <br /><font color=Blue><i>-- our State Monad randomNumber function </i></font><br /><font color=Blue>randomNumber'</font> <font color=Red>::</font> State RandomState Int<br /><font color=Blue>randomNumber'</font> <font color=Red>=</font> State randomNumber<br /><br /><font color=Blue><i>-- State Monad implementation: return two random numbers and the new RandomState</i></font><br /><font color=Blue>twoRandomNumbers'</font> <font color=Red>::</font> State RandomState <font color=Cyan>(</font>Int<font color=Cyan>,</font>Int<font color=Cyan>)</font><br /><font color=Blue>twoRandomNumbers'</font> <font color=Red>=</font> randomNumber' <font color=Cyan>>>=</font> <font color=Red>\</font> a <font color=Red>-></font> <br /> randomNumber' <font color=Cyan>>>=</font> <font color=Red>\</font> b <font color=Red>-></font> <br /> return <font color=Cyan>(</font>a<font color=Cyan>,</font>b<font color=Cyan>)</font><br /><font color=Blue><i>-- or equivalently:</i></font><br /><font color=Blue><i>-- do a <- randomNumber'</i></font><br /><font color=Blue><i>-- b <- randomNumber' </i></font><br /><font color=Blue><i>-- return (a,b)</i></font><br /><br /><br /><font color=Blue><i>-- our tree type (a simple binary tree with values at the Leafs)</i></font><br /><font color=Green><u>data</u></font> Tree a <font color=Red>=</font> Leaf a <font color=Red>|</font> Node <font color=Cyan>(</font>Tree a<font color=Cyan>)</font> <font color=Cyan>(</font>Tree a<font color=Cyan>)</font><br /> <font color=Green><u>deriving</u></font> Show<br /><br /><font color=Blue><i>-- take a tree and give all leafs a unique number. </i></font><br /><font color=Blue><i>-- I number the leafs in depth first order, any order is fine though</i></font><br /><font color=Blue>renumberTree</font> <font color=Red>::</font> Tree a <font color=Red>-></font> Tree Int<br /><font color=Blue>renumberTree</font> tree <font color=Red>=</font> fst <font color=Cyan>$</font> renumberHelper <font color=Cyan>(</font>tree<font color=Cyan>,</font> <font color=Magenta>0</font><font color=Cyan>)</font><br /> <font color=Green><u>where</u></font> renumberHelper <font color=Red>::</font> <font color=Cyan>(</font>Tree a<font color=Cyan>,</font> Int<font color=Cyan>)</font> <font color=Red>-></font> <font color=Cyan>(</font>Tree Int<font color=Cyan>,</font> Int<font color=Cyan>)</font><br /> renumberHelper <font color=Cyan>(</font><font color=Cyan>(</font>Leaf x<font color=Cyan>)</font><font color=Cyan>,</font> n<font color=Cyan>)</font> <font color=Red>=</font> <font color=Cyan>(</font>Leaf n<font color=Cyan>,</font> n<font color=Cyan>+</font><font color=Magenta>1</font><font color=Cyan>)</font><br /> renumberHelper <font color=Cyan>(</font><font color=Cyan>(</font>Node l r<font color=Cyan>)</font><font color=Cyan>,</font> n<font color=Cyan>)</font> <font color=Red>=</font> <font color=Green><u>let</u></font> <font color=Cyan>(</font>t1<font color=Cyan>,</font> n1<font color=Cyan>)</font> <font color=Red>=</font> renumberHelper <font color=Cyan>(</font>l<font color=Cyan>,</font>n<font color=Cyan>)</font><br /> <font color=Cyan>(</font>t2<font color=Cyan>,</font> n2<font color=Cyan>)</font> <font color=Red>=</font> renumberHelper <font color=Cyan>(</font>r<font color=Cyan>,</font> n1<font color=Cyan>)</font><br /> <font color=Green><u>in</u></font> <font color=Cyan>(</font><font color=Cyan>(</font>Node t1 t2<font color=Cyan>)</font><font color=Cyan>,</font> n2<font color=Cyan>)</font> <br /><br /><br /><font color=Blue>tree1</font> <font color=Red>=</font> Node <font color=Cyan>(</font>Node <font color=Cyan>(</font>Leaf <font color=Magenta>'a'</font><font color=Cyan>)</font> <font color=Cyan>(</font>Node <font color=Cyan>(</font>Leaf <font color=Magenta>'b'</font><font color=Cyan>)</font> <font color=Cyan>(</font>Leaf <font color=Magenta>'d'</font><font color=Cyan>)</font><font color=Cyan>)</font><font color=Cyan>)</font> <font color=Cyan>(</font>Leaf <font color=Magenta>'c'</font><font color=Cyan>)</font><br /><font color=Blue>tree2</font> <font color=Red>=</font> Node <font color=Cyan>(</font>Leaf <font color=Magenta>'a'</font><font color=Cyan>)</font> <font color=Cyan>(</font>Leaf <font color=Magenta>'b'</font><font color=Cyan>)</font><br /><br /><br /><font color=Blue><i>-- useful State Monad functions:</i></font><br /><br /><font color=Blue><i>-- pull of the State wrapper</i></font><br /><font color=Blue>runState</font> <font color=Red>::</font> State s a <font color=Red>-></font> <font color=Cyan>(</font>s <font color=Red>-></font> <font color=Cyan>(</font>a<font color=Cyan>,</font> s<font color=Cyan>)</font><font color=Cyan>)</font><br /><font color=Blue>runState</font> <font color=Cyan>(</font>State s<font color=Cyan>)</font> <font color=Red>=</font> s<br /><br /><font color=Blue><i>-- pull of the State wrapper, supply a state resulting in a (value, newState) pair</i></font><br /><font color=Blue><i>-- and take out the resulting value </i></font><br /><font color=Blue>evalState</font> <font color=Red>::</font> State s a <font color=Red>-></font> s <font color=Red>-></font> a <br /><font color=Blue>evalState</font> m s <font color=Red>=</font> fst <font color=Cyan>(</font>runState m s<font color=Cyan>)</font><br /><br /><font color=Blue><i>-- pull of the State wrapper, supply a state resulting in a (value, newState) pair</i></font><br /><font color=Blue><i>-- and take out the resulting new state</i></font><br /><font color=Blue>execState</font> <font color=Red>::</font> State s a <font color=Red>-></font> s <font color=Red>-></font> s<br /><font color=Blue>execState</font> m s <font color=Red>=</font> snd <font color=Cyan>(</font>runState m s<font color=Cyan>)</font><br /><br /><font color=Blue><i>-- return the current state by copying it as a value</i></font><br /><font color=Blue>get</font> <font color=Red>::</font> State s s <br /><font color=Blue>get</font> <font color=Red>=</font> State <font color=Cyan>(</font><font color=Red>\</font> c <font color=Red>-></font> <font color=Cyan>(</font>c<font color=Cyan>,</font> c<font color=Cyan>)</font><font color=Cyan>)</font><br /><br /><font color=Blue><i>-- put the given state s as current state </i></font><br /><font color=Blue>put</font> <font color=Red>::</font> s <font color=Red>-></font> State s ()<br /><font color=Blue>put</font> s <font color=Red>=</font> State <font color=Cyan>(</font><font color=Red>\</font> <font color=Green><u>_</u></font> <font color=Red>-></font> <font color=Cyan>(</font>()<font color=Cyan>,</font> s<font color=Cyan>)</font><font color=Cyan>)</font><br /><br /><font color=Blue>modify</font> <font color=Red>::</font> <font color=Cyan>(</font>s <font color=Red>-></font> s<font color=Cyan>)</font> <font color=Red>-></font> State s ()<br /><font color=Blue>modify</font> f <font color=Red>=</font> <font color=Green><u>do</u></font> x <font color=Red><-</font> get<br /> put <font color=Cyan>$</font> f x <br /><br /><br /><br /><font color=Blue><i>-- increase the state with 1</i></font><br /><font color=Blue>inc</font> <font color=Red>::</font> State Int ()<br /><font color=Blue>inc</font> <font color=Red>=</font> get <font color=Cyan>>>=</font> <font color=Red>\</font> x <font color=Red>-></font> put <font color=Cyan>(</font>x <font color=Cyan>+</font> <font color=Magenta>1</font><font color=Cyan>)</font><br /><font color=Blue><i>-- or equivalently:</i></font><br /><font color=Blue><i>-- inc = do x <- get</i></font><br /><font color=Blue><i>-- put $ x + 1</i></font><br /><font color=Blue><i>-- or even better:</i></font><br /><font color=Blue><i>-- inc = modify (+1)</i></font><br /><br /><font color=Blue><i>-- State Monad implementation: take a tree and give all leafs a unique number. </i></font><br /><font color=Blue><i>-- I number the leafs in depth first order, any order is fine though</i></font><br /><font color=Blue>renumberTree'</font> <font color=Red>::</font> Tree a <font color=Red>-></font> Tree Int<br /><font color=Blue>renumberTree'</font> tree <font color=Red>=</font> fst <font color=Cyan>$</font> runState <font color=Cyan>(</font>renumberHelper tree<font color=Cyan>)</font> <font color=Magenta>0</font><br /> <font color=Blue><i>-- or equivalently: evalState (renumberHelper tree) 0</i></font><br /> <font color=Green><u>where</u></font> renumberHelper <font color=Red>::</font> Tree a <font color=Red>-></font> State Int <font color=Cyan>(</font>Tree Int<font color=Cyan>)</font><br /> renumberHelper <font color=Cyan>(</font>Leaf x<font color=Cyan>)</font> <font color=Red>=</font> <font color=Green><u>do</u></font> n <font color=Red><-</font> get<br /> inc <br /> return <font color=Cyan>(</font>Leaf n<font color=Cyan>)</font><br /> <br /> renumberHelper <font color=Cyan>(</font>Node l r<font color=Cyan>)</font> <font color=Red>=</font> <font color=Green><u>do</u></font> l' <font color=Red><-</font> renumberHelper l<br /> r' <font color=Red><-</font> renumberHelper r<br /> return <font color=Cyan>(</font>Node l' r'<font color=Cyan>)</font><br /></pre><br /><br /><br /><br /><span style="font-weight:bold;">Edit:</span> Added modify, evalState, execState and changed renumberHelper' to function the same as renumberHelper.<br /><span style="font-weight:bold;">Edit:</span> Rephrasing.<br /><br />(Last edit: August 7th) Nebasuke https://www.blogger.com/profile/00690086652715846121 noreply@blogger.com 0 tag:blogger.com,1999:blog-8387731529560364137.post-8981667278441279225 2009-07-19T18:59:00.017+02:00 2009-09-08T19:20:33.806+02:00 Cannibals, Missionaries and the State Monad pt. 1 <a href="https://adoseoflogic.blogspot.com/2009/07/cannibals-missionaries-and-state-monad_21.html">Part 2: A State Monad Introduction</a><br /><a href="https://adoseoflogic.blogspot.com/2009/08/cannibals-missionaries-and-state-monad.html">Part 3: State Monad Implementation of Cannibals and Missionaries</a><br /><br /><br />As a preparation for my master, and to get myself into A.I. a bit more before starting my master, I have started working through Artificial Intelligence: A Modern Approach. I'm combining the exercises and interesting algorithms with functional programming by implementing the problems in Haskell. <br /><br />The last exercise I did was a long solution to the well known <a href="https://en.wikipedia.org/wiki/Missionaries_and_cannibals_problem">Missionaries and Cannibals problem</a>. (This is exercise 3.9b of the second edition of AIMA btw.)<br /><br />From wikipedia: "In the missionaries and cannibals problem, three missionaries and three cannibals must cross a river using a boat which can carry at most two people, under the constraint that, for both banks, if there are missionaries present on the bank, they cannot be outnumbered by cannibals (if they were, the cannibals would eat the missionaries.) The boat cannot cross the river by itself with no people on board."<br /><br />The exercise asks you two solve this problem by first formalizing it, and then searching through the state space by an appropriate search algorithm. (Complete and optimal). I chose <a href="https://en.wikipedia.org/wiki/Iterative_deepening_depth-first_search">iterative deepening depth-first search</a> which is complete if the solution is at finite depth, and optimal if step costs are equal. <br /><br />I'll introduce two solutions to this problem. The first was the solution I worked out the first time. I will work out that solution in this post.<br /><br />But I was not really happy with all the parameters used in the search function and I decided to finally tackle the state monad to try to improve that solution, which I'll work out in the next blog post. <br /><br /><big><span style="font-weight:bold;">An Explicit State Implementation of Cannibals and Missionaries</span></big><br />First formalizing the problem:<br /><br />We have two types of people, namely missionaries and cannibals. Furthermore we have 2 sides of the river, which we'll call left and right. This will be used to track the position of the boat. Therefore:<br /><br /><pre><font color=Green><u>data</u></font> Person <font color=Red>=</font> Missionary <font color=Red>|</font> Cannibal<br /> <font color=Green><u>deriving</u></font> <font color=Cyan>(</font>Ord<font color=Cyan>,</font> Eq<font color=Cyan>,</font> Show<font color=Cyan>)</font> <font color=Blue><i>-- used later</i></font><br /><br /><font color=Green><u>data</u></font> Position <font color=Red>=</font> LeftSide <font color=Red>|</font> RightSide<br /> <font color=Green><u>deriving</u></font> <font color=Cyan>(</font>Eq<font color=Cyan>,</font> Show<font color=Cyan>)</font> <font color=Blue><i>-- used later</i></font></pre><br /><br />This would be nice to track in a record therefore:<br /><br /><pre><font color=Green><u>data</u></font> PState <font color=Red>=</font> PState <font color=Cyan>{</font>left <font color=Red>::</font> <font color=Red>[</font>Person<font color=Red>]</font><font color=Cyan>,</font> right <font color=Red>::</font> <font color=Red>[</font>Person<font color=Red>]</font><font color=Cyan>,</font> boat <font color=Red>::</font> Position<font color=Cyan>}</font> <br /> <font color=Green><u>deriving</u></font> <font color=Cyan>(</font>Eq<font color=Cyan>,</font> Show<font color=Cyan>)</font> <font color=Blue><i>-- used later</i></font></pre><br /><br />With this record we can already define the start and goalstate of the problem, namely:<br /><br /><pre><font color=Blue>beginState</font> <font color=Red>=</font> PState <font color=Cyan>{</font>left <font color=Red>=</font> <font color=Red>[</font>Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Red>]</font><font color=Cyan>,</font> right <font color=Red>=</font> []<font color=Cyan>,</font> boat <font color=Red>=</font> LeftSide<font color=Cyan>}</font><br /><font color=Blue>goalState</font> <font color=Red>=</font> PState <font color=Cyan>{</font>left <font color=Red>=</font> []<font color=Cyan>,</font> right <font color=Red>=</font> <font color=Red>[</font>Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Red>]</font><font color=Cyan>,</font> boat <font color=Red>=</font> RightSide<font color=Cyan>}</font></pre><br /><br />Before trying to tackle the search algorithm we will try define a successors function, meaning a function that given a state, generates the subsequent possible states. Because of the boat size of 2 and the minimum number of passengers 1, we need to consider moves containing combinations of 1 or 2 People. I used a function to generate all permutations of length 1 and 2 and filter all doubles to retain the combinations.<br /><br /><br /><pre><font color=Blue><i>-- unique combinations</i></font><br /><font color=Blue>genCombs</font> <font color=Red>::</font> Ord a <font color=Red>=></font> <font color=Red>[</font>a<font color=Red>]</font> <font color=Red>-></font> <font color=Red>[</font><font color=Red>[</font>a<font color=Red>]</font><font color=Red>]</font><br /><font color=Blue>genCombs</font> <font color=Red>=</font> nub <font color=Cyan>.</font> map sort <font color=Cyan>.</font> genPerms<br /><br /><font color=Blue><i>-- permutations of length 1 and 2 </i></font><br /><font color=Blue>genPerms</font> <font color=Red>::</font> Eq a <font color=Red>=></font> <font color=Red>[</font>a<font color=Red>]</font> <font color=Red>-></font> <font color=Red>[</font><font color=Red>[</font>a<font color=Red>]</font><font color=Red>]</font><br /><font color=Blue>genPerms</font> [] <font color=Red>=</font> []<br /><font color=Blue>genPerms</font> <font color=Cyan>(</font>x<font color=Red><b>:</b></font>xs<font color=Cyan>)</font> <font color=Red>=</font> <font color=Red>[</font>x<font color=Red>]</font> <font color=Red><b>:</b></font> <font color=Cyan>(</font>map <font color=Cyan>(</font><font color=Red><b>:</b></font> <font color=Red>[</font>x<font color=Red>]</font><font color=Cyan>)</font> xs<font color=Cyan>)</font> <font color=Cyan>++</font> genPerms xs</pre><br /><br />nub deletes all double (or more) elements, and sort sorts the list. (That's why I defined Person deriving Ord.) These are both imported from Data.List.<br /><br />Let's generate all successors of a given state using these combinations:<br /><br /><pre><font color=Blue><i>-- generate all states after applying all possible combinations </i></font><br /><font color=Blue>allSucc</font> <font color=Red>::</font> PState <font color=Red>-></font> <font color=Red>[</font>PState<font color=Red>]</font> <br /><font color=Blue>allSucc</font> s <br /> <font color=Red>|</font> boat s <font color=Cyan>==</font> LeftSide <font color=Red>=</font> map <font color=Cyan>(</font>updatePStateLeft s<font color=Cyan>)</font> <font color=Cyan>(</font>genCombs <font color=Cyan>(</font>left s<font color=Cyan>)</font><font color=Cyan>)</font><br /> <font color=Red>|</font> otherwise <font color=Red>=</font> map <font color=Cyan>(</font>updatePStateRight s<font color=Cyan>)</font> <font color=Cyan>(</font>genCombs <font color=Cyan>(</font>right s<font color=Cyan>)</font><font color=Cyan>)</font></pre><br /><br />As you can see we consider two cases, the boat on the left side and on the right side of the river. The possible combinations are generated by taking all the persons available on the specific side of the river and calling genCombs. The sides are then updated for all combinations and returned as a list of possible next states.<br /><br /><pre><font color=Blue><i>-- move a number of cannibals and missonaries to the right side</i></font><br /><font color=Blue>updatePStateLeft</font> s p <font color=Red>=</font> <font color=Green><u>let</u></font> oldLeft <font color=Red>=</font> left s<br /> oldRight <font color=Red>=</font> right s <br /> <font color=Green><u>in</u></font> s <font color=Cyan>{</font>left <font color=Red>=</font> sort <font color=Cyan>$</font> oldLeft <font color=Cyan>\\</font> p<font color=Cyan>,</font><br /> right <font color=Red>=</font> sort <font color=Cyan>$</font> oldRight <font color=Cyan>++</font> p<font color=Cyan>,</font><br /> boat <font color=Red>=</font> RightSide<br /> <font color=Cyan>}</font><br /><br /><font color=Blue><i>-- move a number of cannibals and missonaries to the left side</i></font><br /><font color=Blue>updatePStateRight</font> s p <font color=Red>=</font> <font color=Green><u>let</u></font> oldLeft <font color=Red>=</font> left s<br /> oldRight <font color=Red>=</font> right s <br /> <font color=Green><u>in</u></font> s <font color=Cyan>{</font>left <font color=Red>=</font> sort <font color=Cyan>$</font> oldLeft <font color=Cyan>++</font> p<font color=Cyan>,</font><br /> right <font color=Red>=</font> sort <font color=Cyan>$</font> oldRight <font color=Cyan>\\</font> p<font color=Cyan>,</font><br /> boat <font color=Red>=</font> LeftSide<br /> <font color=Cyan>}</font></pre><br /><br />But now we have a successor function that generates all possible states given the available persons, the other conditions are not met yet though. In some of our states some poor missionaries will be eaten, so we'll have to filter these out too. First we define a new successor function and then the corresponding filter function. <br /><br /><pre><font color=Blue><i>-- filter legal states</i></font><br /><font color=Blue>successors</font> <font color=Red>::</font> PState <font color=Red>-></font> <font color=Red>[</font>PState<font color=Red>]</font><br /><font color=Blue>successors</font> <font color=Red>=</font> filter isLegalState <font color=Cyan>.</font> allSucc <br /><br /><font color=Blue><i>-- legal states are states with the number of cannibals equal or less </i></font><br /><font color=Blue><i>-- to the number of missionaries on one riverside (or sides with no missionaries)</i></font><br /><font color=Blue>isLegalState</font> <font color=Red>::</font> PState <font color=Red>-></font> Bool<br /><font color=Blue>isLegalState</font> s <font color=Red>=</font> hasNoMoreCannibals <font color=Cyan>(</font>left s<font color=Cyan>)</font> <font color=Cyan>&&</font> hasNoMoreCannibals <font color=Cyan>(</font>right s<font color=Cyan>)</font><br /> <font color=Green><u>where</u></font> hasNoMoreCannibals lst <font color=Red>=</font> <font color=Green><u>let</u></font> lenMiss <font color=Red>=</font> length <font color=Cyan>(</font> filter <font color=Cyan>(</font><font color=Cyan>==</font> Missionary<font color=Cyan>)</font> lst<font color=Cyan>)</font> <br /> lenCann <font color=Red>=</font> length <font color=Cyan>(</font> filter <font color=Cyan>(</font><font color=Cyan>==</font> Cannibal<font color=Cyan>)</font> lst<font color=Cyan>)</font><br /> <font color=Green><u>in</u></font> lenMiss <font color=Cyan>==</font> <font color=Magenta>0</font> <font color=Cyan>||</font> lenMiss <font color=Cyan>>=</font> lenCann</pre><br /><br />As you can see we first generate all successors using our previous function, and then filter out the incorrect states using isLegalState and filter. (//) takes a list and deletes the elements given if present. This function is also imported from Data.List.<br /><br />So now that we have a begin and goal state, and a successor function we'll only need a goal test and a search function. <br /><br />The goal test is trivial:<br /><br /><pre><font color=Blue><i>-- check if the state is a goal state</i></font><br /><font color=Blue>isGoalState</font> <font color=Red>::</font> PState <font color=Red>-></font> Bool<br /><font color=Blue>isGoalState</font> <font color=Red>=</font> <font color=Cyan>(</font><font color=Cyan>==</font> goalState<font color=Cyan>)</font></pre><br /><br />The solution to the problem will be a call to the search function with the beginstate and the startdepth to search. The result is a list of PState that depicts the trace of states to the goal state. So:<br /><br /><pre><font color=Blue>solution</font> <font color=Red>::</font> <font color=Red>[</font>PState<font color=Red>]</font><br /><font color=Blue>solution</font> <font color=Red>=</font> idfs beginState <font color=Magenta>0</font> </pre><br /><br />The search function idfs and especially the helper function idfs' will need some more explaining though and they aren't very elegant. First idfs:<br /><br /><pre><font color=Blue>idfs</font> <font color=Red>::</font> PState <font color=Red>-></font> Int <font color=Red>-></font> <font color=Red>[</font>PState<font color=Red>]</font><br /><font color=Blue>idfs</font> s n <font color=Red>=</font> <font color=Green><u>case</u></font> idfs' <font color=Magenta>0</font> n False s <font color=Green><u>of</u></font> <br /> [] <font color=Red>-></font> idfs s <font color=Cyan>(</font>n<font color=Cyan>+</font><font color=Magenta>1</font><font color=Cyan>)</font><br /> other <font color=Red>-></font> other</pre><br /><br />idfs is called with a state (at the first call the beginState), the current maxDepth, and it results in a lists of states containing the trace to the goal.<br />It calls the idfs' helper function to deliver the actual trace. If the result of the helper function is "[]", then there was no solution and the search depth is increased by a recursive call. Otherwise the solution is returned.<br /><br />Now for the more difficult helper function idfs':<br /><pre> <font color=Green><u>where</u></font><br /> idfs' <font color=Red>::</font> Int <font color=Red>-></font> Int <font color=Red>-></font> Bool <font color=Red>-></font> PState <font color=Red>-></font> <font color=Red>[</font>PState<font color=Red>]</font></pre><br /><br />idfs' takes 4 parameters, which respectively are: the current depth, the current max depth, a boolean depicting if the solution is found and finally the current search node (or state). <br /><br />Now I'll first explain the three border cases. The search should end if:<br />1. The boolean depicting the solution is found is true. In that case the current state should be added to the state trace.<br />2. The current state is a goal state. In that case the function should recursively be called with the boolean as true.<br />3. The current search depth is as large as the maximum search depth, in which case the search should stop. (And [] should be returned.<br /><br />Therefore:<br /><pre> idfs' m n True s <font color=Red>=</font> <font color=Red>[</font>s<font color=Red>]</font><br /> idfs' m n False s<br /> <font color=Red>|</font> isGoalState s <font color=Red>=</font> idfs' m n True s <br /> <font color=Red>|</font> m<font color=Cyan>==</font>n <font color=Red>=</font> []</pre><br /><br />If these cases do not happen then the search should recursively be applied to each successor of the current state. The first result of these searches that does not contain the empty list, contains the solution. In that case we should take that first result and return that along with the current state. Therefore:<br /><br /><pre> <font color=Red>|</font> otherwise <font color=Red>=</font> <font color=Green><u>case</u></font> dropWhile <font color=Cyan>(</font><font color=Cyan>==</font>[]<font color=Cyan>)</font> <font color=Cyan>$</font> map <font color=Cyan>(</font>idfs' <font color=Cyan>(</font>m<font color=Cyan>+</font><font color=Magenta>1</font><font color=Cyan>)</font> n False<font color=Cyan>)</font> <font color=Cyan>(</font>successors s<font color=Cyan>)</font> <font color=Green><u>of</u></font><br /> [] <font color=Red>-></font> []<br /> <font color=Cyan>(</font>x<font color=Red><b>:</b></font>xs<font color=Cyan>)</font> <font color=Red>-></font> s <font color=Red><b>:</b></font> x</pre><br /><br />And this concludes the search function :). <br /><br />So now we're ready to call solution! Load up the definitions in ghci and call solution. The result will be:<br /><br /><pre>[PState {left = [Missionary,Missionary,Missionary,Cannibal,Cannibal,Cannibal], r<br />ight = [], boat = LeftSide},PState {left = [Missionary,Missionary,Cannibal,Canni<br />bal], right = [Missionary,Cannibal], boat = RightSide},PState {left = [Missionar<br />y,Missionary,Missionary,Cannibal,Cannibal], right = [Cannibal], boat = LeftSide}<br />,PState {left = [Missionary,Missionary,Missionary], right = [Cannibal,Cannibal,C<br />annibal], boat = RightSide},PState {left = [Missionary,Missionary,Missionary,Can<br />nibal], right = [Cannibal,Cannibal], boat = LeftSide},PState {left = [Missionary<br />,Cannibal], right = [Missionary,Missionary,Cannibal,Cannibal], boat = RightSide}<br />,PState {left = [Missionary,Missionary,Cannibal,Cannibal], right = [Missionary,C<br />annibal], boat = LeftSide},PState {left = [Cannibal,Cannibal], right = [Missiona<br />ry,Missionary,Missionary,Cannibal], boat = RightSide},PState {left = [Cannibal,C<br />annibal,Cannibal], right = [Missionary,Missionary,Missionary], boat = LeftSide},<br />PState {left = [Cannibal], right = [Missionary,Missionary,Missionary,Cannibal,Ca<br />nnibal], boat = RightSide},PState {left = [Missionary,Cannibal], right = [Missio<br />nary,Missionary,Cannibal,Cannibal], boat = LeftSide},PState {left = [], right =<br />[Missionary,Missionary,Missionary,Cannibal,Cannibal,Cannibal], boat = RightSide}<br />]</pre><br /><br />It's not pretty, but at least it's a solution and an optimal one (the shortest solution is 11 steps, and therefore length 12) too. <br /><br />Well this concludes the first part of the cannibals and missonaries problem. I will explain the state monad implementation of the search function in the next blog post. <br /><br />I hope this was enjoyable :-).<br /><br />For a State Monad introduction see <a href="https://adoseoflogic.blogspot.com/2009/07/cannibals-missionaries-and-state-monad_21.html">Cannibals, Missionaries and the State Monad pt. 2</a>. <br /><br />The final code:<br /><pre><font color=Green><u>module</u></font> AIMAMissionaries <font color=Green><u>where</u></font><br /><font color=Green><u>import</u></font> Data<font color=Cyan>.</font>List<font color=Cyan>(</font>sort<font color=Cyan>,</font> nub<font color=Cyan>,</font> <font color=Cyan>(</font><font color=Cyan>\\</font><font color=Cyan>)</font><font color=Cyan>)</font><br /><br /><br /><font color=Green><u>data</u></font> Person <font color=Red>=</font> Missionary <font color=Red>|</font> Cannibal<br /> <font color=Green><u>deriving</u></font> <font color=Cyan>(</font>Ord<font color=Cyan>,</font> Eq<font color=Cyan>,</font> Show<font color=Cyan>)</font><br /> <br /><font color=Green><u>data</u></font> Position <font color=Red>=</font> LeftSide <font color=Red>|</font> RightSide<br /> <font color=Green><u>deriving</u></font> <font color=Cyan>(</font>Eq<font color=Cyan>,</font> Show<font color=Cyan>)</font><br /><br /><font color=Green><u>data</u></font> PState <font color=Red>=</font> PState <font color=Cyan>{</font>left <font color=Red>::</font> <font color=Red>[</font>Person<font color=Red>]</font><font color=Cyan>,</font> right <font color=Red>::</font> <font color=Red>[</font>Person<font color=Red>]</font><font color=Cyan>,</font> boat <font color=Red>::</font> Position<font color=Cyan>}</font> <br /> <font color=Green><u>deriving</u></font> <font color=Cyan>(</font>Eq<font color=Cyan>,</font> Show<font color=Cyan>)</font><br /> <br /><font color=Blue>beginState</font> <font color=Red>=</font> PState <font color=Cyan>{</font>left <font color=Red>=</font> <font color=Red>[</font>Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Red>]</font><font color=Cyan>,</font> right <font color=Red>=</font> []<font color=Cyan>,</font> boat <font color=Red>=</font> LeftSide<font color=Cyan>}</font><br /><font color=Blue>goalState</font> <font color=Red>=</font> PState <font color=Cyan>{</font>left <font color=Red>=</font> []<font color=Cyan>,</font> right <font color=Red>=</font> <font color=Red>[</font>Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Red>]</font><font color=Cyan>,</font> boat <font color=Red>=</font> RightSide<font color=Cyan>}</font><br /><br /><font color=Blue>almostGoalState</font> <font color=Red>=</font> PState <font color=Cyan>{</font>left <font color=Red>=</font> <font color=Red>[</font>Cannibal<font color=Red>]</font><font color=Cyan>,</font> right <font color=Red>=</font> <font color=Red>[</font>Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Red>]</font><font color=Cyan>,</font> boat <font color=Red>=</font> LeftSide<font color=Cyan>}</font><br /><font color=Blue>almostGoalState2</font> <font color=Red>=</font> PState <font color=Cyan>{</font>left <font color=Red>=</font> <font color=Red>[</font>Cannibal<font color=Cyan>,</font> Missionary<font color=Cyan>,</font> Missionary<font color=Red>]</font><font color=Cyan>,</font> right <font color=Red>=</font> <font color=Red>[</font>Missionary<font color=Cyan>,</font> Cannibal<font color=Cyan>,</font> Cannibal<font color=Red>]</font><font color=Cyan>,</font> boat <font color=Red>=</font> LeftSide<font color=Cyan>}</font><br /><br /><br /><br /><font color=Blue>solution</font> <font color=Red>::</font> <font color=Red>[</font>PState<font color=Red>]</font><br /><font color=Blue>solution</font> <font color=Red>=</font> idfs beginState <font color=Magenta>0</font><br /><br /><font color=Blue>idfs</font> <font color=Red>::</font> PState <font color=Red>-></font> Int <font color=Red>-></font> <font color=Red>[</font>PState<font color=Red>]</font><br /><font color=Blue>idfs</font> s n <font color=Red>=</font> <font color=Green><u>case</u></font> idfs' <font color=Magenta>0</font> n False s <font color=Green><u>of</u></font> <br /> [] <font color=Red>-></font> idfs s <font color=Cyan>(</font>n<font color=Cyan>+</font><font color=Magenta>1</font><font color=Cyan>)</font><br /> other <font color=Red>-></font> other<br /> <font color=Green><u>where</u></font><br /> idfs' <font color=Red>::</font> Int <font color=Red>-></font> Int <font color=Red>-></font> Bool <font color=Red>-></font> PState <font color=Red>-></font> <font color=Red>[</font>PState<font color=Red>]</font><br /> idfs' m n True s <font color=Red>=</font> <font color=Red>[</font>s<font color=Red>]</font><br /> idfs' m n False s<br /> <font color=Red>|</font> isGoalState s <font color=Red>=</font> idfs' m n True s <br /> <font color=Red>|</font> m<font color=Cyan>==</font>n <font color=Red>=</font> []<br /> <font color=Red>|</font> otherwise <font color=Red>=</font> <font color=Green><u>case</u></font> dropWhile <font color=Cyan>(</font><font color=Cyan>==</font>[]<font color=Cyan>)</font> <font color=Cyan>$</font> map <font color=Cyan>(</font>idfs' <font color=Cyan>(</font>m<font color=Cyan>+</font><font color=Magenta>1</font><font color=Cyan>)</font> n False<font color=Cyan>)</font> <font color=Cyan>(</font>successors s<font color=Cyan>)</font> <font color=Green><u>of</u></font><br /> [] <font color=Red>-></font> []<br /> <font color=Cyan>(</font>x<font color=Red><b>:</b></font>xs<font color=Cyan>)</font> <font color=Red>-></font> s <font color=Red><b>:</b></font> x<br /><br /><font color=Blue><i>-- check if the state is a goal state</i></font><br /><font color=Blue>isGoalState</font> <font color=Red>::</font> PState <font color=Red>-></font> Bool<br /><font color=Blue>isGoalState</font> <font color=Red>=</font> <font color=Cyan>(</font><font color=Cyan>==</font> goalState<font color=Cyan>)</font><br /><br /><font color=Blue><i>-- filter legal states</i></font><br /><font color=Blue>successors</font> <font color=Red>::</font> PState <font color=Red>-></font> <font color=Red>[</font>PState<font color=Red>]</font><br /><font color=Blue>successors</font> <font color=Red>=</font> filter isLegalState <font color=Cyan>.</font> allSucc <br /><br /><font color=Blue><i>-- generate all states after applying all possible combinations </i></font><br /><font color=Blue>allSucc</font> <font color=Red>::</font> PState <font color=Red>-></font> <font color=Red>[</font>PState<font color=Red>]</font> <br /><font color=Blue>allSucc</font> s <br /> <font color=Red>|</font> boat s <font color=Cyan>==</font> LeftSide <font color=Red>=</font> map <font color=Cyan>(</font>updatePStateLeft s<font color=Cyan>)</font> <font color=Cyan>(</font>genCombs <font color=Cyan>(</font>left s<font color=Cyan>)</font><font color=Cyan>)</font><br /> <font color=Red>|</font> otherwise <font color=Red>=</font> map <font color=Cyan>(</font>updatePStateRight s<font color=Cyan>)</font> <font color=Cyan>(</font>genCombs <font color=Cyan>(</font>right s<font color=Cyan>)</font><font color=Cyan>)</font><br /><br /><font color=Blue><i>-- move a number of cannibals and missonaries to the right side</i></font><br /><font color=Blue>updatePStateLeft</font> s p <font color=Red>=</font> <font color=Green><u>let</u></font> oldLeft <font color=Red>=</font> left s<br /> oldRight <font color=Red>=</font> right s <br /> <font color=Green><u>in</u></font> s <font color=Cyan>{</font>left <font color=Red>=</font> sort <font color=Cyan>$</font> oldLeft <font color=Cyan>\\</font> p<font color=Cyan>,</font><br /> right <font color=Red>=</font> sort <font color=Cyan>$</font> oldRight <font color=Cyan>++</font> p<font color=Cyan>,</font><br /> boat <font color=Red>=</font> RightSide<br /> <font color=Cyan>}</font><br /><br /><font color=Blue><i>-- move a number of cannibals and missonaries to the left side</i></font><br /><font color=Blue>updatePStateRight</font> s p <font color=Red>=</font> <font color=Green><u>let</u></font> oldLeft <font color=Red>=</font> left s<br /> oldRight <font color=Red>=</font> right s <br /> <font color=Green><u>in</u></font> s <font color=Cyan>{</font>left <font color=Red>=</font> sort <font color=Cyan>$</font> oldLeft <font color=Cyan>++</font> p<font color=Cyan>,</font><br /> right <font color=Red>=</font> sort <font color=Cyan>$</font> oldRight <font color=Cyan>\\</font> p<font color=Cyan>,</font><br /> boat <font color=Red>=</font> LeftSide<br /> <font color=Cyan>}</font><br /><br /><font color=Blue><i>-- unique combinations</i></font><br /><font color=Blue>genCombs</font> <font color=Red>::</font> Ord a <font color=Red>=></font> <font color=Red>[</font>a<font color=Red>]</font> <font color=Red>-></font> <font color=Red>[</font><font color=Red>[</font>a<font color=Red>]</font><font color=Red>]</font><br /><font color=Blue>genCombs</font> <font color=Red>=</font> nub <font color=Cyan>.</font> map sort <font color=Cyan>.</font> genPerms<br /><br /><font color=Blue><i>-- permutations of length 1 and 2 </i></font><br /><font color=Blue>genPerms</font> <font color=Red>::</font> Eq a <font color=Red>=></font> <font color=Red>[</font>a<font color=Red>]</font> <font color=Red>-></font> <font color=Red>[</font><font color=Red>[</font>a<font color=Red>]</font><font color=Red>]</font><br /><font color=Blue>genPerms</font> [] <font color=Red>=</font> []<br /><font color=Blue>genPerms</font> <font color=Cyan>(</font>x<font color=Red><b>:</b></font>xs<font color=Cyan>)</font> <font color=Red>=</font> <font color=Red>[</font>x<font color=Red>]</font> <font color=Red><b>:</b></font> <font color=Cyan>(</font>map <font color=Cyan>(</font><font color=Red><b>:</b></font> <font color=Red>[</font>x<font color=Red>]</font><font color=Cyan>)</font> xs<font color=Cyan>)</font> <font color=Cyan>++</font> genPerms xs<br /> <br /><font color=Blue><i>-- legal states are states with the number of cannibals equal or less </i></font><br /><font color=Blue><i>-- to the number of missionaries on one riverside (or sides with no missionaries)</i></font><br /><font color=Blue>isLegalState</font> <font color=Red>::</font> PState <font color=Red>-></font> Bool<br /><font color=Blue>isLegalState</font> s <font color=Red>=</font> hasNoMoreCannibals <font color=Cyan>(</font>left s<font color=Cyan>)</font> <font color=Cyan>&&</font> hasNoMoreCannibals <font color=Cyan>(</font>right s<font color=Cyan>)</font><br /> <font color=Green><u>where</u></font> hasNoMoreCannibals lst <font color=Red>=</font> <font color=Green><u>let</u></font> lenMiss <font color=Red>=</font> length <font color=Cyan>(</font> filter <font color=Cyan>(</font><font color=Cyan>==</font> Missionary<font color=Cyan>)</font> lst<font color=Cyan>)</font> <br /> lenCann <font color=Red>=</font> length <font color=Cyan>(</font> filter <font color=Cyan>(</font><font color=Cyan>==</font> Cannibal<font color=Cyan>)</font> lst<font color=Cyan>)</font><br /> <font color=Green><u>in</u></font> lenMiss <font color=Cyan>==</font> <font color=Magenta>0</font> <font color=Cyan>||</font> lenMiss <font color=Cyan>>=</font> lenCann</pre><br /><br /><span style="font-weight:bold;">Edit:</span> Added colouring :) and link to part 2. Nebasuke https://www.blogger.com/profile/00690086652715846121 noreply@blogger.com 2 tag:blogger.com,1999:blog-8387731529560364137.post-1588589935880018564 2009-07-19T03:24:00.001+02:00 2009-07-19T03:47:27.380+02:00 The blag <span>First a small introduction to why this blag was created. I (Bas) will start a master Agent Technology, a computer science master, in Utrecht University this year. This choice of master corresponds with my interest in functional programming, logic, agents and artificial intelligence, and I intend to combine these interests with my current favourite programming language, Haskell, and discuss my findings in this blog.<br /><br /><br /><br /></span> Nebasuke https://www.blogger.com/profile/00690086652715846121 noreply@blogger.com 1