<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7956560213437381210</id><updated>2011-07-07T18:53:18.942-07:00</updated><category term='visual studio'/><category term='real world'/><category term='scheme'/><category term='meta'/><category term='eopl'/><category term='f#'/><category term='scala'/><category term='LtU'/><category term='logic'/><category term='web'/><category term='books'/><category term='functional'/><category term='haskell'/><category term='vs2008'/><category term='video'/><category term='ocaml'/><category term='monads'/><category term='eclipse'/><category term='hindley-milner'/><category term='review'/><category term='ml'/><category term='types'/><title type='text'>Code Miscellany</title><subtitle type='html'>Smalltalk about code and programming languages, especially functional ones</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>54</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-7487672743384014770</id><published>2008-03-15T00:02:00.000-07:00</published><updated>2009-08-02T00:19:05.420-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='logic'/><title type='text'>Brute force SAT solver in Haskell</title><content type='html'>Sometimes people get wrong impressions after a Theory of Computation course. A "hard" problem there is not necessarily hard to solve with a program, just hard to solve well in realistic circumstances. Take &lt;a href="http://en.wikipedia.org/wiki/Boolean_satisfiability_problem"&gt;SAT&lt;/a&gt;, for example, the boolean satisfiability problem for propositional logic. It's a classic example of a NP-complete problem, whose naive solution -- generate all possible combinations of truth-values for each atomic proposition and then calculate the value for the whole formula -- is clearly exponential. But this naive solution is very easy to write. For example, in Haskell we get something like the following:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color:Green;"&gt;&lt;u&gt;import&lt;/u&gt;&lt;/span&gt; Data&lt;span style="color:Cyan;"&gt;.&lt;/span&gt;List  &lt;span style="color:Cyan;"&gt;(&lt;/span&gt; nub &lt;span style="color:Cyan;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color:Green;"&gt;&lt;u&gt;import&lt;/u&gt;&lt;/span&gt; Data&lt;span style="color:Cyan;"&gt;.&lt;/span&gt;Maybe &lt;span style="color:Cyan;"&gt;(&lt;/span&gt; fromJust &lt;span style="color:Cyan;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:Green;"&gt;&lt;u&gt;data&lt;/u&gt;&lt;/span&gt; Formula &lt;span style="color:Red;"&gt;=&lt;/span&gt; Var String &lt;span style="color:Red;"&gt;|&lt;/span&gt; And Formula Formula &lt;span style="color:Red;"&gt;|&lt;/span&gt;&lt;br /&gt;              Or Formula Formula &lt;span style="color:Red;"&gt;|&lt;/span&gt; Not Formula&lt;br /&gt;&lt;br /&gt;getVarsDup &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;Var v&lt;span style="color:Cyan;"&gt;)&lt;/span&gt;     &lt;span style="color:Red;"&gt;=&lt;/span&gt; &lt;span style="color:Red;"&gt;[&lt;/span&gt;v&lt;span style="color:Red;"&gt;]&lt;/span&gt;&lt;br /&gt;getVarsDup &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;And f1 f2&lt;span style="color:Cyan;"&gt;)&lt;/span&gt; &lt;span style="color:Red;"&gt;=&lt;/span&gt; &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;getVarsDup f1&lt;span style="color:Cyan;"&gt;)&lt;/span&gt; &lt;span style="color:Cyan;"&gt;++&lt;/span&gt; &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;getVarsDup f2&lt;span style="color:Cyan;"&gt;)&lt;/span&gt;&lt;br /&gt;getVarsDup &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;Or f1 f2&lt;span style="color:Cyan;"&gt;)&lt;/span&gt;  &lt;span style="color:Red;"&gt;=&lt;/span&gt; &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;getVarsDup f1&lt;span style="color:Cyan;"&gt;)&lt;/span&gt; &lt;span style="color:Cyan;"&gt;++&lt;/span&gt; &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;getVarsDup f2&lt;span style="color:Cyan;"&gt;)&lt;/span&gt;&lt;br /&gt;getVarsDup &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;Not f&lt;span style="color:Cyan;"&gt;)&lt;/span&gt;     &lt;span style="color:Red;"&gt;=&lt;/span&gt; getVarsDup f&lt;br /&gt;&lt;br /&gt;genValues n &lt;span style="color:Red;"&gt;=&lt;/span&gt; genAux &lt;span style="color:Cyan;"&gt;$&lt;/span&gt; &lt;span style="color:Red;"&gt;[&lt;/span&gt;replicate n True&lt;span style="color:Red;"&gt;]&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:Green;"&gt;&lt;u&gt;where&lt;/u&gt;&lt;/span&gt; genAux &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;v&lt;span style="color:Red;"&gt;&lt;b&gt;:&lt;/b&gt;&lt;/span&gt;vs&lt;span style="color:Cyan;"&gt;)&lt;/span&gt;     &lt;span style="color:Red;"&gt;=&lt;/span&gt; &lt;span style="color:Green;"&gt;&lt;u&gt;if&lt;/u&gt;&lt;/span&gt; not &lt;span style="color:Cyan;"&gt;$&lt;/span&gt; or &lt;span style="color:Cyan;"&gt;$&lt;/span&gt; v &lt;span style="color:Green;"&gt;&lt;u&gt;then&lt;/u&gt;&lt;/span&gt; v&lt;span style="color:Red;"&gt;&lt;b&gt;:&lt;/b&gt;&lt;/span&gt;vs&lt;br /&gt;                             &lt;span style="color:Green;"&gt;&lt;u&gt;else&lt;/u&gt;&lt;/span&gt; genAux &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;&lt;span style="color:Cyan;"&gt;(&lt;/span&gt;next v&lt;span style="color:Cyan;"&gt;)&lt;/span&gt; &lt;span style="color:Red;"&gt;&lt;b&gt;:&lt;/b&gt;&lt;/span&gt; v &lt;span style="color:Red;"&gt;&lt;b&gt;:&lt;/b&gt;&lt;/span&gt; vs&lt;span style="color:Cyan;"&gt;)&lt;/span&gt;&lt;br /&gt;         next &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;True &lt;span style="color:Red;"&gt;&lt;b&gt;:&lt;/b&gt;&lt;/span&gt; ts&lt;span style="color:Cyan;"&gt;)&lt;/span&gt;  &lt;span style="color:Red;"&gt;=&lt;/span&gt; &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;False &lt;span style="color:Red;"&gt;&lt;b&gt;:&lt;/b&gt;&lt;/span&gt; ts&lt;span style="color:Cyan;"&gt;)&lt;/span&gt;&lt;br /&gt;         next &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;False &lt;span style="color:Red;"&gt;&lt;b&gt;:&lt;/b&gt;&lt;/span&gt; ts&lt;span style="color:Cyan;"&gt;)&lt;/span&gt; &lt;span style="color:Red;"&gt;=&lt;/span&gt; &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;True &lt;span style="color:Red;"&gt;&lt;b&gt;:&lt;/b&gt;&lt;/span&gt; &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;next ts&lt;span style="color:Cyan;"&gt;)&lt;/span&gt;&lt;span style="color:Cyan;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;solveFormula &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;Var v&lt;span style="color:Cyan;"&gt;)&lt;/span&gt; env     &lt;span style="color:Red;"&gt;=&lt;/span&gt; fromJust &lt;span style="color:Cyan;"&gt;$&lt;/span&gt; lookup v env&lt;br /&gt;solveFormula &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;And f1 f2&lt;span style="color:Cyan;"&gt;)&lt;/span&gt; env &lt;span style="color:Red;"&gt;=&lt;/span&gt; &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;solveFormula f1 env&lt;span style="color:Cyan;"&gt;)&lt;/span&gt; &lt;span style="color:Cyan;"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;br /&gt;                              &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;solveFormula f2 env&lt;span style="color:Cyan;"&gt;)&lt;/span&gt;&lt;br /&gt;solveFormula &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;Or f1 f2&lt;span style="color:Cyan;"&gt;)&lt;/span&gt; env  &lt;span style="color:Red;"&gt;=&lt;/span&gt; &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;solveFormula f1 env&lt;span style="color:Cyan;"&gt;)&lt;/span&gt; &lt;span style="color:Cyan;"&gt;||&lt;/span&gt;&lt;br /&gt;                              &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;solveFormula f2 env&lt;span style="color:Cyan;"&gt;)&lt;/span&gt;&lt;br /&gt;solveFormula &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;Not f&lt;span style="color:Cyan;"&gt;)&lt;/span&gt; env     &lt;span style="color:Red;"&gt;=&lt;/span&gt; not &lt;span style="color:Cyan;"&gt;$&lt;/span&gt; solveFormula f env&lt;br /&gt;&lt;br /&gt;allSolutions f &lt;span style="color:Red;"&gt;=&lt;/span&gt; map &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;solveFormula f&lt;span style="color:Cyan;"&gt;)&lt;/span&gt; &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;map &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;zip vars&lt;span style="color:Cyan;"&gt;)&lt;/span&gt; vals&lt;span style="color:Cyan;"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:Green;"&gt;&lt;u&gt;where&lt;/u&gt;&lt;/span&gt; vars &lt;span style="color:Red;"&gt;=&lt;/span&gt; nub &lt;span style="color:Cyan;"&gt;$&lt;/span&gt; getVarsDup f&lt;br /&gt;         vals &lt;span style="color:Red;"&gt;=&lt;/span&gt; genValues &lt;span style="color:Cyan;"&gt;(&lt;/span&gt;length vars&lt;span style="color:Cyan;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:Blue;"&gt;-- solve the SAT problem&lt;/span&gt;&lt;br /&gt;sat f &lt;span style="color:Red;"&gt;=&lt;/span&gt; or &lt;span style="color:Cyan;"&gt;$&lt;/span&gt; allSolutions f&lt;br /&gt;&lt;br /&gt;&lt;span style="color:Blue;"&gt;-- pointfree!&lt;/span&gt;&lt;br /&gt;sat2 &lt;span style="color:Red;"&gt;=&lt;/span&gt; or &lt;span style="color:Cyan;"&gt;.&lt;/span&gt; allSolutions&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The idea is the same as creating a truth-table for the formula and then looking for a T in the possible values for it. Function &lt;code&gt;genValues&lt;/code&gt; generates all possible values for the atomic propositions, and this is fed into &lt;code&gt;solveFormula&lt;/code&gt;. It would be very easy to alter the code to output the complete truth-table; I leave it as an exercise to the reader. Another standard exercise in logic textbooks is to prove that if a formula contains n atomic propositions, the truth-table will have 2^n lines. Thus, generating all combinations is easily seen to be exponential in time.&lt;br /&gt;&lt;br /&gt;But the fact that it is hard for the computer to solve doesn't mean that it's hard for someone to write a (naive) program to solve it. In practical applications, like circuit design, we may need to solve SAT for thousands of variables, and the naive algorithm would not work. For this we must use a more clever technique, like &lt;a href="http://en.wikipedia.org/wiki/Binary_decision_diagram"&gt;Binary Decision Diagrams&lt;/a&gt;. They're not that hard to code either; the book &lt;a href="http://codemiscellany.blogspot.com/2008/01/book-review-expert-f.html"&gt;Expert F#&lt;/a&gt; includes an example of BDDs in F#.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-7487672743384014770?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/7487672743384014770/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=7487672743384014770&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/7487672743384014770'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/7487672743384014770'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2008/03/brute-force-sat-solver-in-haskell.html' title='Brute force SAT solver in Haskell'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-5791985256560602996</id><published>2008-03-05T08:40:00.000-08:00</published><updated>2008-03-05T08:45:58.449-08:00</updated><title type='text'>Tumbalalaika</title><content type='html'>It's probably too late to be hip because of this now, but I have created a &lt;a href="http://tautologico.tumblr.com/"&gt;tumblelog&lt;/a&gt;. It's easier to post there, so it should be updated more often than this blog. I'll probably post a good number of links in common with &lt;a href="http://anarchaia.org/"&gt;anarchaia&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-5791985256560602996?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/5791985256560602996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=5791985256560602996&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/5791985256560602996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/5791985256560602996'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2008/03/tumbalalaika.html' title='Tumbalalaika'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-9178578543954321663</id><published>2008-01-23T07:05:00.000-08:00</published><updated>2008-01-23T07:12:50.610-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional'/><title type='text'>Functional programming in the mainstream</title><content type='html'>Here is a bit from &lt;a href="http://blogs.tedneward.com/"&gt;Ted Neward&lt;/a&gt;, &lt;a href="http://blogs.tedneward.com/2007/12/27/2008+Predictions+2007+Predictions+Redux.aspx"&gt;commenting&lt;/a&gt; on the outcome of his predictions for 2007:&lt;blockquote&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;THEN:&lt;/strong&gt; Languages: Interest in functional-object hybrid languages will grow. Scala, Jaskell, F#, and others not-yet-invented will start to capture developers' attention, particularly when they hear the part about functional languages being easier to use in multi-core systems because it encourages immutable objects and discourages side effects (meaning we don't have to worry nearly so much about writing thread-safe code).&lt;/em&gt; &lt;em&gt;&lt;strong&gt;NOW: &lt;/strong&gt;&lt;/em&gt;It grew, and it continues to grow. New languages in general are being released (see Clojure, Jaskell, dynalang, and others), and lots of them are incorporating functional language concepts. If you've never programmed in Haskell, now's a good time to learn, because those concepts and syntax are fast making their way towards you...&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-9178578543954321663?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/9178578543954321663/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=9178578543954321663&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/9178578543954321663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/9178578543954321663'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2008/01/functional-programming-in-mainstream.html' title='Functional programming in the mainstream'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-2455548506540455837</id><published>2008-01-17T13:54:00.000-08:00</published><updated>2008-01-17T14:00:14.533-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='review'/><title type='text'>Book review: Expert F#</title><content type='html'>&lt;a href="http://www.apress.com/book/view/1590598504"&gt;Expert F#&lt;/a&gt;, by Don Syme, Adam Granicz and Antonio Cisternino, Apress&lt;br /&gt;&lt;br /&gt;When a new programming language arrives and manages to make an impact, books about it will certainly appear. However, most often the books will be geared to beginners, to people that is either not very experienced in programming or in the programming paradigms embodied by the language. For a experienced programmer, these books stop right when the fun would begin: the advanced stuff, the corners, the details are left out.&lt;br /&gt;&lt;br /&gt;Expert F#, as suggested by its title, is not like this: it is aimed at more experienced programmers. The book will not teach you, for instance, what is functional programming or hammer to your head the best ways to use lists, an ubiquitous data structure in functional languages. But it explains how the things work in F#, so that programmers already familiar with other functional languages will have no trouble picking it up. F# also has object-oriented capabilities, which are explained in a chapter, without however going much deep into OO concepts; the book is about the language, not the paradigms.&lt;br /&gt;&lt;br /&gt;And it does this well. Roughly half of the book is about the language itself, the other half are examples of applications and how to use some important libraries. As I was already familiar with OCaml and Haskell, I mostly skimmed through chapters 1 to 4, reading more closely from chapters 5 (generic types) and 6 (how objects fit into F#). From chapter 7 (encapsulating and packaging your code) on, the book starts to get really interesting; the next one is about common techniques, and chapter 9 is the best in the first part, explaining language-oriented programming, an area where functional languages really shine.&lt;br /&gt;&lt;br /&gt;There are mandatory chapters about Windows Forms (11), Web programming (14) using .NET and data access, including how to use LINQ in F#, but I really liked chapters 12 (working with symbolic representations), and 13 (concurrency and asynchronous workflows). The former includes two cool examples: a symbolic differentiator and a verifier for logic circuits based on BDDs (Binary Decision Diagrams). There are other important and advanced chapters treating topics like interoperation with C and COM, debugging and testing F# programs, and F# library design.&lt;br /&gt;&lt;br /&gt;All in all a very good book about the best current functional language to use in the Windows platform. I have two minor quibbles about it, though: the first few chapters about the language really could be made more interesting (although it didn't affect me much, as I only skimmed them) and some of the more exciting new features of F# could be explained in more detail. Specifically, workflows and active patterns. They are quite recent additions to the language, however, and there is some additional material promised to feature in the book's site.&lt;br /&gt;&lt;br /&gt;Anyway, I will keep this book nearby when programming in F#. It is this kind of book that you'd want to keep around, even after learning the language.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-2455548506540455837?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/2455548506540455837/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=2455548506540455837&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2455548506540455837'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2455548506540455837'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2008/01/book-review-expert-f.html' title='Book review: Expert F#'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-1037192099179771641</id><published>2007-12-11T09:49:00.001-08:00</published><updated>2007-12-11T09:57:38.133-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='visual studio'/><category scheme='http://www.blogger.com/atom/ns#' term='vs2008'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>Do it yourself: Visual F# Express 2008</title><content type='html'>As noted in &lt;a href="http://11011.net/archives/000721.html"&gt;this post&lt;/a&gt;, if you want Visual Studio just to have an IDE to work with F#, you can get it for free. Now with Visual Studio 2008, Microsoft has released a bare-bones VS, without any language, that can be used with language extensions and plugins, as is the case of F#. This bare-bones VS is called &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=40646580-97FA-4698-B65F-620D4B4B1ED7&amp;amp;displaylang=en"&gt;Visual Studio 2008 Shell (integrated mode)&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;After downloading and installing VS 2008 Shell (it takes a lot of unpacking and installing), you can install &lt;a href="http://blogs.msdn.com/dsyme/archive/2007/11/30/f-1-9-3-candidate-release-now-available.aspx"&gt;F# 1.9.3.7&lt;/a&gt; and voilà, you have a pretty good F# IDE in your box, without having to shell out any cash.&lt;br /&gt;&lt;br /&gt;I tested it with F# version 1.9.3.7 in a machine running Windows XP SP2 and no previous version of Visual Studio installed, and it worked. I even compiled and ran some test projects. If it doesn't work at first, take a look at &lt;a href="http://11011.net/archives/000721.html"&gt;the original post&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-1037192099179771641?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/1037192099179771641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=1037192099179771641&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1037192099179771641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1037192099179771641'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/12/do-it-yourself-visual-f-express-2008.html' title='Do it yourself: Visual F# Express 2008'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-5097581776293620342</id><published>2007-10-17T12:17:00.000-07:00</published><updated>2007-10-17T12:26:59.331-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>Further news on World Domination</title><content type='html'>Don Syme blogs about &lt;a href="http://blogs.msdn.com/dsyme/archive/2007/10/17/s-somasegar-on-taking-f-forward.aspx"&gt;taking F# forward&lt;/a&gt;, which means, it seems, that F# will leave the confines of MS Research and be fully integrated into Visual Studio, as a product. If this is right, it's a great step for F# as a language and for functional programming in general, as we'll have a first-class IDE, by a major vendor, shipping with a functional programming language.&lt;br /&gt;&lt;br /&gt;F# is already a great language to use, so I look forward to it getting still greater. The next step for Microsoft is to embrace &lt;a href="http://www.haskell.org/visualhaskell/"&gt;Visual Haskell&lt;/a&gt; and fully integrate Haskell in Visual Studio too :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-5097581776293620342?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/5097581776293620342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=5097581776293620342&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/5097581776293620342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/5097581776293620342'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/10/further-news-on-world-domination.html' title='Further news on World Domination'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-6325670349655020940</id><published>2007-09-24T19:53:00.000-07:00</published><updated>2007-11-03T09:55:36.471-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='review'/><title type='text'>Review: OCaml for Scientists</title><content type='html'>When we think about what makes a programming book good, what separates a classic from a run-of-the-mill for-dummies-learn-in-X-days book, it's not hard to get to the conclusion that the examples are an important piece of what we perceive as quality. I would say that this is even more so for books on programming languages: &lt;a href="http://en.wikipedia.org/wiki/The_C_Programming_Language_%28book%29"&gt;K&amp;amp;R&lt;/a&gt; had great examples; &lt;a href="http://www.gigamonkeys.com/book/"&gt;Practical Common Lisp&lt;/a&gt; has great examples that are now being copied by many authors; the list could go on.&lt;br /&gt;&lt;br /&gt;So it was not that surprising to discover that one of the reasons of all the praise received by Dr. Jon Harrop's book &lt;a href="http://www.ffconsultancy.com/products/ocaml_for_scientists/"&gt;OCaml for Scientists&lt;/a&gt; is its set of examples. There are even two entire chapters devoted to examples, the first for simple and the second for more significative ones. They are really good: well-chosen, interesting and well-written. Most of them have a scientific flavor, in keeping with the book's title, but to me this is a plus. Also, I don't recall seeing wavelet transforms as examples in a programming language book before; originality also counts.&lt;br /&gt;&lt;br /&gt;The book's title is accurate: it is a book about OCaml primarily targeted for scientific applications. But most of the topics covered are really useful to anyone wanting to learn the OCaml language. Of all the ten chapters, I would say only one -- Chapter 4, Numerical Analysis -- is mostly directed to scientists. Well, probably game programmers too. And programmers of computer graphics applications, and anyone using floating-point arithmetic. Anyway, the other chapters that have somewhat of a scientific bent are: Chapter 6, Visualization, which is really about how to use OpenGL and GLUT in OCaml, which is quite cool in itself; and Chapter 10, Complete Examples, but each example is well explained and can be (mostly) understood without previous knowledge.&lt;br /&gt;&lt;br /&gt;To give some idea about the book's contents, here is a quick tour: Chapter 1 is a quick introduction, covering most important concepts of the core language. Chapter 2 is about how to structure bigger programs, including function nesting, modules, objects, and how to manage dependencies and compilation. Chapter 3 is a very interesting chapter on data structures in OCaml, beginning with a section on algorithmic complexity; it covers the more important containers provided in the library, and also how to implement and work with trees. Chapter 4 is the one about numerical analysis, covering the basics about doing calculations with limited-precision numbers, and how to use more precise forms of arithmetic. Chapter 5 tackles input and output in OCaml, going beyond the call of duty to present the lexer generator (ocamllex) and parser generator (ocamlyacc) in the OCaml toolset. Chapter 6 is about visualization with OpenGL and GLUT, Chapter 7 is a very good one about optimization, and Chapter 8 a very useful one about libraries. The final two chapters have examples, and don't be fooled by the title of Chapter 9, Simple Examples. There is good stuff there. There are also two appendices, about more advanced features and troubleshooting advice respectivelly.&lt;br /&gt;&lt;br /&gt;To be fair, the book has some small weaknesses that, in the end, are not that important, if you consider its target audience and what's common OCaml style. One is the treatment of objects: it is very cursory, and one of the examples (about real and complex numbers) could easily be considered a bad case of OO design. Considering most OCaml programmers rarely use objects, this is not so troubling. The other weakness I'd like to cite is more of a wish from my part: I wish there were more about advanced topics, especially functors (only very lightly touched in Appendix A).&lt;br /&gt;&lt;br /&gt;But it's really a very good book about OCaml, both for beginners and for people with some previous exposure to it. It has advice on good programming style throughout, great examples (shown in color, properly syntax-highlighted), and distilled practical experience on some important topics (optimization, using libraries) that is hard to get elsewhere. It is remarkable not only in the very restricted universe of OCaml books, but as a programming book, in general: it stands between the best I've seen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-6325670349655020940?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/6325670349655020940/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=6325670349655020940&amp;isPopup=true' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/6325670349655020940'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/6325670349655020940'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/09/review-ocaml-for-scientists.html' title='Review: OCaml for Scientists'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-6811023369778345298</id><published>2007-08-21T10:14:00.000-07:00</published><updated>2007-08-21T10:25:25.294-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='monads'/><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='functional'/><title type='text'>Monads in OCaml</title><content type='html'>&lt;div style="text-align: left;"&gt;So, there. Someone who has never programmed in Haskell probably never encountered the idea of monads -- unless it is someone who works in semantics and has read &lt;a href="http://www.disi.unige.it/person/MoggiE/"&gt;Moggi&lt;/a&gt;'s works; but I digress. An interesting way to tackle the idea of monads is to look at them outside of Haskell, and see how it works in other languages. Often, other languages don't have what it takes to express the concept of a monad in its full generality, but specific monads can always be implemented. In this regard, there's &lt;a href="http://okmij.org/ftp/Computation/monads.html"&gt;this page by oleg&lt;/a&gt;, and there's &lt;a href="http://moonbase.rydia.net/mental/writings/programming/monads-in-ruby/00introduction.html"&gt;this other one about monads in Ruby&lt;/a&gt;. I remember seeing somewhere a page that compiled monad implementations in various languages, but I can't seem to find it now.&lt;br /&gt;&lt;br /&gt;Anyhow, Brian Hurt has written a very nice &lt;a href="http://enfranchisedmind.com/blog/archive/2007/08/06/307"&gt;tutorial about monads in OCaml&lt;/a&gt;. It uses the module system and functors (see comments) to define a reasonably general monad concept in OCaml. It's a good read.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-6811023369778345298?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/6811023369778345298/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=6811023369778345298&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/6811023369778345298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/6811023369778345298'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/08/monads-in-ocaml.html' title='Monads in OCaml'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-471629752765489939</id><published>2007-08-07T18:57:00.000-07:00</published><updated>2007-08-07T19:03:52.584-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video'/><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><title type='text'>Towards Global Domination</title><content type='html'>If you haven't yet seen them or heard about them somewhere else, it seems that the &lt;a href="http://www.realworldhaskell.org/blog/2007/08/03/a-brief-haskell-at-oscon-trip-report/"&gt;videos of Simon Peyton-Jones' talks at OSCON&lt;/a&gt; are &lt;a href="http://www.realworldhaskell.org/blog/2007/08/07/wow-oscon-video-viewing-statistics/"&gt;quite a hit&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;And people still look at me funny when I say that functional programming is going to take over the world.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-471629752765489939?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/471629752765489939/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=471629752765489939&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/471629752765489939'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/471629752765489939'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/08/towards-global-domination.html' title='Towards Global Domination'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-658341466861157060</id><published>2007-07-13T13:24:00.000-07:00</published><updated>2007-07-21T13:42:24.411-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><title type='text'>Battle of the OCaml plugins for Eclipse</title><content type='html'>A new OCaml plugin for Eclipse, called &lt;a href="http://ocaml.eclipse.ortsa.com/"&gt;OcaIDE&lt;/a&gt;, has just been announced. Apparently, it has been under development for a long time. It seems to be quite complete in features, although I didn't try it yet. The question is that this is the third OCaml plugin being developed currently; there's &lt;a href="http://ocamldt.free.fr/"&gt;ODT&lt;/a&gt;, about which I talked in &lt;a href="http://codemiscellany.blogspot.com/2007/06/ocaml-with-eclipse.html"&gt;a earlier post&lt;/a&gt;, and another one being developed as one of the OCaml projects in the Google Summer of Code. The competition is good in some ways, but on the other hand the resulting fragmentation can be a problem to a small community like that of OCaml. It would be best if the teams managed to combine their efforts in some way. Let's see how this plays out.&lt;br /&gt;&lt;br /&gt;Speaking of collaboration, there's mention on OcaIDE's site about a &lt;a href="http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html"&gt;free-software license&lt;/a&gt;, but the source code doesn't seem to be available.&lt;br /&gt;&lt;br /&gt;UPDATE: As someone pointed in the comments, the source is available together with the plugin. See &lt;a href="http://ocaml.eclipse.ortsa.com:8480/ocaide/sources.html"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-658341466861157060?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/658341466861157060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=658341466861157060&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/658341466861157060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/658341466861157060'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/07/battle-of-ocaml-plugins-for-eclipse.html' title='Battle of the OCaml plugins for Eclipse'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-2098879315893322834</id><published>2007-07-05T18:23:00.000-07:00</published><updated>2007-07-05T18:28:14.355-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='review'/><title type='text'>Review: Practical OCaml</title><content type='html'>Executive summary: this is not Practical Common Lisp for OCaml. It's ambitious but disappointing. However, it's not so bad as it seems at first sight.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://caml.inria.fr/"&gt;OCaml&lt;/a&gt; is a sexy language that combines the expressiveness and terseness of scripting languages with the static type checking and performance of languages like C++ and Java. A book may be a good investment to learn a new language, and this is one of the few books available on the language. How does it fare?&lt;br /&gt;&lt;br /&gt;This book has received very harsh criticism overall, and it mostly deserves it; it is somewhat of a mess. But it is not uniformly bad: some chapters are very bad, others are acceptable or interesting, depending on your background. The problem seems to be that the worst chapters come first; although it shows signs of bad editing throughout, the first few chapters are especially bad. And I mean really bad: bad text, bad editing, bad examples, lots of senseless repetition, conceptual errors, using language features not yet introduced (and that go unexplained), the list goes on. Later chapters are considerably less irritating.&lt;br /&gt;&lt;br /&gt;Clearly inspired by Peter Seibel's terrific book &lt;a href="http://www.gigamonkeys.com/book/"&gt;Practical Common Lisp&lt;/a&gt;, the chapters on this one are divided in two types: the ones that explain the language, and the "Practical" ones, containing extended examples. This is a great idea, and even badly executed as it may be in Practical OCaml, it still results in interesting chapters. Actually, the Practical chapters are overall better than the language ones; from them, a reader can get a real sense of using OCaml in simple but realistic projects, integrating many different libraries and tools, some of them not contained in the standard OCaml distribution. Still, the code in these chapters can be criticized for their style. For one thing, I think the author uses classes and other OO features much more often than they appear on real OCaml programs. Nonetheless, an experienced programmer could get a lot of interesting pointers from these chapters, by knowing what to salvage and what not to replicate from the code.&lt;br /&gt;&lt;br /&gt;But the rest of the book, the OCaml chapters, are in really bad shape. They don't explain things very well, and fails miserably at the more difficult aspects of the language. The chapter on modules and functors is so bad as to be almost useless; don't try to learn about functors from this book. Camlp4, the nifty tool for metaprogramming and extension, is other subject with a bad treatment. The chapter on Threads could be improved a lot, but it still gives a general idea of how multithreaded programming in OCaml is. Again, for experienced developers, it should provide pointers for further study.&lt;br /&gt;&lt;br /&gt;If experienced developers can get something from this book, novice ones should stay away from it. Not only is the text confusing, but there are a lot of glaring conceptual errors. Maybe some errors are to be expected from a trade book, from an author that is not an academic, but there&lt;br /&gt;are things that are completely confusing. For example, this is the definition of type (page 24): "A type is a thing (or a collection of things) or value." And there is a lot more like this, unfortunately.&lt;br /&gt;&lt;br /&gt;Overall, it has interesting parts, but surely not enough to make worth the full cover price. For experienced programmers and people already familiar with other typed functional programming languages (&lt;a href="http://haskell.org/"&gt;Haskell&lt;/a&gt;, &lt;a href="http://research.microsoft.com/fsharp/fsharp.aspx"&gt;F#&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Standard_ML"&gt;SML&lt;/a&gt;, etc), the book could serve as an initial guide for OCaml programming, but there are better alternatives around.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-2098879315893322834?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/2098879315893322834/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=2098879315893322834&amp;isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2098879315893322834'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2098879315893322834'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/07/review-practical-ocaml.html' title='Review: Practical OCaml'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-1824983581042602917</id><published>2007-06-17T10:54:00.000-07:00</published><updated>2007-06-17T11:05:23.486-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>F# Performance</title><content type='html'>There's a comparison of &lt;a href="http://strangelights.com/blog/archive/2007/06/17/1588.aspx"&gt;F# versus IronPython&lt;/a&gt; in Robert Pickering's blog. The results show that F# has roughly the same level of conciseness and terseness of Python, while being close in performance to C#. This is a .NET-based comparison, but it would be interesting to compare F# with CPython to see where it stands. If we are to believe &lt;a href="http://mail.python.org/pipermail/python-dev/2006-April/064277.html"&gt;this discussion&lt;/a&gt; on the python-dev mailing list, it seems that IronPython's performance must be comparable to CPython's, so there we have it: .NET or not, F# strikes an interesting balance in the expressiveness versus performance trade-offs.&lt;br /&gt;&lt;br /&gt;This is also my personal experience with OCaml: performance roughly comparable to C/C++, but expressive and concise like scripting languages. It is this interesting position in the expressiveness x performance curve that makes both F# and OCaml very worthwhile languages to learn and use today.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-1824983581042602917?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/1824983581042602917/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=1824983581042602917&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1824983581042602917'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1824983581042602917'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/06/f-performance.html' title='F# Performance'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-2622611036552181162</id><published>2007-06-09T17:02:00.000-07:00</published><updated>2007-06-09T17:08:18.770-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>The EOPL in F# wiki</title><content type='html'>I've started moving the content for the "EOPL in F#" translation to a wiki. Unfortunately, I have also been insanely busy as of late, so there's only the beginning there. However, as I'll have more free time from now on, I intend to catch up with what's already here and then start posting more sections that I already translated. I also noticed I never posted some parts because I forgot to, so it will be added to the wiki as well. Anyway, here is the link:&lt;br /&gt;&lt;a href="http://tautologico.stikipad.com/eoplfsharp/show/HomePage"&gt;&lt;br /&gt;EOPL in F# Wiki&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-2622611036552181162?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/2622611036552181162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=2622611036552181162&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2622611036552181162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2622611036552181162'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/06/eopl-in-f-wiki.html' title='The EOPL in F# wiki'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-351833637856656385</id><published>2007-06-01T13:28:00.000-07:00</published><updated>2007-06-01T13:45:44.022-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><title type='text'>OCaml with Eclipse</title><content type='html'>The primary editor on which to write &lt;a href="http://caml.inria.fr/"&gt;OCaml&lt;/a&gt; code has always been &lt;a href="http://www.emacswiki.org/cgi-bin/wiki"&gt;Emacs&lt;/a&gt;. This tends to be a problem for users on Windows, that mostly aren't familiar with the editor. And of course there are many people that use unix platforms and don't like Emacs.&lt;br /&gt;&lt;br /&gt;A good alternative is &lt;a href="http://eclipse.org/"&gt;Eclipse&lt;/a&gt;, which has very good plugins for Java programming, and can be extended to handle other languages. &lt;a href="http://ocamldt.free.fr/"&gt;ODT, a plugin for OCaml development in Eclipse&lt;/a&gt;, is being actively developed by Emmanuel Dieul. Actually there's another plugin in development by someone under the Google Summer of Code, and we hope they can integrate both efforts to get a better plugin in the end.&lt;br /&gt;&lt;br /&gt;Anyway, ODT looks interesting right now, and it's been evolving quite fast. Eclipse is quite a memory hog, but if you already use it or are willing to pay the requirements, it can provide a modern IDE for OCaml under Windows or unix, and a good alternative for Emacs. Let's hope ODT keeps improving.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-351833637856656385?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/351833637856656385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=351833637856656385&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/351833637856656385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/351833637856656385'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/06/ocaml-with-eclipse.html' title='OCaml with Eclipse'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-4708866784586066384</id><published>2007-05-26T14:36:00.000-07:00</published><updated>2007-05-26T14:46:52.794-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><title type='text'>Great news in the Haskell Books front</title><content type='html'>This was recently announced and everyone must already know about it (I was away at a conference), but just in case: &lt;a href="http://www.oreilly.com/"&gt;O'Reilly&lt;/a&gt; will publish a book about &lt;a href="http://haskell.org/"&gt;Haskell&lt;/a&gt; called &lt;a href="http://www.realworldhaskell.org/blog/"&gt;Real-World Haskell&lt;/a&gt;, written by people very active in the Haskell community. Such a book from O'Reilly has the potential to seriously increase Haskell's popularity, and familiarize more people with functional programming.&lt;br /&gt;&lt;br /&gt;Considering that &lt;a href="http://www.apress.com/book/bookDisplay.html?bID=10240"&gt;a book about F#&lt;/a&gt; is already out and &lt;a href="http://www.apress.com/book/bookDisplay.html?bID=10306"&gt;another one&lt;/a&gt; is on the way, and that APress recently published &lt;a href="http://www.apress.com/book/bookDisplay.html?bID=10146"&gt;a book&lt;/a&gt; on &lt;a href="http://caml.inria.fr/"&gt;OCaml&lt;/a&gt; (it doesn't seem to be very good, unfortunately), I guess functional programming is really getting more popular.&lt;br /&gt;&lt;br /&gt;Maybe there's hope that Haskell will take over the world and everyone will use monads and pure lazy functional programming :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-4708866784586066384?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/4708866784586066384/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=4708866784586066384&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/4708866784586066384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/4708866784586066384'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/05/great-news-in-haskell-books-front.html' title='Great news in the Haskell Books front'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-4721916668228804435</id><published>2007-05-16T16:59:00.000-07:00</published><updated>2007-05-16T17:03:52.735-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><category scheme='http://www.blogger.com/atom/ns#' term='meta'/><title type='text'>The EOPL in F# thing</title><content type='html'>I have translated more of the &lt;a href="http://www.cs.indiana.edu/eopl/"&gt;EOPL&lt;/a&gt; book into F#, but the examples keep growing and proving how unfit the whole enterprise is to the blog format. I knew this from the beginning, and would prefer a wiki, but then I couldn't find a decent wiki server. I may have found one now, and if all goes well I'll link to it here after moving there some of the contents posted here. After this, I don't know if this blog will still be useful, but I'll wait and see.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-4721916668228804435?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/4721916668228804435/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=4721916668228804435&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/4721916668228804435'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/4721916668228804435'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/05/eopl-in-f-thing.html' title='The EOPL in F# thing'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-252155612748438695</id><published>2007-04-30T14:39:00.000-07:00</published><updated>2007-04-30T14:47:27.083-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='functional'/><category scheme='http://www.blogger.com/atom/ns#' term='real world'/><title type='text'>Functional programming in Wall Street</title><content type='html'>The latest issue of &lt;a href="http://www.haskell.org/haskellwiki/The_Monad.Reader"&gt;Monad.Reader&lt;/a&gt; (a electronic magazine about Haskell) includes an interesting article about Jane Street Capital (a Wall Street trading company) and its use of &lt;a href="http://caml.inria.fr/"&gt;OCaml&lt;/a&gt;. The author points good and bad things about the language; these aren't new, in fact the things pointed are well-known by the community, but it's good to hear them from someone using the language in a production setting.&lt;br /&gt;&lt;br /&gt;Anyway, it's a case of large-scale adoption -- in the sense of using it as the main language for all development -- of a functional programming language, which is still rare, unfortunately.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-252155612748438695?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/252155612748438695/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=252155612748438695&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/252155612748438695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/252155612748438695'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/04/functional-programming-in-wall-street.html' title='Functional programming in Wall Street'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-1387009452707779730</id><published>2007-04-03T15:42:00.000-07:00</published><updated>2007-04-03T15:49:51.650-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='LtU'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>One Language to Rule Them All</title><content type='html'>A &lt;a href="http://lambda-the-ultimate.org/node/2160"&gt;discussion&lt;/a&gt; on LtU about the Next Big language, the next Java or something like it. Links to the &lt;a href="http://steve-yegge.blogspot.com/2007/02/next-big-language.html"&gt;post&lt;/a&gt; by Steve Yegge too. Once again &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt; is mentioned as a fine language that anyone needing to develop for the JVM should try.&lt;br /&gt;&lt;br /&gt;I don't believe Scala will be the next big language, but it really is fine. At the moment I'm finishing implementation of a simple distributed system written in Scala. It had to run on the JVM to communicate with other Java programs. It was a breeze to do, thanks to the Actors library. Scala's type system is quite interesting too, I plan on giving more attention to it when I have the time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-1387009452707779730?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/1387009452707779730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=1387009452707779730&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1387009452707779730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1387009452707779730'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/04/one-language-to-rule-them-all.html' title='One Language to Rule Them All'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-3074569541835831687</id><published>2007-04-03T15:23:00.000-07:00</published><updated>2007-04-03T15:33:46.417-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 3.2 - Exercise 3.5</title><content type='html'>Exercise 3.5 asks you to add a &lt;code&gt;print&lt;/code&gt; primitive to the language, which prints its argument and returns the value 1. The relevant changes are simple. In module &lt;code&gt;Eopl_3&lt;/code&gt; only the definition of type &lt;code&gt;Primitive&lt;/code&gt; and function &lt;code&gt;apply_primitive&lt;/code&gt; are different: &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// in eopl_3.fs (module Eopl_3)&lt;br /&gt;type Primitive = AddPrim | SubtractPrim | MultPrim | IncrPrim &lt;br /&gt;               | DecrPrim | PrintPrim&lt;br /&gt;&lt;br /&gt;let apply_primitive prim args = &lt;br /&gt;    match (prim, args) with&lt;br /&gt;      (AddPrim, [a; b]) -&gt; a + b&lt;br /&gt;    | (SubtractPrim, [a; b]) -&gt; a - b&lt;br /&gt;    | (MultPrim, [a; b]) -&gt; a * b&lt;br /&gt;    | (IncrPrim, [a]) -&gt; a + 1&lt;br /&gt;    | (DecrPrim, [a]) -&gt; a - 1&lt;br /&gt;    | (PrintPrim, [a]) -&gt; (print_endline (string_of_int a); 1)&lt;br /&gt;    | _ -&gt; failwith "Incorrect argument list for primitive" &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In the lexer specification a token for the &lt;code&gt;print&lt;/code&gt; primitive is added:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;rule token = parse&lt;br /&gt;| whitespace { token lexbuf }&lt;br /&gt;| '%' [^ '\n']* { token lexbuf } &lt;br /&gt;| newline       { record_newline lexbuf; token lexbuf }&lt;br /&gt;| "+"         { PLUS }&lt;br /&gt;| "-"         { MINUS }&lt;br /&gt;| "*"  { MULT }&lt;br /&gt;| "("           { LPAREN }&lt;br /&gt;| ")"         { RPAREN }&lt;br /&gt;| ","           { COMMA  }&lt;br /&gt;| "add1" { INCR }&lt;br /&gt;| "sub1" { DECR }&lt;br /&gt;| "print"       { PRINT }&lt;br /&gt;| id         { ID(lexeme lexbuf) }&lt;br /&gt;| ['-']?digit+  { LIT (Int32.Parse(lexeme lexbuf)) }&lt;br /&gt;| eof   { EOF }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And, in the parser, this token must be declared and dealt with:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;%token PRINT INCR DECR LPAREN RPAREN PLUS MINUS MULT COMMA EOF&lt;br /&gt;&lt;br /&gt;Prim: PLUS                        { AddPrim }&lt;br /&gt;    | MINUS                       { SubtractPrim }&lt;br /&gt;    | MULT                        { MultPrim }&lt;br /&gt;    | INCR                        { IncrPrim }&lt;br /&gt;    | DECR                        { DecrPrim }&lt;br /&gt;    | PRINT                       { PrintPrim }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The remaining parts of these three files are the same as the &lt;a href="http://codemiscellany.blogspot.com/2007/03/eopl-32-front-end-for-first-interpreter.html"&gt;previous&lt;/a&gt; &lt;a href="http://codemiscellany.blogspot.com/2007/03/eopl-section-31.html"&gt;two&lt;/a&gt; posts.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-3074569541835831687?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/3074569541835831687/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=3074569541835831687&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/3074569541835831687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/3074569541835831687'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/04/eopl-32-exercise-35.html' title='EOPL - 3.2 - Exercise 3.5'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-1225595914695147713</id><published>2007-03-23T17:48:00.000-07:00</published><updated>2007-03-23T18:01:47.641-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Scala web programming</title><content type='html'>A &lt;a href="http://lambda-the-ultimate.org/node/2147"&gt;post&lt;/a&gt; on Lambda the Ultimate pointing to &lt;a href="http://blog.lostlake.org/index.php?/archives/45-A-real-world-use-of-lift.html#extended"&gt;this post&lt;/a&gt; on David Pollak's blog. In a comment on the Lambda thread, he writes some points about what makes Scala a good language for web programming, comparing with Java and Ruby (with Rails). Having used all three, he gets to the conclusion that Scala has the best of the other two.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-1225595914695147713?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/1225595914695147713/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=1225595914695147713&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1225595914695147713'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1225595914695147713'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/03/scala-web-programming.html' title='Scala web programming'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-2156089460706022750</id><published>2007-03-18T18:04:00.000-07:00</published><updated>2007-03-18T18:17:25.186-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 3.2 - Front-end for the first interpreter</title><content type='html'>The &lt;a href="http://codemiscellany.blogspot.com/2007/03/eopl-section-31.html"&gt;previous post&lt;/a&gt; showed the code for the interpreter, working on an abstract syntax representation of the interpreted programs. In section 3.2 a front-end is presented to permit working with a concrete syntax. The book uses SLLGEN, a tool developed by the &lt;a href="http://www.plt-scheme.org/"&gt;PLT Scheme&lt;/a&gt; group, to generate lexers and parsers. I used fslex and fsyacc, the standard tools of F# for such purposes. Here's the lexical specification.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;{&lt;br /&gt;// eopl1_lex.fsl&lt;br /&gt;//&lt;br /&gt;// Lexical specification for the first interpreter &lt;br /&gt;// in EOPL (Essentials of Programming Languages)&lt;br /&gt;&lt;br /&gt;open System&lt;br /&gt;open Eopl1_par&lt;br /&gt;open Lexing&lt;br /&gt;&lt;br /&gt;let record_newline (lexbuf : lexbuf) = &lt;br /&gt;    lexbuf.EndPos &lt;- lexbuf.EndPos.AsNewLinePos()&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// These are some regular expression definitions&lt;br /&gt;let digit = ['0'-'9']&lt;br /&gt;let id = ['a'-'z'] ['a'-'z' '0'-'9']*&lt;br /&gt;let whitespace = [' ' '\t' ]&lt;br /&gt;let newline = ('\n' | '\r' '\n')&lt;br /&gt;&lt;br /&gt;rule token = parse&lt;br /&gt;| whitespace { token lexbuf }&lt;br /&gt;| '%' [^ '\n']* { token lexbuf } &lt;br /&gt;| newline       { record_newline lexbuf; token lexbuf }&lt;br /&gt;| "+"         { PLUS }&lt;br /&gt;| "-"         { MINUS }&lt;br /&gt;| "*"  { MULT }&lt;br /&gt;| "("           { LPAREN }&lt;br /&gt;| ")"         { RPAREN }&lt;br /&gt;| ","           { COMMA  }&lt;br /&gt;| "add1" { INCR }&lt;br /&gt;| "sub1" { DECR }&lt;br /&gt;| id         { ID(lexeme lexbuf) }&lt;br /&gt;| ['-']?digit+  { LIT (Int32.Parse(lexeme lexbuf)) }&lt;br /&gt;| eof   { EOF }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And the grammar to use with fsyacc. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// eopl1_par.fsy &lt;br /&gt;// Parser for the first interpreter &lt;br /&gt;// in EOPL (Essentials of Programming Languages)&lt;br /&gt;&lt;br /&gt;%{&lt;br /&gt;&lt;br /&gt;open Eopl_3&lt;br /&gt;&lt;br /&gt;%}&lt;br /&gt;&lt;br /&gt;%start start&lt;br /&gt;&lt;br /&gt;// terminal symbols&lt;br /&gt;%token &lt;string&gt; ID&lt;br /&gt;%token &lt;System.Int32&gt; LIT&lt;br /&gt;%token INCR DECR LPAREN RPAREN PLUS MINUS MULT COMMA EOF&lt;br /&gt;&lt;br /&gt;%type &lt; Eopl_3.Program &gt; start&lt;br /&gt;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;start: Prog {  $1 }&lt;br /&gt;&lt;br /&gt;Prog: Expr                        { Exp ($1)   }&lt;br /&gt;&lt;br /&gt;Expr: ID                          { VarExp($1) }&lt;br /&gt;    | LIT                         { LitExp($1) }&lt;br /&gt;    | Prim LPAREN ArgList RPAREN  { PrimAppExp ($1, List.rev $3) }&lt;br /&gt;&lt;br /&gt;Prim: PLUS                        { AddPrim }&lt;br /&gt;    | MINUS                       { SubtractPrim }&lt;br /&gt;    | MULT                        { MultPrim }&lt;br /&gt;    | INCR                        { IncrPrim }&lt;br /&gt;    | DECR                        { DecrPrim }&lt;br /&gt;    &lt;br /&gt;ArgList: Expr                     { [$1] }&lt;br /&gt;       | ArgList COMMA Expr       { $3 :: $1 }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Module &lt;code&gt;Eopl_3&lt;/code&gt; contains all the code from the &lt;a href="http://codemiscellany.blogspot.com/2007/03/eopl-section-31.html"&gt;previous post&lt;/a&gt;, including a definition of the abstract syntax. Both specifications above were adapted from an example included in the distribution. Now we only need to run these specifications into fslex and fsyacc, and write a driver for the interpreter, a simple read-eval-print loop. Here it is. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// eopl1_main.fs&lt;br /&gt;//&lt;br /&gt;// Driver for the first interpreter in EOPL&lt;br /&gt;// (Essentials of Programming Languages)&lt;br /&gt;&lt;br /&gt;#light &lt;br /&gt;&lt;br /&gt;open Eopl_3&lt;br /&gt;open Eopl1_par&lt;br /&gt;&lt;br /&gt;open Lexing&lt;br /&gt;&lt;br /&gt;let parse str = &lt;br /&gt;    let lexbuf = Lexing.from_string str&lt;br /&gt;    let prog = &lt;br /&gt;        try&lt;br /&gt;            Some (Eopl1_par.start Eopl1_lex.token lexbuf)&lt;br /&gt;        with e -&gt; &lt;br /&gt;            let pos = lexbuf.EndPos&lt;br /&gt;            printf "error near line %d, character %d\n%s\n" &lt;br /&gt;                   pos.pos_cnum &lt;br /&gt;                   (pos.pos_cnum - pos.pos_bol) (e.ToString());&lt;br /&gt;            None&lt;br /&gt;    prog&lt;br /&gt;            &lt;br /&gt;let rec read_eval_print prompt = &lt;br /&gt;    let _ = print_string prompt &lt;br /&gt;    let line = read_line ()&lt;br /&gt;    match line with&lt;br /&gt;      "#quit" -&gt; ()&lt;br /&gt;    | _ -&gt; match parse line with&lt;br /&gt;             None -&gt; read_eval_print prompt&lt;br /&gt;           | Some p -&gt; let v = Eopl_3.eval_program p in &lt;br /&gt;                       (print_endline (string_of_int v); &lt;br /&gt;                        read_eval_print prompt)&lt;br /&gt;           &lt;br /&gt;let main() = &lt;br /&gt;    read_eval_print "--&gt; " &lt;br /&gt;    &lt;br /&gt;do main()&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-2156089460706022750?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/2156089460706022750/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=2156089460706022750&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2156089460706022750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2156089460706022750'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/03/eopl-32-front-end-for-first-interpreter.html' title='EOPL - 3.2 - Front-end for the first interpreter'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-5504567741932868895</id><published>2007-03-11T22:01:00.000-07:00</published><updated>2007-03-11T22:09:43.390-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - Section 3.1</title><content type='html'>This is the first interpreter from Chapter 3, shown in Section 3.1. It needs an implementation of environments, I chose the simplest one and attached it before the code for the interpreter. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// implementation of environments &lt;br /&gt;// (represented as lists of pairs; the first in pair is &lt;br /&gt;//  a list of symbols, the second is a list of associated values)&lt;br /&gt;let list_find_position a lst = &lt;br /&gt;    let rec loop l = &lt;br /&gt;        match l with&lt;br /&gt;          [] -&gt; None&lt;br /&gt;        | (x :: l') when x = a -&gt; Some (List.length l')&lt;br /&gt;        | (x :: l') -&gt; loop l' in&lt;br /&gt;    loop (List.rev lst)&lt;br /&gt;&lt;br /&gt;let empty_env () = &lt;br /&gt;    []&lt;br /&gt;    &lt;br /&gt;let extend_env syms vals env =&lt;br /&gt;    (syms, vals) :: env&lt;br /&gt;    &lt;br /&gt;let rec apply_env env sym = &lt;br /&gt;    match env with&lt;br /&gt;      [] -&gt; failwith (sprintf "No binding for %s" sym)&lt;br /&gt;    | (syms, vals) :: env' -&gt; &lt;br /&gt;        match list_find_position sym syms with &lt;br /&gt;          None -&gt; apply_env env' sym&lt;br /&gt;        | Some i -&gt; List.nth vals i&lt;br /&gt;        &lt;br /&gt;// types for primitives, expressions and programs&lt;br /&gt;type Primitive = AddPrim | SubtractPrim | MultPrim | IncrPrim | DecrPrim&lt;br /&gt;type Expression = LitExp of int | VarExp of string &lt;br /&gt;                | PrimAppExp of (Primitive * Expression list)&lt;br /&gt;type Program = Exp of Expression&lt;br /&gt;&lt;br /&gt;let apply_primitive prim args = &lt;br /&gt;    match (prim, args) with&lt;br /&gt;      (AddPrim, [a; b]) -&gt; a + b&lt;br /&gt;    | (SubtractPrim, [a; b]) -&gt; a - b&lt;br /&gt;    | (MultPrim, [a; b]) -&gt; a * b&lt;br /&gt;    | (IncrPrim, [a]) -&gt; a + 1&lt;br /&gt;    | (DecrPrim, [a]) -&gt; a - 1&lt;br /&gt;    | _ -&gt; failwith "Incorrect argument list for primitive" &lt;br /&gt;&lt;br /&gt;let init_env () = &lt;br /&gt;    extend_env ["i"; "v"; "x"] [1; 5; 10] (empty_env ())&lt;br /&gt;    &lt;br /&gt;let rec eval_expression exp env = &lt;br /&gt;    match exp with&lt;br /&gt;      LitExp datum -&gt; datum&lt;br /&gt;    | VarExp id -&gt; apply_env env id&lt;br /&gt;    | PrimAppExp (prim, rands) -&gt; let args = eval_rands rands env in &lt;br /&gt;                                  apply_primitive prim args&lt;br /&gt;and eval_rands rands env = &lt;br /&gt;    List.map (eval_rand env) rands&lt;br /&gt;and eval_rand env rand = &lt;br /&gt;    eval_expression rand env&lt;br /&gt;&lt;br /&gt;let eval_program pgm = &lt;br /&gt;    match pgm with&lt;br /&gt;      Exp body -&gt; eval_expression body (init_env()) &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-5504567741932868895?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/5504567741932868895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=5504567741932868895&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/5504567741932868895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/5504567741932868895'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/03/eopl-section-31.html' title='EOPL - Section 3.1'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-1163122509813967033</id><published>2007-03-09T15:16:00.000-08:00</published><updated>2007-03-11T22:12:19.762-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='types'/><category scheme='http://www.blogger.com/atom/ns#' term='ml'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Scheme programming in ML</title><content type='html'>As I'm constantly bumping into typing issues when converting EOPL's examples and exercises from Scheme to F# (a ML language), I found &lt;a href="http://okmij.org/ftp/Scheme/misc.html#ML-as-Scheme"&gt;this code/article&lt;/a&gt; by Oleg Kyseliov relevant. It embeds a Scheme-like language into OCaml, using variant types, and defines functions used in Scheme. The &lt;a href="http://okmij.org/ftp/Scheme/scheme.ml"&gt;scheme.ml&lt;/a&gt; file is quite interesting for going all the way with the Scheme conversion, but the use of variant types to capture the need to work with different types in the same context is known to every ML programmer. I even did it sometimes in the EOPL programs.&lt;br /&gt;&lt;br /&gt;Be sure to read Oleg's &lt;a href="http://okmij.org/ftp/Scheme/scheme-ml.txt"&gt;comments&lt;/a&gt; about it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-1163122509813967033?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/1163122509813967033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=1163122509813967033&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1163122509813967033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1163122509813967033'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/03/scheme-programming-in-ml.html' title='Scheme programming in ML'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-1890957678515245584</id><published>2007-03-07T15:40:00.000-08:00</published><updated>2007-03-07T15:45:52.215-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 2.3.4 - Exercise 2.25</title><content type='html'>Using the data type definitions from the &lt;a href="http://codemiscellany.blogspot.com/2007/03/eopl-exercise-224.html"&gt;previous exercise&lt;/a&gt;, it's easy to define the necessary additional operations and then complete the definition of the unification function. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let is_var_term t =&lt;br /&gt;    match t with Id _ -&gt; true | _ -&gt; false&lt;br /&gt;        &lt;br /&gt;let unit_subst i t =&lt;br /&gt;    extend_subst i t (empty_subst ())&lt;br /&gt;    &lt;br /&gt;let rec compose_substs s1 s2 =&lt;br /&gt;    match s1 with&lt;br /&gt;      EmptySub -&gt; s2&lt;br /&gt;    | ExtendedSub (i, t, s) -&gt; ExtendedSub (i, t, compose_substs s s2)&lt;br /&gt;&lt;br /&gt;let rec unify_term t u = &lt;br /&gt;    match t with&lt;br /&gt;      Id tid -&gt; if (is_var_term u) || &lt;br /&gt;                    (not (List.mem tid (term_all_ids u))) then&lt;br /&gt;                    Some (unit_subst tid u)&lt;br /&gt;                else&lt;br /&gt;                    None&lt;br /&gt;    | _ -&gt; match u with&lt;br /&gt;             Id _ -&gt; unify_term u t&lt;br /&gt;           | Constant udat -&gt; &lt;br /&gt;              (match t with &lt;br /&gt;                 Constant tdat when tdat = udat -&gt; Some (empty_subst ())&lt;br /&gt;               | _ -&gt; None)&lt;br /&gt;           | App us -&gt; (match t with&lt;br /&gt;                          App ts -&gt; unify_terms ts us &lt;br /&gt;                        | _ -&gt; None)&lt;br /&gt;and unify_terms ts us = &lt;br /&gt;    match ts, us with&lt;br /&gt;      [], [] -&gt; Some (empty_subst ())&lt;br /&gt;    | ([], _) -&gt; None&lt;br /&gt;    | (_, []) -&gt; None&lt;br /&gt;    | (t :: ts', u :: us') -&gt; &lt;br /&gt;        let subst_car = unify_term t u in&lt;br /&gt;        match subst_car with&lt;br /&gt;          None -&gt; None&lt;br /&gt;        | Some s -&gt; let new_ts = subst_in_terms ts' s in&lt;br /&gt;                    let new_us = subst_in_terms us' s in&lt;br /&gt;                    let subst_cdr = unify_terms new_ts new_us in&lt;br /&gt;                    match subst_cdr with&lt;br /&gt;                      None -&gt; None&lt;br /&gt;                    | Some s' -&gt; Some (compose_substs s s')&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The occurs check is necessary, of course, to avoid infinity. I won't say more than that, to force people that arrive here looking for solutions to EOPL's exercises to think a little about it, at least.&lt;br /&gt;&lt;br /&gt;And this concludes Chapter 2.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-1890957678515245584?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/1890957678515245584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=1890957678515245584&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1890957678515245584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1890957678515245584'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/03/eopl-234-exercise-225.html' title='EOPL - 2.3.4 - Exercise 2.25'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-6196901519561747509</id><published>2007-03-07T15:32:00.000-08:00</published><updated>2007-03-07T15:45:05.172-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 2.3.4 - Exercise 2.24</title><content type='html'>This exercise asks for an implementation of substitutions on terms, the terms being defined by a previous exercise (2.13). In F#, they are thus defined:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type Value = Integer of int | String of string&lt;br /&gt;type Term = Id of string | Constant of Value | App of Term list&lt;br /&gt;&lt;br /&gt;let rec term_all_ids t = &lt;br /&gt;    match t with&lt;br /&gt;      Id s -&gt; [s]&lt;br /&gt;    | Constant _ -&gt; []&lt;br /&gt;    | App tl -&gt; List.concat (List.map term_all_ids tl)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Function &lt;code&gt;term_all_ids&lt;/code&gt; gets all identifiers from a term, also part of exercise 2.13. Then for the part specific to exercise 2.24, which are substitutions. I chose to use an abstract syntax tree representation, because it is more convenient in F#. Using the definition, it was easy to write the operations on substitutions. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type Subst = EmptySub | ExtendedSub of string * Term * Subst&lt;br /&gt;&lt;br /&gt;let empty_subst () = &lt;br /&gt;    EmptySub&lt;br /&gt;    &lt;br /&gt;let extend_subst i t s = &lt;br /&gt;    ExtendedSub (i, t, s)&lt;br /&gt;    &lt;br /&gt;let rec apply_subst s i = &lt;br /&gt;    match s with&lt;br /&gt;      EmptySub -&gt; Id i&lt;br /&gt;    | ExtendedSub (i', t, s') when i = i' -&gt; t&lt;br /&gt;    | ExtendedSub (_, _, s') -&gt; apply_subst s' i&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;With the substitution data type completed, we can write a substitution function without any difficulties.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec subst_in_term s t = &lt;br /&gt;    match t with &lt;br /&gt;      Id i -&gt; apply_subst s i&lt;br /&gt;    | Constant _ -&gt; t&lt;br /&gt;    | App tl -&gt; App (List.map (subst_in_term s) tl)&lt;br /&gt;&lt;br /&gt;let subst_in_terms lt s = &lt;br /&gt;    List.map (subst_in_term s) lt&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I guess &lt;code&gt;subst_in_terms&lt;/code&gt; might have been intended as a little more difficult to write. I don't know. In any case, it's just a &lt;code&gt;map&lt;/code&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-6196901519561747509?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/6196901519561747509/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=6196901519561747509&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/6196901519561747509'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/6196901519561747509'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/03/eopl-exercise-224.html' title='EOPL - 2.3.4 - Exercise 2.24'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-6923272896657631053</id><published>2007-03-06T16:24:00.000-08:00</published><updated>2007-03-06T16:26:31.914-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 2.3.4 - Alternative Representation</title><content type='html'>A simple representation of environments as a list of pairs &lt;code&gt;(syms, vals)&lt;/code&gt; where &lt;code&gt;syms&lt;/code&gt; is a list of symbols and &lt;code&gt;vals&lt;/code&gt; is a list of values positionally associated with the symbols. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let list_find_position a lst = &lt;br /&gt;    let rec loop l = &lt;br /&gt;        match l with&lt;br /&gt;          [] -&gt; None&lt;br /&gt;        | (x :: l') when x = a -&gt; Some (List.length l')&lt;br /&gt;        | (x :: l') -&gt; loop l' in&lt;br /&gt;    loop (List.rev lst)&lt;br /&gt;&lt;br /&gt;let empty_env () = &lt;br /&gt;    []&lt;br /&gt;    &lt;br /&gt;let extend_env syms vals env =&lt;br /&gt;    (syms, vals) :: env&lt;br /&gt;    &lt;br /&gt;let rec apply_env env sym = &lt;br /&gt;    match env with&lt;br /&gt;      [] -&gt; failwith (sprintf "No binding for %s" sym)&lt;br /&gt;    | (syms, vals) :: env' -&gt; &lt;br /&gt;        match list_find_position sym syms with &lt;br /&gt;          None -&gt; apply_env env' sym&lt;br /&gt;        | Some i -&gt; List.nth vals i&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-6923272896657631053?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/6923272896657631053/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=6923272896657631053&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/6923272896657631053'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/6923272896657631053'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/03/eopl-234-alternative-representation.html' title='EOPL - 2.3.4 - Alternative Representation'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-563686096212229187</id><published>2007-03-06T16:02:00.000-08:00</published><updated>2007-03-06T16:27:45.367-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 2.3.3 - Exercise 2.20</title><content type='html'>It's simple to add new operations when the data is represented as an abstract syntax tree. Here's the operation &lt;code&gt;has_association&lt;/code&gt; for stacks as defined in the &lt;a href="http://codemiscellany.blogspot.com/2007/03/eopl-233-exercise-219.html"&gt;previous exercise&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// Exercise 2.20&lt;br /&gt;let rec has_association env sym = &lt;br /&gt;    match env with&lt;br /&gt;      EmptyEnv -&gt; false&lt;br /&gt;    | ExtendedEnv (syms, vals, env') -&gt; (List.mem sym syms) || &lt;br /&gt;                                        (has_association env' sym)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-563686096212229187?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/563686096212229187/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=563686096212229187&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/563686096212229187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/563686096212229187'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/03/eopl-233-exercise-220.html' title='EOPL - 2.3.3 - Exercise 2.20'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-2162232204103016345</id><published>2007-03-06T16:01:00.000-08:00</published><updated>2007-03-06T16:27:27.034-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 2.3.3 - Exercise 2.19</title><content type='html'>Another simple exercise. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// Exercise 2.19&lt;br /&gt;type 'a Stack = EmptyStack | ExtendedStack of 'a * 'a Stack&lt;br /&gt;&lt;br /&gt;let empty_stack () = &lt;br /&gt;    EmptyStack&lt;br /&gt;    &lt;br /&gt;let push elt stk = &lt;br /&gt;    ExtendedStack (elt, stk)&lt;br /&gt;    &lt;br /&gt;let pop stk = &lt;br /&gt;    match stk with&lt;br /&gt;      EmptyStack -&gt; failwith "Stack empty"&lt;br /&gt;    | ExtendedStack (_, s) -&gt; s&lt;br /&gt;    &lt;br /&gt;let top stk = &lt;br /&gt;    match stk with&lt;br /&gt;      EmptyStack -&gt; failwith "Stack empty"&lt;br /&gt;    | ExtendedStack (e, _) -&gt; e&lt;br /&gt;    &lt;br /&gt;let is_stack_empty stk = &lt;br /&gt;    stk = EmptyStack&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-2162232204103016345?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/2162232204103016345/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=2162232204103016345&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2162232204103016345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2162232204103016345'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/03/eopl-233-exercise-219.html' title='EOPL - 2.3.3 - Exercise 2.19'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-3437751202683927715</id><published>2007-03-06T15:58:00.000-08:00</published><updated>2007-03-06T16:27:07.695-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - Section 2.3.3</title><content type='html'>The abstract syntax tree representation for environments is quite straightforward in F#; it is shown below. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type Value = Integer of int | String of string&lt;br /&gt;type Environment = EmptyEnv &lt;br /&gt;                 | ExtendedEnv of string list * &lt;br /&gt;                                  Value list * &lt;br /&gt;                                  Environment&lt;br /&gt;&lt;br /&gt;// helper function&lt;br /&gt;let list_find_position a lst = &lt;br /&gt;    let rec loop l = &lt;br /&gt;        match l with&lt;br /&gt;          [] -&gt; None&lt;br /&gt;        | (x :: l') when x = a -&gt; Some (List.length l')&lt;br /&gt;        | (x :: l') -&gt; loop l' in&lt;br /&gt;    loop (List.rev lst)&lt;br /&gt;&lt;br /&gt;let empty_env () = &lt;br /&gt;    EmptyEnv&lt;br /&gt;    &lt;br /&gt;let extend_env syms vals env = &lt;br /&gt;    ExtendedEnv (syms, vals, env)&lt;br /&gt;    &lt;br /&gt;let rec apply_env env sym = &lt;br /&gt;    match env with&lt;br /&gt;      EmptyEnv -&gt; failwith (sprintf "No binding for %s" sym)&lt;br /&gt;    | ExtendedEnv (syms, vals, env') -&gt; &lt;br /&gt;        match list_find_position sym syms with&lt;br /&gt;          None -&gt; apply_env env' sym&lt;br /&gt;        | Some i -&gt; List.nth vals i&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-3437751202683927715?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/3437751202683927715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=3437751202683927715&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/3437751202683927715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/3437751202683927715'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/03/eopl-section-233.html' title='EOPL - Section 2.3.3'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-5593753674287445200</id><published>2007-03-05T13:40:00.000-08:00</published><updated>2007-03-05T13:43:06.066-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 2.3.2 - Exercise 2.16</title><content type='html'>Easy one, in two versions. &lt;br /&gt;&lt;br /&gt;Version 1&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec list_find_last_position sym los = &lt;br /&gt;    match los with&lt;br /&gt;      [] -&gt; None&lt;br /&gt;    | (s :: los') when s = sym -&gt; &lt;br /&gt;        (match list_find_last_position sym los' with&lt;br /&gt;             None -&gt; Some 0&lt;br /&gt;         |   Some i -&gt; Some (i + 1))&lt;br /&gt;    | (s :: los') -&gt; &lt;br /&gt;        (match list_find_last_position sym los' with&lt;br /&gt;             None -&gt; None&lt;br /&gt;         |   Some i -&gt; Some (i + 1))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Version 2&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec list_find_last_position sym los = &lt;br /&gt;    match los with&lt;br /&gt;      [] -&gt; None&lt;br /&gt;    | (s :: los') -&gt; &lt;br /&gt;        match list_find_last_position sym los' with&lt;br /&gt;          None -&gt; if s = sym then Some 0 else None&lt;br /&gt;        | Some i -&gt; Some (i + 1)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Version 2 was obtained by observing similarities in Version 1. The idea appeared in previous examples: pattern guards do not always lead to shorter code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-5593753674287445200?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/5593753674287445200/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=5593753674287445200&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/5593753674287445200'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/5593753674287445200'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/03/eopl-232-exercise-216.html' title='EOPL - 2.3.2 - Exercise 2.16'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-913397807672993266</id><published>2007-03-05T13:18:00.000-08:00</published><updated>2007-03-05T13:38:21.645-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 2.3.2 - Exercise 2.15</title><content type='html'>I solved this exercise in quite a "lispy" way, so it's a bit alien in F#. It works, but in a quite awkward way. The idea was to maintain the stack as a pair containing the current top element and the old stack, and this means that, in F#, each operation that adds or removes elements produces a stack with a different type than the original. An interesting consequence of this is that the stack size is reflected in its type, so that we could define functions that work on "stacks of size 3" or so on. Who needs dependent types? :)&lt;br /&gt;&lt;br /&gt;So here's the code. It first defines a type synonym to ease working with stacks, and then the functions that implement basic operations.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type 'a stack = (unit -&gt; 'a) * (unit -&gt; bool)&lt;br /&gt;&lt;br /&gt;let empty_stack () = &lt;br /&gt;    let top () = failwith "The stack is empty, no top element" in&lt;br /&gt;    let is_empty_stack () = true in&lt;br /&gt;    (top, is_empty_stack)&lt;br /&gt;&lt;br /&gt;let push elt stk = &lt;br /&gt;    let top () = (elt, stk) in&lt;br /&gt;    let is_empty_stack () = false in&lt;br /&gt;    (top, is_empty_stack)&lt;br /&gt;    &lt;br /&gt;let pop stk = &lt;br /&gt;    let oldstk : 'a stack = snd ((fst stk) ()) in&lt;br /&gt;    let top = fst oldstk in&lt;br /&gt;    let is_empty_stack = snd oldstk in&lt;br /&gt;    (top, is_empty_stack)&lt;br /&gt;    &lt;br /&gt;let is_empty_stack stk = &lt;br /&gt;    let empty = snd stk in empty ()&lt;br /&gt;    &lt;br /&gt;let top stk = &lt;br /&gt;    let t = fst stk in fst (t ())&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And it is used like this: you must assign a type for the &lt;code&gt;empty_stack&lt;/code&gt; call, otherwise you are nagged by the value restriction again. That's where the type synonym comes in handy:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt; let (x : int stack) = (empty_stack());;&lt;br /&gt;&lt;br /&gt;val x : int stack&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then you can push elements into &lt;code&gt;x&lt;/code&gt;. Note how the type of the result is different from &lt;code&gt;int stack&lt;/code&gt;, even considering type synonyms. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt; push 3 x;;&lt;br /&gt;val it : (unit -&gt; int * int stack) * (unit -&gt; bool)&lt;br /&gt;       = (&amp;lt;fun:push@173&amp;gt;, &amp;lt;fun:push@174&amp;gt;)&lt;br /&gt;&gt; push 4 (push 3 x);;&lt;br /&gt;val it : (unit -&gt; int * &lt;br /&gt;            ((unit -&gt; int * int stack) * (unit -&gt; bool))) * &lt;br /&gt;         (unit -&gt; bool) &lt;br /&gt;       = (&amp;lt;fun:push@173&amp;gt;, &amp;lt;fun:push@174&amp;gt;)&lt;br /&gt;&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you pop elements, the types get back to what they were, obviously. A funny side-effect of this strange definition is that &lt;code&gt;top&lt;/code&gt; and &lt;code&gt;pop&lt;/code&gt; don't work on empty stacks because of type-checking, not any run-time checking -- so that the &lt;code&gt;failwith&lt;/code&gt; in the definition of &lt;code&gt;empty_stack&lt;/code&gt; will never be executed. Empty stacks have actually a different type. &lt;br /&gt;&lt;br /&gt;There must be a more type-friendly implementation of stacks using a procedural representation, but I decided to leave it for now and publish this solution because it is quite interesting by itself (although almost unusable in real code).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-913397807672993266?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/913397807672993266/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=913397807672993266&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/913397807672993266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/913397807672993266'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/03/eopl-232-exercise-215.html' title='EOPL - 2.3.2 - Exercise 2.15'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-365976875877760177</id><published>2007-03-05T13:03:00.000-08:00</published><updated>2007-03-05T13:11:32.103-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 2.3.2 - Procedural Representation</title><content type='html'>Section 2.3 is about strategies for representing data types. In section 2.3.1 an abstract interface for environments is presented, and then in section 2.3.2, Figure 2.3 shows a procedural implementation for the environment interface. Translated into F#, Figure 2.3 would be like the following:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let find_index a lst = &lt;br /&gt;    let rec loop l = &lt;br /&gt;        match l with&lt;br /&gt;          [] -&gt; raise Not_found&lt;br /&gt;        | (x :: l') when x = a -&gt; List.length l'&lt;br /&gt;        | (x :: l') -&gt; loop l' in&lt;br /&gt;    loop (List.rev lst)&lt;br /&gt;        &lt;br /&gt;let list_find_position sym los = &lt;br /&gt;    if List.mem sym los then&lt;br /&gt;        Some (find_index sym los)&lt;br /&gt;    else&lt;br /&gt;        None&lt;br /&gt;        &lt;br /&gt;let empty_env () = &lt;br /&gt;    fun sym -&gt; failwith (sprintf "No binding for %s" sym)&lt;br /&gt;&lt;br /&gt;let apply_env env sym = &lt;br /&gt;    env sym&lt;br /&gt;    &lt;br /&gt;let extend_env syms vals env = &lt;br /&gt;    fun sym -&gt; match list_find_position sym syms with&lt;br /&gt;                 None -&gt; apply_env env sym&lt;br /&gt;               | Some i -&gt; List.nth vals i&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In this case, function &lt;code&gt;find_list_position&lt;/code&gt; is redundant, because &lt;code&gt;find_index&lt;/code&gt; does not take a predicate, so it's less generic than the version in the book. It shouldn't be a problem at this point, though. Function &lt;code&gt;find_index&lt;/code&gt; reverses the list, we can write a version that does without that:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec find_index2 a lst = &lt;br /&gt;    match lst with &lt;br /&gt;      [] -&gt; raise Not_found&lt;br /&gt;    | (x :: lst') when x = a -&gt; 0&lt;br /&gt;    | (x :: lst') -&gt; 1 + find_index2 a lst'&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-365976875877760177?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/365976875877760177/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=365976875877760177&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/365976875877760177'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/365976875877760177'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/03/eopl-232-procedural-representation.html' title='EOPL - 2.3.2 - Procedural Representation'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-2687432735349284662</id><published>2007-02-21T10:35:00.000-08:00</published><updated>2007-02-21T11:04:17.436-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 2.2.2 - Exercise 2.12</title><content type='html'>This one asks you to implement alpha, beta and eta conversion on lambda-calculus expressions based on the substitution function of the previous exercise. For this we need a function to see if an identifier occurs free in an expression, similar to the one presented on section 1.3 and easy enough. The conversion functions can then be implemented quite simply:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec occurs_free v exp =&lt;br /&gt;   match exp with&lt;br /&gt;     Identifier i when v = i -&gt; true&lt;br /&gt;   | Lambda (x, e) when v &lt;&gt; x -&gt; occurs_free v e&lt;br /&gt;   | App (e1, e2) -&gt; (occurs_free v e1) || (occurs_free v e2)&lt;br /&gt;   | Prim (p, e1, e2) -&gt; (occurs_free v e1) || (occurs_free v e2)&lt;br /&gt;   | _ -&gt; false&lt;br /&gt;&lt;br /&gt;let alpha_conversion exp new_id =&lt;br /&gt;   match exp with&lt;br /&gt;     Lambda (id, body) when not (occurs_free new_id body) -&gt;&lt;br /&gt;         Lambda (new_id, lambda_calculus_subst body (Identifier new_id) id)&lt;br /&gt;   | _ -&gt; exp&lt;br /&gt;  &lt;br /&gt;let beta_conversion exp =&lt;br /&gt;   match exp with&lt;br /&gt;     App (Lambda (id, body), e) -&gt; lambda_calculus_subst body e id&lt;br /&gt;   | _ -&gt; exp&lt;br /&gt;  &lt;br /&gt;let eta_conversion exp =&lt;br /&gt;   match exp with&lt;br /&gt;     Lambda (id, App (e, Identifier id'))&lt;br /&gt;     when (id=id') &amp;&amp;amp; (not (occurs_free id e)) -&gt; e&lt;br /&gt;   | _ -&gt; exp&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;These conversion functions simply return the same expression if they aren't of the right form. They could signal an error, depending on the application.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-2687432735349284662?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/2687432735349284662/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=2687432735349284662&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2687432735349284662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2687432735349284662'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/02/eopl-exercise-212.html' title='EOPL - 2.2.2 - Exercise 2.12'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-2776862711338925026</id><published>2007-02-21T10:08:00.000-08:00</published><updated>2007-02-21T11:04:55.223-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 2.2.2 - Exercise 2.11</title><content type='html'>Exercise 2.11 asks you to correct the definition of a substitution function on the lambda-calculus, to avoid variable capture. To do that, we need function &lt;code&gt;fresh-id&lt;/code&gt; from the previous exercise, but alas, we can't use it as is, because it is also asked to extend the definition of a lambda-calculus expression to includes literals and primitives. Nevertheless, it's an easy exercise.&lt;br /&gt;&lt;br /&gt;To define the new lambda-calculus expression type, we first define a type to specify primitives:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type Primitive = Sum | Mult&lt;br /&gt;&lt;br /&gt;type LPExp = Identifier of string | Lambda of string * LPExp&lt;br /&gt;          | App of LPExp * LPExp | Literal of int&lt;br /&gt;          | Prim of Primitive * LPExp * LPExp&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And here is the code for auxiliary functions and the substitution function:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec all_ids exp =&lt;br /&gt;   match exp with&lt;br /&gt;     Identifier i -&gt; [i]&lt;br /&gt;   | Lambda (x, e) -&gt; x :: (all_ids e)&lt;br /&gt;   | App (e1, e2) -&gt; (all_ids e1) @ (all_ids e2)&lt;br /&gt;   | _ -&gt; []&lt;br /&gt;  &lt;br /&gt;let fresh_id exp s =&lt;br /&gt;   let syms = all_ids' exp in&lt;br /&gt;   let rec loop n =&lt;br /&gt;       let sym = s + (string_of_int n) in&lt;br /&gt;       if List.mem sym syms then loop (n + 1) else sym in&lt;br /&gt;   loop 0&lt;br /&gt;         &lt;br /&gt;let rec lambda_calculus_subst exp subst_exp subst_id =&lt;br /&gt;   let rec subst exp =&lt;br /&gt;       match exp with&lt;br /&gt;         Identifier id when id = subst_id -&gt; subst_exp&lt;br /&gt;       | Identifier id -&gt; exp&lt;br /&gt;       | Lambda (id, body) when id = subst_id -&gt; exp&lt;br /&gt;       | Lambda (id, body) -&gt;&lt;br /&gt;           let id'=fresh_id body id in&lt;br /&gt;           let body'=lambda_calculus_subst body (Identifier id') id in&lt;br /&gt;           Lambda (id', subst body')&lt;br /&gt;       | App (e1, e2) -&gt; App (subst e1, subst e2)&lt;br /&gt;       | Literal l -&gt; exp&lt;br /&gt;       | Prim (p, e1, e2) -&gt; Prim (p, subst e1, subst e2) in&lt;br /&gt;   subst exp&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The substitution function always does an alpha conversion (substitution of the identifier bound by the lambda) unless the bound identifier is the same as the one being substituted for. This surely works, as alpha conversion doesn't change the meaning of a lambda expression. An alternative would be to alpha convert only when a capture would occur, but this would require a further check like&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if List.mem id (all_ids body) then&lt;br /&gt; // do alpha conversion&lt;br /&gt;else&lt;br /&gt; // just simple substitution&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It would make the code bigger, but not better. Both versions require linear scans of the body, so the efficiency shouldn't differ much between them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-2776862711338925026?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/2776862711338925026/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=2776862711338925026&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2776862711338925026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2776862711338925026'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/02/eopl-chaper-2-exercise-211.html' title='EOPL - 2.2.2 - Exercise 2.11'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-2495374925119373285</id><published>2007-02-20T18:20:00.001-08:00</published><updated>2007-02-21T11:06:04.880-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 2.2.2 - Exercise 2.10</title><content type='html'>Chapter 2 includes examples and exercises for parsing and unparsing textual representations (e.g. &lt;code&gt;parse-expression&lt;/code&gt; on page 51). The parsing functions assume a Scheme reader, and just convert from a list representation to an abstract syntax-tree representation based on &lt;code&gt;define-datatype&lt;/code&gt;. The unparsing functions do the converse, from the syntax-tree representation to a list representation. As we don't have a list reader in F#, I skipped the examples and exercises related to parsing and unparsing. I also skipped other exercises that I felt wouldn't add much.&lt;br /&gt;&lt;br /&gt;So here is Exercise 2.10 about generating fresh identifiers for renaming of variables that might be captured. I first defined a type for lambda-calculus expressions.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type Exp = Identifier of string | Lambda of string * Exp&lt;br /&gt;        | App of Exp * Exp&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then there's &lt;code&gt;all-ids&lt;/code&gt; and a converted version of &lt;code&gt;fresh-id&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec all_ids exp =&lt;br /&gt;   match exp with&lt;br /&gt;     Identifier i -&gt; [i]&lt;br /&gt;   | Lambda (x, e) -&gt; x :: (all_ids e)&lt;br /&gt;   | App (e1, e2) -&gt; (all_ids e1) @ (all_ids e2)&lt;br /&gt;  &lt;br /&gt;let fresh_id exp s =&lt;br /&gt;   let syms = all_ids exp in&lt;br /&gt;   let rec loop n =&lt;br /&gt;       let sym = s + (string_of_int n) in&lt;br /&gt;       if List.mem sym syms then loop (n + 1)&lt;br /&gt;       else Identifier sym in&lt;br /&gt;   loop 0&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-2495374925119373285?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/2495374925119373285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=2495374925119373285&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2495374925119373285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2495374925119373285'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/02/eopl-chapter-2-exercise-210.html' title='EOPL - 2.2.2 - Exercise 2.10'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-5172886687948726279</id><published>2007-02-19T21:07:00.000-08:00</published><updated>2007-02-20T18:19:47.883-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL -  Chapter 2, Exercise 2.5</title><content type='html'>Chapter 2 is about data abstraction. Section 2.1 describes the concepts of interface, representation and implementation, and how a single interface may be implemented by different representations. Not much code there. Section 2.2 presents the constructions &lt;code&gt;define-datatype&lt;/code&gt; and &lt;code&gt;cases&lt;/code&gt;, to define and pattern-match over variant data types (or disjoint unions, or sum types, choose your preferred terminology). That is roughly equivalent to facilities already present in F#, so there's not much new here. &lt;br /&gt;&lt;br /&gt;Exercise 2.5 is a simple pattern-matching exercise to work with the definition of a binary tree data type, expressed in F# as&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type BinTree = Leaf of int | Interior of string * BinTree * BinTree&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then we can define &lt;code&gt;max-interior&lt;/code&gt; using pattern guards, which aren't available in the Scheme &lt;code&gt;cases&lt;/code&gt; construct:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let max_interior bt = &lt;br /&gt;    let rec maxint t = &lt;br /&gt;        match t with&lt;br /&gt;          Leaf _ -&gt; failwith "Shouldn't get here"&lt;br /&gt;        | Interior (tag, Leaf l1, Leaf l2) -&gt; (tag, l1 + l2)&lt;br /&gt;        | Interior (tag, Leaf l1, t2) -&gt; &lt;br /&gt;            let tg, s = maxint t2 in &lt;br /&gt;            if s &gt; s + l1 then (tg, s) else (tag, s+l1)&lt;br /&gt;        | Interior (tag, t1, Leaf l2) -&gt; &lt;br /&gt;            let tg, s = maxint t1 in &lt;br /&gt;            if s &gt; s + l2 then (tg, s) else (tag, s+l2)&lt;br /&gt;        | Interior (tag, t1, t2) -&gt; &lt;br /&gt;            let tg1, s1 = maxint t1 in&lt;br /&gt;            let tg2, s2 = maxint t2 in&lt;br /&gt;            if s1 &gt; s2 then &lt;br /&gt;                if s1 &gt; s1 + s2 then (tg1, s1) else (tag, s1+s2)&lt;br /&gt;            else&lt;br /&gt;                if s2 &gt; s1 + s2 then (tg2, s2) else (tag, s1+s2) in&lt;br /&gt;    fst (maxint bt)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But this is a case where it's actually shorter to just use a single pattern match and a conditional, instead of pattern guards:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let max_interior bt = &lt;br /&gt;    let rec maxint t = &lt;br /&gt;        match t with&lt;br /&gt;          Leaf i -&gt; (None, i)&lt;br /&gt;        | Interior (tag, t1, t2) -&gt; &lt;br /&gt;            let tg1, s1 = maxint t1 in&lt;br /&gt;            let tg2, s2 = maxint t2 in&lt;br /&gt;            if tg1 = None &amp;&amp; tg2 = None then&lt;br /&gt;                (Some tag, s1 + s2)&lt;br /&gt;            elif s1 &gt; s2 || tg2 = None then&lt;br /&gt;                if s1 &gt; s1+s2 then (tg1, s1) &lt;br /&gt;                else (Some tag, s1+s2)&lt;br /&gt;            else&lt;br /&gt;                if s2 &gt; s1+s2 then (tg2, s2) &lt;br /&gt;                else (Some tag, s1+s2) in&lt;br /&gt;    match bt with&lt;br /&gt;      Leaf _ -&gt; failwith "Shouldn't happen"&lt;br /&gt;    | t -&gt; maxint t |&gt; fst |&gt; Option.get&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Even so, the function is somewhat big, and could be broken in two, but we'll let it as it is.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-5172886687948726279?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/5172886687948726279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=5172886687948726279&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/5172886687948726279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/5172886687948726279'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/02/eopl-chapter-2-exercise-25.html' title='EOPL -  Chapter 2, Exercise 2.5'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-2699096440345632339</id><published>2007-02-12T10:37:00.000-08:00</published><updated>2007-01-25T15:50:40.036-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Scala</title><content type='html'>My choice for a functional programming language that integrates with .NET is F#.  By the same token, when I think about writing software for the Java platform and wish to use a language better suited to my tastes, my choice is &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt;. It's a pretty cool language that mixes OO and functional programming quite neatly, and with interesting &lt;a href="http://www.scala-lang.org/docu/papers.html"&gt;theoretical studies&lt;/a&gt; to support it. The syntax was chosen to be similar to Java, which I don't like, but it's a minor problem. It's actively supported and developed, and is gaining momentum right now, which can be a good thing.&lt;br /&gt;&lt;br /&gt;I need to write a simple program to talk to a Java program in the next few days, so I'll probably be using Scala for it. This means I may write posts about it in the near future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-2699096440345632339?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/2699096440345632339/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=2699096440345632339&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2699096440345632339'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2699096440345632339'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/02/scala.html' title='Scala'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-1852129732176283967</id><published>2007-01-25T15:37:00.000-08:00</published><updated>2007-01-25T15:50:40.125-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 1.2.4 - Exercise 1.18</title><content type='html'>Exercise 1.18 takes advantage of Scheme's uniform treatment of code and data, so the functions proposed should return lists that can be &lt;code&gt;eval&lt;/code&gt;uated to get some effect. Furthermore, there are typing issues, so adaptations are needed. The first function, &lt;code&gt;compose&lt;/code&gt;, is easy enough:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let compose p1 p2 = fun x -&gt; p1 (p2 x)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Next, I defined a data type to represent list operations:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type ListOp = Car | Cdr | Compose of ListOp * ListOp | Error&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So it's easy to define &lt;code&gt;car_cdr&lt;/code&gt;, but it doesn't return a list to evaluate, rather a &lt;code&gt;ListOp&lt;/code&gt; object. Also, because of typing it was easier to include a variant &lt;code&gt;Error&lt;/code&gt; of type &lt;code&gt;ListOp&lt;/code&gt; and eliminate parameter &lt;code&gt;errval&lt;/code&gt;. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec car_cdr s slist =&lt;br /&gt;    match slist with &lt;br /&gt;      [] -&gt; Error &lt;br /&gt;    | s1 :: rslist when s1 = s -&gt; Car&lt;br /&gt;    | _ :: rslist -&gt; Compose (car_cdr s rslist, Cdr)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Thus we get&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt; car_cdr "c" ["a"; "b"; "c"];;&lt;br /&gt;val it : ListOp = Compose (Compose (Car,Cdr),Cdr)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So we have a description of the necessary list operations, but it's not directly executable as in Scheme. So we need a function to execute the list operations returned on a list, and this is &lt;code&gt;run_listop&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec run_listop op lst = &lt;br /&gt;    match op with&lt;br /&gt;      Car -&gt; List.hd lst&lt;br /&gt;    | Compose (c1, Cdr) -&gt; run_listop c1 (List.tl lst)&lt;br /&gt;    | _ -&gt; failwith "can't do"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The case that leads to an exception is to find a single &lt;code&gt;Cdr&lt;/code&gt; without a previous &lt;code&gt;Car&lt;/code&gt;. This is a good indication that the type was not designed properly, but we will not bother with this here. Function &lt;code&gt;car_cdr2&lt;/code&gt; doesn't need explicit &lt;code&gt;Compose&lt;/code&gt; operations, and returns a list of list operations that must be applied in succession. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let car_cdr2 s slist errval =&lt;br /&gt;    let rec loop lst =&lt;br /&gt;        match lst with&lt;br /&gt;          [] -&gt; []&lt;br /&gt;        | l :: rlst when s = l -&gt; [Car]&lt;br /&gt;        | _ :: rlst -&gt; Cdr :: (loop rlst) in&lt;br /&gt;    List.rev (loop slist)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It's quite easy to define a function to execute these &lt;code&gt;ListOp&lt;/code&gt; lists, but not that interesting at this point.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-1852129732176283967?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/1852129732176283967/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=1852129732176283967&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1852129732176283967'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1852129732176283967'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/01/eopl-124-exercise-118.html' title='EOPL - 1.2.4 - Exercise 1.18'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-873673162171661563</id><published>2007-01-15T13:04:00.000-08:00</published><updated>2007-01-15T15:14:10.989-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 1.2.4 - Exercise 1.17, sorting</title><content type='html'>Another exercise. This one involves binary trees and sorting. For the bintrees and finding a path through them to an element, we define two types:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type BinTree = Empty | Node of int * BinTree * BinTree&lt;br /&gt;type direction = Left | Right&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then we can define function &lt;code&gt;path&lt;/code&gt;, returning a list of directions:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec path n bst = &lt;br /&gt;    match bst with&lt;br /&gt;      Empty -&gt; failwith ("number " + (string_of_int n) + " not found in tree")&lt;br /&gt;    | (Node (x, left, right)) when n = x -&gt; []&lt;br /&gt;    | (Node (x, left, right)) when n &lt; x -&gt; Left :: path n left&lt;br /&gt;    | (Node (_, left, right)) -&gt; Right :: path n right&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;For sorting, I chose to implement a rudimentary &lt;a href="http://en.wikipedia.org/wiki/Quick_sort"&gt;quicksort&lt;/a&gt; (with the first element as pivot). As with previous functions, beware of the value restriction.  &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec sort lst = &lt;br /&gt;    let left_part x (lp, rp) = (x :: lp, rp) in&lt;br /&gt;    let right_part x (lp, rp) = (lp, x :: rp) in&lt;br /&gt;    let rec partition p lst = &lt;br /&gt;        match lst with &lt;br /&gt;          [] -&gt; ([], [])&lt;br /&gt;        | (x :: rlst) when x &lt; p -&gt; left_part x (partition p rlst)&lt;br /&gt;        | (x :: rlst) when x &gt; p -&gt; right_part x (partition p rlst)&lt;br /&gt;        | (x :: rlst) -&gt; partition p rlst in&lt;br /&gt;    match lst with&lt;br /&gt;      [] -&gt; []&lt;br /&gt;    | (x :: rlst) -&gt; let lp, rp = partition x lst in &lt;br /&gt;                     (sort lp) @ [x] @ (sort rp)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I wrote the internal function &lt;code&gt;partition&lt;/code&gt; because it was part of the exercise, but it is already there in the standard library. Using this fact, we can get a much shorter version of quicksort:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec sort lst = &lt;br /&gt;    match lst with&lt;br /&gt;      [] -&gt; []&lt;br /&gt;    | (x :: rlst) -&gt; let lp, rp = List.partition (fun n -&gt; n &lt; x) rlst in &lt;br /&gt;                     (sort lp) @ [x] @ (sort rp)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To sort with a different predicate is a straightforward change in either version. Here is the longer version working with a predicate:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec sort pred lst = &lt;br /&gt;    let left_part x (lp, rp) = (x :: lp, rp) in&lt;br /&gt;    let right_part x (lp, rp) = (lp, x :: rp) in&lt;br /&gt;    let rec partition p lst = &lt;br /&gt;        match lst with &lt;br /&gt;          [] -&gt; ([], [])&lt;br /&gt;        | (x :: rlst) when x = p -&gt; partition p rlst&lt;br /&gt;        | (x :: rlst) when (pred x p) -&gt; left_part x (partition p rlst)&lt;br /&gt;        | (x :: rlst) -&gt; right_part x (partition p rlst) in&lt;br /&gt;    match lst with&lt;br /&gt;      [] -&gt; []&lt;br /&gt;    | (x :: rlst) -&gt; let lp, rp = partition x lst in &lt;br /&gt;                     (sort pred lp) @ [x] @ (sort pred rp)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Finally, just for fun, I wrote a &lt;a href="http://en.wikipedia.org/wiki/Merge_sort"&gt;merge sort&lt;/a&gt; function too. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec merge_sort (lst:'a list) =  &lt;br /&gt;    let merge_pairs (ll1, rl1) (ll2, rl2) = &lt;br /&gt;        (ll1 @ ll2, rl1 @ rl2) in&lt;br /&gt;    let split_pairs i x = &lt;br /&gt;        if i &lt; (lst.Length / 2) then ([x], []) else ([], [x]) in&lt;br /&gt;    let split l = &lt;br /&gt;        List.fold_right merge_pairs (List.mapi split_pairs l) ([], []) in&lt;br /&gt;    let rec merge lon1 lon2 = &lt;br /&gt;        match (lon1, lon2) with&lt;br /&gt;          ([], _) -&gt; lon2&lt;br /&gt;        | (_, []) -&gt; lon1&lt;br /&gt;        | (x :: rlon1, y :: rlon2) when x &lt;= y -&gt; x :: (merge rlon1 lon2)&lt;br /&gt;        | (x :: rlon1, y :: rlon2) -&gt; y :: (merge lon1 rlon2) in&lt;br /&gt;    match lst with&lt;br /&gt;      [] -&gt; []&lt;br /&gt;    | [x] -&gt; [x]&lt;br /&gt;    | _ -&gt; let l, r = split lst in merge (merge_sort l) (merge_sort r)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It's quite long, but I didn't bother trying to get a shorter version.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-873673162171661563?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/873673162171661563/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=873673162171661563&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/873673162171661563'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/873673162171661563'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/01/eopl-124-exercise-117-sorting.html' title='EOPL - 1.2.4 - Exercise 1.17, sorting'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-9201061749232529096</id><published>2007-01-14T18:47:00.000-08:00</published><updated>2007-01-14T18:53:24.129-08:00</updated><title type='text'>EOPL - 1.2.4 - Exercise 1.16</title><content type='html'>And now back to business,  nothing really exciting yet: the next batch of exercises. The first is function &lt;code&gt;up&lt;/code&gt; that in F# ends up being the same as concat, unless we define some new type.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// if not defining a new type that may be a list or a single element, &lt;br /&gt;// up will work like concat, on lists of lists&lt;br /&gt;let rec up lst = &lt;br /&gt;    match lst with&lt;br /&gt;      [] -&gt; []&lt;br /&gt;    | (l :: rlst) -&gt; l @ (up rlst)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This is the Scheme version of &lt;code&gt;up&lt;/code&gt;, for comparison:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define up&lt;br /&gt;  (lambda (lst)&lt;br /&gt;    (if (null? lst)&lt;br /&gt;      '()&lt;br /&gt;      (if (list? (car lst)&lt;br /&gt;        (append (car lst) (up (cdr lst)))&lt;br /&gt;        (cons (car lst) (up (cdr lst)))))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The next functions work on lists of symbols, so we repeat here the necessary type definition for symbol expressions.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type SymbolExp = Symbol of string | SList of SymbolExp list &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And the functions can thus be written:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec swapper s1 s2 slist = &lt;br /&gt;    match slist with&lt;br /&gt;      [] -&gt; []&lt;br /&gt;    | (s :: rslist) -&gt; swapper_in_symbol_exp s1 s2 s :: &lt;br /&gt;                      (swapper s1 s2 rslist)&lt;br /&gt;and swapper_in_symbol_exp s1 s2 sexp = &lt;br /&gt;    match sexp with&lt;br /&gt;      (Symbol s) when s = s1 -&gt; Symbol s2&lt;br /&gt;    | (Symbol s) when s = s2 -&gt; Symbol s1&lt;br /&gt;    | (SList sl) -&gt; SList (swapper s1 s2 sl)&lt;br /&gt;    | _ -&gt; sexp&lt;br /&gt;&lt;br /&gt;let rec count_occurrences sym slist = &lt;br /&gt;    match slist with&lt;br /&gt;      [] -&gt; 0&lt;br /&gt;    | (s :: rsl) -&gt; (count_occurrences_sexp sym s) + &lt;br /&gt;                    (count_occurrences sym rsl)&lt;br /&gt;and count_occurrences_sexp sym sexp = &lt;br /&gt;    match sexp with&lt;br /&gt;      (Symbol s) when s = sym -&gt; 1&lt;br /&gt;    | (SList sl) -&gt; count_occurrences sym sl&lt;br /&gt;    | _ -&gt; 0&lt;br /&gt;    &lt;br /&gt;let rec flatten slist = &lt;br /&gt;    match slist with&lt;br /&gt;      [] -&gt; []&lt;br /&gt;    | ((Symbol s) :: rsl) -&gt; (Symbol s) :: (flatten rsl)&lt;br /&gt;    | ((SList sl) :: rsl) -&gt; (flatten sl) @ (flatten rsl)&lt;br /&gt;    &lt;br /&gt;// lon1 and lon2 are sorted lists of numbers&lt;br /&gt;let rec merge lon1 lon2 = &lt;br /&gt;    match (lon1, lon2) with&lt;br /&gt;      ([], _) -&gt; lon2&lt;br /&gt;    | (_, []) -&gt; lon1&lt;br /&gt;    | (x :: rlon1, y :: rlon2) when x &lt;= y -&gt; x :: (merge rlon1 lon2)&lt;br /&gt;    | (x :: rlon1, y :: rlon2) -&gt; y :: (merge lon1 rlon2)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-9201061749232529096?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/9201061749232529096/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=9201061749232529096&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/9201061749232529096'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/9201061749232529096'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/01/eopl-124-exercise-116.html' title='EOPL - 1.2.4 - Exercise 1.16'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-6141828018334285861</id><published>2007-01-02T18:11:00.000-08:00</published><updated>2007-01-02T18:16:51.898-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 1.2.3 - Other Patterns of Recursion</title><content type='html'>Forgot to post the code for this section. Simple stuff, and only three functions. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec list_sum l = &lt;br /&gt;    match l with&lt;br /&gt;      [] -&gt; 0&lt;br /&gt;    | (x :: rl) -&gt; x + list_sum rl&lt;br /&gt;    &lt;br /&gt;let rec partial_vector_sum von n =&lt;br /&gt;    if n = 0 then 0 &lt;br /&gt;    else von.(n - 1) + partial_vector_sum von (n - 1)&lt;br /&gt;     &lt;br /&gt;let vector_sum von = &lt;br /&gt;    partial_vector_sum von von.Length&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-6141828018334285861?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/6141828018334285861/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=6141828018334285861&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/6141828018334285861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/6141828018334285861'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/01/eopl-123-other-patterns-of-recursion.html' title='EOPL - 1.2.3 - Other Patterns of Recursion'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-7681429543121205327</id><published>2007-01-02T17:34:00.000-08:00</published><updated>2007-01-02T17:56:46.655-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 1.2.4 - Some Exercises - 1.15</title><content type='html'>These are F# solutions to Exercise 1.15. In some places the functions proposed in the exercise are not completely suited to a ML language, so I made notes in the comments, but otherwise there is little that is exciting about these functions. I did alternative versions in some cases, even though the whole point of this exercise (and the rest from Section 1.2) is to write recursive functions to get a feel for them. &lt;br /&gt;&lt;br /&gt;The function &lt;code&gt;product&lt;/code&gt; once again runs into troubles with the value restriction. If one of the parameters is an empty list, the F# system won't recognize the result as a simple data value, so it will complain. The only way around it is to use type annotations, as noted in the comments after both versions of the function. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec duple n x = &lt;br /&gt;    if n = 0 then [] else x :: (duple (n - 1) x)&lt;br /&gt;&lt;br /&gt;// invert would probably accept a list of real pairs in F#&lt;br /&gt;let invert lp = &lt;br /&gt;    let invpair p = &lt;br /&gt;        match p with &lt;br /&gt;          [] -&gt; [] &lt;br /&gt;        | (a :: b :: []) -&gt; [b; a] &lt;br /&gt;        | _ -&gt; failwith "invalid list" in&lt;br /&gt;    List.map invpair lp&lt;br /&gt;&lt;br /&gt;let rec filter_in p lst = &lt;br /&gt;    match lst with &lt;br /&gt;      [] -&gt; []&lt;br /&gt;    | (x :: rl) when p x -&gt; x :: (filter_in p rl)&lt;br /&gt;    | (_ :: rl) -&gt; filter_in p rl&lt;br /&gt;&lt;br /&gt;let rec every p lst = &lt;br /&gt;    match lst with &lt;br /&gt;      [] -&gt; true&lt;br /&gt;    | (x :: rl) when p x -&gt; every p rl&lt;br /&gt;    | _ -&gt; false&lt;br /&gt;&lt;br /&gt;let every2 p lst = &lt;br /&gt;   List.fold_left (fun b x -&gt; b &amp;&amp; p x) true lst&lt;br /&gt;&lt;br /&gt;let rec exists p lst = &lt;br /&gt;    match lst with &lt;br /&gt;      [] -&gt; false&lt;br /&gt;    | (x :: rl) when p x -&gt; true&lt;br /&gt;    | (_ :: rl) -&gt; exists p rl&lt;br /&gt;&lt;br /&gt;// It's not possible to return numbers and booleans, so we could &lt;br /&gt;// use an algebraic data type, or int option, which seems better&lt;br /&gt;let vector_index p (v:'a array) = &lt;br /&gt;    let rec search i = &lt;br /&gt;        if i = v.Length then None&lt;br /&gt;        elif p v.(i) then Some i&lt;br /&gt;        else search (i + 1) in&lt;br /&gt;    search 0&lt;br /&gt;    &lt;br /&gt;// the test given can't be easily expressed in F#&lt;br /&gt;// also: fragile for negative n&lt;br /&gt;let rec list_set lst n x = &lt;br /&gt;    match (lst, n) with&lt;br /&gt;      ([], _) -&gt; []&lt;br /&gt;    | (elt :: rl, 0) -&gt; x :: rl&lt;br /&gt;    | (elt :: rl, i) -&gt; elt :: (list_set rl (n - 1) x)&lt;br /&gt;&lt;br /&gt;// value restriction troubles: any empty list gives an error    &lt;br /&gt;let rec product l1 l2 = &lt;br /&gt;    match (l1, l2) with&lt;br /&gt;      (_, []) -&gt; []&lt;br /&gt;    | ([], _) -&gt; []&lt;br /&gt;    | (x :: rl1, _) -&gt; (List.map (fun e -&gt; (x, e)) l2) @ (product rl1 l2)&lt;br /&gt;&lt;br /&gt;// value restriction troubles: any empty list gives an error    &lt;br /&gt;let product2 l1 l2 = &lt;br /&gt;    List.concat (List.map (fun x -&gt; List.map (fun e -&gt; (x, e)) l2) l1)&lt;br /&gt;&lt;br /&gt;(* &lt;br /&gt;To call product with an empty list as argument, you must annotate its type:&lt;br /&gt;&gt; product [1; 2; 3] ([] : int list);;&lt;br /&gt;val it : (int * int) list = []&lt;br /&gt;*)&lt;br /&gt;&lt;br /&gt;// once again, this function makes less sense in F# than in Scheme&lt;br /&gt;let down lst = &lt;br /&gt;    List.map (fun x -&gt; [x]) lst &lt;br /&gt;&lt;br /&gt;// explicitly recursive version:&lt;br /&gt;let rec down2 lst =  &lt;br /&gt;    match lst with [] -&gt; [] | (x::rl) -&gt; [x] :: (down2 rl)&lt;br /&gt;&lt;br /&gt;// scheme version    &lt;br /&gt;(* &lt;br /&gt;(define down&lt;br /&gt;  (lambda (lst)&lt;br /&gt;    (if (null? lst)&lt;br /&gt;      '()&lt;br /&gt;      (cons (list (car lst))&lt;br /&gt;            (down (cdr lst))))))&lt;br /&gt;*)&lt;br /&gt;    &lt;br /&gt;// more type inference nuances: these types must be written down&lt;br /&gt;let vector_append_list (v:'a array) (lst:'a list) = &lt;br /&gt;    let rec copy src dst i = &lt;br /&gt;        if i = 0 then () &lt;br /&gt;        else (dst.(i-1) &lt;- src.(i-1); copy src dst (i-1)) in&lt;br /&gt;    let rec copy_list_to_vector ls vc i = &lt;br /&gt;        match ls with &lt;br /&gt;          [] -&gt; () &lt;br /&gt;        | (x :: rls) -&gt; (vc.(i) &lt;- x; &lt;br /&gt;                         copy_list_to_vector rls vc (i + 1)) in&lt;br /&gt;    let newv = Array.create (v.Length + lst.Length) 0 in&lt;br /&gt;    (copy v newv v.Length; &lt;br /&gt;     copy_list_to_vector lst newv v.Length; &lt;br /&gt;     newv)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-7681429543121205327?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/7681429543121205327/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=7681429543121205327&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/7681429543121205327'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/7681429543121205327'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2007/01/eopl-124-some-exercises-115.html' title='EOPL - 1.2.4 - Some Exercises - 1.15'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-7482241377993707896</id><published>2006-12-31T13:57:00.000-08:00</published><updated>2006-12-31T14:43:31.884-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 1.2.2 - Some Important Examples</title><content type='html'>The first 2 chapters of the book are quite basic, but in this section we get some interesting tidbits regarding static &lt;span style="font-style: italic;"&gt;versus&lt;/span&gt; dynamic typing.&lt;br /&gt;&lt;br /&gt;Beginning with two easy functions, &lt;code&gt;remove&lt;/code&gt; and &lt;code&gt;remove-first&lt;/code&gt;. The type definition for a list of symbols is&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;list-of-symbols&amp;gt; ::= [] | &amp;lt;symbol&amp;gt; :: &amp;lt;list_of_symbols&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And the implementation of the functions are:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec remove_first s los =&lt;br /&gt;   match los with&lt;br /&gt;     [] -&gt; []&lt;br /&gt;   | (smb :: los') when smb = s -&gt; los'&lt;br /&gt;   | (smb :: los') -&gt; smb :: (remove_first s los')&lt;br /&gt;  &lt;br /&gt;let rec remove s los =&lt;br /&gt;   match los with&lt;br /&gt;     [] -&gt; []&lt;br /&gt;   | (smb :: los') when smb = s -&gt; remove s los'&lt;br /&gt;   | (smb :: los') -&gt; smb :: (remove s los')&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Of course, the structural equality operator (&lt;code&gt;=&lt;/code&gt;) here implies that these functions work not only with lists of symbols, but lists of any type. The type checker correctly infers the type &lt;code&gt;'a -&gt; 'a list -&gt; 'a list&lt;/code&gt; for both lists. In Scheme too it's possible to get generic functions using the structural equality function &lt;code&gt;equal?&lt;/code&gt; -- and as it is the function is guaranteed to work with symbols, numbers and characters because it uses &lt;code&gt;eqv?&lt;/code&gt; -- but the authors probably didn't want to talk about parametric polymorphism at this point in the discussion.&lt;br /&gt;&lt;br /&gt;Now to two more functions, &lt;code&gt;subst&lt;/code&gt; and &lt;code&gt;notate-depth&lt;/code&gt;, that work on symbol expressions. A symbol expression is either a symbol or a list of symbol expressions, called an &lt;code&gt;slist&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;s-list&amp;gt;            ::= [] | &amp;lt;symbol-expression&amp;gt; :: &amp;lt;s-list&amp;gt;&lt;br /&gt;&amp;lt;symbol-expression&amp;gt; ::= &amp;lt;symbol&amp;gt; | &amp;lt;s-list&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So now we can't directly define in F# functions that work either on a symbol or a list of similar data. We must define a new type that is a disjoint union of symbols and lists of symbol expressions:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type SymbolExp = Symbol of string | SList of SymbolExp list&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And now define the function &lt;code&gt;subst&lt;/code&gt; as in the book:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec subst n old slist =&lt;br /&gt;   match slist with&lt;br /&gt;     [] -&gt; []&lt;br /&gt;   | (s :: sls) -&gt; (subst_in_symbol_expression n old s) ::&lt;br /&gt;                   (subst n old sls)&lt;br /&gt;and subst_in_symbol_expression n old sexp =&lt;br /&gt;   match sexp with&lt;br /&gt;     Symbol s when s = old -&gt; Symbol n&lt;br /&gt;   | Symbol s -&gt; Symbol s&lt;br /&gt;   | SList sl -&gt; SList (subst n old sl)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that &lt;code&gt;subst&lt;/code&gt; receives plain strings as the &lt;code&gt;new&lt;/code&gt; and &lt;code&gt;old&lt;/code&gt; parameters, not a &lt;code&gt;Symbol str&lt;/code&gt; where &lt;code&gt;str&lt;/code&gt; is a string. Also, the list that &lt;code&gt;subst&lt;/code&gt; receives is a &lt;code&gt;SymbolExp list&lt;/code&gt; and not a &lt;code&gt;SymbolExp&lt;/code&gt; that is a &lt;code&gt;SList&lt;/code&gt;. The former fact is a difference in relation to the Scheme version (but could easily be changed) and the latter is consistent with the Scheme version; both may seem a bit confusing.&lt;br /&gt;&lt;br /&gt;For &lt;code&gt;notate-depth&lt;/code&gt; there's still another problem: the values returned by it are not really &lt;code&gt;slist&lt;/code&gt;s. While in Scheme this causes no problem, in F# we have to define a new type that includes the depth information with every symbol. So we get&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type NotatedSymbolExp = NSymbol of string * int &lt;br /&gt;                      | NSList of NotatedSymbolExp list&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And finally, the function:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec notate_depth_in_slist slist n =&lt;br /&gt;   match slist with&lt;br /&gt;     [] -&gt; []&lt;br /&gt;   | (s :: sls) -&gt; (notate_depth_in_symbol_expression s n) ::&lt;br /&gt;                   (notate_depth_in_slist sls n)&lt;br /&gt;and notate_depth_in_symbol_expression sexp n =&lt;br /&gt;   match sexp with&lt;br /&gt;     Symbol s -&gt; NSymbol (s, n)&lt;br /&gt;   | SList sl -&gt; NSList (notate_depth_in_slist sl (n + 1))&lt;br /&gt;  &lt;br /&gt;let notate_depth slist = notate_depth_in_slist slist 0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The rest of the code are solutions to the exercises that require coding.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.11&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec subst n o slist =&lt;br /&gt;   match slist with&lt;br /&gt;     [] -&gt; []&lt;br /&gt;   | ((Symbol s)::sls) when s=old -&gt; ((Symbol n)::subst n o sls)&lt;br /&gt;   | ((SList sl)::sls) -&gt; ((SList (subst n o sl))::subst n o sls)&lt;br /&gt;   | (s::sls) -&gt; s :: subst n o sls&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.12&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec subst_in_symbol_expression n old sexp =&lt;br /&gt;   match sexp with&lt;br /&gt;     Symbol s when s = old -&gt; Symbol n&lt;br /&gt;   | Symbol s -&gt; Symbol s&lt;br /&gt;   | SList sl -&gt; SList (subst3 n old sl)&lt;br /&gt;and subst n old slist =&lt;br /&gt;   List.map (subst_in_symbol_expression n old) slist&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.13&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec notate_depth_in_slist slist n =&lt;br /&gt;   List.map (notate_depth_in_symbol_expression n) slist&lt;br /&gt;and notate_depth_in_symbol_expression n sexp =&lt;br /&gt;   match sexp with&lt;br /&gt;     Symbol s -&gt; NSymbol (s, n)&lt;br /&gt;   | SList sl -&gt; NSList (notate_depth_in_slist sl (n + 1))&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-7482241377993707896?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/7482241377993707896/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=7482241377993707896&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/7482241377993707896'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/7482241377993707896'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2006/12/eopl-122-some-important-examples.html' title='EOPL - 1.2.2 - Some Important Examples'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-9027494035129270314</id><published>2006-12-31T11:59:00.000-08:00</published><updated>2007-01-01T10:15:48.160-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 1.2.1 - Deriving Programs from BNF Data Specifications</title><content type='html'>It's not necessary to have functions like &lt;code&gt;list-of-numbers?&lt;/code&gt; in F#, because types are checked statically. An &lt;code&gt;int list&lt;/code&gt; will always be a list of integers if the code compiles. The type checker takes care of that. So here are versions of &lt;code&gt;nth-elt&lt;/code&gt; and &lt;code&gt;list-length&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec nth_elt l n = &lt;br /&gt;    match (l, n) with &lt;br /&gt;      ([], _) -&gt; failwith ("List too short by " + &lt;br /&gt;                           string_of_int (n + 1) + " elements")&lt;br /&gt;    | (x :: rl, 0) -&gt; x&lt;br /&gt;    | (_ :: rl, _) -&gt; nth_elt rl (n - 1)&lt;br /&gt;    &lt;br /&gt;let rec list_length l = &lt;br /&gt;    match l with&lt;br /&gt;      [] -&gt; 0&lt;br /&gt;    | (_ :: rl) -&gt; 1 + list_length rl&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Just for fun, here is a non-recursive version of &lt;code&gt;list-length&lt;/code&gt;, using a fold:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let list_length l = List.fold_left (fun n _ -&gt; n + 1) 0 l&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Unfortunately the F# compiler doesn't let us write this version in &lt;a href="http://haskell.org/haskellwiki/Pointfree"&gt;point-free&lt;/a&gt; style because of some trouble with the value restriction. &lt;br /&gt;&lt;br /&gt;Exercises 1.5 and 1.6 make no sense in F#, once again because of the static type checker. Exercise 1.7 is quite easy, thanks to &lt;code&gt;any_to_string&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let nth_elt l n = &lt;br /&gt;    let rec loop l' n' =&lt;br /&gt;        match (l', n') with&lt;br /&gt;          ([], _) -&gt; failwith ((any_to_string l) + &lt;br /&gt;                               " does not have an element " + &lt;br /&gt;                               string_of_int n)&lt;br /&gt;        | (x :: rl, 0) -&gt; x&lt;br /&gt;        | (_ :: rl, _) -&gt; loop rl (n' - 1) in&lt;br /&gt;    loop l n&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-9027494035129270314?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/9027494035129270314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=9027494035129270314&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/9027494035129270314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/9027494035129270314'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2006/12/eopl-121-deriving-programs-from-bnf.html' title='EOPL - 1.2.1 - Deriving Programs from BNF Data Specifications'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-3220020214066284185</id><published>2006-12-31T08:38:00.000-08:00</published><updated>2006-12-31T10:43:16.773-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>IRC messages and 2 more Haskell functions</title><content type='html'>An &lt;a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat"&gt;IRC (Internet Relay Chat)&lt;/a&gt; message is composed of fields delimited by a space, up to an optional last argument which may include spaces.  This last argument is delimited by a field whose first character is a colon; in this case, from the colon to the terminating CR-LF pair, every character is part of the same argument. This is done to send chat messages that may include spaces, of course. A message to the person with nickname &lt;code&gt;lovecraft&lt;/code&gt; is sent (from the client to the server) like this:&lt;br /&gt;&lt;code&gt;"PRIVMSG lovecraft :hi there, man!\r\n"&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Also, the message may include a sender field as its first field. This is indicated by the very first character of the message being a colon. When the above &lt;code&gt;PRIVMSG&lt;/code&gt; is sent by a user &lt;code&gt;cthulhu&lt;/code&gt; to the server, it redirects the message to the recipient, but now indicating who sent it; like this:&lt;br /&gt;&lt;code&gt;":cthulhu PRIVMSG lovecraft :hi there, man!\r\n"&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So the task is to break an incoming IRC message into its constituent fields. There are two complications: 1) it's not possible to just split using spaces as separators, because of the last argument and 2) the first and last argument both may begin with a colon, and so it's not sufficient to just stop splitting at the first sight of a colon in the first character of a field. &lt;br /&gt;&lt;br /&gt;I first defined a recursive function that did most of the work after a call to &lt;code&gt;String.split&lt;/code&gt;, but then thought about using higher-order functions. Two Haskell functions could be used, called &lt;code&gt;takeWhile&lt;/code&gt; and &lt;code&gt;dropWhile&lt;/code&gt;. They are like &lt;code&gt;take&lt;/code&gt; and &lt;code&gt;drop&lt;/code&gt;, but instead of using a numeric index to decide where to stop taking (or dropping) elements to (or from) the list, it uses a predicate testing over the elements. So, &lt;code&gt;takeWhile p l&lt;/code&gt; will return a list taking elements &lt;code&gt;x&lt;/code&gt; from &lt;code&gt;l&lt;/code&gt; while &lt;code&gt;p x&lt;/code&gt; is true. Here is the code for these functions:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec takeWhile p l = &lt;br /&gt;    match l with&lt;br /&gt;      [] -&gt; []&lt;br /&gt;    | (x :: rl) when p x -&gt; x :: (takeWhile p rl)&lt;br /&gt;    | _ -&gt; []&lt;br /&gt;    &lt;br /&gt;let rec dropWhile p l = &lt;br /&gt;    match l with &lt;br /&gt;      [] -&gt; []&lt;br /&gt;    | (x :: rl) when p x -&gt; dropWhile p rl&lt;br /&gt;    | _ -&gt; l&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now it's easy to define the function &lt;code&gt;splitLine&lt;/code&gt; that splits an incoming IRC message into fields, keeping the last field intact. It assumes that the trailing CR-LF characters where already stripped from the message. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let splitLine line = &lt;br /&gt;    let noColon s = s.[0] &lt;&gt; ':' in&lt;br /&gt;    let concat l = match l with [] -&gt; [] | _ -&gt; [String.concat " " l] in&lt;br /&gt;    let words = line |&gt; String.split [' '] in&lt;br /&gt;    match words with&lt;br /&gt;      [] -&gt; []&lt;br /&gt;    | (w :: wds) -&gt; w :: ((takeWhile noColon wds) @ &lt;br /&gt;                          (concat (dropWhile noColon wds)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So, to show an example: &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt; splitLine &lt;br /&gt;   ":cthulhu PRIVMSG lovecraft :hi there, man!\r\n";;&lt;br /&gt;val it : string list = [":cthulhu"; &lt;br /&gt;                        "PRIVMSG"; &lt;br /&gt;                        "lovecraft"; &lt;br /&gt;                        ":hi there, man!"]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It's necessary, at this stage, to keep the colon in the sender field (to signal that the message has a sender field), but it could be removed from the last field. Anyway, &lt;code&gt;splitLine&lt;/code&gt; will be used by another function that builds a &lt;code&gt;Message&lt;/code&gt; record, removing all the colons that are added by the protocol.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-3220020214066284185?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/3220020214066284185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=3220020214066284185&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/3220020214066284185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/3220020214066284185'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2006/12/irc-messages-and-2-more-haskell.html' title='IRC messages and 2 more Haskell functions'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-1603598510456846577</id><published>2006-12-27T09:26:00.000-08:00</published><updated>2006-12-27T09:53:43.678-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>Good news</title><content type='html'>It seems &lt;a href="http://list.research.microsoft.com/scripts/lyris.pl?visit=fsharp&amp;id=325723483"&gt;String.map will be added to the F# library&lt;/a&gt; in its next release. Also, there were &lt;a href="http://list.research.microsoft.com/scripts/lyris.pl?visit=fsharp&amp;amp;id=325723483"&gt;quite&lt;/a&gt; &lt;a href="http://list.research.microsoft.com/scripts/lyris.pl?visit=fsharp&amp;id=325723483"&gt;good&lt;/a&gt; &lt;a href="http://list.research.microsoft.com/scripts/lyris.pl?visit=fsharp&amp;amp;id=325723483"&gt;responses&lt;/a&gt; to the points I raised about library functions in the &lt;a href="http://list.research.microsoft.com/scripts/lyris.pl?enter=fsharp"&gt;F# mailing list&lt;/a&gt;. &lt;a href="http://blogs.msdn.com/dsyme"&gt;Don Syme&lt;/a&gt; noted that &lt;code&gt;zip&lt;/code&gt; is already there, and it's called &lt;code&gt;List.combine&lt;/code&gt;. I hadn't noticed this.&lt;br /&gt;&lt;br /&gt;Also, Robert Pickering, author of the upcoming APress book &lt;a href="http://www.apress.com/book/bookDisplay.html?bID=10240"&gt;Foundations of F#&lt;/a&gt;, responded on his blog with a short version of the ROT13 algorithm, using only functions already present in the current library:&lt;br /&gt;&lt;a href="http://strangelights.com/blog/archive/2006/12/27/1580.aspx"&gt;http://strangelights.com/blog/archive/2006/12/27/1580.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It basically uses &lt;code&gt;List.mapi&lt;/code&gt; instead of my combo of &lt;code&gt;zip&lt;/code&gt;, &lt;code&gt;drop&lt;/code&gt; and &lt;code&gt;take&lt;/code&gt;. &lt;code&gt;List.mapi&lt;/code&gt; maps a function over a list, but this function gets as arguments the list element and its index. And mapping over a string is implemented by converting the string to a char array, using &lt;code&gt;Array.map&lt;/code&gt; over it and then creating a new string based on the result.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-1603598510456846577?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/1603598510456846577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=1603598510456846577&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1603598510456846577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1603598510456846577'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2006/12/good-news.html' title='Good news'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-8245610193167486247</id><published>2006-12-25T09:15:00.000-08:00</published><updated>2006-12-25T09:26:30.918-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>Still more ROT13</title><content type='html'>This is the last post on ROT13, I promise. The shortest version in F# is a low-level one, working with character codes. This is the most obvious solution to C programmers, and I considered it from the start, but I feel it loses something from the other versions. We have to "break" the abstraction of characters and think about their representation, and this lowers the level we are working. Here it is: &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#light&lt;br /&gt;&lt;br /&gt;let strmap f (s : string) = &lt;br /&gt;    let sb = new System.Text.StringBuilder(s) &lt;br /&gt;    let rec aux i = &lt;br /&gt;        if i = sb.Length then () else&lt;br /&gt;        (sb.Chars(i) &lt;- f (sb.Chars(i)) ; aux (i + 1))&lt;br /&gt;    ( aux 0; sb.ToString() )&lt;br /&gt;&lt;br /&gt;// still another one&lt;br /&gt;let rot13 s = &lt;br /&gt;    strmap &lt;br /&gt;     (fun c -&gt; Char.chr ((((Char.code c) - 97 + 13) mod 26) + 97)) &lt;br /&gt;     s&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I should probably substitute &lt;code&gt;Char.code 'a'&lt;/code&gt; for 97 there, and this would work as long as the encoding guaranteed that letters a to z were assigned contiguous codes, which I believe is valid in most or all current text encodings. Still, we have  to think about text encodings and character representations. And we still need a function to map over strings.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-8245610193167486247?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/8245610193167486247/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=8245610193167486247&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/8245610193167486247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/8245610193167486247'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2006/12/still-more-rot13.html' title='Still more ROT13'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-2904855271620947431</id><published>2006-12-24T22:31:00.000-08:00</published><updated>2006-12-24T22:40:51.440-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>ROT13 in F#, revisited</title><content type='html'>So after seeing the &lt;a href="http://codemiscellany.blogspot.com/2006/12/rot13-in-haskell.html"&gt;Haskell version&lt;/a&gt; I thought, &lt;code&gt;lookup&lt;/code&gt; is actually &lt;code&gt;assoc&lt;/code&gt;, in F# included in the module &lt;code&gt;List&lt;/code&gt;. So how about trying a F# version similar to the Haskell one? Well, the problem is, as I mentioned, that F# doesn't have &lt;code&gt;zip&lt;/code&gt;, &lt;code&gt;take&lt;/code&gt; and &lt;code&gt;drop&lt;/code&gt;, and there is no way to map over a string. So we have to define all these functions, and then define &lt;code&gt;rot13&lt;/code&gt; as in the Haskell version. I defined &lt;code&gt;zipWith&lt;/code&gt; from the Haskell prelude as well, and then used it to define &lt;code&gt;zip&lt;/code&gt; (as it is in Haskell). &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#light&lt;br /&gt;&lt;br /&gt;let strmap f (s : string) = &lt;br /&gt;    let sb = new System.Text.StringBuilder(s) &lt;br /&gt;    let rec aux i = &lt;br /&gt;        if i = sb.Length then () else&lt;br /&gt;        (sb.Chars(i) &lt;- f (sb.Chars(i)) ; aux (i + 1))&lt;br /&gt;    ( aux 0; sb.ToString() )&lt;br /&gt;&lt;br /&gt;let rec drop n l = &lt;br /&gt;    match (l, n) with&lt;br /&gt;      ([], _) -&gt; []&lt;br /&gt;    | (l, 0) -&gt; l&lt;br /&gt;    | (_ :: rl, n) -&gt; drop (n - 1) rl&lt;br /&gt;    &lt;br /&gt;let rec take n l = &lt;br /&gt;    match (l, n) with&lt;br /&gt;      ([], _) -&gt; []&lt;br /&gt;    | (l, 0) -&gt; []&lt;br /&gt;    | (x :: rl, n) -&gt; x :: (take (n - 1) rl)&lt;br /&gt;&lt;br /&gt;let rec zipWith f l1 l2 = &lt;br /&gt;    match (l1, l2) with&lt;br /&gt;      ([], _) -&gt; []&lt;br /&gt;    | (_, []) -&gt; []&lt;br /&gt;    | (x1 :: rl1, x2 :: rl2) -&gt; (f x1 x2) :: (zipWith f rl1 rl2)&lt;br /&gt;&lt;br /&gt;let zip l1 l2 = &lt;br /&gt;    zipWith (fun a b -&gt; (a, b)) l1 l2&lt;br /&gt;&lt;br /&gt;// and now for something completely different&lt;br /&gt;let rot13 s = &lt;br /&gt;    let letters = ['a' .. 'z']&lt;br /&gt;    let transp = zip letters ((drop 13 letters) @ (take 13 letters))&lt;br /&gt;    let rotchar c = List.assoc c transp&lt;br /&gt;    strmap rotchar s&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Works as expected, but we ended with code that is still longer than the first version, only because it was necessary to define some general-use functions. I guess I will create a Prelude module to use with F#, containing the Haskell functions I use most.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-2904855271620947431?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/2904855271620947431/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=2904855271620947431&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2904855271620947431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2904855271620947431'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2006/12/rot13-in-f-revisited.html' title='ROT13 in F#, revisited'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-4699391578003152137</id><published>2006-12-24T21:32:00.000-08:00</published><updated>2006-12-24T21:55:19.596-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 1.2 - Recursively Specified Programs</title><content type='html'>The first program is easy enough:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec e n x = &lt;br /&gt;    if n = 0 then 1 else x * (e (n-1) x)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But the second one uses the definition of bintrees from section 1.1. I should have noted there that some differences are caused because of static vs. dynamic typing. Scheme is "dynamically typed" (that's the usual term, anyway -- maybe it should be called "dynamically checked"), so it can define a bintree data type that may be a number or a list. Parts of the program that use this type must check if it received a number or a list, and act accordingly. But F# is statically typed, so we can't do it like this, because a number is a member of a type and a list is from another one. The way to solve this in F# is by creating a disjoint union data type that includes numbers and lists; well, as we know the second possibility has only 3 components, we'll do this as a tuple. So we get&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type Bintree = Leaf of int | Node of string * Bintree * Bintree&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;With this definition, and some pattern matching, it's easy to write &lt;code&gt;count-nodes&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec count_nodes s = &lt;br /&gt;    match s with&lt;br /&gt;      Leaf _ -&gt; 1&lt;br /&gt;    | Node (_, bt1, bt2) -&gt; (count_nodes bt1) + (count_nodes bt2)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The program still follows the same structure as the proof given earlier for the property. &lt;br /&gt;&lt;br /&gt;It's interesting to note that we have to define a type, where in Scheme it wouldn't need any definition. Of course, the Scheme program is harder to understand because of the use of implicit list structure (&lt;code&gt;cadr&lt;/code&gt; and &lt;code&gt;caddr&lt;/code&gt; are used to decompose the list). But in F# we have to define a representation in terms of a tagged union type, and to hide the representation we would have to define an interface with an opaque type. A bit more of work but we get static checking and better runtime performance.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-4699391578003152137?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/4699391578003152137/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=4699391578003152137&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/4699391578003152137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/4699391578003152137'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2006/12/eopl-12-recursively-specified-programs.html' title='EOPL - 1.2 - Recursively Specified Programs'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-5458862632538030146</id><published>2006-12-24T19:53:00.000-08:00</published><updated>2006-12-24T19:58:03.478-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><title type='text'>ROT13 in Haskell</title><content type='html'>To drive home the point of F#/OCaml lacking some predefined functions that make life easier, here is a version of the same &lt;a href="http://en.wikipedia.org/wiki/Rot13"&gt;ROT13&lt;/a&gt; encoding algorithm, now in Haskell. Of course the whole thing is easier not only because of functions like &lt;code&gt;zip&lt;/code&gt;, &lt;code&gt;take&lt;/code&gt; and &lt;code&gt;drop&lt;/code&gt;, but also because strings in Haskell are actually lists of characters. Anyway, here it is. Compare with the &lt;a href="http://codemiscellany.blogspot.com/2006/12/rot13-in-f.html"&gt;F# version&lt;/a&gt;.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;rot13 s = map rotchar s &lt;br /&gt;    where rotchar c = maybe '#' id (lookup c transp)&lt;br /&gt;          transp = zip letters ((drop 13 letters) ++ (take 13 letters))&lt;br /&gt;          letters = ['a' .. 'z']&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And now for the use case: &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;*Rot13&gt; rot13 "feijoada"&lt;br /&gt;"srvwbnqn"&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-5458862632538030146?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/5458862632538030146/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=5458862632538030146&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/5458862632538030146'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/5458862632538030146'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2006/12/rot13-in-haskell.html' title='ROT13 in Haskell'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-2379991654430482210</id><published>2006-12-24T16:42:00.000-08:00</published><updated>2006-12-24T16:54:24.375-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>ROT13 in F#</title><content type='html'>So, this is nothing really exciting, I wrote a simple program to do &lt;a href="http://en.wikipedia.org/wiki/Rot13"&gt;ROT13&lt;/a&gt; text encoding, and in the way bumped into some minor quirks of the standard library. One of the problems with OCaml is its idiosyncratic standard library which is missing a lot of simple and useful functions. Granted, most of them you can write in less than five minutes, but it would be better if they were already done and standardized. I guess I became spoiled by Haskell. Anyway, F# seems to have inherited this as well. Below you can see the code, and a sample use case.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#light&lt;br /&gt;&lt;br /&gt;let letters = Array.of_list(['a' .. 'z'] @ ['a' .. 'z'])&lt;br /&gt;&lt;br /&gt;let index a c =&lt;br /&gt;  let rec aux i = if a.(i) = c then i else aux (i + 1) in&lt;br /&gt;  aux 0&lt;br /&gt;&lt;br /&gt;let strmap f (s : string) =&lt;br /&gt;  let sb = new System.Text.StringBuilder(s) in&lt;br /&gt;  let rec aux i =&lt;br /&gt;      if i = sb.Length then () else&lt;br /&gt;      (sb.Chars(i) &lt;- f (sb.Chars(i)) ; aux (i + 1)) in     &lt;br /&gt;      ( aux 0; sb.ToString() )     &lt;br /&gt;&lt;br /&gt;let rotchar c =     &lt;br /&gt;    let i = index letters c in     &lt;br /&gt;    letters.(i + 13)  &lt;br /&gt;&lt;br /&gt;let rot13 s =     &lt;br /&gt;    strmap rotchar s &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And now for the use case:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt; rot13 "feijoada";;&lt;br /&gt;val it : string = "srvwbnqn"&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-2379991654430482210?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/2379991654430482210/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=2379991654430482210&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2379991654430482210'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2379991654430482210'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2006/12/rot13-in-f.html' title='ROT13 in F#'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-1633332485948241018</id><published>2006-12-23T16:48:00.000-08:00</published><updated>2006-12-23T17:12:33.581-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eopl'/><category scheme='http://www.blogger.com/atom/ns#' term='f#'/><title type='text'>EOPL - 1.1 - Recursive Sets of Data</title><content type='html'>The ML languages, unlike Scheme, don't have a "cons pair" type. For pairs one can use tuples, and for proper lists  there are lists. This means it is not possible to build an improper list in ML. So it is with F#, and this implies a simple change to the definition of lists of numbers (Definition 1.1.2, page 2).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Definition 1.1.2&lt;/span&gt; The set list-of-numbers is the smallest set of values satisfying the two properties:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The empty list is a list-of-numbers, and&lt;/li&gt;&lt;li&gt;If l is a list-of-numbers and n is a number, then the cons expression (n :: l) is a list-of-numbers&lt;/li&gt;&lt;/ol&gt;Another point of difference is that F# lacks a native symbol type. Regarding the examples in the book, it seems we can safely use strings in place of symbols, although I don't know if later chapters make use of the fact that the symbols may have associated values. Regarding types, we can use a simple type synonym:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;type Symbol = string&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Or a tagged type:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;type Symbol = Symbol of string&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The latter will be more useful when defining other types of expressions, like the examples for the lambda-calculus. In this case there will be symbols, applications and abstractions, and not only a single variant.&lt;br /&gt;&lt;br /&gt;With this in mind, it's easy to define a list-of-symbols type. At this point in the book, though, there's not much attention to representation of the data types, as the goal is to become familiar with recursive definitions. It uses the lisp pair notation, however, and lisp symbols, and these dependencies would be thus represented in F#. The same would hold for Standard ML or OCaml, of course.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-1633332485948241018?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/1633332485948241018/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=1633332485948241018&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1633332485948241018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/1633332485948241018'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2006/12/eopl-11-recursive-sets-of-data.html' title='EOPL - 1.1 - Recursive Sets of Data'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-2855879425508528479</id><published>2006-12-22T17:58:00.000-08:00</published><updated>2006-12-23T17:10:22.086-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ml'/><category scheme='http://www.blogger.com/atom/ns#' term='hindley-milner'/><title type='text'>ML type systems and Hindley-Milner type inference</title><content type='html'>Two texts I've come across in the last few days dealing with type systems for ML-like languages and Hindley-Milner type inference.&lt;br /&gt;&lt;br /&gt;First, from a rather simple question about principal typings and principal types in the Caml list came a link to the paper &lt;a href="http://www.dcc.ufmg.br/%7Ecamarao/ml-has-pt.pdf"&gt;ML Has Principal Typings&lt;/a&gt; by &lt;a href="http://www.dcc.ufmg.br/%7Ecamarao/"&gt;Carlos Camarão&lt;/a&gt; and Lucília Figueiredo; it shows a type system for ML that has principal typings, whereas the usual Damas-Milner type system found in ML languages has not.&lt;br /&gt;&lt;br /&gt;Then, &lt;a href="http://lambda-the-ultimate.org/"&gt;LtU&lt;/a&gt; links today to &lt;a href="http://lambda-the-ultimate.org/node/1929"&gt;A modern eye on ML type inference&lt;/a&gt;, some seemingly interesting lecture notes that explain Hindley-Milner type inference in current terms, including extensions. I didn't read it yet, but will do.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-2855879425508528479?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/2855879425508528479/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=2855879425508528479&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2855879425508528479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/2855879425508528479'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2006/12/ml-type-systems-and-hindley-milner-type.html' title='ML type systems and Hindley-Milner type inference'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7956560213437381210.post-5542583895606612713</id><published>2006-12-22T17:26:00.000-08:00</published><updated>2006-12-22T17:49:55.683-08:00</updated><title type='text'>Just beginning</title><content type='html'>This will be used to collect some code, mostly snippets I'm writing from time to time, often as exercices in books. One of the ideas is to translate code in some interesting books to other languages, like the &lt;a href="http://www.codepoetics.com/wiki/index.php?title=Topics:SICP_in_other_languages"&gt;SICP in other languages&lt;/a&gt; stuff. The language I'll be tackling will be, mostly, &lt;a href="http://research.microsoft.com/fsharp/fsharp.aspx"&gt;F#&lt;/a&gt;, but I guess some Haskell will appear too. Initially the idea is to work through the book &lt;a href="http://www.amazon.com/Essentials-Programming-Languages-Daniel-Friedman/dp/0262062178/sr=1-1/qid=1166837704/ref=pd_bbs_sr_1/002-6423630-6291206?ie=UTF8&amp;amp;s=books"&gt;Essentials of Programming Languages&lt;/a&gt;, but there are other candidates.&lt;br /&gt;&lt;br /&gt;And maybe something else beyond book translations, I don't know. I'll try to comment on the code where I think it's necessary.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7956560213437381210-5542583895606612713?l=codemiscellany.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codemiscellany.blogspot.com/feeds/5542583895606612713/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7956560213437381210&amp;postID=5542583895606612713&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/5542583895606612713'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7956560213437381210/posts/default/5542583895606612713'/><link rel='alternate' type='text/html' href='http://codemiscellany.blogspot.com/2006/12/just-beginning.html' title='Just beginning'/><author><name>tautologico</name><uri>http://www.blogger.com/profile/03658701069636639534</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
