<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.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"><id>tag:blogger.com,1999:blog-4129300230262819780</id><updated>2010-02-19T11:49:04.813-08:00</updated><title type="text">Forty Six and Two</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default?start-index=26&amp;max-results=25" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>40</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/FortySixAndTwo" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="fortysixandtwo" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-316875756862098145</id><published>2010-02-15T12:08:00.000-08:00</published><updated>2010-02-15T12:09:44.817-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fscheck" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title type="text">FsCheck 0.6.3 for Visual Studio 2010 RC and F# February 2010 CTP</title><content type="html">&lt;p&gt;A new release of &lt;a title="F# homepage" href="http://research.microsoft.com/fsharp/fsharp.aspx" target="_blank"&gt;F#&lt;/a&gt; means a new release of &lt;a href="http://www.codeplex.com/fscheck" target="_blank"&gt;FsCheck&lt;/a&gt;.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Removed the dependency on the F# PowerPack. This makes FsCheck easier to use, especially since the PowerPack is now&amp;#160; separately distributed. Besides, it was only used to pretty print functions. &lt;/li&gt;    &lt;li&gt;Cleaned up reflective generators a bit. &lt;/li&gt;    &lt;li&gt;All projects are upgraded to build with Visual Studio 2010 now. For backwards compatibility, I’ve added an FsCheck2008.sln solution which allows you to build in Visual Studio 2008 with the February 2010 CTP. You’ll get a warning from MSBuild saying that ToolsVersion 4.0 is not supported and that it is treating the build as a 3.5 build. Good – that’s exactly what you want. FsCheck is still targeting .NET3.5 until .NET4 is out.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Enjoy.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e7108255-21aa-4d82-87e7-437019ed4114" class="wlWriterEditableSmartContent"&gt;Technorati: &lt;a href="http://technorati.com/tags/FsCheck" rel="tag"&gt;FsCheck&lt;/a&gt;,&lt;a href="http://technorati.com/tags/random+testing" rel="tag"&gt;random testing&lt;/a&gt;,&lt;a href="http://technorati.com/tags/F%23" rel="tag"&gt;F#&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-316875756862098145?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/316875756862098145/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=316875756862098145" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/316875756862098145" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/316875756862098145" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2010/02/fscheck-063-for-visual-studio-2010-rc.html" title="FsCheck 0.6.3 for Visual Studio 2010 RC and F# February 2010 CTP" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-4682904819737086709</id><published>2010-02-11T12:54:00.001-08:00</published><updated>2010-02-11T12:54:36.706-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="tidbits" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title type="text">Visug presentation in Leuven, Belgium on 8 Feb 2010</title><content type="html">&lt;p&gt;Thanks to everyone who attended – hope you got something out of it (besides the free food and drinks…).&lt;/p&gt;  &lt;p&gt;Here are the &lt;a href="http://cid-f6a45280389d5d06.skydrive.live.com/self.aspx/Public/fsharp%20intro.pdf"&gt;slides&lt;/a&gt; I used, as well as &lt;a href="http://cid-f6a45280389d5d06.skydrive.live.com/self.aspx/Public/FSharpIntro.zip"&gt;the (completed) demo project&lt;/a&gt;. There are some extra slides and some extra parts to the demo which I didn’t present. Apparently the whole thing will also appear on MSDN chopsticks, at which point I’ll update this post with the link.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-4682904819737086709?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/4682904819737086709/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=4682904819737086709" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/4682904819737086709" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/4682904819737086709" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2010/02/visug-presentation-in-leuven-belgium-on.html" title="Visug presentation in Leuven, Belgium on 8 Feb 2010" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-470284202826557193</id><published>2009-12-22T08:57:00.000-08:00</published><updated>2009-12-22T08:59:38.932-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="tidbits" /><title type="text">On Understanding Data Abstraction, Revisited</title><content type="html">&lt;p&gt;I’m not in the habit of posting links, but &lt;a href="http://www.cs.utexas.edu/~wcook/Drafts/2009/essay.pdf"&gt;this essay by Willam R. Cook&lt;/a&gt; on the difference between ADTs and objects made such an excellent and humbling read... Humbling because in my arrogance I had assumed that I knew the difference – after all this is basic stuff. Excellent because despite the humbling experience, it’s a very enjoyable read.&lt;/p&gt;  &lt;p&gt;Enjoy.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:835cdb56-45db-4c92-b99c-863563ba2c38" class="wlWriterEditableSmartContent"&gt;Technorati: &lt;a href="http://technorati.com/tags/ADT" rel="tag"&gt;ADT&lt;/a&gt;,&lt;a href="http://technorati.com/tags/objects" rel="tag"&gt;objects&lt;/a&gt;,&lt;a href="http://technorati.com/tags/data+abstraction" rel="tag"&gt;data abstraction&lt;/a&gt;&lt;/div&gt; &lt;span class="sbmLink"&gt;   &lt;table cellspacing="1" cellpadding="1"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td class="sbmText"&gt;Share this post : &lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to Technet!" href="http://social.technet.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2009/12/on-understanding-data-abstraction.html&amp;amp;ttl=On Understanding Data Abstraction, Revisited" target="_blank"&gt;&lt;img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" /&gt;&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to del.icio.us" href="http://del.icio.us/post?url=http://fortysix-and-two.blogspot.com/2009/12/on-understanding-data-abstraction.html&amp;amp;;title=On Understanding Data Abstraction, Revisited" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" /&gt;&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&amp;amp;address=http://fortysix-and-two.blogspot.com/2009/12/on-understanding-data-abstraction.html&amp;amp;title=On Understanding Data Abstraction, Revisited" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" /&gt;&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to digg" href="http://digg.com/submit?phase=2&amp;amp;url=http://fortysix-and-two.blogspot.com/2009/12/on-understanding-data-abstraction.html&amp;amp;title=On Understanding Data Abstraction, Revisited" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" /&gt;&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to dotnetkicks" href="http://www.dotnetkicks.com/kick/?url=http://fortysix-and-two.blogspot.com/2009/12/on-understanding-data-abstraction.html&amp;amp;title=On Understanding Data Abstraction, Revisited" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to reddit!" href="http://reddit.com/submit?url=http://fortysix-and-two.blogspot.com/2009/12/on-understanding-data-abstraction.html&amp;amp;title=On Understanding Data Abstraction, Revisited" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" /&gt;&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to technorati!" href="http://technorati.com/faves/?add=http://fortysix-and-two.blogspot.com/2009/12/on-understanding-data-abstraction.html&amp;amp;title=On Understanding Data Abstraction, Revisited" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" /&gt;&lt;/a&gt;&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-470284202826557193?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/470284202826557193/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=470284202826557193" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/470284202826557193" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/470284202826557193" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/12/on-understanding-data-abstraction.html" title="On Understanding Data Abstraction, Revisited" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-8106871407108772948</id><published>2009-12-08T11:51:00.000-08:00</published><updated>2009-12-08T11:55:11.040-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="mercurial" /><category scheme="http://www.blogger.com/atom/ns#" term="tidbits" /><title type="text">How to get hg-git working with Mercurial without installing Python on Windows</title><content type="html">&lt;p&gt;Sorry for the horrendous search keyword-driven title, but I’ve been trying to get this to work for ages.&lt;/p&gt;  &lt;p&gt;Here’s a step by step guide, along with some potential pitfalls.&lt;/p&gt;  &lt;p&gt;1) Download &lt;a href="http://tortoisehg.bitbucket.org/"&gt;TortoiseHg&lt;/a&gt;. I used 0.9.1.1. with Mercurial 1.4.1. Do not use the windows &lt;a href="http://www.selenic.com/mercurial/wiki/"&gt;Mercurial&lt;/a&gt; command line only distribution – we’ll need to modify a zip file later and for some reason the zip file with the command line distribution cannot be modified with either WinRar, Winzip or 7-zip.&lt;/p&gt;  &lt;p&gt;2) Install TortoiseHg as usual.&lt;/p&gt;  &lt;p&gt;3) Download &lt;a href="http://pypi.python.org/pypi/dulwich"&gt;dulwich 0.4.0&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;4) Add the directory called ‘dulwich’ inside the dulwich download (the one with the file __init__.py in it) to the library.zip file in the TortoiseHg folder (normally just C: \Program Files\TortoiseHg) using your favorite zip utility.&lt;/p&gt;  &lt;p&gt;5) Download the tip of an up to date hg-git fork. I used &lt;a title="http://bitbucket.org/gwik/hg-git/" href="http://bitbucket.org/gwik/hg-git/"&gt;http://bitbucket.org/gwik/hg-git/&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;6) Put the hg-git directory in the TortoiseHg directory.&lt;/p&gt;  &lt;p&gt;7) Add the following lines to your Mercurial.ini file:&lt;/p&gt;  &lt;p&gt;&lt;font face="con"&gt;bookmarks =&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="con"&gt;hggit = C:\Program Files\TortoiseHg\hg-git\hggit&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;That’s it. I finally managed to clone the ClojureClr repository with the above install:&lt;/p&gt;  &lt;pre&gt;&amp;gt; hg clone git://github.com/richhickey/clojure-clr.git
destination directory: clojure-clr.git
importing Hg objects into Git
Counting objects: 4001, done.
Compressing objects: 100% (1816/1816), done.
Total 4001 (delta 3153), reused 2774 (delta 2148)
importing Git objects into Hg
at:   0/307
at: 100/307
at: 200/307
at: 300/307
updating to branch default
313 files updated, 0 files merged, 0 files removed, 0 files unresolved&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;And with this we’re back to functional programming languages ;)&lt;/p&gt;

&lt;p&gt;I didn’t test this any further.&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:d7bf807d-7bb0-458a-811f-90c51817d5c2:9edadbb3-00ac-468c-b928-62f4e7c3c230" class="wlWriterEditableSmartContent"&gt;&lt;p&gt;&lt;span class="TagSite"&gt;Technorati:&lt;/span&gt; &lt;a href="http://technorati.com/tag/mercurial" rel="tag" class="tag"&gt;mercurial&lt;/a&gt;, &lt;a href="http://technorati.com/tag/hg" rel="tag" class="tag"&gt;hg&lt;/a&gt;, &lt;a href="http://technorati.com/tag/hg-git" rel="tag" class="tag"&gt;hg-git&lt;/a&gt;, &lt;a href="http://technorati.com/tag/git" rel="tag" class="tag"&gt;git&lt;/a&gt;&lt;br /&gt;&lt;!-- StartInsertedTags: mercurial,hg,hg-git,git :EndInsertedTags --&gt;&lt;/p&gt;&lt;/div&gt;
&lt;span class="sbmLink"&gt;
  &lt;table cellspacing="1" cellpadding="1"&gt;&lt;tbody&gt;
      &lt;tr&gt;
        &lt;td class="sbmText"&gt;Share this post : &lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to Technet!" href="http://social.technet.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2009/12/how-to-get-hg-git-working-with.html&amp;amp;ttl=How to get hg-git working with Mercurial without installing Python on Windows" target="_blank"&gt;&lt;img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" /&gt;&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to del.icio.us" href="http://del.icio.us/post?url=http://fortysix-and-two.blogspot.com/2009/12/how-to-get-hg-git-working-with.html&amp;amp;;title=How to get hg-git working with Mercurial without installing Python on Windows" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" /&gt;&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&amp;amp;address=http://fortysix-and-two.blogspot.com/2009/12/how-to-get-hg-git-working-with.html&amp;amp;title=How to get hg-git working with Mercurial without installing Python on Windows" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" /&gt;&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to digg" href="http://digg.com/submit?phase=2&amp;amp;url=http://fortysix-and-two.blogspot.com/2009/12/how-to-get-hg-git-working-with.html&amp;amp;title=How to get hg-git working with Mercurial without installing Python on Windows" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" /&gt;&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to dotnetkicks" href="http://www.dotnetkicks.com/kick/?url=http://fortysix-and-two.blogspot.com/2009/12/how-to-get-hg-git-working-with.html&amp;amp;title=How to get hg-git working with Mercurial without installing Python on Windows" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to reddit!" href="http://reddit.com/submit?url=http://fortysix-and-two.blogspot.com/2009/12/how-to-get-hg-git-working-with.html&amp;amp;title=How to get hg-git working with Mercurial without installing Python on Windows" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" /&gt;&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to technorati!" href="http://technorati.com/faves/?add=http://fortysix-and-two.blogspot.com/2009/12/how-to-get-hg-git-working-with.html&amp;amp;title=How to get hg-git working with Mercurial without installing Python on Windows" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" /&gt;&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;&lt;/table&gt;
&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-8106871407108772948?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/8106871407108772948/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=8106871407108772948" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/8106871407108772948" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/8106871407108772948" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/12/how-to-get-hg-git-working-with.html" title="How to get hg-git working with Mercurial without installing Python on Windows" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-2253718114378551111</id><published>2009-10-26T03:10:00.000-07:00</published><updated>2009-10-26T03:22:45.318-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fscheck" /><title type="text">FsCheck 0.6.2: F# October 2009 CTP/2010 Beta 2</title><content type="html">&lt;p&gt;&lt;a href="http://fscheck.codeplex.com"&gt;FsCheck&lt;/a&gt; is updated for the new F# release! Conversion was fairly straightforward, some name changes and indentation changes mostly. Furthermore, the following smaller changes: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;A nice set of new default generators contributed by Howard Mansell. FsCheck can now generate any Enum instance, as well as generators for DateTime, arrays, positive and negative ints and so on. Check out the Arbitrary.fs file for a complete overview.&lt;/li&gt;&lt;li&gt;Some more examples&lt;/li&gt;&lt;li&gt;registerInstances and overwriteInstances now throws an exception if it cannot find any instances in the given type.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Happy FsChecking!



&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-2253718114378551111?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/2253718114378551111/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=2253718114378551111" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/2253718114378551111" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/2253718114378551111" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/10/fscheck-062-f-october-2009-ctp2010-beta.html" title="FsCheck 0.6.2: F# October 2009 CTP/2010 Beta 2" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-2267112906835982001</id><published>2009-09-19T06:53:00.000-07:00</published><updated>2009-09-19T06:59:17.647-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><category scheme="http://www.blogger.com/atom/ns#" term="backtracking" /><title type="text">Simple and Fair Backtracking Computations</title><content type="html">&lt;p&gt;Translated to &lt;a title="F# homepage" href="http://research.microsoft.com/fsharp/fsharp.aspx" target="_blank"&gt;F#&lt;/a&gt; from the &lt;a href="http://okmij.org/ftp/Computation/monads.html#fair-bt-stream"&gt;fair and terminating backtracking monad and monad transformer&lt;/a&gt; by Oleg Kiselyov. &lt;/p&gt;  &lt;p&gt;Sequence expressions in F# can be seen as backtracking computations. For example,&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;backtrack =
    seq {   &lt;span style="color: blue"&gt;for &lt;/span&gt;i &lt;span style="color: blue"&gt;in &lt;/span&gt;1..10 &lt;span style="color: blue"&gt;do
            for &lt;/span&gt;j &lt;span style="color: blue"&gt;in &lt;/span&gt;1..10 &lt;span style="color: blue"&gt;do
            if &lt;/span&gt;i*j &amp;gt; 10 &lt;span style="color: blue"&gt;then yield &lt;/span&gt;(i,j) }&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;will yield one by one (i.e. lazily) all the tuples i,j that satisfy the guard i*j&amp;gt;10. In Haskell, you would use list comprehensions to much the same effect. Once the values of j are exhausted for a given i, the computation backtracks, takes the next value for i and retries all values for j. Don’t mistake the syntactic sugar for nested loops&amp;#160; – there is really a computation builder behind this that translates to something like &lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;1..10 &amp;gt;&amp;gt;= (fun i –&amp;gt; 1..10 &amp;gt;&amp;gt;= (fun j –&amp;gt; …))&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;where (&amp;gt;&amp;gt;=) represents monadic bind. This translations shows more clearly that the binds are really doing backtracking. It’s just F#’s syntactic sugar for computation expressions that makes the computation look like a nested loop.&lt;/p&gt;

&lt;p&gt;Unfortunately, this simplicity has some drawbacks.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;infinite =
    seq {   &lt;span style="color: blue"&gt;for &lt;/span&gt;i &lt;span style="color: blue"&gt;in &lt;/span&gt;1..10 &lt;span style="color: blue"&gt;do
            for &lt;/span&gt;j &lt;span style="color: blue"&gt;in &lt;/span&gt;Seq.initInfinite id &lt;span style="color: blue"&gt;do
            if &lt;/span&gt;i &amp;gt; 5 &lt;span style="color: blue"&gt;then yield &lt;/span&gt;(i,j) }&lt;/pre&gt;

&lt;p&gt;will never return any results, although there is an infinite number of solutions. The reason is that generation gets stuck on j – an infinite stream that will never yield a solution as long as the computation does not backtrack and tries new values for i. The computation is unfair in its choice of values to try – it always chooses the last stream until that is exhausted.&lt;/p&gt;

&lt;p&gt;The thing to realize is that, if viewed as a backtracking computation, there are basically two operations that are important: &lt;em&gt;choice&lt;/em&gt; and &lt;em&gt;bind. &lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Choice&lt;/em&gt; gives the computation a range of elements to choose from. In the example above, we have an element i that can be chosen from the interval [1,10] and an element j that can be chosen from the interval [0,Infinity]. It can be viewed as logical disjunction: for i, choose 1 or 2 or 3 or 4 or…&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bind &lt;/em&gt;gives the computation a number of sub-computations that all need to return a value if the complete computation is to return a value. It can be understood as logical conjunction: in the example above, i should be chosen from [1,10] &lt;em&gt;and &lt;/em&gt;j should be chosen from [0,Infinity] &lt;em&gt;and &lt;/em&gt;i should be &amp;gt; 5.&lt;/p&gt;

&lt;p&gt;Theoretically, it does not matter in which order these kinds of generate-and-test computations are executed. However, for performance and once you start using infinite streams, it becomes important that the computation is fair – in the sense that the choices it makes give every option consideration, even if once choice has not been exhausted yet. The results of all backtracking computations should be equivalent modulo the order in which the results are returned.&lt;/p&gt;

&lt;p&gt;So, can we make an alternative computation builder for which this kind of computation returns results?&lt;/p&gt;

&lt;h5&gt;Fair streams&lt;/h5&gt;

&lt;p&gt;Let’s start by making a new datatype of streams, that we can use to make fairer choices, and that also can be suspended so that infinite streams can be supported:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Stream&amp;lt;'a&amp;gt; = 
    | Nil                               &lt;span style="color: green"&gt;//empty
    &lt;/span&gt;| One &lt;span style="color: blue"&gt;of &lt;/span&gt;'a                         &lt;span style="color: green"&gt;//one element
    &lt;/span&gt;| Choice &lt;span style="color: blue"&gt;of &lt;/span&gt;'a * Stream&amp;lt;'a&amp;gt;         &lt;span style="color: green"&gt;//one element, and maybe more
    &lt;/span&gt;| Incomplete &lt;span style="color: blue"&gt;of &lt;/span&gt;Lazy&amp;lt;Stream&amp;lt;'a&amp;gt;&amp;gt;    &lt;span style="color: green"&gt;//suspended stream
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Using this stream, we can code a fair choice function:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;choice r r' = &lt;span style="color: green"&gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;match &lt;/span&gt;r &lt;span style="color: blue"&gt;with
    &lt;/span&gt;| Nil &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;r' &lt;span style="color: green"&gt;//first empty-&amp;gt; try the second
    &lt;/span&gt;| One a &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Choice (a,r') &lt;span style="color: green"&gt;//Put in front of the new stream
    &lt;/span&gt;| Choice (a,rs) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Choice (a,choice r' rs) &lt;span style="color: green"&gt;//interleave r and r' here
    &lt;/span&gt;| Incomplete i &lt;span style="color: blue"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;
        &lt;/span&gt;&lt;span style="color: blue"&gt;match &lt;/span&gt;r' &lt;span style="color: blue"&gt;with
        &lt;/span&gt;| Nil &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;r&lt;span style="color: green"&gt;
        &lt;/span&gt;| One b &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Choice (b,r)&lt;span style="color: green"&gt;
        &lt;/span&gt;| Choice (b,rs') &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Choice (b,choice r rs') &lt;span style="color: green"&gt;
        &lt;/span&gt;| Incomplete j &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Incomplete (&lt;span style="color: blue"&gt;lazy &lt;/span&gt;(choice i.Value j.Value))&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The important thing here is the switch of argument order in the recursive call to choice in the third case. This ensures that, in contrary to normal sequences, a choice will choose alternatively from the first and second stream (and so on, recursively, for more streams). Choice is actually somewhat equivalent to concatenate on sequences, only it interleaves the elements so that the choice is fair.&lt;/p&gt;

&lt;p&gt;Bind is more straightforward:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;bind m f =
    &lt;span style="color: blue"&gt;match &lt;/span&gt;m &lt;span style="color: blue"&gt;with
        &lt;/span&gt;| Nil &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Nil
        | One a &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;(f a)
        | Choice (a,r) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;choice (f a) (Incomplete (&lt;span style="color: blue"&gt;lazy &lt;/span&gt;bind r f))&lt;span style="color: green"&gt;
        &lt;/span&gt;| Incomplete i &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Incomplete (&lt;span style="color: blue"&gt;lazy &lt;/span&gt;bind i.Value f)&lt;/pre&gt;

&lt;p&gt;This is what you would expect from a normal monadic bind on a list like type: a variant of map – concat on each element of the first stream. Note in the third case that we take care to encode the resulting stream as a number of choices that we can choose from fairly.&lt;/p&gt;

&lt;p&gt;We now have the important elements to make a computation builder:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;FairStream() =
    &lt;span style="color: blue"&gt;member &lt;/span&gt;x.Return a = One a
    &lt;span style="color: blue"&gt;member &lt;/span&gt;x.Yield a = One a
    &lt;span style="color: blue"&gt;member &lt;/span&gt;x.Bind (m, f) = bind m f&lt;span style="color: green"&gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;member &lt;/span&gt;x.Zero() = Nil
    &lt;span style="color: blue"&gt;member &lt;/span&gt;x.Combine (r,r') = choice r r'
    &lt;span style="color: blue"&gt;member &lt;/span&gt;x.Delay (f:unit&lt;span style="color: blue"&gt;-&amp;gt;&lt;/span&gt;Stream&amp;lt;_&amp;gt;) = Incomplete (Lazy.Create f)&lt;/pre&gt;

&lt;pre class="code"&gt;   
&lt;span style="color: blue"&gt;let &lt;/span&gt;bt = FairStream()&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I called it bt, short for backtracking. Now we need a function to run our computation:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;run d st =
    &lt;span style="color: blue"&gt;match &lt;/span&gt;(d,st) &lt;span style="color: blue"&gt;with
    &lt;/span&gt;| _,Nil &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Seq.empty
    | _,One a &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;seq { &lt;span style="color: blue"&gt;yield &lt;/span&gt;a }
    | _,Choice (a,r) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;seq { &lt;span style="color: blue"&gt;yield &lt;/span&gt;a; &lt;span style="color: blue"&gt;yield! &lt;/span&gt;run d r }
    | Some 0,Incomplete i &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Seq.empty &lt;span style="color: green"&gt;//exhausted depth
    &lt;/span&gt;| d,Incomplete (Lazy r) &lt;span style="color: blue"&gt;-&amp;gt; let &lt;/span&gt;d' = Option.map ((-) 1) d &lt;span style="color: blue"&gt;in &lt;/span&gt;run d' r&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The run function takes an optional parameter to bound the number of backtracking steps, which may be useful to help with termination.&lt;/p&gt;

&lt;h5&gt;A few examples&lt;/h5&gt;

&lt;p&gt;First, let’s define a stream of numbers [0,Infinity]:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;number() = bt { &lt;span style="color: blue"&gt;yield &lt;/span&gt;0
                        &lt;span style="color: blue"&gt;let! &lt;/span&gt;n = number() &lt;span style="color: blue"&gt;in yield &lt;/span&gt;n+1 }&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Nothing really amazing here – you could do something similar with sequences as well. However, if we use the choice constructor explicitly, we can define number as a &lt;em&gt;left-recursive&lt;/em&gt; function:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;number() = choice (bt { &lt;span style="color: blue"&gt;let! &lt;/span&gt;n = number() &lt;span style="color: blue"&gt;in return &lt;/span&gt;n+1 }) (bt {&lt;span style="color: blue"&gt;return &lt;/span&gt;0})&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Both number functions yield the same results.&lt;/p&gt;

&lt;p&gt;Now for something a bit more spectacular. &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;guard assertion = 
    bt { &lt;span style="color: blue"&gt;if &lt;/span&gt;assertion &lt;span style="color: blue"&gt;then return &lt;/span&gt;() }&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;pythagoreanTriples =
    bt{ &lt;span style="color: blue"&gt;let! &lt;/span&gt;i = number()
        &lt;span style="color: blue"&gt;do! &lt;/span&gt;guard (i &amp;gt; 0)&lt;span style="color: green"&gt;
        &lt;/span&gt;&lt;span style="color: blue"&gt;let! &lt;/span&gt;j = number()
        &lt;span style="color: blue"&gt;do! &lt;/span&gt;guard (j &amp;gt; 0) 
        &lt;span style="color: blue"&gt;let! &lt;/span&gt;k = number()
        &lt;span style="color: blue"&gt;do! &lt;/span&gt;guard (k &amp;gt; 0)
        &lt;span style="color: blue"&gt;do! &lt;/span&gt;guard (i*i + j*j = k*k)
        &lt;span style="color: blue"&gt;return &lt;/span&gt;(i,j,k) }&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;This computation will never yield any results in a standard sequence expression, but with the fair streams it works, even if you leave off the guards.&lt;/p&gt;

&lt;p&gt;The discerning reader might wonder why we can’t write:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;number() = 
    bt { &lt;span style="color: blue"&gt;let! &lt;/span&gt;n = number() &lt;span style="color: blue"&gt;in return &lt;/span&gt;n+1
         &lt;span style="color: blue"&gt;return &lt;/span&gt;0 }&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;which is a left recursive version in a computation expression style. I don’t know the answer myself – some details are lost in the translation to the methods on the computation builder, but I’m guessing it has something to do with the bind not being lazy enough, and/or the choice function not getting inserted in the appropriate place. I’ve tried various approaches, but couldn’t get it to work. So I guess there’s some homework for you :) In the mean time, I think I’m going to work through &lt;a href="http://okmij.org/ftp/papers/LogicT.pdf"&gt;Backtracking, Interleaving, and Terminating Monad Transformers&lt;/a&gt; by Kiselyov et al…&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:76e20eb4-dc49-44ef-b58c-27dd390c7889" class="wlWriterEditableSmartContent"&gt;Technorati: &lt;a href="http://technorati.com/tags/F%23" rel="tag"&gt;F#&lt;/a&gt;,&lt;a href="http://technorati.com/tags/computation+builder" rel="tag"&gt;computation builder&lt;/a&gt;,&lt;a href="http://technorati.com/tags/backtracking" rel="tag"&gt;backtracking&lt;/a&gt;,&lt;a href="http://technorati.com/tags/monads" rel="tag"&gt;monads&lt;/a&gt;&lt;/div&gt;
&lt;span class="sbmLink"&gt;
  &lt;table cellspacing="1" cellpadding="1"&gt;&lt;tbody&gt;
      &lt;tr&gt;
        &lt;td class="sbmText"&gt;Share this post : &lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to Technet!" href="http://social.technet.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2009/09/simple-and-fair-backtracking.html&amp;amp;ttl=Simple and Fair Backtracking Computations" target="_blank"&gt;&lt;img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" /&gt;Technet!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to del.icio.us" href="http://del.icio.us/post?url=http://fortysix-and-two.blogspot.com/2009/09/simple-and-fair-backtracking.html&amp;amp;;title=Simple and Fair Backtracking Computations" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" /&gt;del.icio.us it!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&amp;amp;address=http://fortysix-and-two.blogspot.com/2009/09/simple-and-fair-backtracking.html&amp;amp;title=Simple and Fair Backtracking Computations" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" /&gt;del.iri.ous!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to digg" href="http://digg.com/submit?phase=2&amp;amp;url=http://fortysix-and-two.blogspot.com/2009/09/simple-and-fair-backtracking.html&amp;amp;title=Simple and Fair Backtracking Computations" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" /&gt;digg it!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to dotnetkicks" href="http://www.dotnetkicks.com/kick/?url=http://fortysix-and-two.blogspot.com/2009/09/simple-and-fair-backtracking.html&amp;amp;title=Simple and Fair Backtracking Computations" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" /&gt;dotnetkicks it!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to reddit!" href="http://reddit.com/submit?url=http://fortysix-and-two.blogspot.com/2009/09/simple-and-fair-backtracking.html&amp;amp;title=Simple and Fair Backtracking Computations" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" /&gt;reddit!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to technorati!" href="http://technorati.com/faves/?add=http://fortysix-and-two.blogspot.com/2009/09/simple-and-fair-backtracking.html&amp;amp;title=Simple and Fair Backtracking Computations" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" /&gt;technorati!&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;&lt;/table&gt;
&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-2267112906835982001?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/2267112906835982001/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=2267112906835982001" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/2267112906835982001" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/2267112906835982001" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/09/simple-and-fair-backtracking.html" title="Simple and Fair Backtracking Computations" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-8168518752159805742</id><published>2009-06-27T04:32:00.000-07:00</published><updated>2009-06-27T04:34:48.491-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="tidbits" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title type="text">More fun with data structures, continuations and call/cc</title><content type="html">&lt;p&gt;&lt;a href="http://fortysix-and-two.blogspot.com/2009/06/fun-with-data-structures-continuations.html"&gt;Last time&lt;/a&gt; I showed a few ways of implementing insert into an unbalanced binary tree, as an implementation of a set data structure. This post adds an implementation that is similar in functionality to the example that uses call/cc, but using the more familiar exceptions to avoid allocating elements needlessly:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;insertExc x t =
    &lt;span style="color: blue"&gt;try
        let rec &lt;/span&gt;insertRec x t =
            &lt;span style="color: blue"&gt;match &lt;/span&gt;t &lt;span style="color: blue"&gt;with
            &lt;/span&gt;| Empty &lt;span style="color: blue"&gt;-&amp;gt;  &lt;/span&gt;cont { &lt;span style="color: blue"&gt;return &lt;/span&gt;Elem(empty,x,empty) }
            | Elem (left,e,right) &lt;span style="color: blue"&gt;when &lt;/span&gt;x &amp;lt; e &lt;span style="color: blue"&gt;-&amp;gt; 
                &lt;/span&gt;cont {  &lt;span style="color: blue"&gt;let! &lt;/span&gt;t' = insertRec x left
                        &lt;span style="color: blue"&gt;return &lt;/span&gt;Elem(t',e,right) }
            | Elem (left,e,right) &lt;span style="color: blue"&gt;when &lt;/span&gt;x &amp;gt; e &lt;span style="color: blue"&gt;-&amp;gt; 
                &lt;/span&gt;cont {  &lt;span style="color: blue"&gt;let! &lt;/span&gt;t' = insertRec x right
                        &lt;span style="color: blue"&gt;return &lt;/span&gt;Elem(left,e,t') }
            | Elem _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;failwith &lt;span style="color: maroon"&gt;&amp;quot;alreadyExists&amp;quot;
        &lt;/span&gt;insertRec x t id
    &lt;span style="color: blue"&gt;with &lt;/span&gt;e –&lt;span style="color: blue"&gt;&amp;gt; &lt;/span&gt;t&lt;/pre&gt;

&lt;h4&gt;&lt;/h4&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;h4&gt;Performance shootout&lt;/h4&gt;

&lt;p&gt;A comment on the last post indicated that exceptions should be much slower (on .NET, at least) than the callCC approach. Furthermore, I said that callCC was necessary to avoid re-allocating elements needlessly on the search path to an already existing element. Let’s put these claims to the test with a simple benchmark:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;longList = 
    &lt;span style="color: blue"&gt;let &lt;/span&gt;r = &lt;span style="color: blue"&gt;new &lt;/span&gt;System.Random()
    &lt;span style="color: blue"&gt;let &lt;/span&gt;l = 100000
    [ &lt;span style="color: blue"&gt;for &lt;/span&gt;i &lt;span style="color: blue"&gt;in &lt;/span&gt;1..l &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;r.Next(0,l) ]

&lt;span style="color: blue"&gt;let &lt;/span&gt;insertALot f nbRuns =
    &lt;span style="color: blue"&gt;for &lt;/span&gt;i &lt;span style="color: blue"&gt;in &lt;/span&gt;1..nbRuns &lt;span style="color: blue"&gt;do
        &lt;/span&gt;longList |&amp;gt; List.fold (&lt;span style="color: blue"&gt;fun &lt;/span&gt;t elem &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;f elem t) empty&lt;/pre&gt;

&lt;p&gt;How many duplicates are in the long list (i.e. how much can we expect to gain by using callCC/exceptions):&lt;/p&gt;

&lt;pre class="code"&gt;&amp;gt; longList |&amp;gt; Seq.distinct |&amp;gt; Seq.length;;
val it : int = 63362&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;So about 35% duplicates. The results:

&lt;pre&gt;&amp;gt; insertALot insert 100;;
Real: 00:01:38.717, CPU: 00:01:37.516, GC gen0: 2247, gen1: 520, gen2: 8
val it : unit = ()
&amp;gt; insertALot insert' 100;;
Real: 00:01:44.583, CPU: 00:01:37.251, GC gen0: 4050, gen1: 1444, gen2: 18
val it : unit = ()
&amp;gt; insertALot insertM 100;;
Real: 00:02:35.101, CPU: 00:02:29.792, GC gen0: 12698, gen1: 1875, gen2: 24
val it : unit = ()
&amp;gt; insertALot insertCallCC 100;;
Real: 00:01:09.410, CPU: 00:01:02.540, GC gen0: 12149, gen1: 7, gen2: 0
val it : unit = ()
&amp;gt; insertALot insertExc 100;;

- Interrupt&lt;/pre&gt;

&lt;p&gt;Observe that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the readability of computation expressions comes with a cost;&lt;/li&gt;

  &lt;li&gt;even with that cost, the callCC code is still significantly faster;&lt;/li&gt;

  &lt;li&gt;Exceptions are indeed horribly slow – I interrupted after about an hour.&lt;/li&gt;
&lt;/ul&gt;
&lt;span class="sbmLink"&gt;
  &lt;table cellspacing="1" cellpadding="1"&gt;&lt;tbody&gt;
      &lt;tr&gt;
        &lt;td class="sbmText"&gt;Share this post : &lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to Technet!" href="http://social.technet.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2009/06/more-fun-with-data-structures.html&amp;amp;ttl=Mire fun with data structures, continuations and call/cc" target="_blank"&gt;&lt;img src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" border="0" /&gt;Technet!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to del.icio.us" href="http://del.icio.us/post?url=http://fortysix-and-two.blogspot.com/2009/06/more-fun-with-data-structures.html&amp;amp;;title=Mire fun with data structures, continuations and call/cc" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" border="0" /&gt;del.icio.us it!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&amp;amp;address=http://fortysix-and-two.blogspot.com/2009/06/more-fun-with-data-structures.html&amp;amp;title=Mire fun with data structures, continuations and call/cc" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" border="0" /&gt;del.iri.ous!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to digg" href="http://digg.com/submit?phase=2&amp;amp;url=http://fortysix-and-two.blogspot.com/2009/06/more-fun-with-data-structures.html&amp;amp;title=Mire fun with data structures, continuations and call/cc" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" border="0" /&gt;digg it!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to dotnetkicks" href="http://www.dotnetkicks.com/kick/?url=http://fortysix-and-two.blogspot.com/2009/06/more-fun-with-data-structures.html&amp;amp;title=Mire fun with data structures, continuations and call/cc" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" border="0" /&gt;dotnetkicks it!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to reddit!" href="http://reddit.com/submit?url=http://fortysix-and-two.blogspot.com/2009/06/more-fun-with-data-structures.html&amp;amp;title=Mire fun with data structures, continuations and call/cc" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" border="0" /&gt;reddit!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to technorati!" href="http://technorati.com/faves/?add=http://fortysix-and-two.blogspot.com/2009/06/more-fun-with-data-structures.html&amp;amp;title=Mire fun with data structures, continuations and call/cc" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" border="0" /&gt;technorati!&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;&lt;/table&gt;
&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-8168518752159805742?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/8168518752159805742/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=8168518752159805742" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/8168518752159805742" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/8168518752159805742" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/06/more-fun-with-data-structures.html" title="More fun with data structures, continuations and call/cc" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-3158212243224204490</id><published>2009-06-24T13:00:00.000-07:00</published><updated>2009-06-24T13:12:55.107-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="tidbits" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title type="text">Fun with data structures, continuations and call/cc</title><content type="html">&lt;p&gt;Prompted by exercise 2.3 in &lt;a href="http://www.amazon.com/Purely-Functional-Structures-Chris-Okasaki/dp/0521663504"&gt;Purely Functional Data Structures&lt;/a&gt;, by Chris Okasaki.&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Tree&amp;lt;'a&amp;gt; = Empty | Elem &lt;span style="color: blue"&gt;of &lt;/span&gt;'a Tree * 'a * 'a Tree

&lt;span style="color: blue"&gt;let &lt;/span&gt;empty = Empty&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;h5&gt;Recursive&lt;/h5&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;insert x t =
    &lt;span style="color: blue"&gt;match &lt;/span&gt;t &lt;span style="color: blue"&gt;with
    &lt;/span&gt;| Empty &lt;span style="color: blue"&gt;-&amp;gt;  &lt;/span&gt;Elem(empty,x,empty)
    | Elem (left,e,right) &lt;span style="color: blue"&gt;when &lt;/span&gt;x &amp;lt; e &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Elem (insert x left,e,right)
    | Elem (left,e,right) &lt;span style="color: blue"&gt;when &lt;/span&gt;x &amp;gt; e &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Elem (left,e, insert x right)
    | Elem _ –&lt;span style="color: blue"&gt;&amp;gt; &lt;/span&gt;t&lt;/pre&gt;

&lt;h5&gt;Tail Recursive&lt;/h5&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;insert' x t =
    &lt;span style="color: blue"&gt;let rec &lt;/span&gt;cont x t k =
        &lt;span style="color: blue"&gt;match &lt;/span&gt;t &lt;span style="color: blue"&gt;with
        &lt;/span&gt;| Empty &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;k (Elem(empty,x,empty))
        | Elem (left,e,right) &lt;span style="color: blue"&gt;when &lt;/span&gt;x &amp;lt; e &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;cont x left (&lt;span style="color: blue"&gt;fun &lt;/span&gt;t' &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;k &amp;lt;| Elem (t',e,right))
        | Elem (left,e,right) &lt;span style="color: blue"&gt;when &lt;/span&gt;x &amp;gt; e &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;cont x right (&lt;span style="color: blue"&gt;fun &lt;/span&gt;t' &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;k &amp;lt;| Elem (left,e,t'))
        | Elem _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;k t
    cont x t id&lt;/pre&gt;

&lt;h5&gt;Using a continuation monad&lt;/h5&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Cont&amp;lt;'a,'r&amp;gt; = ('a &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;'r) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;'r

&lt;span style="color: blue"&gt;type &lt;/span&gt;ContBuilder() =
    &lt;span style="color: blue"&gt;member &lt;/span&gt;x.Return (a):Cont&amp;lt;'a,'r&amp;gt; = &lt;span style="color: blue"&gt;fun &lt;/span&gt;k &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;k a
    &lt;span style="color: blue"&gt;member &lt;/span&gt;x.Bind (c:Cont&amp;lt;'a,'r&amp;gt;, f:'a &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Cont&amp;lt;'b,_&amp;gt;) =
        (&lt;span style="color: blue"&gt;fun &lt;/span&gt;k &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;c (&lt;span style="color: blue"&gt;fun &lt;/span&gt;a &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;f a k))
    &lt;span style="color: blue"&gt;member &lt;/span&gt;this.Delay(f) = f()

&lt;span style="color: blue"&gt;let &lt;/span&gt;cont = ContBuilder()&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;insertM x t =
    &lt;span style="color: blue"&gt;let rec &lt;/span&gt;insertRecM x t =
        &lt;span style="color: blue"&gt;match &lt;/span&gt;t &lt;span style="color: blue"&gt;with
        &lt;/span&gt;| Empty &lt;span style="color: blue"&gt;-&amp;gt;  &lt;/span&gt;cont { &lt;span style="color: blue"&gt;return &lt;/span&gt;Elem(empty,x,empty) }
        | Elem (left,e,right) &lt;span style="color: blue"&gt;when &lt;/span&gt;x &amp;lt; e &lt;span style="color: blue"&gt;-&amp;gt; 
            &lt;/span&gt;cont {  &lt;span style="color: blue"&gt;let! &lt;/span&gt;t' = insertRecM x left
                    &lt;span style="color: blue"&gt;return &lt;/span&gt;Elem(t',e,right) }
        | Elem (left,e,right) &lt;span style="color: blue"&gt;when &lt;/span&gt;x &amp;gt; e &lt;span style="color: blue"&gt;-&amp;gt; 
            &lt;/span&gt;cont {  &lt;span style="color: blue"&gt;let! &lt;/span&gt;t' = insertRecM x right
                    &lt;span style="color: blue"&gt;return &lt;/span&gt;Elem(left,e,t') }
        | Elem _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;cont { &lt;span style="color: blue"&gt;return &lt;/span&gt;t }
    insertRecM x t id&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;h5&gt;Using call with current continuation&lt;/h5&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;callCC (f:('a &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Cont&amp;lt;'b,'r&amp;gt;) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Cont&amp;lt;'a,'r&amp;gt;) : Cont&amp;lt;'a,'r&amp;gt; = &lt;span style="color: blue"&gt;fun &lt;/span&gt;k &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;f (&lt;span style="color: blue"&gt;fun &lt;/span&gt;a _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;k a) k&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;insertCallCC x t =
    callCC (&lt;span style="color: blue"&gt;fun &lt;/span&gt;alreadyExists &lt;span style="color: blue"&gt;-&amp;gt;
        let rec &lt;/span&gt;insertRecCallCC x t =
            &lt;span style="color: blue"&gt;match &lt;/span&gt;t &lt;span style="color: blue"&gt;with
            &lt;/span&gt;| Empty &lt;span style="color: blue"&gt;-&amp;gt;  &lt;/span&gt;cont { &lt;span style="color: blue"&gt;return &lt;/span&gt;Elem(empty,x,empty) }
            | Elem (left,e,right) &lt;span style="color: blue"&gt;when &lt;/span&gt;x &amp;lt; e &lt;span style="color: blue"&gt;-&amp;gt; 
                &lt;/span&gt;cont {  &lt;span style="color: blue"&gt;let! &lt;/span&gt;t' = insertRecCallCC x left
                        &lt;span style="color: blue"&gt;return &lt;/span&gt;Elem(t',e,right) }
            | Elem (left,e,right) &lt;span style="color: blue"&gt;when &lt;/span&gt;x &amp;gt; e &lt;span style="color: blue"&gt;-&amp;gt; 
                &lt;/span&gt;cont {  &lt;span style="color: blue"&gt;let! &lt;/span&gt;t' = insertRecCallCC x right
                        &lt;span style="color: blue"&gt;return &lt;/span&gt;Elem(left,e,t') }
            | Elem _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;alreadyExists t
        insertRecCallCC x t
    ) id&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Please note that the complexity of the last implementation is not obfuscation – it avoids recreating nodes on the path to an already existing element (exercise 2.3 actually asks to do it using exceptions, which works just as well).&lt;/p&gt;
&lt;span class="sbmLink"&gt;
  &lt;table cellspacing="1" cellpadding="1"&gt;&lt;tbody&gt;
      &lt;tr&gt;
        &lt;td class="sbmText"&gt;Share this post : &lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to Technet!" href="http://social.technet.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2009/06/fun-with-data-structures-continuations.html&amp;amp;ttl=Fun with data structures, continuations and call/cc" target="_blank"&gt;&lt;img src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" border="0" /&gt;Technet!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to del.icio.us" href="http://del.icio.us/post?url=http://fortysix-and-two.blogspot.com/2009/06/fun-with-data-structures-continuations.html&amp;amp;;title=Fun with data structures, continuations and call/cc" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" border="0" /&gt;del.icio.us it!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&amp;amp;address=http://fortysix-and-two.blogspot.com/2009/06/fun-with-data-structures-continuations.html&amp;amp;title=Fun with data structures, continuations and call/cc" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" border="0" /&gt;del.iri.ous!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to digg" href="http://digg.com/submit?phase=2&amp;amp;url=http://fortysix-and-two.blogspot.com/2009/06/fun-with-data-structures-continuations.html&amp;amp;title=Fun with data structures, continuations and call/cc" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" border="0" /&gt;digg it!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to dotnetkicks" href="http://www.dotnetkicks.com/kick/?url=http://fortysix-and-two.blogspot.com/2009/06/fun-with-data-structures-continuations.html&amp;amp;title=Fun with data structures, continuations and call/cc" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" border="0" /&gt;dotnetkicks it!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to reddit!" href="http://reddit.com/submit?url=http://fortysix-and-two.blogspot.com/2009/06/fun-with-data-structures-continuations.html&amp;amp;title=Fun with data structures, continuations and call/cc" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" border="0" /&gt;reddit!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to technorati!" href="http://technorati.com/faves/?add=http://fortysix-and-two.blogspot.com/2009/06/fun-with-data-structures-continuations.html&amp;amp;title=Fun with data structures, continuations and call/cc" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" border="0" /&gt;technorati!&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;&lt;/table&gt;
&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-3158212243224204490?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/3158212243224204490/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=3158212243224204490" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/3158212243224204490" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/3158212243224204490" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/06/fun-with-data-structures-continuations.html" title="Fun with data structures, continuations and call/cc" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-6519181874879423769</id><published>2009-06-13T07:25:00.000-07:00</published><updated>2009-06-14T02:17:25.555-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="quotations" /><category scheme="http://www.blogger.com/atom/ns#" term="howto" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title type="text">Traversing and transforming F# quotations: A guided tour</title><content type="html">&lt;p&gt;There seems to be some lack of information about quotations – most is either short, a specific example, or is a bit outdated. The most comprehensive example is probably &lt;a href="http://tomasp.net/"&gt;Tomáš Petříček&lt;/a&gt;’s Quotations Visualizer in the&amp;#160; &lt;a href="http://www.codeplex.com/fsharpsamples"&gt;F# samples&lt;/a&gt;. His site is also one of the better resources about quotations that I’ve found. Another one with some recent activity is &lt;a href="http://www.russiantequila.com/wordpress/"&gt;Alex Pedenko&lt;/a&gt;’s blog. Furthermore, even the otherwise excellent &lt;a title="Expert F#" href="http://www.apress.com/book/view/1590598504" target="_blank"&gt;Expert F#&lt;/a&gt; book has little to say about it, and predates the major changes that were made in the September CTP.&lt;/p&gt;  &lt;p&gt;Here I’ll focus on the important &lt;em&gt;general&lt;/em&gt; patterns of using quotations. That is, I’m going to show how to traverse and transform quotations, independent of any specific example. I’m going to focus more on the API and programming aspects, than on introductory concepts, so this assumes some intermediate-level knowledge of F#. Basic knowledge about quotations doesn’t hurt either, as I‘ll make explanations terse.&lt;/p&gt;  &lt;p&gt;Either way, this post represents some knowledge that took me a while to figure out on my own, piecing together scattered sources.&lt;/p&gt;  &lt;p&gt;I would like to point out that once you get over the learning curve, working with quotations is actually enjoyable. I’ve been refraining from using them because I was put off by some bad experiences with System.Reflection (I think System.Reflection truly sucks as an API) and because I felt that to do anything useful, you’d almost be forced to support (i.e. at the very least provide default implementations of) every single construct in &lt;a title="F# homepage" href="http://research.microsoft.com/fsharp/fsharp.aspx" target="_blank"&gt;F#&lt;/a&gt;. It turns out that the quotations API is very enjoyable to work with and that there are built-in means to start small and focus on the things that are interesting to you.&lt;/p&gt;  &lt;h4&gt;The basics&lt;/h4&gt;  &lt;p&gt;In short, a quotation is metadata that represents the code of a particular function or code snippet, that gets compiled into the dll (along with the actual executable code, in some cases) by the F# compiler. To those of you who are familiar with LINQ Expression trees, it’s the same concept only F#’s quotations cover the entire reach of the F# language.&lt;/p&gt;  &lt;p&gt;There are three ways to obtain a quotation:&lt;/p&gt;  &lt;p&gt;1) Use the &amp;lt;@&amp;#160; @&amp;gt; operation around a code snippet to get a typed quotation of type Expr&amp;lt;’a&amp;gt;, where ‘a is the type of the actual value you put into the snippet. The Expr “wrapper” essentially indicates that we’re not dealing with an actual value of type ‘a, but instead with a reified representation of that value – the quotation:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;typedExpr = &amp;lt;@ 1 + 5 @&amp;gt;

&lt;span style="color: blue"&gt;let &lt;/span&gt;typedExpr2 = &amp;lt;@ &lt;span style="color: blue"&gt;fun &lt;/span&gt;i &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;i + 5 @&amp;gt;&lt;/pre&gt;

&lt;p&gt;Sending these to FSI gives:&lt;/p&gt;

&lt;pre class="code"&gt;val typedExpr : Quotations.Expr&amp;lt;int&amp;gt; =
  Call (None, Int32 op_Addition[Int32,Int32,Int32](Int32, Int32),
      [Value (1), Value (5)])
val typedExpr2 : Quotations.Expr&amp;lt;(int -&amp;gt; int)&amp;gt; =
  Lambda (i,
        Call (None, Int32 op_Addition[Int32,Int32,Int32](Int32, Int32),
              [i, Value (5)]))&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;First notice the types: the first is Expr&amp;lt;int&amp;gt; because 1 + 5 of course is an int value. The second example illustrates a function value, of type Expr&amp;lt;int-&amp;gt;int&amp;gt;.&lt;/p&gt;

&lt;p&gt;FSI has printed the values of the quotations: a representation of the code! In fact, as we’ll soon see, the Expr type is nothing more than a discriminated union with one case for each possible language construct in F# (it’s not actually a discriminated union under the covers, but that’s how it’s abstracted, and the abstraction is very clean. It doesn’t hurt to think about it that way.)&lt;/p&gt;

&lt;p&gt;2) Use the &amp;lt;@@&amp;#160; @@&amp;gt; operator around a code snippet to get an untyped quotation, of type Expr. Expr&amp;lt;’a&amp;gt; is a subtype of Expr, and every Expr&amp;lt;’a&amp;gt; can be converted to an Expr by calling .Raw:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;untypedExpr = &amp;lt;@@ 1 + 5 @@&amp;gt;

&lt;span style="color: blue"&gt;let &lt;/span&gt;untypedExpr2 = &amp;lt;@@ &lt;span style="color: blue"&gt;fun &lt;/span&gt;i &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;i + 5 @@&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Sending to FSI gives:&lt;/p&gt;

&lt;pre class="code"&gt;val untypedExpr : Quotations.Expr =
  Call (None, Int32 op_Addition[Int32,Int32,Int32](Int32, Int32),
      [Value (1), Value (5)])
val untypedExpr2 : Quotations.Expr =
  Lambda (i,
        Call (None, Int32 op_Addition[Int32,Int32,Int32](Int32, Int32),
              [i, Value (5)]))&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Pretty much exactly the same information, except for the type. For library writers, the Expr type does all the heavy lifting of inspecting and transforming quotations: since in a library you almost always want to write some code for any quotation, you cannot write this code in a generic way with typed quotations. &lt;/p&gt;

&lt;p&gt;3) Using the ReflectedDefinition attribute on a top level function gives you the best of both worlds: the function can be called and executed as normal, but it can also be inspected as a quotation:&lt;/p&gt;

&lt;pre class="code"&gt;[&amp;lt;ReflectedDefinitionAttribute&amp;gt;]
&lt;span style="color: blue"&gt;let &lt;/span&gt;quotation i = i + 5&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Based on a MethodInfo, the Expression.TryGetReflectedDefinition method allows you to get to the Expr associated with the function. The necessary metadata is actually marshaled into the dll when this function is compiled.&lt;/p&gt;

&lt;h4&gt;The Microsoft.FSharp.Quotations namespace&lt;/h4&gt;

&lt;p&gt;This namespace in the FSharp core libraries contains three modules and three types. The types are Expr, Expr&amp;lt;’a&amp;gt; and Var. The first two we’ve discussed already, the third one is just the representation of a variable.&lt;/p&gt;

&lt;p&gt;The meat of quotations processing is in the module Quotations.Patterns and the static methods on Expr. If you compare these two, you’ll notice that for every active pattern in the Patterns modules, there is a static method on Expr. For example, you have Patters.Call(…) and Expr.Call(…), with equivalent signatures. This is no coincidence: the Patterns module contains all the patterns you’ll need to &lt;strong&gt;deconstruct&lt;/strong&gt; a quotation expression. Together, these patterns can traverse any F# abstract syntax tree. It contains 32 active patterns (that’s a lot, but don’t despair yet: it gets better. ). &lt;/p&gt;

&lt;p&gt;Its dual, the static methods on the Expr type, &lt;strong&gt;construct&lt;/strong&gt; quotation expressions programmatically.&lt;/p&gt;

&lt;p&gt;If you know F#, it shouldn’t be too hard to figure out what the arguments mean. For example:&lt;/p&gt;

&lt;p&gt;Expr.Call : obj:Expr * methodInfo:MethodInfo * arguments:Expr list –&amp;gt; Expr&lt;/p&gt;

&lt;p&gt;constructs an expression that represents a method call (defined by a methodInfo) on a target object (i.e. it’s an instance method), taking the given&amp;#160; arguments. Conversely,&lt;/p&gt;

&lt;p&gt;( |Call|_| ) : Expr -&amp;gt; (Expr option * MethodInfo * Expr list) option&lt;/p&gt;

&lt;p&gt;is an active pattern that matches a method call, with an (optional) target, methodinfo and a list of arguments. &lt;/p&gt;

&lt;p&gt;This duality makes it fairly easy to get started with constructing and deconstructing quotations. Try to make some quotations and print them using fsi – it will give you a good idea of what code constructs the patterns represent. Alternatively, use the quotation visualizer mentioned above.&lt;/p&gt;

&lt;p&gt;Another module, Quotations.DerivedPatterns, contains additional active patterns that are not needed in the strict sense, but that represent some common use cases for deconstructing a quotation. An example is&lt;/p&gt;

&lt;p&gt;( |SpecificCall|_| ) : Expr -&amp;gt; (Expr -&amp;gt; (Type list * Expr list) option)&lt;/p&gt;

&lt;p&gt;which is a variant of Call that takes an expression and matches if the quotation is the given method or function call. The beauty of this particular active pattern is that you can use quotations to match on the given quotation:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;recognizePlus quotation =
    &lt;span style="color: blue"&gt;match &lt;/span&gt;quotation &lt;span style="color: blue"&gt;with
    &lt;/span&gt;| SpecificCall &amp;lt;@ (+) @&amp;gt; (types,exprs) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;Plus! types=%A  exprs=%A&amp;quot; &lt;/span&gt;types exprs
    | _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;something else&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;pre class="code"&gt;&amp;gt; recognizePlus &amp;lt;@ 1 + 2 @&amp;gt;;;
Plus! types=[System.Int32; System.Int32; System.Int32]  exprs=[Value (1); Value (2)]&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;h4&gt;&lt;/h4&gt;

&lt;h4&gt;Come on, this is still a lot of work, isn’t it?&lt;/h4&gt;

&lt;p&gt;That last example has one major shortcoming, which will hit you pretty hard when you’re trying to do anything useful with quotations. Even when you’re only interested in one particular kind of node (say, you’re interested in doing something with all (+) calls), you still have to walk the whole expression tree in order to be sure that you’ve seen all the method calls. Consider:&lt;/p&gt;

&lt;pre class="code"&gt;&amp;gt; recognizePlus &amp;lt;@ 1 * (2 + 3) @&amp;gt;;;
something else&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Why? Because the tree looks like:&lt;/p&gt;

&lt;pre class="code"&gt;Call (None, Int32 op_Multiply[Int32,Int32,Int32](Int32, Int32),
      [Value (1),
       Call (None, Int32 op_Addition[Int32,Int32,Int32](Int32, Int32),
             [Value (2), Value (3)])])&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;so we’re calling multiply first – and our function doesn’t do anything with that. In order to find all plus calls, we need to look through the whole tree recursively – including the multiply call’s children. But doesn’t that mean that we’ll have to rewrite our recognizePlus function to incorporate a match on &lt;em&gt;all of the 32&lt;/em&gt; active patterns in Quotations.Patterns (or at least those that return child expressions, which is pretty much all of them) just to be able to traverse the whole expression tree looking for a plus call?&lt;/p&gt;

&lt;p&gt;Luckily, no. This is were the third module in the Quotations namespace comes in.&lt;/p&gt;

&lt;h4&gt;The secret sauce: Quotations.ExprShape&lt;/h4&gt;

&lt;p&gt;This module is really the workhorse of pretty much anything you’ll do with quotations. Now, I believe this will come as a surprise to most people – in fact, it took me a bit of luck (when I saw it being used in passing, in a post on hubfs) to really understand what this module was all about. It was one of those moments for which a beautiful German word exists: &lt;a href="http://en.wikipedia.org/wiki/Insight"&gt;Aha-Erlebnis&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;This module’s mystery is in no small part thanks to its“terse” documentation. In fact, it’s so short I’ll reproduce it completely here:&lt;/p&gt;

&lt;table cellspacing="0" cellpadding="2" width="1096" border="0"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td valign="top" width="479"&gt;val RebuildShapeCombination : obj * Expr list -&amp;gt; Expr&lt;/td&gt;

      &lt;td valign="top" width="615"&gt;Re-build combination expressions. The first parameter should be an object returned by the ShapeCombination case of the active pattern in this module.&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="479"&gt;
        &lt;p&gt;val ( |ShapeVar|ShapeLambda|ShapeCombination| ) : 
          &lt;br /&gt;&amp;#160; Expr -&amp;gt; Choice&amp;lt;Var,(Var * Expr),(obj * Expr list)&amp;gt;&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="615"&gt;An active pattern that performs a complete decomposition viewing the expression tree as a binding structure.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;First, look at the active pattern. The key thing is that this active pattern is &lt;em&gt;complete: &lt;/em&gt;every quotation will match with one of the three cases of the active pattern: either it is a variable (ShapeVar), a lambda (ShapeLambda)&amp;#160; or a “combination” (ShapeCombination). So, we now have a general and complete decomposition of any quotation, and it is short:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;workhorse quotation =
    &lt;span style="color: blue"&gt;match &lt;/span&gt;quotation &lt;span style="color: blue"&gt;with
    &lt;/span&gt;| ShapeVar v &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;()
    | ShapeLambda (v,expr) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;()
    | ShapeCombination (o, exprs) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;()&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Notice if you paste this in an .fs file that the compiler does not complain about any missing match cases, reinforcing my point. So, now we can do this recursively, which gives us:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;traverse quotation =
    &lt;span style="color: blue"&gt;match &lt;/span&gt;quotation &lt;span style="color: blue"&gt;with
    &lt;/span&gt;| ShapeVar v &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;()
    | ShapeLambda (v,expr) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;traverse expr
    | ShapeCombination (o, exprs) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;List.map traverse exprs |&amp;gt; ignore&lt;/pre&gt;

&lt;p&gt;Here’s the beauty: this simple function traverses &lt;em&gt;all &lt;/em&gt;the expressions and sub-expressions in &lt;em&gt;any&lt;/em&gt; quotation. You don’t have to deal with all 32 cases in order to do something with one node. This function should be the basis of all your work with traversing quotations: anything you want to do, as far as inspecting the tree goes, can be built on top of this simple structure. Let’s revisit our earlier example:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;recognizePlus' quotation =
    &lt;span style="color: blue"&gt;match &lt;/span&gt;quotation &lt;span style="color: blue"&gt;with
    &lt;/span&gt;| SpecificCall &amp;lt;@ (+) @&amp;gt; (types,exprs) &lt;span style="color: blue"&gt;-&amp;gt; 
        &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;Plus! types=%A  exprs=%A&amp;quot; &lt;/span&gt;types exprs
        List.map recognizePlus' exprs |&amp;gt; ignore
    | ShapeVar v &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;()
    | ShapeLambda (v,expr) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;recognizePlus' expr
    | ShapeCombination (o, exprs) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;List.map recognizePlus' exprs |&amp;gt; ignore&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Let’s run this on our failing example of earlier:&lt;/p&gt;

&lt;pre class="code"&gt;&amp;gt; recognizePlus' &amp;lt;@ 1 * (2 + 3) @&amp;gt;;;
Plus! types=[System.Int32; System.Int32; System.Int32]  exprs=[Value (2); Value (3)]&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;It sure found the plus now. 

&lt;h4&gt;Transforming quotations&lt;/h4&gt;

&lt;p&gt;So far, we’ve just been inspecting the quotation. Now let’s actually do something with it. Again, the ExprShape module will be a big win: the workhorse here is the ShapeCombination and RebuildShapeCombination duality.&lt;/p&gt;

&lt;p&gt;You might have noticed the o parameter in the ShapeCombination; this is an opaque marker that stores how the sub-expressions in a shape combination can be put back together , i.e. whether it is a function call, a let binding, or anything else that has child expressions. This is were the function RebuildShapeCombination comes into play: given an o marker and the right number and type of child expressions, it can put an expression deconstructed by ShapeCombination back together . So, whereas above we wrote a general traversal function for quotations, a general transformation function looks like:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;transform quotation =
    &lt;span style="color: blue"&gt;match &lt;/span&gt;quotation &lt;span style="color: blue"&gt;with
    &lt;/span&gt;| ShapeVar v &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Expr.Var v
    | ShapeLambda (v,expr) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Expr.Lambda (v,transform expr)
    | ShapeCombination (o, exprs) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;RebuildShapeCombination (o,List.map transform exprs)&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;This function takes any quotation and transforms it into itself, visiting, deconstructing and reconstructing every node in the expression tree along the way.&lt;/p&gt;

&lt;p&gt;If you’re familiar with a &lt;a href="http://en.wikipedia.org/wiki/Zipper_(data_structure)"&gt;zipper&lt;/a&gt; data structure, this reminds me of it: the active patterns “open the zipper” and the RebuildShapeCombination function “closes the zipper”. (Actually, I’m not sure that the sub-expressions get reused or are made anew, but it seemed familiar anyway.) &lt;/p&gt;

&lt;p&gt;So, let’s do some transformation: let’s replace all calls to (+) with calls to (-). (Maniacal laugh and organ playing):&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;evilTransform quotation =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;minus l r = &amp;lt;@@ %%l - %%r @@&amp;gt;
    &lt;span style="color: blue"&gt;match &lt;/span&gt;quotation &lt;span style="color: blue"&gt;with
    &lt;/span&gt;| SpecificCall &amp;lt;@ (+) @&amp;gt; (types,l::r::[]) &lt;span style="color: blue"&gt;-&amp;gt; 
        &lt;/span&gt;minus (evilTransform l) (evilTransform r)
    | ShapeVar v &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Expr.Var v
    | ShapeLambda (v,expr) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Expr.Lambda (v,evilTransform expr)
    | ShapeCombination (o, exprs) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;RebuildShapeCombination (o,List.map evilTransform exprs)&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Ignoring the specifics of the actual transformation, which I’ll get to in a moment, notice that the structure of the transformation is exactly the same as above, except now we’ve added one pattern to deal with the case we’re interested in: a call to addition.&amp;#160; Essentially, this is saying: do something special for addition, and just traverse the tree, leaving it unchanged, for all the rest.&lt;/p&gt;

&lt;h4&gt;Splicing&lt;/h4&gt;

&lt;p&gt;Now, I know I said earlier that the Expr.Call static method is the dual of the Call active pattern, so you’d expect that I would have used that in the result of the SpecificCall match above. I could have done that, but instead I chose to demonstrate another useful technique for constructing expressions: splicing, denoted by the % or %% operator, for typed and untyped splicing respectively. All this operator does is insert an expression in a certain place (or places) into a quotation. So the minus function constructs a quotation that represents the subtraction of two given expressions (this doesn’t always make sense – in that case we’ll get a runtime exception with untyped quotations). Splicing is a very readable and versatile way of constructing expressions, because you can actually write your expressions in F# instead of using Expr.Call and friends.&lt;/p&gt;

&lt;h4&gt;The proof of the pudding&lt;/h4&gt;

&lt;p&gt;In the F# powerpack, there are some useful (but somewhat experimental) functions to actually compile and evaluate any F# quotation. The process is somewhat convoluted: the quotation trees are first translated to .NET Expressions, and then that API is used to compile them. This comes with a significant performance hit: code compiled using that route can be a factor of 5 slower. So don’t use it for optimization. So far, I haven’t run into any limitations yet, and it’s a nice way to check whether everything works:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;before = &amp;lt;@ 1 + 2 * 3 + 5 @&amp;gt;
&lt;span style="color: blue"&gt;let &lt;/span&gt;after = evilTransform &amp;lt;@ 1 + 2 * 3 + 5 @&amp;gt;
printfn &lt;span style="color: maroon"&gt;&amp;quot;%A&amp;quot; &lt;/span&gt;&amp;lt;| before.EvalUntyped()
printfn &lt;span style="color: maroon"&gt;&amp;quot;%A&amp;quot; &lt;/span&gt;&amp;lt;| after.EvalUntyped()&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Shows:&lt;/p&gt;

&lt;pre class="code"&gt;12
-10

val evilTransform : Expr -&amp;gt; Expr
val before : Expr&amp;lt;int&amp;gt; =
  Call (None, Int32 op_Addition[Int32,Int32,Int32](Int32, Int32),
      [Call (None, Int32 op_Addition[Int32,Int32,Int32](Int32, Int32),
             [Value (1),
              Call (None, Int32 op_Multiply[Int32,Int32,Int32](Int32, Int32),
                    [Value (2), Value (3)])]), Value (5)])
val after : Expr =
  Call (None, Int32 op_Subtraction[Int32,Int32,Int32](Int32, Int32),
      [Call (None, Int32 op_Subtraction[Int32,Int32,Int32](Int32, Int32),
             [Value (1),
              Call (None, Int32 op_Multiply[Int32,Int32,Int32](Int32, Int32),
                    [Value (2), Value (3)])]), Value (5)])&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Pretty cool, and it opens up all kinds of interesting possibilities. For example, you can write a lazy transformer, which inserts lazy and force in the appropriate places to simulate call-by-need semantics in F#. You can add side-effects to print the result of each call as it is evaluated. Or you can transform the expression in something completely different – SQL, PHP, FPGA instructions, whatever you want.&lt;/p&gt;

&lt;h3&gt;Conclusions&lt;/h3&gt;

&lt;p&gt;The three main things you should know about the quotations API:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Quotations.Expr and Quotations.Patterns are each other’s dual: they are used for constructing and deconstructing Expr types respectively; &lt;/li&gt;

  &lt;li&gt;Quotations.ExprShape contains the workhorse of any quotations-using implementation: a zipper-like pattern for traversing and transforming any quotation in a straightforward way; &lt;/li&gt;

  &lt;li&gt;Splicing is used to effectively and readably construct parameterized expressions as an alternative to Expr.Whatever calls. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Like I said before, I think the API strikes an excellent balance between simplicity and abstraction. F#’s features come together nicely to provide a clean development experience. I was somewhat afraid of quotations before, because I had an image in my mind that it would be messy, lots of work, and lots of special cases. Turns out it isn’t, and I hope this post will do its part in getting some more attention to this aspect of F#.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://cid-f6a45280389d5d06.skydrive.live.com/self.aspx/Public/QuotBlog.fs"&gt;Download the example .fs file&lt;/a&gt;. Don’t forget to add references to FSharp.PowerPack and FSharp.PowerPack.Linq, if you want to run the dynamic compilation examples.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:6dbedb1d-294c-4505-9198-520d65a0c422" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati: &lt;a href="http://technorati.com/tags/F%23+quotations" rel="tag"&gt;F# quotations&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;
&lt;span class="sbmLink"&gt;&lt;span class="sbmLink"&gt;
    &lt;table cellspacing="1" cellpadding="1"&gt;&lt;tbody&gt;
        &lt;tr&gt;
          &lt;td class="sbmText"&gt;Share this post : &lt;/td&gt;

          &lt;td&gt;&lt;a title="Post it to Technet!" href="http://social.technet.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2009/06/traversing-and-transforming-f.html&amp;amp;ttl=Traversing and transforming quotations: A guided tour" target="_blank"&gt;&lt;img src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" border="0" /&gt;Technet!&lt;/a&gt;&lt;/td&gt;

          &lt;td&gt;&lt;a title="Post it to del.icio.us" href="http://del.icio.us/post?url=http://fortysix-and-two.blogspot.com/2009/06/traversing-and-transforming-f.html&amp;amp;;title=Traversing and transforming quotations: A guided tour" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" border="0" /&gt;del.icio.us it!&lt;/a&gt;&lt;/td&gt;

          &lt;td&gt;&lt;a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&amp;amp;address=http://fortysix-and-two.blogspot.com/2009/06/traversing-and-transforming-f.html&amp;amp;title=Traversing and transforming quotations: A guided tour" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" border="0" /&gt;del.iri.ous!&lt;/a&gt;&lt;/td&gt;

          &lt;td&gt;&lt;a title="Post it to digg" href="http://digg.com/submit?phase=2&amp;amp;url=http://fortysix-and-two.blogspot.com/2009/06/traversing-and-transforming-f.html&amp;amp;title=Traversing and transforming quotations: A guided tour" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" border="0" /&gt;digg it!&lt;/a&gt;&lt;/td&gt;

          &lt;td&gt;&lt;a title="Post it to dotnetkicks" href="http://www.dotnetkicks.com/kick/?url=http://fortysix-and-two.blogspot.com/2009/06/traversing-and-transforming-f.html&amp;amp;title=Traversing and transforming quotations: A guided tour" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" border="0" /&gt;dotnetkicks it!&lt;/a&gt;&lt;/td&gt;

          &lt;td&gt;&lt;a title="Post it to reddit!" href="http://reddit.com/submit?url=http://fortysix-and-two.blogspot.com/2009/06/traversing-and-transforming-f.html&amp;amp;title=Traversing and transforming quotations: A guided tour" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" border="0" /&gt;reddit!&lt;/a&gt;&lt;/td&gt;

          &lt;td&gt;&lt;a title="Post it to technorati!" href="http://technorati.com/faves/?add=http://fortysix-and-two.blogspot.com/2009/06/traversing-and-transforming-f.html&amp;amp;title=Traversing and transforming quotations: A guided tour" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" border="0" /&gt;technorati!&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;&lt;/table&gt;
  &lt;/span&gt;&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-6519181874879423769?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/6519181874879423769/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=6519181874879423769" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/6519181874879423769" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/6519181874879423769" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/06/traversing-and-transforming-f.html" title="Traversing and transforming F# quotations: A guided tour" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-7430979790558280803</id><published>2009-05-23T09:36:00.000-07:00</published><updated>2009-05-23T09:43:38.094-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fscheck" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title type="text">Announcing FsCheck 0.6.1</title><content type="html">&lt;p&gt;No functional changes, just an update as a result of the May CTP released by the &lt;a title="F# homepage" href="http://research.microsoft.com/fsharp/fsharp.aspx" target="_blank"&gt;F#&lt;/a&gt; team.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://fscheck.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=21777"&gt;Get it here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Change log:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Many name changes as a result of name changes in the F# API &lt;/li&gt;    &lt;li&gt;Used the new formatting API, which gets rid of a bunch of obsolete warnings &lt;/li&gt;    &lt;li&gt;Tried to solve issues resulting from changed initialization order &lt;/li&gt;    &lt;li&gt;Added a standalone version of the &lt;a href="http://www.codeplex.com/fscheck" target="_blank"&gt;FsCheck&lt;/a&gt; binary, to accommodate C#/VB users better&lt;/li&gt;    &lt;li&gt;Added a contributors file. Want your name in there? Then contribute ;)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Enjoy the new CTP!&lt;/p&gt; &lt;span class="sbmLink"&gt;   &lt;table cellspacing="1" cellpadding="1"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td class="sbmText"&gt;Share this post : &lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to Technet!" href="http://social.technet.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-061.html&amp;amp;ttl=Announcing FsCheck 0.6.1" target="_blank"&gt;&lt;img src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" border="0" /&gt;Technet!&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to del.icio.us" href="http://del.icio.us/post?url=http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-061.html&amp;amp;;title=Announcing FsCheck 0.6.1" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" border="0" /&gt;del.icio.us it!&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&amp;amp;address=http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-061.html&amp;amp;title=Announcing FsCheck 0.6.1" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" border="0" /&gt;del.iri.ous!&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to digg" href="http://digg.com/submit?phase=2&amp;amp;url=http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-061.html&amp;amp;title=Announcing FsCheck 0.6.1" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" border="0" /&gt;digg it!&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to dotnetkicks" href="http://www.dotnetkicks.com/kick/?url=http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-061.html&amp;amp;title=Announcing FsCheck 0.6.1" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" border="0" /&gt;dotnetkicks it!&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to reddit!" href="http://reddit.com/submit?url=http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-061.html&amp;amp;title=Announcing FsCheck 0.6.1" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" border="0" /&gt;reddit!&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to technorati!" href="http://technorati.com/faves/?add=http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-061.html&amp;amp;title=Announcing FsCheck 0.6.1" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" border="0" /&gt;technorati!&lt;/a&gt;&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-7430979790558280803?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/7430979790558280803/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=7430979790558280803" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/7430979790558280803" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/7430979790558280803" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-061.html" title="Announcing FsCheck 0.6.1" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-5500259037381034725</id><published>2009-05-12T13:50:00.001-07:00</published><updated>2009-05-12T13:52:48.102-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fscheck" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><category scheme="http://www.blogger.com/atom/ns#" term="fscheck case study" /><title type="text">How to test DSLs (and: FsChecking FsCheck)</title><content type="html">&lt;p&gt;There are two causes for this post. &lt;/p&gt;  &lt;p&gt;First, I’ve been watching videos from &lt;a href="http://www.langnetsymposium.com/2009/talks.aspx"&gt;Lang.NET&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/oslo/videos.aspx#dsl"&gt;DSL DevCon&lt;/a&gt;, so I’m in language-mode. It occurred to me that (domain specific) languages seem difficult to test using traditional unit tests: after all, the usage possibilities are far greater for a language than for, say, a typical user interface (maybe this means that typical user interfaces suck - you decide). The word “combinator library”, which are internal DSLs avant la lettre, says it all: the usage possibilities are combinatorial. Classic, example based unit testing thus becomes combinatorially expensive as well.&lt;/p&gt;  &lt;p&gt;Second, I’ve been saying in the last release announcement of &lt;a href="http://www.codeplex.com/fscheck" target="_blank"&gt;FsCheck&lt;/a&gt; that I wanted to write some FsChecks for FsCheck itself. So far, this effort is about 60% complete. As a sort of challenge, I want to check as much as possible from FsCheck &lt;em&gt;without any traditional example-based unit testing – &lt;/em&gt;in other words, I want to test FsCheck using only FsCheck (and maybe some &lt;a href="http://research.microsoft.com/en-us/projects/Pex/"&gt;Pex&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/nl-be/devlabs/dd491992(en-us).aspx"&gt;Code Contracts&lt;/a&gt; later on). &lt;/p&gt;  &lt;p&gt;FsCheck itself consists of basically two internal DSLs: one for &lt;a href="http://fscheck.codeplex.com/Wiki/View.aspx?title=Test%20Data%20Generators"&gt;constructing random value generators&lt;/a&gt; for whatever value it is your tests need, and one for &lt;a href="http://fscheck.codeplex.com/Wiki/View.aspx?title=Properties"&gt;constructing properties&lt;/a&gt;: basically assertions augmented with property combinators for adding labels, classifying generated values and such. It’s the latter DSL that I’m going to test, and draw some general conclusions that may apply to testing other DSLs or even general purpose languages as well.&lt;/p&gt;  &lt;p&gt;To see what we’re dealing with, here’s an example of using the property DSL:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_InsertCombined (x:int) xs = 
    ordered xs ==&amp;gt; (ordered (insert x xs))
        |&amp;gt; classify (ordered (x::xs)) &lt;span style="color: maroon"&gt;&amp;quot;at-head&amp;quot;
        &lt;/span&gt;|&amp;gt; classify (ordered (xs @ [x])) &lt;span style="color: maroon"&gt;&amp;quot;at-tail&amp;quot;
        &lt;/span&gt;|&amp;gt; collect (List.length xs)
quickCheck prop_InsertCombined&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;This property asserts that the insert function maintains the invariant that the list is ordered. The classify and collect property combinators are used to gather some information about the generated data. So in this test, there are three property combinators at work: implies (==&amp;gt;), classify and collect. Also, the arguments to the property (x and xs) are implicitly universally quantified using the forAll property combinator. These and more combinators in FsCheck can be combined an arbitrary ways, so testing this using example-based testing can be quite tedious. Can FsCheck do better?&lt;/p&gt;

&lt;h4&gt;The property DSL’s syntax tree&lt;/h4&gt;

&lt;p&gt;First, we’re going to need to generate an arbitrary property, i.e. an arbitrary combination of property combinators. To do that, I made a symbolic representation of the property language – a sort of abstract syntax tree of the language. It’s no secret that discriminated unions are great for this, and this case is not different:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;SymProp =  | Unit | Bool &lt;span style="color: blue"&gt;of &lt;/span&gt;bool | Exception
                | ForAll &lt;span style="color: blue"&gt;of &lt;/span&gt;int * SymProp
                | Implies &lt;span style="color: blue"&gt;of &lt;/span&gt;bool * SymProp
                | Classify &lt;span style="color: blue"&gt;of &lt;/span&gt;bool * string * SymProp
                | Collect &lt;span style="color: blue"&gt;of &lt;/span&gt;int * SymProp&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;So, a property can consist of, respectively:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A function that returns the unit value; &lt;/li&gt;

  &lt;li&gt;A function that returns a bool value; &lt;/li&gt;

  &lt;li&gt;A function that throws an exception; &lt;/li&gt;

  &lt;li&gt;A function that uses the implies combinator, which needs two arguments: a boolean condition and another property; &lt;/li&gt;

  &lt;li&gt;A function that classifies the generated values, which needs three arguments: a boolean condition, the name to classify with if the condition is true and another property; &lt;/li&gt;

  &lt;li&gt;A function that collects values, which takes two arguments: the value to collect, and another property. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that I’ve made some simplifications here: in fact forAll takes a generator that generates values of an arbitrary type – but since we’re not testing generators here, I’ve assumed the forAll always generates a constant int value. Also, collect would normally collect a (function of a) generated value, but it’s here constrained to collecting a constant int value.&lt;/p&gt;

&lt;p&gt;We can build an actual property from this symbolic representation:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec private &lt;/span&gt;toProperty prop =
        &lt;span style="color: blue"&gt;match &lt;/span&gt;prop &lt;span style="color: blue"&gt;with
        &lt;/span&gt;| Unit &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;property ()
        | Bool b &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;property b
        | Exception &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;property (&lt;span style="color: blue"&gt;lazy &lt;/span&gt;(raise &amp;lt;| InvalidOperationException()))
        | ForAll (i,prop) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;forAll (constant i) (&lt;span style="color: blue"&gt;fun &lt;/span&gt;i &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;toProperty prop)
        | Implies (b,prop) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;b ==&amp;gt; (toProperty prop)
        | Classify (b,stamp,prop) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;classify b stamp (toProperty prop)
        | Collect (i,prop) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;collect i (toProperty prop)&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;The simplifications are plainly visible here.&lt;/p&gt;

&lt;h4&gt;Defining the semantics of properties&lt;/h4&gt;

&lt;p&gt;Now, let’s define a specification of what a symbolic property means, in terms of what it should produce as Result. Result is an internal datatype used by FsCheck to track the result of one execution of a property. This is the gist of it:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Outcome = 
    | Timeout &lt;span style="color: blue"&gt;of &lt;/span&gt;int
    | Exception &lt;span style="color: blue"&gt;of &lt;/span&gt;exn
    | False
    | True
    | Rejected&lt;span style="color: green"&gt;

&lt;/span&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Result = 
    {   Outcome     : Outcome
        Stamp       : list&amp;lt;string&amp;gt;
        Labels      : Set&amp;lt;string&amp;gt;
        Arguments   : list&amp;lt;obj&amp;gt; }&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;So, a result tracks the outcome of a property: timed out, raised exception, returned false or true, or value rejected. The latter means a generated value did not pass the condition of an implies combinator. Furthermore, it also tracks the generated arguments, the stamps applied using classify and collect, as well as labels which are not tested here.&lt;/p&gt;

&lt;p&gt;And here is a formal, executable specification of a subset of the FsCheck property DSL:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec private &lt;/span&gt;determineResult prop =
        &lt;span style="color: blue"&gt;let &lt;/span&gt;addStamp stamp res = { res &lt;span style="color: blue"&gt;with &lt;/span&gt;Stamp = stamp :: res.Stamp }
        &lt;span style="color: blue"&gt;let &lt;/span&gt;addArgument arg res = { res &lt;span style="color: blue"&gt;with &lt;/span&gt;Arguments = arg :: res.Arguments }
        &lt;span style="color: blue"&gt;match &lt;/span&gt;prop &lt;span style="color: blue"&gt;with
        &lt;/span&gt;| Unit &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;succeeded
        | Bool &lt;span style="color: blue"&gt;true -&amp;gt; &lt;/span&gt;succeeded
        | Bool &lt;span style="color: blue"&gt;false -&amp;gt; &lt;/span&gt;failed
        | Exception  &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;exc &amp;lt;| InvalidOperationException()
        | ForAll (i,prop) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;determineResult prop |&amp;gt; addArgument i
        | Implies (&lt;span style="color: blue"&gt;true&lt;/span&gt;,prop) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;determineResult prop
        | Implies (&lt;span style="color: blue"&gt;false&lt;/span&gt;,_) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;rejected
        | Classify (&lt;span style="color: blue"&gt;true&lt;/span&gt;,stamp,prop) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;determineResult prop |&amp;gt; addStamp stamp
        | Classify (&lt;span style="color: blue"&gt;false&lt;/span&gt;,_,prop) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;determineResult prop
        | Collect (i,prop) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;determineResult prop |&amp;gt; addStamp (any_to_string i)&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;You can check this definition with the FsCheck documentation. For example, it shows that an assertion that returns unit or true is interpreted as succeeded, false as failed and so on. The succeeded function and friends are defined in FsCheck and just construct basic Result instances:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let private &lt;/span&gt;result =
  { Outcome     = Rejected
  ; Stamp       = []
  ; Labels       = Set.empty
  ; Arguments   = []
  }

&lt;span style="color: blue"&gt;let internal &lt;/span&gt;failed = { result &lt;span style="color: blue"&gt;with &lt;/span&gt;Outcome = False }&lt;/pre&gt;

&lt;h4&gt;The test&lt;/h4&gt;

&lt;p&gt;Armed with these functions, we can write our test:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;SymProperty (symprop:SymProp) = 
        &lt;span style="color: blue"&gt;let &lt;/span&gt;expected = determineResult symprop 
        &lt;span style="color: blue"&gt;let &lt;/span&gt;(MkRose (Common.Lazy actual,_)) = generate 1 (Random.newSeed()) (toProperty symprop) 
        areSame expected actual
        |&amp;gt; label (sprintf &lt;span style="color: maroon"&gt;&amp;quot;expected = %A - actual = %A&amp;quot; &lt;/span&gt;expected actual)
        |&amp;gt; collect symprop&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Ignore the specifics of the “actual” symbol definition – it executes an actual property and extracts the Result from it. The gist of the property is the comparison between the actual Result of the execution of the property (that was built from the symbolic property representation), and compare that with our expected semantics. Just to see what kind of properties we’re testing, I’ve also added a collect combinator, as well as a label to see what’s wrong if the test should fail. Thanks to FsCheck’s built-in discriminated union generator, running this gives:&lt;/p&gt;

&lt;pre&gt;Property.SymProperty-Ok, passed 100 tests.
22% Exception.
12% Unit.
6% Bool true.
6% Bool false.
4% Classify (false,&amp;quot;&amp;quot;,Unit).
2% Implies (false,Exception).
2% Classify (true,&amp;quot;&amp;quot;,Unit).
2% Classify (true,&amp;quot;&amp;quot;,Exception).
2% Classify (false,&amp;quot;&amp;quot;,Exception).
1% Implies (true,Exception).
1% Implies (true,Collect (2,Bool true)).
1% Implies (true,Collect (0,Unit)).
1% Implies (true,Collect (0,Collect (0,Bool false))).
(and so on)&lt;/pre&gt;

&lt;h4&gt;Generating more interesting properties&lt;/h4&gt;

&lt;p&gt;This leaves something to be desired: the depth of combinations isn’t very high, and almost half of the generated properties are the trivial bool, unit or exception cases. One way of increasing this depth is by increasing the size of the generator, but that didn’t work very well: it mostly increased the length of the generated strings, without increasing the depth too much. The reason is that three of the seven options are “leaf” nodes, where generation ends. So I wrote my own generator for the SymProp type:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec private &lt;/span&gt;symPropGen =
        &lt;span style="color: blue"&gt;let rec &lt;/span&gt;recGen size =
            &lt;span style="color: blue"&gt;match &lt;/span&gt;size &lt;span style="color: blue"&gt;with
            &lt;/span&gt;| 0 &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;oneof [constant Unit; liftGen (Bool) arbitrary; constant Exception]
            | n &lt;span style="color: blue"&gt;when &lt;/span&gt;n&amp;gt;0 &lt;span style="color: blue"&gt;-&amp;gt;
                let &lt;/span&gt;subProp = recGen (size/2)
                oneof   [ liftGen2 (curry ForAll) arbitrary (subProp)
                        ; liftGen2 (curry Implies) arbitrary (subProp)
                        ; liftGen2 (curry Collect) arbitrary (subProp)
                        ; liftGen3 (&lt;span style="color: blue"&gt;fun &lt;/span&gt;b s p &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Classify (b,s,p)) arbitrary arbitrary (subProp)]
            | _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;failwith &lt;span style="color: maroon"&gt;&amp;quot;symPropGen: size must be positive&amp;quot;
        &lt;/span&gt;sized recGen&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;If you’re somewhat familiar with FsCheck’s generator combinators, this shouldn’t be hard to read. The idea is that we only generate one of the leaf nodes if the size equals zero, and halve the size if we generate a “real” property combinator to ensure the generation ends at some point. Let’s change the property to incorporate this generator:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;Property = 
        forAllShrink symPropGen shrink (&lt;span style="color: blue"&gt;fun &lt;/span&gt;symprop &lt;span style="color: blue"&gt;-&amp;gt;
            let &lt;/span&gt;expected = determineResult symprop 
            &lt;span style="color: blue"&gt;let &lt;/span&gt;(MkRose (Common.Lazy actual,_)) = generate 1 (Random.newSeed()) (toProperty symprop) 
            areSame expected actual
            |&amp;gt; label (sprintf &lt;span style="color: maroon"&gt;&amp;quot;expected = %A - actual = %A&amp;quot; &lt;/span&gt;expected actual)
            |&amp;gt; collect (depth symprop)&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;I added a depth function that calculates the depth of the generated symbolic property (i.e. depth of Unit, Bool and Exception is zero, and the rest adds one to the depth of it’s subproperty). Running this gives:&lt;/p&gt;

&lt;pre&gt;Property.get_Property-Ok, passed 100 tests.
26% 5.
26% 4.
18% 3.
12% 2.
7% 6.
6% 0.
4% 1.&lt;/pre&gt;

&lt;p&gt;which shows that FsCheck is now generating more properties with greater depth (4-5), and trivial properties only 6% of the time.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;This post showed an approach for testing DSLs, combinator libraries or “language-oriented” programs, whatever you’d like to call it:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Write a symbolic representation of the abstract syntax tree of the language you want to test. This symbolic representation is used to abstract from details you don’t want to test, to define semantics of the language later on, and it to generate output for counter-examples that FsCheck may find. &lt;/li&gt;

  &lt;li&gt;Generate the actual representation in your compiler or interpreter from the symbolic representation. &lt;/li&gt;

  &lt;li&gt;Specify the semantics of the symbolic representation. &lt;/li&gt;

  &lt;li&gt;Rely on FsCheck’s built-in generators, or make your own generator to generate the symbolic representation. &lt;/li&gt;

  &lt;li&gt;Write an FsCheck property to compare the actual with the expected semantics. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach may even be usable for testing compilers of general purpose programming languages. The effort involved will be much larger, but it’s easy to start small. &lt;/p&gt;

&lt;p&gt;Want more of this? Also check out the Checks.fs file in the FsCheck distribution for a complete test of the FsCheck property language.&lt;/p&gt;
&lt;span class="sbmLink"&gt;
  &lt;table cellspacing="1" cellpadding="1"&gt;&lt;tbody&gt;
      &lt;tr&gt;
        &lt;td class="sbmText"&gt;Share this post : &lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to Technet!" href="http://social.technet.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2009/05/how-to-test-dsls-and-fschecking-fscheck.html&amp;amp;ttl=How to test DSLs" target="_blank"&gt;&lt;img src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" border="0" /&gt;Technet!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to del.icio.us" href="http://del.icio.us/post?url=http://fortysix-and-two.blogspot.com/2009/05/how-to-test-dsls-and-fschecking-fscheck.html&amp;amp;;title=How to test DSLs" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" border="0" /&gt;del.icio.us it!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&amp;amp;address=http://fortysix-and-two.blogspot.com/2009/05/how-to-test-dsls-and-fschecking-fscheck.html&amp;amp;title=How to test DSLs" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" border="0" /&gt;del.iri.ous!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to digg" href="http://digg.com/submit?phase=2&amp;amp;url=http://fortysix-and-two.blogspot.com/2009/05/how-to-test-dsls-and-fschecking-fscheck.html&amp;amp;title=How to test DSLs" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" border="0" /&gt;digg it!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to dotnetkicks" href="http://www.dotnetkicks.com/kick/?url=http://fortysix-and-two.blogspot.com/2009/05/how-to-test-dsls-and-fschecking-fscheck.html&amp;amp;title=How to test DSLs" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" border="0" /&gt;dotnetkicks it!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to reddit!" href="http://reddit.com/submit?url=http://fortysix-and-two.blogspot.com/2009/05/how-to-test-dsls-and-fschecking-fscheck.html&amp;amp;title=How to test DSLs" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" border="0" /&gt;reddit!&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to technorati!" href="http://technorati.com/faves/?add=http://fortysix-and-two.blogspot.com/2009/05/how-to-test-dsls-and-fschecking-fscheck.html&amp;amp;title=How to test DSLs" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" border="0" /&gt;technorati!&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;&lt;/table&gt;
&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-5500259037381034725?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/5500259037381034725/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=5500259037381034725" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/5500259037381034725" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/5500259037381034725" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/05/how-to-test-dsls-and-fschecking-fscheck.html" title="How to test DSLs (and: FsChecking FsCheck)" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-8031068609563061314</id><published>2009-05-12T13:17:00.000-07:00</published><updated>2009-05-12T13:21:09.919-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fscheck" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title type="text">Announcing FsCheck 0.6: Dot is the new pipe</title><content type="html">&lt;p&gt;It is about time to release a new version of &lt;a href="http://www.codeplex.com/fscheck" target="_blank"&gt;FsCheck&lt;/a&gt;, and &lt;a href="http://fscheck.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=21777"&gt;here&lt;/a&gt; it is.&lt;/p&gt; &lt;p&gt;What’s new in this release?&lt;/p&gt; &lt;ul&gt; &lt;li&gt; &lt;p&gt;A fluent interface for C# and VB&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;This is in prototype stage at the moment, and has some limitations with respect to the &lt;a title="F# homepage" href="http://research.microsoft.com/fsharp/fsharp.aspx" target="_blank"&gt;F#&lt;/a&gt; interface, but I would say it’s about 90% functional. An example of a property in C#:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;Spec&lt;/span&gt;.ForAny&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;, &lt;span style="color: blue"&gt;int&lt;/span&gt;[]&amp;gt;((x, xs) =&amp;gt; xs.Insert(x).IsOrdered())
                .When((x, xs) =&amp;gt; xs.IsOrdered())
                .Classify((x, xs) =&amp;gt; &lt;span style="color: blue"&gt;new int&lt;/span&gt;[] { x }.Concat(xs).IsOrdered(), &lt;span style="color: #a31515"&gt;"at-head"&lt;/span&gt;)
                .Classify((x, xs) =&amp;gt; xs.Concat(&lt;span style="color: blue"&gt;new int&lt;/span&gt;[] { x }).IsOrdered(), &lt;span style="color: #a31515"&gt;"at-tail"&lt;/span&gt;)
                .QuickCheck(&lt;span style="color: #a31515"&gt;"InsertClassify"&lt;/span&gt;);&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;This property is the equivalent of the following in F#:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_InsertClassify (x:int) xs = 
    ordered xs ==&amp;gt; (ordered (insert x xs))
    |&amp;gt; classify (ordered (x::xs)) &lt;span style="color: maroon"&gt;"at-head"
    &lt;/span&gt;|&amp;gt; classify (ordered (xs @ [x])) &lt;span style="color: maroon"&gt;"at-tail" 
&lt;/span&gt;quickCheck prop_InsertClassify&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;As you can see, it’s about the same amount of code, but because of the fluent interface I have to add a class for each number of type arguments - currently limited to three. Ideally, I’d like to &lt;em&gt;generate&lt;/em&gt; some code for classes up to six or nine, but for the moment it’s all copy-paste and you can only write properties with up to three parameters this way. For the rest, almost everything should be working: you can register generators, provide configuration, add shrinkers, and write generators using some combinators and LINQ:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;var &lt;/span&gt;gen = &lt;span style="color: blue"&gt;from &lt;/span&gt;x &lt;span style="color: blue"&gt;in &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Any&lt;/span&gt;.OfType&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt;()
          &lt;span style="color: blue"&gt;from &lt;/span&gt;y &lt;span style="color: blue"&gt;in &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Any&lt;/span&gt;.IntBetween(5, 10)
          &lt;span style="color: blue"&gt;where &lt;/span&gt;x &amp;gt; 5
          &lt;span style="color: blue"&gt;select new &lt;/span&gt;{ Fst = x, Snd = y };&lt;/pre&gt;
&lt;p&gt;Pretty neat.&lt;/p&gt;
&lt;p&gt;Incidentally, there is no C# code in FsCheck itself, and the fluent interface is all pure F# code. This was a good test to see how interoperable F# really is. Overall, the experience has been great, with just a few minor hiccups.&lt;/p&gt;
&lt;p&gt;I translated most of the F# examples from the documentation to C# as well, you can find those in the F# source distribution.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Possibility to replay a test run. FsCheck now displays the seed it used to start a test run when it fails. You can give this seed to a configuration parameter, so that FsCheck will repeat the run with exactly the same generated values:&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre class="code"&gt;check { quick &lt;span style="color: blue"&gt;with &lt;/span&gt;Name=&lt;span style="color: maroon"&gt;"Counter-replay"&lt;/span&gt;; Replay = Some &amp;lt;| Random.StdGen (395461793,1) } (asProperty spec)&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Various bug fixes and updates to xml docs.&lt;/p&gt;
&lt;li&gt;
&lt;p&gt;I’m making headway in testing FsCheck using FsCheck itself. It’s an interesting experience, and I have a blog post lined up about it.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;The C#/VB “mainstream” support is something that I hope to continue to improve – I also plan to add reflective object generators and &lt;a href="http://www.gallio.org/"&gt;Gallio&lt;/a&gt; integration, mainly as a means to get some more attention for FsCheck. It’s also an interesting exercise to compare approaches. So far, if you know F#, I’d stick with it, but you can see that LINQ is occasionally very elegant for defining generators.&lt;/p&gt;
&lt;p&gt;Happy FsChecking!&lt;/p&gt;&lt;span class="sbmLink"&gt;
&lt;table cellspacing="1" cellpadding="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class="sbmText"&gt;Share this post : &lt;/td&gt;
&lt;td&gt;&lt;a title="Post it to Technet!" href="http://social.technet.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-06-dot-is-new-pipe.html&amp;amp;ttl=Announcing FsCheck 0.6" target="_blank"&gt;&lt;img src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" border="0"&gt;Technet!&lt;/a&gt;
&lt;td&gt;&lt;a title="Post it to del.icio.us" href="http://del.icio.us/post?url=http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-06-dot-is-new-pipe.html&amp;amp;;title=Announcing FsCheck 0.6" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" border="0"&gt;del.icio.us it!&lt;/a&gt;
&lt;td&gt;&lt;a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&amp;amp;address=http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-06-dot-is-new-pipe.html&amp;amp;title=Announcing FsCheck 0.6" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" border="0"&gt;del.iri.ous!&lt;/a&gt;
&lt;td&gt;&lt;a title="Post it to digg" href="http://digg.com/submit?phase=2&amp;amp;url=http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-06-dot-is-new-pipe.html&amp;amp;title=Announcing FsCheck 0.6" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" border="0"&gt;digg it!&lt;/a&gt;
&lt;td&gt;&lt;a title="Post it to dotnetkicks" href="http://www.dotnetkicks.com/kick/?url=http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-06-dot-is-new-pipe.html&amp;amp;title=Announcing FsCheck 0.6" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" border="0"&gt;dotnetkicks it!&lt;/a&gt;
&lt;td&gt;&lt;a title="Post it to reddit!" href="http://reddit.com/submit?url=http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-06-dot-is-new-pipe.html&amp;amp;title=Announcing FsCheck 0.6" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" border="0"&gt;reddit!&lt;/a&gt;
&lt;td&gt;&lt;a title="Post it to technorati!" href="http://technorati.com/faves/?add=http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-06-dot-is-new-pipe.html&amp;amp;title=Announcing FsCheck 0.6" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" border="0"&gt;technorati!&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/span&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;pre class="code"&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-8031068609563061314?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/8031068609563061314/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=8031068609563061314" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/8031068609563061314" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/8031068609563061314" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-06-dot-is-new-pipe.html" title="Announcing FsCheck 0.6: Dot is the new pipe" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-1503614048149432705</id><published>2009-05-06T13:03:00.000-07:00</published><updated>2009-05-06T13:12:55.692-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="rant" /><title type="text">Tests are not specifications</title><content type="html">&lt;p&gt;There seems to be some consensus in the TDD and BDD community that the tests (or behaviors) for a given software system constitute an (executable) specification of the system.&lt;/p&gt;  &lt;p&gt;Wrong.&lt;/p&gt;  &lt;p&gt;A specification is an &lt;em&gt;unambiguous&lt;/em&gt; and &lt;em&gt;complete &lt;/em&gt;description of a system or subsystem. Or at least it should be a heroic attempt.&lt;/p&gt;  &lt;p&gt;A test, whether written as a traditional&amp;#160; unit test, or as an executable scenario in BDD is neither unambiguous nor complete. Worse, it’s not even&lt;em&gt; trying.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;A test is almost always written as one specific &lt;em&gt;example &lt;/em&gt;of how a subsystem should behave. An implementation that can fail on other examples will pass the test, and so still fulfill the non-specification. Furthermore, there are many implementations with wildly differing behavior that can pass the test.Doesn't sound like a specification to me, or at least not a good one.&lt;/p&gt;  &lt;p&gt;In fact, if TDD/BDD advocates would &lt;em&gt;really &lt;/em&gt;follow their advice to program no more than what the tests test, then given the following test:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Assert.Equal (Reverse [1,2,3] , [3,2,1])&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;they should implement the pseudo function:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Reverse list = [3,2,1]&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Compare with what FsCheck's properties look like (again, in pseudo-code):&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Reverse [x] = [x] &lt;/p&gt;    &lt;p&gt;Reverse (x::xs) = Reverse xs @ [x]&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;That's what I call a specification: unambiguous, and complete. So TDD talks the talk, but does not walk the walk.&lt;/p&gt;  &lt;p&gt;Before you start commenting, foam at the mouth, I’m not saying testing is bad – on the contrary. It’s just that you should stop kidding yourself by calling tests specifications. It’s like saying that “8” is an algorithm for adding two numbers, because it happens to work for 3 and 5.&amp;#160; &lt;/p&gt;  &lt;p&gt;Using frameworks and tools such as &lt;a href="http://msdn.microsoft.com/nl-be/devlabs/dd491992(en-us).aspx"&gt;Code Contracts&lt;/a&gt;, &lt;a href="http://research.microsoft.com/en-us/projects/Pex/"&gt;Pex&lt;/a&gt; and &lt;a href="http://www.codeplex.com/fscheck" target="_blank"&gt;FsCheck&lt;/a&gt; (I’m being completely unbiased here, of course), you will take a big step towards writing real specifications, not tests. That’s where their real value is.&lt;/p&gt; &lt;span class="sbmLink"&gt;&lt;/span&gt;&lt;span class="sbmLink"&gt;   &lt;table cellspacing="1" cellpadding="1"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td class="sbmText"&gt;Share this post : &lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to Technet!" href="http://social.technet.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2009/05/tests-are-not-specifications.html&amp;amp;ttl=Tests are not specifications" target="_blank"&gt;&lt;img src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" border="0" /&gt;Technet!&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to del.icio.us" href="http://del.icio.us/post?url=http://fortysix-and-two.blogspot.com/2009/05/tests-are-not-specifications.html&amp;amp;;title=Tests are not specifications" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" border="0" /&gt;del.icio.us it!&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&amp;amp;address=http://fortysix-and-two.blogspot.com/2009/05/tests-are-not-specifications.html&amp;amp;title=Tests are not specifications" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" border="0" /&gt;del.iri.ous!&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to digg" href="http://digg.com/submit?phase=2&amp;amp;url=http://fortysix-and-two.blogspot.com/2009/05/tests-are-not-specifications.html&amp;amp;title=Tests are not specifications" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" border="0" /&gt;digg it!&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to dotnetkicks" href="http://www.dotnetkicks.com/kick/?url=http://fortysix-and-two.blogspot.com/2009/05/tests-are-not-specifications.html&amp;amp;title=Tests are not specifications" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" border="0" /&gt;dotnetkicks it!&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to reddit!" href="http://reddit.com/submit?url=http://fortysix-and-two.blogspot.com/2009/05/tests-are-not-specifications.html&amp;amp;title=Tests are not specifications" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" border="0" /&gt;reddit!&lt;/a&gt;&lt;/td&gt;          &lt;td&gt;&lt;a title="Post it to technorati!" href="http://technorati.com/faves/?add=http://fortysix-and-two.blogspot.com/2009/05/tests-are-not-specifications.html&amp;amp;title=Tests are not specifications" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" border="0" /&gt;technorati!&lt;/a&gt;&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-1503614048149432705?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/1503614048149432705/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=1503614048149432705" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/1503614048149432705" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/1503614048149432705" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/05/tests-are-not-specifications.html" title="Tests are not specifications" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-4177205617766265898</id><published>2009-03-13T08:37:00.000-07:00</published><updated>2009-03-13T13:22:17.548-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fscheck" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><category scheme="http://www.blogger.com/atom/ns#" term="dnanalytics" /><category scheme="http://www.blogger.com/atom/ns#" term="fscheck case study" /><title type="text">FsChecking dnAnalytics – Part 3</title><content type="html">&lt;p&gt;Thanks to &lt;a href="http://cuda.net/"&gt;Marcus Cuda&lt;/a&gt;, coordinator of the &lt;a href="http://www.codeplex.com/dnAnalytics" target="_blank"&gt;dnAnalytics&lt;/a&gt; project, I can end my little series (&lt;a href="http://fortysix-and-two.blogspot.com/2009/02/fschecking-dnanalytics.html"&gt;part 1&lt;/a&gt; – &lt;a href="http://fortysix-and-two.blogspot.com/2009/02/fschecking-dnanalytics-part-2.html"&gt;part 2&lt;/a&gt;) with a nice result: the dnAnalytics team&amp;#160; have decided to incorporate &lt;a href="http://www.codeplex.com/fscheck" target="_blank"&gt;FsCheck&lt;/a&gt; in their testing. Cool! So next time, I’ll probably choose another project to “experiment” with (all in the interest of science), but this post I had lined up already. &lt;/p&gt;  &lt;p&gt;Last time I described one kind of property based on invariants that hold over two or more related functions or methods. The example I gave was mathematically oriented (i.e. directly originating from the problem domain). Today I’ll show a property that should be familiar to many of you, and is applicable for quite a few of your types.&lt;/p&gt;  &lt;p&gt;It happens that the Complex type in dnAnalytics can be constructed by parsing it from a string such as “1 + 3.0i”. On the other hand, calling ToString() on a Complex object produces a similar string. So, we specify that the ToString of a Complex value can be parsed, and produces the original value again:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_ParseToString (c:Complex) =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;actual = Complex.Parse(c.ToString(CultureInfo.InvariantCulture), CultureInfo.InvariantCulture)
    &lt;span style="color: blue"&gt;if &lt;/span&gt;Complex.IsInfinity(c) &lt;span style="color: blue"&gt;then &lt;/span&gt;Complex.IsInfinity(actual)
    &lt;span style="color: blue"&gt;elif &lt;/span&gt;Complex.IsNaN(c) &lt;span style="color: blue"&gt;then &lt;/span&gt;Complex.IsNaN(actual)
    &lt;span style="color: blue"&gt;else &lt;/span&gt;equalsUpTo 12 c actual&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;The only thing to watch out for is again the special values infinity and NaN. Also, since the ToString of a complex does not return a representation of Complex value up to its complete precision, we’re just checking equality up to a certain number of significant digits by using the equalsTo function.&lt;/p&gt;

&lt;p&gt;In dnAnalytics version 0.3, running this property produces:&lt;/p&gt;

&lt;pre&gt;Parse ToString-Falsifiable, after 4 tests (0 shrinks):
0 + 1,79769313486232E+308i
with exception:
System.FormatException: One of the identified items was in a bad format&lt;/pre&gt;

&lt;p&gt;This bug was due to the fact that the string is split on the basis of the ‘+’ character – which is also used when a floating point number is printed in scientific notation – clearly visible in the counter example given by FsCheck. This is a &lt;a href="http://dnanalytics.codeplex.com/Thread/View.aspx?ThreadId=49506"&gt;confirmed bug&lt;/a&gt; that is solved by now. Apparently the same property also detected a bug when parsing NaN and Infinity values.&lt;/p&gt;

&lt;p&gt;This again shows that writing properties, or specifications, for your code in FsCheck is easy, short, and most importantly, finds bugs!&lt;/p&gt;

&lt;p&gt;The kind of property that is described here you can write for any pair of functions or methods that convert a representation A to a representation B and back (in this case, a Complex value to a string and back). It can be generalized as follows:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;toAndFro x transformTo transformFrom equals =
    x |&amp;gt; transformTo |&amp;gt; transformFrom |&amp;gt; equals x&lt;/pre&gt;

&lt;p&gt;Applied to the example:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_ParseToString (c:Complex) =
    toAndFro c 
        (&lt;span style="color: blue"&gt;fun &lt;/span&gt;c &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;c.ToString(CultureInfo.InvariantCulture)) 
        (&lt;span style="color: blue"&gt;fun &lt;/span&gt;s &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Complex.Parse(s, CultureInfo.InvariantCulture)) 
        (&lt;span style="color: blue"&gt;fun &lt;/span&gt;c actual &lt;span style="color: blue"&gt;-&amp;gt; 
            if &lt;/span&gt;Complex.IsInfinity(c) &lt;span style="color: blue"&gt;then &lt;/span&gt;Complex.IsInfinity(actual)
            &lt;span style="color: blue"&gt;elif &lt;/span&gt;Complex.IsNaN(c) &lt;span style="color: blue"&gt;then &lt;/span&gt;Complex.IsNaN(actual)
            &lt;span style="color: blue"&gt;else &lt;/span&gt;equalsUpTo 12 c actual)&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;This kind of property is fairly common: think about Parse/ToString, serializing/deserializing, and all kinds of conversion and formatting functions.&lt;/p&gt;

&lt;p&gt;(I was at TechDays 2009 in Antwerp this week, and watched a presentation about &lt;a href="http://research.microsoft.com/en-us/projects/Pex/"&gt;Pex&lt;/a&gt; by Peli de Halleux. He showed a similar pattern when using Pex to write parameterized unit tests. In fact, a lot of the patterns and scenarios he described sounded very recognizable to my ears. If you like FsCheck, definitely check out Pex as well.)&lt;/p&gt;

&lt;h5&gt;Conclusion&lt;/h5&gt;

&lt;p&gt;One project converted, a gazillion to go. If you maintain an open source project and are unsure or even better, skeptical! how FsCheck can be used for testing in your project, contact me and you’ll probably get me crazy enough to write some tests for you. I choose a scientific domain because &lt;a title="F# homepage" href="http://research.microsoft.com/fsharp/fsharp.aspx" target="_blank"&gt;F#&lt;/a&gt; is targeted towards that, but the applicability goes far beyond that, as I hope to have showed in this post. On the other hand, I am also curious for what kind of projects or domains you are already using FsCheck. Did you encounter testing patterns like “toAndFro” that you’d like to share? Got any wishes? Don’t hesitate to let me know. Or even better, spread the word and blog about FsCheck yourself.&lt;/p&gt;

&lt;p&gt;Happy FsChecking!&lt;/p&gt;

&lt;table cellspacing="0" cellpadding="2" width="696" border="0"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td valign="top" width="330"&gt;
        &lt;div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:45769a77-6560-42e8-adaf-14e960d106a2" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati: &lt;a href="http://technorati.com/tags/fscheck" rel="tag"&gt;fscheck&lt;/a&gt;,&lt;a href="http://technorati.com/tags/dnanalytics" rel="tag"&gt;dnanalytics&lt;/a&gt;,&lt;a href="http://technorati.com/tags/random+testing" rel="tag"&gt;random testing&lt;/a&gt;,&lt;a href="http://technorati.com/tags/F%23" rel="tag"&gt;F#&lt;/a&gt;&lt;/div&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="364"&gt;
        &lt;div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:6f27e1c5-47bc-4bc5-825e-ece1f7bbf957" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;del.icio.us Tags: &lt;a href="http://del.icio.us/popular/fscheck" rel="tag"&gt;fscheck&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/dnanalytics" rel="tag"&gt;dnanalytics&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/random+testing" rel="tag"&gt;random testing&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/F%23" rel="tag"&gt;F#&lt;/a&gt;&lt;/div&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;&lt;/p&gt;
&lt;span class="sbmLink"&gt;
  &lt;table cellspacing="1" cellpadding="1"&gt;&lt;tbody&gt;
      &lt;tr&gt;
        &lt;td class="sbmText"&gt;Share this post : &lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to del.icio.us" href="http://del.icio.us/post?url=http://fortysix-and-two.blogspot.com/2009/03/fschecking-dnanalytics-part-3.html&amp;amp;;title=FsChecking dnAnalytics &amp;ndash; Part 3" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" border="0" /&gt;&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to dotnetkicks" href="http://www.dotnetkicks.com/kick/?url=http://fortysix-and-two.blogspot.com/2009/03/fschecking-dnanalytics-part-3.html&amp;amp;title=FsChecking dnAnalytics &amp;ndash; Part 3" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" border="0" /&gt;&lt;/a&gt;&lt;/td&gt;

        &lt;td&gt;&lt;a title="Post it to technorati!" href="http://technorati.com/faves/?add=http://fortysix-and-two.blogspot.com/2009/03/fschecking-dnanalytics-part-3.html&amp;amp;title=FsChecking dnAnalytics &amp;ndash; Part 3" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" border="0" /&gt;&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;&lt;/table&gt;
&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-4177205617766265898?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/4177205617766265898/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=4177205617766265898" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/4177205617766265898" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/4177205617766265898" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/03/fschecking-dnanalytics-part-3.html" title="FsChecking dnAnalytics – Part 3" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-2964929970347139553</id><published>2009-03-06T12:14:00.000-08:00</published><updated>2009-03-06T12:15:39.873-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fscheck" /><category scheme="http://www.blogger.com/atom/ns#" term="tidbits" /><title type="text">FsCheck on Ohloh</title><content type="html">&lt;p&gt;I found out about &lt;a href="http://www.ohloh.net/"&gt;Ohloh&lt;/a&gt;&amp;#160; recently and decided to play around with it by adding &lt;a href="http://www.codeplex.com/fscheck" target="_blank"&gt;FsCheck&lt;/a&gt;. From &lt;a href="https://www.ohloh.net/p/fscheck"&gt;FsCheck’s Ohloh page&lt;/a&gt; we learn that:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;it’s mostly written in Make. Uhm, what?&lt;/li&gt;    &lt;li&gt;it has a short source control history (that’s right: I do all my local development using &lt;a href="http://www.selenic.com/mercurial/wiki/"&gt;Mercurial&lt;/a&gt;, and only export to codeplex on release)&lt;/li&gt;    &lt;li&gt;it has a single active developer (I’m not single, I have a lovely wife!)&lt;/li&gt;    &lt;li&gt;it has very few source code comments (I didn’t put any comments in the Makefile. Sorry.)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;It seems that the appraisal of an open source project can not be replaced by a small shell script…&lt;/p&gt;  &lt;p&gt;Anyway, it’s nice to see how many related projects there are (and how many projects in general). If you’re in the neighborhood, come say hi, add a rating, add a user, whatever…&lt;/p&gt;  &lt;p&gt;   &lt;div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:9bf50914-db4e-415b-8f53-df94e9cee1a5" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati: &lt;a href="http://technorati.com/tags/fscheck" rel="tag"&gt;fscheck&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ohloh" rel="tag"&gt;ohloh&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-2964929970347139553?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/2964929970347139553/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=2964929970347139553" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/2964929970347139553" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/2964929970347139553" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/03/fscheck-on-ohloh.html" title="FsCheck on Ohloh" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-5460577936984871285</id><published>2009-03-01T03:54:00.001-08:00</published><updated>2009-03-04T12:09:57.506-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fscheck" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title type="text">FsCheck 0.5.1</title><content type="html">&lt;p&gt;Just a short note to announce v0.5.1 of &lt;a href="http://www.codeplex.com/fscheck"&gt;FsCheck&lt;/a&gt;, which fixes some bugs in 0.5 and includes one improvement in the category I-can't-believe-I-didn't-see-this-earlier.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Bug fix: no more escaping exceptions when using lazy &lt;/li&gt;    &lt;li&gt;Bug fix: no extra initialization (init.Value) necessary when registering generators 'early' &lt;/li&gt;    &lt;li&gt;check (and quickCheck, verboseCheck) now take a simple value 'a instead of a function value 'a-&amp;gt;'b as argument, so you can just write 'quickCheck &amp;lt;| forAll ...' instead of 'quickCheck (fun () -&amp;gt; forAll ...)'. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I don't see any reason not to update if you're using 0.5.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:3461cba6-6ccd-41e9-93dd-9faa7ea239e0" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati: &lt;a href="http://technorati.com/tags/F%23" rel="tag"&gt;F#&lt;/a&gt;,&lt;a href="http://technorati.com/tags/FsCheck" rel="tag"&gt;FsCheck&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-5460577936984871285?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/5460577936984871285/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=5460577936984871285" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/5460577936984871285" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/5460577936984871285" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/03/fscheck-051.html" title="FsCheck 0.5.1" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-8693230923129170823</id><published>2009-02-27T15:10:00.000-08:00</published><updated>2009-02-27T15:25:07.893-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fscheck" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><category scheme="http://www.blogger.com/atom/ns#" term="dnanalytics" /><category scheme="http://www.blogger.com/atom/ns#" term="fscheck case study" /><title type="text">FsChecking dnAnalytics Part 2</title><content type="html">&lt;p&gt;In &lt;a href="http://fortysix-and-two.blogspot.com/2009/02/fschecking-dnanalytics.html"&gt;part 1&lt;/a&gt;, I started out with defining some &lt;a href="http://www.codeplex.com/fscheck"&gt;FsCheck&lt;/a&gt; properties on &lt;a href="http://www.codeplex.com/dnAnalytics"&gt;dnAnalytics&lt;/a&gt;' Complex class. The properties I showed were fairly straightforward: break the complex number in its real and imaginary part, apply the definition of the operation and compare that to the result of the actual operation under test.&lt;/p&gt;  &lt;p&gt;A possible critique on this kind of property is that it partly duplicates the implementation of the operation under test. In my experience, it almost never does completely: there is of course some overlap, but the property is invariably simpler, takes into account less detail, and is easier to understand. The property is mostly unusable for an actual implementation, for example because it is inefficient, is not tail recursive, causes more rounding errors etc.&amp;#160; The only important thing about such a property is that is simple, so that you are sure it is correct (in fact, FsCheck will verify that it is correct...). So this critique is not justified.&lt;/p&gt;  &lt;p&gt;But anyway, such definition properties are not the only kind that can be written using FsCheck. Today we'll look at properties that relate different operations (functions, methods) of the same class or module together.&lt;/p&gt;  &lt;p&gt;As an example, we'll test that the complex numbers form a field over addition and multiplication, i.e. the field C+,*.&lt;/p&gt;  &lt;p&gt;Now, the first thing to realize here is that instances of type Complex &lt;em&gt;do not&lt;/em&gt; form an actual field, due to the presence of NaN, Infinity, rounding errors and overflow. So, for the purpose of this property we're about to write, we need to be able to generate Complex instances where these values are not generated. &lt;/p&gt;  &lt;p&gt;There is a nice trick to define a custom generator that filters or otherwise manipulates values from another generator but keeps the other generator's type. First define a wrapper union type and define a generator for that:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;NoSpecials = NoSpecials &lt;span style="color: blue"&gt;of &lt;/span&gt;Complex

&lt;span style="color: blue"&gt;type &lt;/span&gt;Generators =
    &lt;span style="color: blue"&gt;static member &lt;/span&gt;NoSpecials() =
        { &lt;span style="color: blue"&gt;new &lt;/span&gt;Arbitrary&amp;lt;NoSpecials&amp;gt;() &lt;span style="color: blue"&gt;with
            override &lt;/span&gt;x.Arbitrary = 
                arbitrary 
                |&amp;gt; suchThat (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(C (r,i) &lt;span style="color: blue"&gt;as &lt;/span&gt;a) &lt;span style="color: blue"&gt;-&amp;gt; 
                    &lt;/span&gt;not (Complex.IsInfinity(a)) &amp;amp;&amp;amp; 
                    not (Complex.IsNaN(a))      &amp;amp;&amp;amp; 
                    r &amp;gt; 1e-16  &amp;amp;&amp;amp; r &amp;lt; 1e16      &amp;amp;&amp;amp;
                    i &amp;gt; 1e-16  &amp;amp;&amp;amp; i &amp;lt; 1e16  )  
                |&amp;gt; fmapGen NoSpecials
            &lt;span style="color: blue"&gt;override &lt;/span&gt;x.Shrink (NoSpecials c) = shrink c |&amp;gt; Seq.map NoSpecials
        }&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Notice how special values like NaN, and very low and high values are filtered out in the generator using the &lt;em&gt;suchThat&lt;/em&gt; generator combinator.&lt;/p&gt;

&lt;p&gt;Now, we can write a property with a signature like:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_ComplexField (NoSpecials a,NoSpecials b,NoSpecials c) =&lt;/pre&gt;

&lt;p&gt;which will generate &amp;quot;non-special&amp;quot; complex values in a, b and c. F#'s pattern matching and FsCheck's type directed value generation come together nicely here. (The alternative for this style is to use an explicit generator using forAll or forAllShrink).&lt;/p&gt;

&lt;p&gt;Our property should check that both addition and multiplication are commutative, associative, distributive and have an an identity. So, the following functions will be useful:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;(=~=) (expected:Complex) actual = 
    &lt;span style="color: blue"&gt;try &lt;/span&gt;TestHelper.TestRelativeError(expected, actual, 2e-10); &lt;span style="color: blue"&gt;true with &lt;/span&gt;_ &lt;span style="color: blue"&gt;-&amp;gt; false

let &lt;/span&gt;commutative f (a,b) = f a b =~= f b a 
&lt;span style="color: blue"&gt;let &lt;/span&gt;associative f (a,b,c) = f (f a b) c =~=  f a (f b c) &lt;span style="color: green"&gt;//e.g. (a+b)+c = a+(b+c)
&lt;/span&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;rightdistributive f g (a,b,c) =  g (f a b) c =~= f (g a c) (g b c) &lt;span style="color: green"&gt;//e.g. (a+b)c = ac+bc
&lt;/span&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;leftdistributive f g (a,b,c) = g c (f a b) =~= f (g c a) (g c b) &lt;span style="color: green"&gt;// e.g. c(a+b) = ca+cb
&lt;/span&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;identity f id a = f a id = a&lt;/pre&gt;

&lt;p&gt;Armed with these, our property can be written as:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_ComplexField (NoSpecials a,NoSpecials b,NoSpecials c) =
    commutative (+) (a,b)               |@ &lt;span style="color: maroon"&gt;&amp;quot;+ commutative&amp;quot;      &lt;/span&gt;.&amp;amp;.
    commutative (*) (a,b)               |@ &lt;span style="color: maroon"&gt;&amp;quot;* commutative&amp;quot;      &lt;/span&gt;.&amp;amp;.
    associative (+) (a,b,c)             |@ &lt;span style="color: maroon"&gt;&amp;quot;+ associative&amp;quot;      &lt;/span&gt;.&amp;amp;.
    associative (*) (a,b,c)             |@ &lt;span style="color: maroon"&gt;&amp;quot;* associative&amp;quot;      &lt;/span&gt;.&amp;amp;.
    rightdistributive (+) (*) (a,b,c)   |@ &lt;span style="color: maroon"&gt;&amp;quot;right distributive&amp;quot; &lt;/span&gt;.&amp;amp;.
    leftdistributive (+) (*) (a,b,c)    |@ &lt;span style="color: maroon"&gt;&amp;quot;left distributive&amp;quot;  &lt;/span&gt;.&amp;amp;.
    identity (+) Complex.Zero a         |@ &lt;span style="color: maroon"&gt;&amp;quot;0 is identity of +&amp;quot; &lt;/span&gt;.&amp;amp;.
    identity (*) Complex.One a          |@ &lt;span style="color: maroon"&gt;&amp;quot;1 is identity of *&amp;quot; 
&lt;/span&gt;quickCheckN &lt;span style="color: maroon"&gt;&amp;quot;Complex numbers are a field&amp;quot;  &lt;/span&gt;prop_ComplexField  &lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Which produces:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Complex numbers are a field-Ok, passed 100 tests.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It should be clear that the possibilities for coming up with such properties are almost limitless, and that you'll never have to repeat any part of your implementation to express them.&lt;/p&gt;

&lt;h4&gt;&lt;/h4&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;FsCheck makes it easy to test whether relations between a set of related methods or functions hold. This technique is in my experience sometimes neglected when unit testing, because of the focus on the &lt;em&gt;unit. &lt;/em&gt;Nevertheless, such properties can have great value in documentation and testing.&lt;/p&gt;

&lt;p&gt;In this post I took a few shortcuts to avoid having to deal with the &amp;quot;specials&amp;quot;, and so in that sense this specification could be called misleading because indeed, instances of Complex do not form a field. I did this for two reasons. First, I wanted to show the wrapper type/pattern match technique to define derived generators that generate a subset of the values of an original generator. Second, I wanted to show that FsCheck makes you work&amp;#160; if you want to ignore these special values - in other words, you have to make a very conscious decision to ignore them. In contrast, using unit tests the default is that you forget about these values until it's too late.&lt;/p&gt;

&lt;p&gt;A third point I wanted to show is that with a little refactoring and common sense, you can write elegant and very readable properties that could conceivably be part of your documentation - in other words, true executable specifications.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://cid-f6a45280389d5d06.skydrive.live.com/self.aspx/Public/Complex-Pt2.fs"&gt;Download fs file&lt;/a&gt;&lt;/p&gt;

&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:c7da7472-df42-4708-8089-6f021e478f30" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati: &lt;a href="http://technorati.com/tags/F#" rel="tag"&gt;F#&lt;/a&gt;,&lt;a href="http://technorati.com/tags/fscheck%20case%20study" rel="tag"&gt;fscheck case study&lt;/a&gt;,&lt;a href="http://technorati.com/tags/fscheck" rel="tag"&gt;fscheck&lt;/a&gt;,&lt;a href="http://technorati.com/tags/dnAnalytics" rel="tag"&gt;dnAnalytics&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-8693230923129170823?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/8693230923129170823/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=8693230923129170823" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/8693230923129170823" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/8693230923129170823" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/02/fschecking-dnanalytics-part-2.html" title="FsChecking dnAnalytics Part 2" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-2292391042491882685</id><published>2009-02-23T14:06:00.000-08:00</published><updated>2009-02-23T14:10:07.987-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fscheck" /><category scheme="http://www.blogger.com/atom/ns#" term="dnanalytics" /><category scheme="http://www.blogger.com/atom/ns#" term="fscheck case study" /><title type="text">FsChecking dnAnalytics</title><content type="html">&lt;p&gt;I've been thinking lately what I can do to make &lt;a href="http://www.codeplex.com/fscheck"&gt;FsCheck&lt;/a&gt; more widely used. Whenever I write &amp;quot;regular&amp;quot; unit tests, I feel like I'm back in the stone ages. It just feels so clumsy and tedious. Why don't more people see this? Is it because there's a learning curve? Surely that's part of it, but the benefit is so huge that this can't be the whole story. I came across &lt;a href="http://stackoverflow.com/questions/32458/random-data-in-unit-tests"&gt;this question&lt;/a&gt; on stackoverflow, and read a lot of misunderstandings about random testing (luckily the chosen answer was well-informed, and even mentions FsCheck). I could respond to each of those, but I'll keep that to a later post; instead, I'm resolved to convert the world to FsCheck, even if I have to do it one project at a time ;)&lt;/p&gt;  &lt;p&gt;Today's candidate: &lt;a href="http://www.codeplex.com/dnAnalytics"&gt;dnAnalytics&lt;/a&gt;. dnAnalytics makes a good candidate for FsChecking because&amp;#160; it is in the mathematical field - finding properties for the functionality to satisfy should be straightforward: there's millennia of mathematical knowledge to choose from. Secondly, dnAnalytics already has some tests that I can trash later. Also, dnAnalytics&amp;#160; has an F# interface which I won't be using in this post, but at least the maintainers are familiar with F#, so I have some hope of &amp;quot;converting&amp;quot; them. Finally, dnAnalytics has quite a few downloads (over a 1000), so hopefully this can raise visibility of FsCheck outside the F# community. &lt;/p&gt;  &lt;p&gt;Without further ado, let's go find bugs!&amp;#160; (I'll give it away now to keep you interested, as this has become a long post: I found a bug...read on.)&lt;/p&gt;  &lt;p&gt;For my first experiment, I choose to test the Complex class, which represents a complex number a+bi, along with some operations. Fairly straightforward stuff that even a mathematically challenged person like myself can follow.&lt;/p&gt;  &lt;p&gt;For education and amusement, I'll give an overview of how the tests I wrote revolved over time - errors and imperfections included.&lt;/p&gt;  &lt;h6&gt;&lt;/h6&gt;  &lt;h4&gt;The complex number generator&lt;/h4&gt;  &lt;p&gt;To test a type, typically the first step to take when using FsCheck is writing a generator for a type. In this case, we'll just be using a generator for a tuple of two floats, and map that to a complex number:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Generators =
    &lt;span style="color: blue"&gt;static member &lt;/span&gt;Complex() =
        { &lt;span style="color: blue"&gt;new &lt;/span&gt;Arbitrary&amp;lt;Complex&amp;gt;() &lt;span style="color: blue"&gt;with
            override &lt;/span&gt;x.Arbitrary = two arbitrary |&amp;gt; fmapGen ( &lt;span style="color: blue"&gt;fun &lt;/span&gt;(a,b) &lt;span style="color: blue"&gt;-&amp;gt; new &lt;/span&gt;Complex(a,b))
            &lt;span style="color: blue"&gt;override &lt;/span&gt;x.Shrink (C (r,i)) = 
                shrink (r,i)  
                |&amp;gt; Seq.map (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(r,i) &lt;span style="color: blue"&gt;-&amp;gt; new &lt;/span&gt;Complex(r,i))
        }
registerGenerators&amp;lt;Generators&amp;gt;()&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Pretty easy. The shrink function also exploits the relation between a complex number and a pair of floats. In case you're wondering, I added an active pattern C to deal with the Complex class, it's just:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;(|C|) (c:Complex) = (c.Real, c.Imaginary)&lt;/pre&gt;

&lt;h4&gt;The Absolute of a complex number&lt;/h4&gt;

&lt;p&gt;I started out with testing the Complex type's Absolute method. It's supposed to return the Absolute value of the Complex instance it's applied to. Here's the property I wrote:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_Absolute (C (r,i) &lt;span style="color: blue"&gt;as &lt;/span&gt;c) = 
    &lt;span style="color: blue"&gt;let &lt;/span&gt;lhs = c.Absolute
    &lt;span style="color: blue"&gt;let &lt;/span&gt;rhs = Math.Sqrt( r*r + i*i)
    sprintf &lt;span style="color: maroon"&gt;&amp;quot;lhs=%O, rhs=%O&amp;quot; &lt;/span&gt;lhs rhs @| (lhs = rhs)&lt;/pre&gt;

&lt;p&gt;Basically this just checks that the outcome of the Absolute method is equal to the mathematical definition of the absolute value of a complex number. The sprintf and the label operator @| are there to display the intermediate values should the property fail. And failing it does:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Absolute-Falsifiable, after 6 tests (1 shrink): 
    &lt;br /&gt;Label of failing property: lhs=NaN (Niet-een-getal), rhs=NaN (Niet-een-getal) 

    &lt;br /&gt;NaN&lt;/p&gt;

  &lt;p&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Classic mistake: NaN is a special case; NaN is never equal to NaN. That's easily solved:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_Absolute (C (r,i) &lt;span style="color: blue"&gt;as &lt;/span&gt;c) = 
    &lt;span style="color: blue"&gt;let &lt;/span&gt;lhs = c.Absolute
    &lt;span style="color: blue"&gt;let &lt;/span&gt;rhs = Math.Sqrt( r*r + i*i)
    sprintf &lt;span style="color: maroon"&gt;&amp;quot;lhs=%O, rhs=%O&amp;quot; &lt;/span&gt;lhs rhs @|
    (&lt;span style="color: blue"&gt;if &lt;/span&gt;Complex.IsNaN(c) &lt;span style="color: blue"&gt;then &lt;/span&gt;Double.IsNaN(lhs) &lt;span style="color: blue"&gt;else &lt;/span&gt;lhs = rhs)&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;produces&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Absolute-Falsifiable, after 10 tests (2 shrinks): 
    &lt;br /&gt;Label of failing property: lhs=7,00446286306095, rhs=7,00446286306095 

    &lt;br /&gt;7 + 0,25i&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hmm. Instead of looking up how I could see &lt;em&gt;all&lt;/em&gt;&amp;#160; of a float's significant digits, I just assumed a rounding error. I explored dnAnalytics existing tests and found just the thing to deal with that: a method to test equality taking into account a relative error. Using that method in the property results in:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_Absolute (C (r,i) &lt;span style="color: blue"&gt;as &lt;/span&gt;c) = 
    &lt;span style="color: blue"&gt;let &lt;/span&gt;lhs = c.Absolute
    &lt;span style="color: blue"&gt;let &lt;/span&gt;rhs = Math.Sqrt( r*r + i*i)
    sprintf &lt;span style="color: maroon"&gt;&amp;quot;lhs=%O, rhs=%O&amp;quot; &lt;/span&gt;lhs rhs @|
    (   &lt;span style="color: blue"&gt;if &lt;/span&gt;Complex.IsNaN(c) &lt;span style="color: blue"&gt;then &lt;/span&gt;Double.IsNaN(lhs) 
        &lt;span style="color: blue"&gt;else &lt;/span&gt;TestHelper.TestRelativeError(lhs, rhs, 2e-16);&lt;span style="color: blue"&gt;true&lt;/span&gt;)&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;And yes:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Absolute-Ok, passed 100 tests.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice that FsCheck works nicely with NUnit here; suppose we introduce a &amp;quot;bug&amp;quot; by adding 1 to the right hand side:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_Absolute (C (r,i) &lt;span style="color: blue"&gt;as &lt;/span&gt;c) = 
    &lt;span style="color: blue"&gt;let &lt;/span&gt;lhs = c.Absolute
    &lt;span style="color: blue"&gt;let &lt;/span&gt;rhs = Math.Sqrt( r*r + i*i)
    sprintf &lt;span style="color: maroon"&gt;&amp;quot;lhs=%O, rhs=%O&amp;quot; &lt;/span&gt;lhs rhs @|
    (   &lt;span style="color: blue"&gt;if &lt;/span&gt;Complex.IsNaN(c) &lt;span style="color: blue"&gt;then &lt;/span&gt;Double.IsNaN(lhs) 
        &lt;span style="color: blue"&gt;else &lt;/span&gt;TestHelper.TestRelativeError(lhs, rhs+1.0, 2e-16);&lt;span style="color: blue"&gt;true&lt;/span&gt;)&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;produces:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Absolute-Falsifiable, after 1 test (0 shrinks): 
    &lt;br /&gt;0 + 0i 

    &lt;br /&gt;with exception: 

    &lt;br /&gt;NUnit.Framework.AssertionException:&amp;#160;&amp;#160; Expected: less than 2E-16.0d 

    &lt;br /&gt;&amp;#160; But was:&amp;#160; 1.0d &lt;/p&gt;

  &lt;p&gt;&amp;#160;&amp;#160; at NUnit.Framework.Assert.That(Object actual, Constraint constraint, String message, Object[] args) 
    &lt;br /&gt;&amp;#160;&amp;#160; at NUnit.Framework.Assert.Less(Double arg1, Double arg2, String message, Object[] args) 

    &lt;br /&gt;&amp;#160;&amp;#160; at NUnit.Framework.Assert.Less(Double arg1, Double arg2) 

    &lt;br /&gt;&amp;#160;&amp;#160; at dnAnalytics.Tests.TestHelper.TestRelativeError(Double expected, Double approx, Double acceptableError) in c:\Documents and Settings\Kurt\My Documents\dnAnalytics\0.3\src\dnAnalytics.Tests\TestHelper.cs:line 53 

    &lt;br /&gt;&amp;#160;&amp;#160; at Complex.prop_Absolute(Complex _arg1) in C:\Documents and Settings\Kurt\MyDocuments\dnAnalytics\0.3\src\dnAnalytics.FsCheck\Complex.fs:line 32 

    &lt;br /&gt;&amp;#160;&amp;#160; at FsCheck.Property.evaluate[T,U](FastFunc`2 body, T a) in C:\Documents and Settings\Kurt\My Documents\FsCheck\FsCheck\Property.fs:line 162&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But wait! Why aren't our labels displayed? We've found a bug...in FsCheck :) Hold on, I didn't con you earlier, I really did find a bug in dnAnalytics as well.&lt;/p&gt;

&lt;p&gt;People can get a bit nervous now because they're not actually seeing what values FsCheck is generating. Let's find out:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_Absolute (C (r,i) &lt;span style="color: blue"&gt;as &lt;/span&gt;c) = 
    &lt;span style="color: blue"&gt;let &lt;/span&gt;lhs = c.Absolute
    &lt;span style="color: blue"&gt;let &lt;/span&gt;rhs = Math.Sqrt( r*r + i*i)
    sprintf &lt;span style="color: maroon"&gt;&amp;quot;lhs=%O, rhs=%O&amp;quot; &lt;/span&gt;lhs rhs @|
    &lt;span style="color: blue"&gt;if &lt;/span&gt;Complex.IsNaN(c) &lt;span style="color: blue"&gt;then &lt;/span&gt;Double.IsNaN(lhs) 
    &lt;span style="color: blue"&gt;else &lt;/span&gt;TestHelper.TestRelativeError(lhs, rhs, 2e-16);&lt;span style="color: blue"&gt;true
    &lt;/span&gt;|&amp;gt; classify (Complex.IsNaN(c)) &lt;span style="color: maroon"&gt;&amp;quot;NaN&amp;quot;
    &lt;/span&gt;|&amp;gt; classify (Complex.IsInfinity(c)) &lt;span style="color: maroon"&gt;&amp;quot;Infinity&amp;quot;
    &lt;/span&gt;|&amp;gt; classify (c = Complex.Zero) &lt;span style="color: maroon"&gt;&amp;quot;Zero&amp;quot;
    &lt;/span&gt;|&amp;gt; classify (c = Complex.One) &lt;span style="color: maroon"&gt;&amp;quot;One&amp;quot;&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;blockquote&gt;
  &lt;p&gt;Absolute-Ok, passed 100 tests. 
    &lt;br /&gt;17% Infinity. 

    &lt;br /&gt;8% NaN. 

    &lt;br /&gt;2% Zero.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As you can see, using the classify combinator you can make FsCheck print out the ratio of test cases that fulfill a certain criterion. Here we learn that One is never generated; and infinity quite a bit. This is due to the fact that the built in generator for floats generates these special values with preference. We can change this behavior by changing the generator. Suppose we'd like to generate the value One also:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;override &lt;/span&gt;x.Arbitrary = 
  frequency   [ (98,two arbitrary |&amp;gt; fmapGen ( &lt;span style="color: blue"&gt;fun &lt;/span&gt;(a,b) &lt;span style="color: blue"&gt;-&amp;gt; new &lt;/span&gt;Complex(a,b)))
              ; (2, constant Complex.One) ]&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;blockquote&gt;
  &lt;p&gt;Absolute-Ok, passed 100 tests. 
    &lt;br /&gt;10% Infinity. 

    &lt;br /&gt;9% NaN. 

    &lt;br /&gt;4% Zero. 

    &lt;br /&gt;2% One. 

    &lt;br /&gt;1% Infinity, NaN.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Easy enough. Our generator now indeed generates One as well.&lt;/p&gt;

&lt;p&gt;But hold on: we see also that a Complex number can be both Infinity and NaN. That doens't make sense. Let's write a property to check this:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_NaNInfinity (c:Complex) =
    not ( Complex.IsInfinity(c) &amp;amp;&amp;amp;  Complex.IsNaN(c))
checkName  &lt;span style="color: maroon"&gt;&amp;quot;Both NaN and Infinity&amp;quot; &lt;/span&gt;{ quick &lt;span style="color: blue"&gt;with &lt;/span&gt;MaxTest = 1000} prop_NaNInfinity &lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Note that I didn't use the usual quickCheckN function to run the tests, because the Absolute test indicated that only one test in a hundred exhibited the behavior. So I made FsCheck run this test a bit more, 1000 times to be exact. Running this sure enough produces:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Both NaN and Infinity-Falsifiable, after 418 tests (0 shrinks):
    &lt;br /&gt;NaN&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; and this find was &lt;a href="http://www.codeplex.com/dnAnalytics/Thread/View.aspx?ThreadId=48156"&gt;confirmed as a bug by the dnAnalytics team&lt;/a&gt;. A small victory for FsCheck.&lt;/p&gt;

&lt;h4&gt;The conjugate of a complex number&lt;/h4&gt;

&lt;p&gt;Let's do one more: finding the conjugate.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_Conjugate (C (r,i) &lt;span style="color: blue"&gt;as &lt;/span&gt;c) =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;lhs = c.Conjugate
    &lt;span style="color: blue"&gt;let &lt;/span&gt;rhs = &lt;span style="color: blue"&gt;new &lt;/span&gt;Complex(r,-i)
    sprintf &lt;span style="color: maroon"&gt;&amp;quot;lhs=%O, rhs=%O&amp;quot; &lt;/span&gt;lhs rhs @|
    &lt;span style="color: blue"&gt;if &lt;/span&gt;Complex.IsNaN(c) &lt;span style="color: blue"&gt;then &lt;/span&gt;Complex.IsNaN(lhs) 
    &lt;span style="color: blue"&gt;else &lt;/span&gt;lhs = rhs&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Since the Absolute property, I've become a bit wiser and factored in the possibility of NaN from the start. Running this gives:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Conjugate-Ok, passed 100 tests.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And all is well. Except one thing: our tests like a bit ugly, because we had to duplicate some code. &lt;/p&gt;

&lt;h4&gt;Red, green, refactor!&lt;/h4&gt;

&lt;p&gt;We're going to refactor two things.&lt;/p&gt;

&lt;p&gt;First, all the classify's we've added to the Absolute property are actually common to every property where we use our Complex generator. These kinds of &amp;quot;tests&amp;quot; are not uncommon when writing a new FsCheck generator - for example, it ensures that our generator does not throw an exception when generating values (which can happen when certain objects are constructed). I've taken the habit of separating these kinds of tests into a single separate property:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_ComplexGen c = 
    ()
    |&amp;gt; classify (Complex.IsNaN(c)) &lt;span style="color: maroon"&gt;&amp;quot;NaN&amp;quot;
    &lt;/span&gt;|&amp;gt; classify (Complex.IsInfinity(c)) &lt;span style="color: maroon"&gt;&amp;quot;Infinity&amp;quot;
    &lt;/span&gt;|&amp;gt; classify (c = Complex.Zero) &lt;span style="color: maroon"&gt;&amp;quot;Zero&amp;quot;
    &lt;/span&gt;|&amp;gt; classify (c = Complex.One) &lt;span style="color: maroon"&gt;&amp;quot;One&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;And we leave these classify's out of the other properties. (Note that a property that returns unit or true is interpreted as succeeded by FsCheck. An exception or false indicates failure.)&lt;/p&gt;

&lt;p&gt;Then, we add the following helper method to abstract out the labeling of left and right hand side; cleaning it up in the process:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;compare expected actual prop = 
      sprintf &lt;span style="color: maroon"&gt;&amp;quot;expected=%O, actual=%O&amp;quot; &lt;/span&gt;expected actual @| (prop expected actual)&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Now our two properties can be written:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_Absolute (C (r,i) &lt;span style="color: blue"&gt;as &lt;/span&gt;c) = 
    compare (Math.Sqrt(r*r + i*i)) c.Absolute (&lt;span style="color: blue"&gt;fun &lt;/span&gt;expected actual &lt;span style="color: blue"&gt;-&amp;gt;
        if &lt;/span&gt;Complex.IsNaN(c) &lt;span style="color: blue"&gt;then &lt;/span&gt;Double.IsNaN(actual) 
        &lt;span style="color: blue"&gt;else &lt;/span&gt;TestHelper.TestRelativeError(expected, actual, 2e-16);&lt;span style="color: blue"&gt;true&lt;/span&gt;)&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_Conjugate (C (r,i) &lt;span style="color: blue"&gt;as &lt;/span&gt;c) =
    compare (Complex(r,-i)) c.Conjugate (&lt;span style="color: blue"&gt;fun &lt;/span&gt;expected actual &lt;span style="color: blue"&gt;-&amp;gt;
        if &lt;/span&gt;Complex.IsNaN(c) &lt;span style="color: blue"&gt;then &lt;/span&gt;Complex.IsNaN(actual) 
        &lt;span style="color: blue"&gt;else &lt;/span&gt;expected = actual)&lt;/pre&gt;

&lt;h4&gt;&lt;/h4&gt;

&lt;h3&gt;A successful experiment&lt;/h3&gt;

&lt;p&gt;In my eyes, the FsCheck based tests are hugely superior to the original tests, for the following reasons.&lt;/p&gt;

&lt;p&gt;First, we've replaced 2 x 100 &lt;em&gt;hand-written&lt;/em&gt; tests with presumably &lt;em&gt;manually calculated values &lt;/em&gt;in dnAnalytics with just a few lines of code.&amp;#160; An excerpt from the original tests:&lt;/p&gt;

&lt;pre class="code"&gt;[&lt;span style="color: #2b91af"&gt;Test&lt;/span&gt;]
&lt;span style="color: blue"&gt;public void &lt;/span&gt;Absolute()
{
  &lt;span style="color: #2b91af"&gt;TestHelper&lt;/span&gt;.TestRelativeError(&lt;span style="color: #2b91af"&gt;ComplexMath&lt;/span&gt;.Absolute(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Complex&lt;/span&gt;(0.0, 1.19209289550780998537e-7)), 1.19209289550780998537e-7, 2e-016);
  &lt;span style="color: #2b91af"&gt;TestHelper&lt;/span&gt;.TestRelativeError(&lt;span style="color: #2b91af"&gt;ComplexMath&lt;/span&gt;.Absolute(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Complex&lt;/span&gt;(0.0, -1.19209289550780998537e-7)), 1.19209289550780998537e-7, 2e-016);
  &lt;span style="color: #2b91af"&gt;TestHelper&lt;/span&gt;.TestRelativeError(&lt;span style="color: #2b91af"&gt;ComplexMath&lt;/span&gt;.Absolute(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Complex&lt;/span&gt;(0.0, 5.0e-1)), 5.0e-1, 2e-016);
  &lt;span style="color: #2b91af"&gt;TestHelper&lt;/span&gt;.TestRelativeError(&lt;span style="color: #2b91af"&gt;ComplexMath&lt;/span&gt;.Absolute(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Complex&lt;/span&gt;(0.0, -5.0e-1)), 5.0e-1, 2e-016);&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;(Note that these are actually tests for a static method on ComplexMath, but Complex.Absolute calls this method directly without further ado. In any case we could easily rewrite our properties to call this method directly as well.)&lt;/p&gt;

&lt;p&gt;These must've been a pain to write. Probably someone generated a little script to apply the definition of Absolute in each of these cases. That should be the work of a computer! Using FsCheck, it is.&lt;/p&gt;

&lt;p&gt;Second, the original tests do not reveal the &lt;em&gt;intent&lt;/em&gt; of the Absolute or Conjugate methods. Basically you just see a bunch of values going in, and the expected values coming out. In a normal program, you would call these &amp;quot;magic numbers&amp;quot; and call the developer that wrote them names. In unit tests, this is commonly tolerated.&lt;/p&gt;

&lt;p&gt;FsCheck's specification on the other hand reveals the intent of the tested methods directly - in fact, I just looked up the mathematical definition of these operators to come up with the properties, and this definition is still readily apparent.&lt;/p&gt;

&lt;p&gt;Third, FsCheck &lt;em&gt;forced&lt;/em&gt; us to make the specification complete, and factor in NaN values. I could not find any test using NaN in the original dnAnalytics tests. This led directly to the discovery of a previously unknown bug.&lt;/p&gt;

&lt;p&gt;In conclusion; FsCheck's tests are shorter, clearer and more complete than the original tests.&lt;/p&gt;

&lt;p&gt;To boot, I dare say they are faster to write: I downloaded dnAnalytics, explored the code, choose a type to test, wrote the above properties, reported the bug, and typed in the bulk of this blog post in the course of about 4 hours yesterday. I spent another hour or two today cleaning up the post itself.&lt;/p&gt;

&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:afb9df77-d485-4e6c-a7cd-7d80960fad72" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati: &lt;a href="http://technorati.com/tags/FsCheck" rel="tag"&gt;FsCheck&lt;/a&gt;,&lt;a href="http://technorati.com/tags/dnAnalytics" rel="tag"&gt;dnAnalytics&lt;/a&gt;,&lt;a href="http://technorati.com/tags/FsCheck%20case%20study" rel="tag"&gt;FsCheck case study&lt;/a&gt;&lt;/div&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-2292391042491882685?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/2292391042491882685/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=2292391042491882685" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/2292391042491882685" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/2292391042491882685" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/02/fschecking-dnanalytics.html" title="FsChecking dnAnalytics" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-2415132589755783157</id><published>2009-02-19T13:19:00.000-08:00</published><updated>2009-02-19T13:19:00.788-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fscheck" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title type="text">Announcing FsCheck 0.5</title><content type="html">&lt;p&gt;Another month has gone by, another release of FsCheck is a fact. (No, I won't keep this up). Check out the goodies.&lt;/p&gt;  &lt;h5&gt;Major:&lt;/h5&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h5&gt;&lt;/h5&gt;  &lt;h5&gt;&lt;/h5&gt;  &lt;ul&gt;   &lt;li&gt;Shrinking, which was introduced in FsCheck 0.4, is now fully customizable per type. This concludes the integration of Neil Mitchell's shrinking code (modulo the extra bugs I introduced, obviously)&lt;/li&gt;    &lt;li&gt;Combining properties using and, or, and giving a name to subproperties, similar to functionality in a port of QuickCheck to Scala: &lt;a href="http://code.google.com/p/scalacheck/"&gt;scalacheck&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Model based testing for stateful types, another shameless scalacheck rip-off. A surprisingly small extension to FsCheck that allows you to check stateful object types.&lt;/li&gt;    &lt;li&gt;Thanks to some excellent feedback from Ganesh (from the Cr&amp;#233;dit Suisse team, which has been generous with contributions; thanks!) property combinators have become more general, in particular any Lazy&amp;lt;property&amp;gt; can now be tested (as opposed to only Lazy&amp;lt;bool&amp;gt; in 0.4).&lt;/li&gt; &lt;/ul&gt;  &lt;h5&gt;&lt;/h5&gt;  &lt;h5&gt;Minor&lt;/h5&gt;  &lt;ul&gt;   &lt;li&gt;New property combinators: throws (expect an exception), within (expect a result within some time). The latter is from QuickCheck 2. &lt;/li&gt;    &lt;li&gt;New generator combinators: listOf, constant, suchThat, suchThatMaybe, again from QuickCheck 2.&lt;/li&gt;    &lt;li&gt;Pretty printing and shrinking of function values. You guessed it, ported from QuickCheck 2.&lt;/li&gt;    &lt;li&gt;Added support to TypeClass.fs to define typeclasses of arrays (this needs to be special cased since an array is not an ordinary generic type. Hurray for the consistencies of language design). FsCheck now also knows how to generate and shrink arrays.&lt;/li&gt;    &lt;li&gt;Added makefile for Mono users, thanks to toyvo. I've tried to keep it up to date, but have not tested it so let me know if you have any problems.&lt;/li&gt;    &lt;li&gt;Various bug fixes and smaller improvements.Notably the generator for discriminated unions should now produce &amp;quot;bigger&amp;quot; values, and the float generator now generates NaN, Infinity and Epsilon fairly often.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;With these changes, I can safely say that FsCheck 0.5 has reached near &lt;strong&gt;feature parity&lt;/strong&gt; with the &lt;strong&gt;combination(!)&lt;/strong&gt; of both QuickCheck 2.1.0.1 and Scalacheck 1.5. Not bad for half a release on a technology preview platform.&lt;/p&gt;  &lt;p&gt;I plan to let this stabilize over the next few months, and finally adding those FsChecks to FsCheck itself - FsCheck is fornicating priestware at the moment (*). I have however used FsCheck fairly frequently in private projects and I must say it has helped me a lot. Hopefully I'll have time to blog more about my experiences soon.&lt;/p&gt;  &lt;p&gt;As usual, let me know if you have any feedback, always a pleasure to hear from you!&lt;/p&gt;  &lt;p&gt;(*) i.e. it does not practice what it preaches&lt;/p&gt;  &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e204cfb1-01a0-4a8b-9d23-a88d2883b4bf" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati: &lt;a href="http://technorati.com/tags/F#" rel="tag"&gt;F#&lt;/a&gt;,&lt;a href="http://technorati.com/tags/FsCheck" rel="tag"&gt;FsCheck&lt;/a&gt;,&lt;a href="http://technorati.com/tags/quickcheck" rel="tag"&gt;quickcheck&lt;/a&gt;,&lt;a href="http://technorati.com/tags/scalacheck" rel="tag"&gt;scalacheck&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-2415132589755783157?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/2415132589755783157/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=2415132589755783157" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/2415132589755783157" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/2415132589755783157" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/02/announcing-fscheck-05.html" title="Announcing FsCheck 0.5" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-8208141365690014787</id><published>2009-01-24T06:28:00.000-08:00</published><updated>2009-01-24T06:30:20.178-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="howto" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title type="text">How to deal with out parameters in F#</title><content type="html">&lt;p&gt;This is the third installment of my modest '&lt;a href="http://fortysix-and-two.blogspot.com/2008/11/how-to-use-named-arguments-in-f.html"&gt;how&lt;/a&gt; &lt;a href="http://fortysix-and-two.blogspot.com/2008/12/how-to-change-accessibility-of.html"&gt;to&lt;/a&gt;' series, where I try to highlight some in my opinion unappreciated (or under-marketed) gems of F#: little language features that pleasantly surprised me when I first learned about them.&lt;/p&gt;  &lt;p&gt;Don't you hate out parameters? It's such a chore to use them: you need to declare a variable, pass it in the method with the out parameter modifier, and then check the results. Out parameters suck: they're just a poor excuse for not having to add a decent tuple type to your language. Unfortunately, some methods in the .NET framework use out parameters, and you might be dealing with some legacy code that uses them (some developers, apparently, think out parameters are the greatest idea since sliced bread).&lt;/p&gt;  &lt;p&gt;Luckily, calling methods with out parameters is very easy in F#: they are converted to a tuple type automatically. For example, the Math.DivRem method has the following signature:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public static int DivRem(&amp;#160; int a,&amp;#160; int b,&amp;#160; out int result )&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;which calculates the quotient of two numbers and also returns the remainder in an output parameter (in F#, this is a byref parameter).&lt;/p&gt;  &lt;p&gt;Using this method in F# is simple:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;(q,r) = Math.DivRem(n,d)&lt;/pre&gt;

&lt;p&gt;The out parameter has been automatically converted to the second element of the resulting tuple.&lt;/p&gt;

&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:54279d66-f19d-4747-88c5-dbb17325a93e" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati: &lt;a href="http://technorati.com/tags/F#" rel="tag"&gt;F#&lt;/a&gt;,&lt;a href="http://technorati.com/tags/out%20parameters" rel="tag"&gt;out parameters&lt;/a&gt;&lt;/div&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-8208141365690014787?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/8208141365690014787/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=8208141365690014787" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/8208141365690014787" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/8208141365690014787" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/01/how-to-deal-with-out-parameters-in-f.html" title="How to deal with out parameters in F#" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-4688677127452201799</id><published>2009-01-14T14:18:00.000-08:00</published><updated>2009-01-14T14:35:08.249-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fscheck" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title type="text">Announcing FsCheck 0.4</title><content type="html">&lt;p&gt;It's been a month and a half since &lt;a href="http://fortysix-and-two.blogspot.com/2008/12/announcing-fscheck-03.html"&gt;the last release&lt;/a&gt; of &lt;a href="http://www.codeplex.com/fscheck"&gt;FsCheck&lt;/a&gt;. Time for an update!&lt;/p&gt;  &lt;p&gt;Major changes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Rewrote the back end using &lt;a href="http://fortysix-and-two.blogspot.com/2009/01/poor-man-typeclass.html"&gt;typeclasses&lt;/a&gt;. The result: much less reflection, cleaner code, and improved flexibility in the property combinators. In particular, the 'prop' and 'propl' combinators can now be omitted. Properties can take any nunber of arguments, that do not need to be tupled. Generators can now be more easily defined, and function generators are also derived based on type. &lt;/li&gt;    &lt;li&gt;Two major new features were contributed generously by Howard Mansell and team at Credit Suisse. Most of the implementation was done by Neil Mitchell, who has also helped me a lot in integrating the changes in the main FsCheck branch. Thank you both!      &lt;br /&gt;The features are:       &lt;ul&gt;       &lt;li&gt;Automatic generation of records, discriminated unions (including recursive ones), arrays and tuples. So once you define a generator for a type, FsCheck can now automatically generate lists, arrays, record types, functions, discriminated unions and options involving that type. &lt;/li&gt;        &lt;li&gt;Shrinking. Especially with recursive datatypes, counter examples can become quite large. FsCheck now automatically shrinks these examples to a smaller one, making bug finding lots easier. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Minor changes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Some performance improvements &lt;/li&gt;    &lt;li&gt;Improvements in FsCheck's output. &lt;/li&gt;    &lt;li&gt;Factored out the function that prints the result of a test, so you can use it in your IRunner implementation if necessary &lt;/li&gt;    &lt;li&gt;Because FsCheck uses less reflection, stack traces of exceptions when a test case fails are shorter and clearer &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Breaking changes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;em&gt;quickCheck&lt;/em&gt; no longer checks types; instead use quickCheckAll, verboseCheckAll or checkAll. quickCheck is the preferred way to check properties: it is faster, clearer and more flexible. &lt;/li&gt;    &lt;li&gt;You'll need to redefine some of your custom generators; the mechanism to define and register generators has changed. See the manual for details, an don't hesitate to ask questions. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;This is a bit of an intermediary release - for v0.5 I'd like to integrate shrinking better, so you can define your own shrinkers for a given datatype. Should be straightforward now that I've reworked the back-end, but I wanted to get this release out first - I think shrinking and the reflective datatype generators by themselves are worth a new release. Most of the churn should be over now, I'm finally happy now with the way a user can define new properties and generators.&lt;/p&gt;  &lt;p&gt;Enjoy!&lt;/p&gt;  &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:88a391c5-626d-4a0f-8e70-59b6ce1741c9" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati: &lt;a href="http://technorati.com/tags/FsCheck" rel="tag"&gt;FsCheck&lt;/a&gt;,&lt;a href="http://technorati.com/tags/quickcheck" rel="tag"&gt;quickcheck&lt;/a&gt;,&lt;a href="http://technorati.com/tags/F#" rel="tag"&gt;F#&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-4688677127452201799?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/4688677127452201799/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=4688677127452201799" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/4688677127452201799" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/4688677127452201799" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/01/announcing-fscheck-04.html" title="Announcing FsCheck 0.4" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-6122047561001245374</id><published>2009-01-13T12:43:00.000-08:00</published><updated>2009-01-13T13:18:40.737-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><category scheme="http://www.blogger.com/atom/ns#" term="Reflection" /><category scheme="http://www.blogger.com/atom/ns#" term="Haskell" /><title type="text">A poor man's typeclass</title><content type="html">&lt;p&gt;This post contains a surprisingly short library which allows you to emulate Haskell's typeclasses in F#, except the type-safety. You might think that takes a lot away from the concept, but there is still plenty usefulness left. Not in the least it allows you to use an almost one-to-one translation of Haskell code including typeclasses to F#. At runtime both behave identically. In addition, since this is a library, its functionality can be extended beyond Haskell's typeclasses. Finally, if nothing else, you might be interested in how typeclasses work: this post shows you an implementation.&lt;/p&gt;  &lt;h5&gt;What is a typeclass, really?&lt;/h5&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;p&gt;If you don't know what typeclasses are, I recommend reading &lt;a href="http://book.realworldhaskell.org/read/using-typeclasses.html"&gt;this chapter&lt;/a&gt; in the excellent Real World Haskell book. Let's look at a simple example of a typeclass from that chapter:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;class BasicEq a where      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; isEqual :: a -&amp;gt; a -&amp;gt; Bool&lt;/p&gt;    &lt;p&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This &lt;em&gt;defines&lt;/em&gt; a typeclass BasicEq. All &lt;em&gt;instances&lt;/em&gt; (which are defined later) will need to provide a function isEqual, which compares two values of the instance a. An example of such an instance is:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;instance BasicEq Bool where      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; isEqual True&amp;#160; True&amp;#160; = True       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; isEqual False False = True       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; isEqual _&amp;#160;&amp;#160;&amp;#160;&amp;#160; _&amp;#160;&amp;#160;&amp;#160;&amp;#160; = False&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This example provides an instance of BasicEq for the type Bool. A lot of people coming from an OO background compare this with an abstract class BasicEq with a subclass Bool, when in fact it is nothing like that. There is absolutely no subtyping of any kind going on. The only relevant type here is Bool; after the instance definition Haskell just knows what isEqual function to call when applied to type Bool. There is absolutely no abstract class. Even more, although Bool is an already defined type, we are adding it as an instance of BasicEq after the fact, something which is not possible in any mainstream statically typed OO language with subtyping.&lt;/p&gt;  &lt;p&gt;Typeclasses are a form of so called &lt;em&gt;ad-hoc polymorphism.&lt;/em&gt; It has much more in common with operator overloading as it is known in F#, than with subclassing. In fact, the type of isEqual is:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;isEqual :: (BasicEq a) =&amp;gt; a -&amp;gt; a -&amp;gt; Bool&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This indicates that isEqual can be called on any instance a of the typeclass BasicEq. In fact, Haskell only knows the specific function to call when it knows the type a: then, it just looks up the functions associated with that type. So, in fact, the (BasicEq a) =&amp;gt; in front of the arguments can (besides as a type annotation) be seen as a dictionary that maps types a to functions implementing the BasicEq typeclass functions for a. The great thing about this is that because of type inference, the actual type a is inferred without any programmer annotation. So Haskell can choose the correct function to call automatically.&lt;/p&gt;  &lt;p&gt;So, in the end, what is a typeclass? It's just a dictionary from type to a record of functions, where on each application of a typeclass function Haskell passes along the dictionary to it's calling function implicitly (i.e. without requiring the caller to pass it in). Because of type inference, this sometimes looks like pulling a function or value out of thin air.&lt;/p&gt;  &lt;h5&gt;The idea&lt;/h5&gt;  &lt;p&gt;If a typeclass at runtime is nothing more than using type information to pass in an implicit parameter to a function, then in F# we can use respectively reflection and side effects to emulate much the same thing:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Using reflection, we can obtain the type arguments with which a function is called &lt;/li&gt;    &lt;li&gt;Using side effects, we can build a globally accessible dictionary of types to functions, that can be accessed &amp;quot;transparently&amp;quot;, without needing the caller to thread it in calls. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The rest is some syntactic sugar.&lt;/p&gt;  &lt;p&gt;Let's first look at how we can use the library, before diving into it's internals. Usage is remarkably similar to that of typeclasses. First, we &lt;em&gt;define &lt;/em&gt;the typeclass:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;IListOf&amp;lt;'a&amp;gt; =
    &lt;span style="color: blue"&gt;abstract &lt;/span&gt;ListOf : list&amp;lt;'a&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;This looks like a traditional class or interface type definition, that represents the functions in the typeclass. This type should have exactly one type parameter, which represents the type that we'll be defining instances for. &lt;/p&gt;

&lt;p&gt;Now, let's register this new typeclass with our library:&lt;/p&gt;

&lt;pre class="code"&gt;newTypeClass&amp;lt;IListOf&amp;lt;_&amp;gt;&amp;gt;&lt;/pre&gt;

&lt;p&gt;newTypeClass takes one generic parameter, of which only the generic type definition part is important; this registers IListOf&amp;lt;'a&amp;gt; as a typeclass with which instances for certain types 'a can be registered.&lt;/p&gt;

&lt;p&gt;Now, let's make some instances:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;IListOfInstances() =
    &lt;span style="color: blue"&gt;static member &lt;/span&gt;Unit() = 
        { &lt;span style="color: blue"&gt;new &lt;/span&gt;IListOf&amp;lt;unit&amp;gt; &lt;span style="color: blue"&gt;with
            override &lt;/span&gt;x.ListOf = [()]}
    &lt;span style="color: blue"&gt;static member &lt;/span&gt;Bool() = 
        { &lt;span style="color: blue"&gt;new &lt;/span&gt;IListOf&amp;lt;bool&amp;gt; &lt;span style="color: blue"&gt;with
            override &lt;/span&gt;x.ListOf = [&lt;span style="color: blue"&gt;true&lt;/span&gt;;&lt;span style="color: blue"&gt;false&lt;/span&gt;] }
    &lt;span style="color: blue"&gt;static member &lt;/span&gt;Int() = 
        { &lt;span style="color: blue"&gt;new &lt;/span&gt;IListOf&amp;lt;int&amp;gt; &lt;span style="color: blue"&gt;with
            override &lt;/span&gt;x.ListOf = [1..20] }&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;That defined instances for our typeclass IListOf with three instances for types unit, bool and int. As you can see, the corresponding interface implementations should be returned as the result of static members. &lt;/p&gt;

&lt;p&gt;These instances must now be registered with the typeclass:&lt;/p&gt;

&lt;pre class="code"&gt;registerInstances&amp;lt;IListOf&amp;lt;_&amp;gt;,IListOfInstances&amp;gt;()&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;A function that we need to give two type arguments: the typeclass we're registering instances for, and the the type with the static members which return the instances. &lt;/p&gt;

&lt;p&gt;Now we can get a specific IListOf implementation for a specific type:&lt;/p&gt;

&lt;pre class="code"&gt;getInstance (typedefof&amp;lt;IListOf&amp;lt;_&amp;gt;&amp;gt;,typeof&amp;lt;unit&amp;gt;)&lt;/pre&gt;

&lt;p&gt;However, this returns an obj - not nice. We'd like a typed listOf function that can be used whenever we want a list of some typeclass instance. Let's define such a function:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;listOf&amp;lt;'a&amp;gt; = getInstance (typedefof&amp;lt;IListOf&amp;lt;_&amp;gt;&amp;gt;,typeof&amp;lt;'a&amp;gt;) |&amp;gt; unbox&amp;lt;IListOf&amp;lt;'a&amp;gt;&amp;gt; |&amp;gt; (&lt;span style="color: blue"&gt;fun &lt;/span&gt;l &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;l.ListOf)&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The function takes only a type argument - which is used to get the instance, unbox the result (if the implementation of the typeclass library is correct, the unbox should always succeed), and then call the ListOf property which should return the correct list. This function can now be used just like an overloaded function:&lt;/p&gt;

&lt;pre class="code"&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;%A&amp;quot; &lt;/span&gt;(listOf |&amp;gt; List.map (&lt;span style="color: blue"&gt;fun &lt;/span&gt;x &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;x+5))
printfn &lt;span style="color: maroon"&gt;&amp;quot;%A&amp;quot; &lt;/span&gt;(listOf |&amp;gt; List.map (&lt;span style="color: blue"&gt;fun &lt;/span&gt;x &lt;span style="color: blue"&gt;-&amp;gt; if &lt;/span&gt;x &lt;span style="color: blue"&gt;then &lt;/span&gt;&lt;span style="color: maroon"&gt;&amp;quot;pos&amp;quot; &lt;/span&gt;&lt;span style="color: blue"&gt;else &lt;/span&gt;&lt;span style="color: maroon"&gt;&amp;quot;neg&amp;quot;&lt;/span&gt;))&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;What is going on? The first listOf returns a list of ints, while the second returns a list of bools, although it seems we're not passing it any argument or hint as to what list to produce. Magic? Of course not.&lt;/p&gt;

&lt;p&gt;We &lt;em&gt;are&lt;/em&gt; passing listOf information - in its type argument. The reason we don't have to explicitly mention this argument is because F# infers it for us. So this is a great way to let type inference do some work at runtime.&lt;/p&gt;

&lt;h5&gt;The implementation&lt;/h5&gt;

&lt;p&gt;The library maintains an internal dictionary of typeclass names to instances of that typeclass:&lt;/p&gt;

&lt;p&gt;&lt;span style="color: blue"&gt;let private &lt;/span&gt;typeClasses = &lt;span style="color: blue"&gt;new &lt;/span&gt;Dictionary&amp;lt;_,_&amp;gt;()&lt;/p&gt;

&lt;p&gt;Defining a new typeclass prepares the one value of that dictionary to hold another dictionary which will map the actual instance types to their implementation of the typeclass functions:&lt;/p&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;newTypeClass&amp;lt;'typeClass&amp;gt; = typeClasses.Add((typeof&amp;lt;'typeClass&amp;gt;).GetGenericTypeDefinition(), &lt;span style="color: blue"&gt;new &lt;/span&gt;Dictionary&amp;lt;_,_&amp;gt;())&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The following method then uses some reflection to find all the instances of a given typeclass, which should be defined as static members on a given class type:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let private &lt;/span&gt;findInstances (typeClass:Type) = 
    &lt;span style="color: blue"&gt;let &lt;/span&gt;addMethods l (t:Type) =
        t.GetMethods((BindingFlags.Static ||| BindingFlags.Public)) |&amp;gt;
        Seq.fold (&lt;span style="color: blue"&gt;fun &lt;/span&gt;l m &lt;span style="color: blue"&gt;-&amp;gt;
            match &lt;/span&gt;m.ReturnType &lt;span style="color: blue"&gt;with
                &lt;/span&gt;| GenericTypeDef typeClass args &lt;span style="color: blue"&gt;-&amp;gt; 
                    if &lt;/span&gt;(args.Length &amp;lt;&amp;gt; 1) &lt;span style="color: blue"&gt;then
                        &lt;/span&gt;failwithf &lt;span style="color: maroon"&gt;&amp;quot;Typeclasses must have exactly one generic parameter. Typeclass %A has %i&amp;quot; &lt;/span&gt;typeClass args.Length
                    &lt;span style="color: blue"&gt;else
                        let &lt;/span&gt;instance = args.[0]
                        &lt;span style="color: blue"&gt;if &lt;/span&gt;instance.IsGenericType 
                            &amp;amp;&amp;amp; (instance.GetGenericArguments() |&amp;gt; Array.for_all (&lt;span style="color: blue"&gt;fun &lt;/span&gt;t &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;t.IsGenericParameter)) &lt;span style="color: blue"&gt;then
                            &lt;/span&gt;(args.[0].GetGenericTypeDefinition(), m) :: l   
                        &lt;span style="color: blue"&gt;else
                            &lt;/span&gt;(args.[0], m) :: l
                | _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;l
            ) l
    addMethods []&lt;/pre&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;///Register instances in a given class as instances of the given type class. 
&lt;/span&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;registerInstancesByType typeClass instance =
    findInstances typeClass instance |&amp;gt; Seq.iter (typeClasses.[typeClass].Add)

&lt;span style="color: green"&gt;///Register instances in a given class as instances of the given type class.
&lt;/span&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;registerInstances&amp;lt;'typeClass,'instance&amp;gt;() = &lt;span style="color: green"&gt;
    &lt;/span&gt;registerInstancesByType (typedefof&amp;lt;'typeClass&amp;gt;) (typeof&amp;lt;'instance&amp;gt;)&lt;/pre&gt;

&lt;p&gt;The final ingredient is the lookup function, to get the implementation of a typeclass given a type:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;getInstance   =
    memoize (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(typeClass:Type, instance:Type) &lt;span style="color: blue"&gt;-&amp;gt;
        let &lt;/span&gt;instances = typeClasses.[typeClass]
        &lt;span style="color: blue"&gt;let &lt;/span&gt;mi =
            &lt;span style="color: blue"&gt;match &lt;/span&gt;instances.TryGetValue(instance) &lt;span style="color: blue"&gt;with
            &lt;/span&gt;| (&lt;span style="color: blue"&gt;true&lt;/span&gt;, res) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;res
            | _ &lt;span style="color: blue"&gt;when &lt;/span&gt;instance.IsGenericType &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;&lt;span style="color: green"&gt;//exact type is not known, try the generic type
                &lt;/span&gt;&lt;span style="color: blue"&gt;match &lt;/span&gt;instances.TryGetValue(instance.GetGenericTypeDefinition()) &lt;span style="color: blue"&gt;with
                &lt;/span&gt;| (&lt;span style="color: blue"&gt;true&lt;/span&gt;, mi') &lt;span style="color: blue"&gt;-&amp;gt; if &lt;/span&gt;mi'.ContainsGenericParameters &lt;span style="color: blue"&gt;then &lt;/span&gt;(mi'.MakeGenericMethod(instance.GetGenericArguments())) &lt;span style="color: blue"&gt;else &lt;/span&gt;mi'
                | _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;failwithf &lt;span style="color: maroon"&gt;&amp;quot;No instances of class %A for type %A&amp;quot; &lt;/span&gt;typeClass instance 
            | _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;failwithf &lt;span style="color: maroon"&gt;&amp;quot;No instances of class %A for type %A&amp;quot; &lt;/span&gt;typeClass instance 
        mi.Invoke(&lt;span style="color: blue"&gt;null&lt;/span&gt;, Array.empty))&lt;/pre&gt;

&lt;p&gt;There is some heavy reflection going on here, which I'll let you figure out in your own time. The memoize function I took from the Expert F# book. Full implementation is downloadable below.&lt;/p&gt;

&lt;h5&gt;Conclusions&lt;/h5&gt;

&lt;p&gt;This posts shows how to get all the advantages of typeclasses in F#, except the static checking. I've found these advantages considerable:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The use of reflection is heavy, but it is very nicely encapsulated: all the un-typesafeness goes on strictly inside the library and definition. What goes in and what comes out is strongly typed, and from a user point of view, the reflection is completely behind the scenes. &lt;/li&gt;

  &lt;li&gt;Although reflection is involved, it is actually fast: there is some manipulation of&amp;#160; Types, but this is highly optimized in .NET. There is one reflective invocation per instance that is looked up, but the result is memoized so this can be considered startup cost. Finally, there are two constant time dictionary lookups. &lt;/li&gt;

  &lt;li&gt;To give a real world example, in FsCheck 0.4 (which will be out real soon) I have been able to use this simple library to translate the Arbitrary and Testable typeclasses from QuickCheck directly into F#, making property combinators more powerful. For one, there is no longer a need for the 'prop' and 'propl' functions, a feat which I was not able to accomplish using reflection alone (and I did try!). So the typeclass abstraction is a nice way to structure your code around overloading. &lt;/li&gt;

  &lt;li&gt;It has also allowed me to reduce the amount of reflection code in FsCheck and other projects - which is a Good Thing as reflection is always a pain to use. &lt;/li&gt;

  &lt;li&gt;It's a great way to let type inference work for you, also at run time. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, some things for the future:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;This library is not thread safe, although it could be made thread safe at the cost of some locking. &lt;/li&gt;

  &lt;li&gt;Are multi-parameter type classes possible using this technique? &lt;/li&gt;

  &lt;li&gt;... &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anyway, I hope that this post has shown that with some imagination and a little work, you can do great things with F#, not in the least thanks to a lot of infrastructure in the form of .NET libraries, without which this would not have been possible.&lt;/p&gt;

&lt;p&gt;Download &lt;a href="http://cid-f6a45280389d5d06.skydrive.live.com/self.aspx/Public/TypeClass.fs"&gt;the full implementation&lt;/a&gt;. It will also be distributed with FsCheck 0.4 (soon, I promise :).&lt;/p&gt;

&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:6eabc46d-3fac-4250-8dbe-796e7557dd24" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati: &lt;a href="http://technorati.com/tags/F#" rel="tag"&gt;F#&lt;/a&gt;,&lt;a href="http://technorati.com/tags/typeclass" rel="tag"&gt;typeclass&lt;/a&gt;,&lt;a href="http://technorati.com/tags/haskell" rel="tag"&gt;haskell&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-6122047561001245374?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/6122047561001245374/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=6122047561001245374" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/6122047561001245374" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/6122047561001245374" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2009/01/poor-man-typeclass.html" title="A poor man&amp;#39;s typeclass" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-4038301181282714909</id><published>2008-12-20T08:54:00.001-08:00</published><updated>2008-12-20T08:54:19.949-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="howto" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title type="text">How to change the accessibility of a constructor using implicit object construction</title><content type="html">&lt;p&gt;The recommended way to define a class in F# is by using so-called implicit object construction.&amp;#160; The more traditional (for C# programmers, that is) but typically more tedious explicit object construction syntax feels distinctly less &amp;quot;functional&amp;quot;. In short, implicit construction relieves you of writing an explicit constructor for your class, and also allows you to use let and do clauses in the body of your class that take the place of static or instance initializers. Check out &lt;a href="http://www.strangelights.com/blog/"&gt;Robert Pickering&lt;/a&gt;'s &lt;a href="http://www.strangelights.com/fsharp/wiki/default.aspx/FSharpWiki/ObjectModelSyntaxExamples.html"&gt;F# wiki&lt;/a&gt; for a nice overview.&lt;/p&gt;  &lt;p&gt;The other day I was writing a class that needs &lt;em&gt;only&lt;/em&gt; factory methods to construct it, a not so uncommon pattern. In C#, I wouldn't think twice about how to do this: just add a private or internal constructor, and a few public factory methods. This is also straightforward to do using F#'s &lt;em&gt;explicit&lt;/em&gt; object construction syntax, but &lt;a href="http://cs.hubfs.net/forums/7697/ShowThread.aspx#7697"&gt;I wondered&lt;/a&gt; if it is possible using implicit construction. Turns out it is!&lt;/p&gt;  &lt;p&gt;The trick is simple:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Foo &lt;span style="color: blue"&gt;internal&lt;/span&gt;()=&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;static member &lt;/span&gt;FactoryMethod = &lt;span style="color: blue"&gt;new &lt;/span&gt;Foo()&lt;/pre&gt;

  &lt;p&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Notice the position of the 'internal' modifier. Modifying the accessibility of the 'Foo' class proper is done in the usual way, by putting the modifier right after the 'type' keyword. You can even mix these up: &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type internal &lt;/span&gt;Foo &lt;span style="color: blue"&gt;private&lt;/span&gt;()=&lt;/pre&gt;

&lt;p&gt;This defines an internal class with a private constructor.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="http://lorgonblog.spaces.live.com/"&gt;Brian&lt;/a&gt; and &lt;a href="http://tomasp.net/default.aspx"&gt;Tomas&lt;/a&gt; for helping me out on this one!&lt;/p&gt;

&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:9403e3f9-1c16-413e-9237-d0c48e74e265" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati: &lt;a href="http://technorati.com/tags/F#" rel="tag"&gt;F#&lt;/a&gt;,&lt;a href="http://technorati.com/tags/implicit%20object%20construction" rel="tag"&gt;implicit object construction&lt;/a&gt;,&lt;a href="http://technorati.com/tags/syntax" rel="tag"&gt;syntax&lt;/a&gt;,&lt;a href="http://technorati.com/tags/accessibility%20modifier" rel="tag"&gt;accessibility modifier&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-4038301181282714909?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/4038301181282714909/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=4038301181282714909" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/4038301181282714909" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/4038301181282714909" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2008/12/how-to-change-accessibility-of.html" title="How to change the accessibility of a constructor using implicit object construction" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-608295331109105948</id><published>2008-12-03T14:28:00.000-08:00</published><updated>2008-12-05T03:35:00.206-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fscheck" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title type="text">Announcing FsCheck 0.3</title><content type="html">&lt;p&gt;I am very pleased to announce a new release of &lt;a href="http://www.codeplex.com/fscheck" target="_blank"&gt;FsCheck&lt;/a&gt;, for the first time on codeplex! Here is a short description.&lt;/p&gt;  &lt;p&gt;FsCheck is a port of Haskell's QuickCheck: it is a tool for testing F# programs automatically. The programmer provides a specification of the program, in the form of properties which functions, methods or objects should satisfy, and FsCheck then tests that the properties hold in a large number of randomly generated cases. While writing the properties, you are actually writing a testable specification of your program. Specifications are expressed in F#, using combinators defined in the FsCheck library. FsCheck provides combinators to define properties, observe the distribution of test data, and define test data generators.&lt;/p&gt;  &lt;p&gt;This release brings FsCheck about up to par with QuickCheck 0.1, and adds some smaller features. An overview:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Added feature to derive a generator from the type of arguments. You can add your own generators for custom types. Radically reduces the use of forAll. &lt;/li&gt;    &lt;li&gt;Added feature to reduce use of prop and propl. For example: &amp;quot;quickCheck (fun a -&amp;gt; a+a = 2*a)&amp;quot; just works. &lt;/li&gt;    &lt;li&gt;Added feature to group related properties in a class, and check it at once. Can also be used to check all toplevel properties in a module. &lt;/li&gt;    &lt;li&gt;FsChecks no longer dies when a property throws an exception, but reports a test failure. &lt;/li&gt;    &lt;li&gt;Bug fixes and suggestions received through this blog, email and hubfs implemented. Thanks Neil, Chance, Mat and Anton, and everyone who emailed me! &lt;/li&gt;    &lt;li&gt;Some extension points to use FsCheck with whateverUnit frameworks. &lt;/li&gt;    &lt;li&gt;Updated examples, and documentation, the whole codeplex thing. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;It was a lot of work, but I hope it was worth it. &lt;/p&gt;  &lt;p&gt;I plan to devote more of my time to other projects from now on, at least for the next coming months. That said, your contributions to FsCheck are more than welcome. Besides, this release should keep you quiet for a while ;).&lt;/p&gt;  &lt;p&gt;I will be posting some suggestions for features and improvements soon, should you run out of ideas. &lt;/p&gt;  &lt;p&gt;[Update: check out &lt;a href="http://www.codeplex.com/fscheck/WorkItem/List.aspx"&gt;the FsCheck issue tracker&lt;/a&gt; for some ideas on how to contribute]&lt;/p&gt;  &lt;p&gt;   &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:97a0d6ce-fa45-4f68-a4e7-ce92b0cb0380" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati: &lt;a href="http://technorati.com/tags/F#" rel="tag"&gt;F#&lt;/a&gt;,&lt;a href="http://technorati.com/tags/FsCheck" rel="tag"&gt;FsCheck&lt;/a&gt;,&lt;a href="http://technorati.com/tags/random%20testing" rel="tag"&gt;random testing&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-608295331109105948?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/608295331109105948/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=608295331109105948" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/608295331109105948" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/608295331109105948" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2008/12/announcing-fscheck-03.html" title="Announcing FsCheck 0.3" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-8531321898948032867</id><published>2008-11-15T06:18:00.000-08:00</published><updated>2008-11-15T06:20:33.338-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fscheck" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title type="text">Future plans for FsCheck</title><content type="html">&lt;p&gt;Because of a &lt;a href="http://cs.hubfs.net/forums/7757/ShowThread.aspx#7757"&gt;recent question&lt;/a&gt; on HubFS, I made my future plans for &lt;a href="http://fortysix-and-two.blogspot.com/2008/05/fscheck-random-testing-for-f.html"&gt;FsCheck&lt;/a&gt; public. I'm re-iterating them here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;smaller bug fixes, some cleaning (mostly done) &lt;/li&gt;    &lt;li&gt;adding FsCheck.fsi module declaration &amp;amp; comments &lt;/li&gt;    &lt;li&gt;Feature: derive generators from types of arguments (mostly done) &lt;/li&gt;    &lt;li&gt;Feature: ability to group properties in classes, and check the class with one command (mostly done) &lt;/li&gt;    &lt;li&gt;Investigate using FsCheck with unit testing frameworks like MbUnit &amp;amp; co, or generally how to use it in practice (currently active) &lt;/li&gt;    &lt;li&gt;putting the project on codeplex + clarifying license . I'm checking compatibility with the QuickCheck license, but I'm aiming for a permissive license, like the new BSD license. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I intend to finalize this before the end of the year. &lt;/p&gt;  &lt;p&gt;Finally, you can help by answering the following question. How are you using FsCheck? Do you have a separate console app that you run that contains your properties, or do you use F# interactive with the properties inline, or something else?&lt;/p&gt;  &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:4cbc25ee-20dd-4a99-b68d-135b52dd0dc8" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati: &lt;a href="http://technorati.com/tags/F#" rel="tag"&gt;F#&lt;/a&gt;,&lt;a href="http://technorati.com/tags/random%20testing" rel="tag"&gt;random testing&lt;/a&gt;,&lt;a href="http://technorati.com/tags/FsCheck" rel="tag"&gt;FsCheck&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-8531321898948032867?l=fortysix-and-two.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://fortysix-and-two.blogspot.com/feeds/8531321898948032867/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4129300230262819780&amp;postID=8531321898948032867" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/8531321898948032867" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4129300230262819780/posts/default/8531321898948032867" /><link rel="alternate" type="text/html" href="http://fortysix-and-two.blogspot.com/2008/11/future-plans-for-fscheck.html" title="Future plans for FsCheck" /><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>kurt.schelfthout@gmail.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="02592177143352984164" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total></entry></feed>
