<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4129300230262819780</id><updated>2012-01-05T19:37:45.488Z</updated><category term='Haskell'/><category term='Visual Studio'/><category term='Reflection'/><category term='fscheck case study'/><category term='WCF'/><category term='fslex'/><category term='howto'/><category term='quotations'/><category term='graph control'/><category term='fscheck'/><category term='xunit'/><category term='tidbits'/><category term='F#'/><category term='fsyacc'/><category term='code contracts'/><category term='parsing'/><category term='mercurial'/><category term='WPF'/><category term='API design'/><category term='dnanalytics'/><category term='rant'/><category term='backtracking'/><title type='text'>Forty Six and Two</title><subtitle type='html'></subtitle><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='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>49</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-1687402776478302087</id><published>2012-01-04T01:46:00.000Z</published><updated>2012-01-04T01:50:36.992Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><category scheme='http://www.blogger.com/atom/ns#' term='API design'/><title type='text'>API design: Record types and backwards compatibility</title><content type='html'>&lt;p&gt;If you’re designing an API in F#, be very careful when exposing any of the public types as record types. Record types, as they stand in F# 2.0, by default are impossible to change while keeping backwards binary compatibility.&lt;/p&gt;  &lt;p&gt;Let’s look at a couple of changes that you might want to make to a record type:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Adding a new field. &lt;/li&gt;    &lt;li&gt;Changing the type of a field. &lt;/li&gt;    &lt;li&gt;Changing the order of the fields. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;None of these changes are backwards compatible. A record type is compiled by F# to a normal .NET class, with a constructor that takes the fields as arguments. This means order of the fields matters, and also the number and types of fields of course. Accessing the record fields is accomplished through a getter for each of the fields. So if your clients are using a very limited usage pattern – basically only accessing an existing record type using a getter – you may be alright with 1 and 3, and even 2 if they don’t happen to access the particular field whose type you’re changing. Anything else, including &lt;em&gt;with &lt;/em&gt;syntax, is a no-no. &lt;/p&gt;  &lt;p&gt;To make this abundantly clear – a record type definition and usage:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;MyRecord =
    { Field : int
      SecondField : string }

&lt;span style="color: blue"&gt;let &lt;/span&gt;instance = { Field = 3; SecondField = &lt;span style="color: maroon"&gt;&amp;quot;3&amp;quot; &lt;/span&gt;}&lt;/pre&gt;

&lt;p&gt;Is translated by the F# compiler to:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;MyRecordTranslated(field:int,secondfield:string) =
    &lt;span style="color: blue"&gt;member &lt;/span&gt;this.Field = field
    &lt;span style="color: blue"&gt;member &lt;/span&gt;this.SecondField = secondfield

&lt;span style="color: blue"&gt;let &lt;/span&gt;instanceTranslated = &lt;span style="color: blue"&gt;new &lt;/span&gt;MyRecordTranslated(3,&lt;span style="color: maroon"&gt;&amp;quot;3&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;p&gt;Now in the translated case, it’s intuitively clear that changing the order of the arguments in the constructor is not backwards compatible. With the record syntax however, the F# syntax makes the record type look like a bag of fields. However, the compiler looks up the one and only constructor for the type, and explicitly calls that. So, if you change the constructor in any way, clients are going to fail at runtime if they are not recompiled first.&lt;/p&gt;

&lt;h4&gt;&lt;/h4&gt;

&lt;h4&gt;Two solutions (sort of)&lt;/h4&gt;

&lt;p&gt;The first solution is not to use record types as part of a public API that needs to be backwards compatible – use class types instead.&lt;/p&gt;

&lt;p&gt;If record types are still handy, say because they have automatic value-based comparison and equality, then with some planning you can still use them – but to your clients they won’t look much like record types anymore, because we’re going to prevent clients from accessing the constructor and getters (unfortunately there’s no way to set accessibility on those two separately). And there is a lot of tedious code involved. Here’s an example – here’s the first version of a “record type” that can be kept backwards compatible:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;module &lt;/span&gt;A_v0 =
    &lt;span style="color: blue"&gt;type &lt;/span&gt;MyRecord =
        &lt;span style="color: blue"&gt;internal &lt;/span&gt;{ _Field : int } &lt;span style="color: blue"&gt;with
        static member &lt;/span&gt;Create(field:int) = { _Field = field }
        &lt;span style="color: blue"&gt;member &lt;/span&gt;this.Field = this._Field
        &lt;span style="color: blue"&gt;member &lt;/span&gt;this.With(?Field:int) = { this &lt;span style="color: blue"&gt;with &lt;/span&gt;_Field = defaultArg Field this.Field }  &lt;/pre&gt;

&lt;p&gt;Note that the most important change is that we made the constructor internal (private does not make much sense, as everything in the assembly of the record type itself should be trivial to update in concert with any change to the record type). To create the record type from outside of the assembly there is the factory method ‘Create’. Note that using F# method call syntax, we can still make this look much like a record type: ‘MyRecord.Create(field=3)’ for example.&lt;/p&gt;

&lt;p&gt;Then we need to provide a getter for each field ourselves (because we’ve made them internal...). I’ve chosen to start the actual field names with an underscore above, just to allow the explicit getters.&lt;/p&gt;

&lt;p&gt;Finally, using optional fields, we can regain some sort of with syntax. Here’s an example of usage:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;a = A_v0.MyRecord.Create(2).With(Field = 3).Field&lt;/pre&gt;

&lt;p&gt;Now, suppose we want to add a new field. We can do that as follows, without breaking any clients:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;module &lt;/span&gt;A_v1 =
    &lt;span style="color: blue"&gt;type &lt;/span&gt;MyRecord =
        &lt;span style="color: blue"&gt;internal &lt;/span&gt;{ _Field : int 
                   _Foo   : string } &lt;span style="color: blue"&gt;with
        static member &lt;/span&gt;Create(field:int) = { _Field = field; _Foo = &lt;span style="color: maroon"&gt;&amp;quot;default&amp;quot; &lt;/span&gt;}
        &lt;span style="color: blue"&gt;static member &lt;/span&gt;Create(field:int,foo:string) = { _Field = field; _Foo = foo }
        &lt;span style="color: blue"&gt;member &lt;/span&gt;this.Field = this._Field
        &lt;span style="color: blue"&gt;member &lt;/span&gt;this.Foo = this._Foo
        &lt;span style="color: blue"&gt;member &lt;/span&gt;this.With(?Field:int) = { this &lt;span style="color: blue"&gt;with &lt;/span&gt;_Field = defaultArg Field this.Field }                                   
        &lt;span style="color: blue"&gt;member &lt;/span&gt;this.With(?Field:int,?Foo:string) = { this &lt;span style="color: blue"&gt;with &lt;/span&gt;_Field = defaultArg Field this.Field
                                                               _Foo = defaultArg Foo this.Foo }&lt;/pre&gt;

&lt;p&gt;Note how we can now use overloading of both Create and With to our advantage.&lt;/p&gt;

&lt;p&gt;In this way, we prevent clients from using the record constructor directly, but pay the cost of re-implementing most of the useful functionality for record types ourselves. It’s not much less work than basically doing the same with a class type.&lt;/p&gt;

&lt;h4&gt;Can F# v_next solve this?&lt;/h4&gt;

&lt;p&gt;The&amp;#160; problem is that the syntax is deceiving: it looks like the order of arguments does not matter – both in the definition syntax, and in construction syntax. Also, if you use ‘with’ it looks like the call is resilient to adding a new field. And in fact, it is as long as you recompile – which makes the problem worse in some sense as a programmer will see her intuitions confirmed with every compilation. &lt;/p&gt;

&lt;p&gt;Given that the syntax is pretty much set in stone at this point, I don’t see a good way around it. If you want to keep the illusion of order-independence of the fields, one thing to do is make the compiler generate some kind of discovery phase at runtime, which would incur an unreasonable performance cost. Another approach would be to have Set method per field that returns a new record instance, and make the constructor private – but then setting many fields would involve as many object creations – again unreasonable for performance reasons.&lt;/p&gt;

&lt;p&gt;In fact, I don’t think this is such a big problem at all, as 95% of users will probably not encounter it, and for them the abstraction is valid. What v next could address though, is a way for the other 5% to control backwards compatibility of record types better.&lt;/p&gt;

&lt;p&gt;A first idea would be to allow the declaration of “optional fields”, and compile those as overloaded constructors – say you could write:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;MyRecord =
    { Field : int
      SecondField : string
      ?OptionalField = 5 }&lt;/pre&gt;

&lt;p&gt;which would be compiled to:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;MyRecordTranslated(field:int,secondfield:string, optionalField:int) =
        &lt;span style="color: blue"&gt;new&lt;/span&gt;(field:int,secondfield:string) = MyRecordTranslated(field,secondfield, 5)
        &lt;span style="color: blue"&gt;member &lt;/span&gt;this.Field = field
        &lt;span style="color: blue"&gt;member &lt;/span&gt;this.SecondField = secondfield
        &lt;span style="color: blue"&gt;member &lt;/span&gt;this.OptionalField = optionalField&lt;/pre&gt;

&lt;p&gt;I.e. make an overloaded constructor per optional field, and the F# compiler can enforce that optional fields should always be last in the definition. This shouldn’t be too much of a surprise, as the same restriction holds for optional arguments, and also helps somewhat to counter the wrong intuition that order of record fields does not matter. This would at least allow people to add new optional fields without breaking backwards compatibility.&lt;/p&gt;

&lt;p&gt;Another option is to explicitly allow overloaded constructors – similar to the implicit class definition syntax, it could be enforced that all the overloads call into the same constructor. Syntax may be a bit of a pain, but I’m sure something can be worked out.&lt;/p&gt;

&lt;p&gt;Finally, it would be good to be able to control the visibility of the constructor and the getters separately. In fact it would be nice for other reasons too to control accessibility of the getter for each field separately anyway. internal/private could be allowed in front of the field definitions to control visibility of the getter, while the visibility in front of the curly brace, as now, would only influence visibility of the constructor.&lt;/p&gt;

&lt;p&gt;In retrospect, I think there’s something to be said for having the compiler emit a warning or even error when constructing a record type with the fields in a different order from the record type definition, if only to counter the wrong intuition.&lt;/p&gt;

&lt;p&gt;I believe the best option here is the second one, allowing overloaded constructors. 3 and 4 are not backwards compatible as far as the F# compiler is concerned, and although the optional fields are nice, this is probably best left as some syntactic sugar over real overloaded constructors as the latter are more flexible.&lt;/p&gt;

&lt;h4&gt;&lt;/h4&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;Binary compatibility may not be a big issue for you. It’s certainly not an issue if you don’t expose any programmatic API as part of your F# projects. In that case, live happily ever after.&lt;/p&gt;

&lt;p&gt;On the other hand, you may want to think about giving yourself some flexibility in keeping your API backwards compatible. In that case, hopefully this post has given you some tools to come up with an appropriate strategy. Note that if you can reasonably expect that your clients will recompile whenever you release a new version, the whole problem is moot too.&lt;/p&gt;

&lt;p&gt;Overall many F# programmers don’t need to consider this at all. However it deserves a bit more attention than it’s getting, and might catch some people unaware (it certainly caught me out at some point...).&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 MSDN!" href="http://social.msdn.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2012/01/api-design-record-types-and-backwards.html&amp;amp;ttl=API design: Record types and backwards compatibility" target="_blank"&gt;&lt;img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/msdn.png" /&gt;MSDN!&lt;/a&gt;&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/2012/01/api-design-record-types-and-backwards.html&amp;amp;ttl=API design: Record types and backwards compatibility" 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/2012/01/api-design-record-types-and-backwards.html&amp;amp;;title=API design: Record types and backwards compatibility" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" /&gt;Del.icio.us!&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/2012/01/api-design-record-types-and-backwards.html&amp;amp;title=API design: Record types and backwards compatibility" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" /&gt;Digg!&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/2012/01/api-design-record-types-and-backwards.html&amp;amp;title=API design: Record types and backwards compatibility" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" /&gt;Dotnetkicks!&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/2012/01/api-design-record-types-and-backwards.html&amp;amp;title=API design: Record types and backwards compatibility" 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/2012/01/api-design-record-types-and-backwards.html&amp;amp;title=API design: Record types and backwards compatibility" 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-1687402776478302087?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/1687402776478302087/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2012/01/api-design-record-types-and-backwards.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/1687402776478302087'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/1687402776478302087'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2012/01/api-design-record-types-and-backwards.html' title='API design: Record types and backwards compatibility'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-653759976705021198</id><published>2011-05-29T21:32:00.000+01:00</published><updated>2011-05-29T21:35:25.235+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fscheck'/><title type='text'>FsCheck 0.7.1: NuGet packaging</title><content type='html'>&lt;p&gt;I’ve released a minor update to &lt;a href="http://fscheck.codeplex.com"&gt;FsCheck&lt;/a&gt;, mostly so it can now be downloaded as a &lt;a href="http://nuget.codeplex.com"&gt;NuGet&lt;/a&gt; package. It also comes with source server support, courtesy of &lt;a href="http://www.symbolsource.org/"&gt;SymbolSource.org&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;Furthermore, there are a couple of bug fixes.&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:7de390ea-d1a4-4aaa-9aa6-169194274c8a" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &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;/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 MSDN!" href="http://social.msdn.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2011/05/fscheck-071-nuget-packaging.html&amp;amp;ttl=FsCheck 0.7.1: NuGet packaging" target="_blank"&gt;&lt;img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/msdn.png" /&gt;MSDN!&lt;/a&gt;&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/2011/05/fscheck-071-nuget-packaging.html&amp;amp;ttl=FsCheck 0.7.1: NuGet packaging" 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/2011/05/fscheck-071-nuget-packaging.html&amp;amp;;title=FsCheck 0.7.1: NuGet packaging" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" /&gt;Del.icio.us!&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/2011/05/fscheck-071-nuget-packaging.html&amp;amp;title=FsCheck 0.7.1: NuGet packaging" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" /&gt;Digg!&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/2011/05/fscheck-071-nuget-packaging.html&amp;amp;title=FsCheck 0.7.1: NuGet packaging" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" /&gt;Dotnetkicks!&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/2011/05/fscheck-071-nuget-packaging.html&amp;amp;title=FsCheck 0.7.1: NuGet packaging" 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/2011/05/fscheck-071-nuget-packaging.html&amp;amp;title=FsCheck 0.7.1: NuGet packaging" 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-653759976705021198?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/653759976705021198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2011/05/fscheck-071-nuget-packaging.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/653759976705021198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/653759976705021198'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2011/05/fscheck-071-nuget-packaging.html' title='FsCheck 0.7.1: NuGet packaging'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-6958191686218372401</id><published>2011-01-02T21:57:00.000Z</published><updated>2011-01-02T22:00:03.853Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><title type='text'>F# projects someone should start</title><content type='html'>&lt;p&gt;Some ideas for projects that would scratch a few itches I have. However it’s unlikely that I’ll ever have to time to actually get round to doing them myself, so by blogging about them I hope someone who is looking for ideas can pick one of these up and make them real. Hope there is some room after New Year’s resolutions! The difficulty and work involved varies widely. Look at it this way – if you pick one of these up, you can be assured you’ll have at least one user.&lt;/p&gt;  &lt;h4&gt;A usable documentation system&lt;/h4&gt;  &lt;p&gt;I’m not talking about xml doc comments here (although that is a part of it). It should be possible to come up with a good domain specific language to write documentation of any kind – be it straightforward API documentation, a tutorial or a cookbook, that is easy to keep up to date with the current API you’re documenting, and that can export to a variety of different formats.&lt;/p&gt;  &lt;p&gt;My main inspiration here is &lt;a href="http://docs.racket-lang.org/scribble/"&gt;Scribble&lt;/a&gt;, for &lt;a href="http://racket-lang.org/"&gt;Racket&lt;/a&gt; (formerly PLT Scheme). From the &lt;a href="http://www.cs.utah.edu/plt/publications/icfp09-fbf.pdf"&gt;scribble paper’s&lt;/a&gt; abstract:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Scribble is a system for writing library documentation, user guides, and tutorials. It builds on PLT Scheme’s technology for language extension, and at its heart is a new approach to connecting prose references with library bindings. Besides the base system, we have built Scribble libraries for JavaDoc-style API documentation, literate programming, and conference papers. We have used Scribble to produce thousands of pages of documentation for PLT Scheme; the new documentation is more complete, more accessible, and better organized, thanks in large part to Scribble’s ﬂexibility and the ease with which we cross-reference information across levels. This paper reports on the use of Scribble and on its design as both an extension and an extensible part of PLT Scheme.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The cool thing here is that you write your documentation in Scheme itself – you write a function or member in your text, and it uses the default name resolution rules to look up what you’re referring to, and if you say export to HTML, adds a hyperlink to the actual API documentation for that particular function. Also you can write a short program, have it typeset in place, along with the results of running the program. That would be hugely useful for cookbook style documentation.&lt;/p&gt;  &lt;p&gt;I realize it is probably not possible to do this in F# in the same way due to the lack of macros. Maybe &lt;a href="https://github.com/richhickey/clojure-clr"&gt;ClojureCLR&lt;/a&gt; would be a better choice. On the other hand, now that the F# compiler is open source – how about a compiler extension? For some inspiration closer to home, have a look at &lt;a href="http://www.agical.com/bumblebee/bumblebee_doc.html"&gt;BumbleBee&lt;/a&gt;. Bonus points for Visual Studio integration. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Difficulty&lt;/strong&gt;: Medium. The hard part is figuring out how to do this cleanly – but maybe a fairly straightforward pre-processor is enough to make people happy.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Work&lt;/strong&gt;: Lots. Getting all this stuff to work together reliably and preferably inside Visual Studio...that’ll take some time.&lt;/p&gt;  &lt;h4&gt;Mirror-based reflection library&lt;/h4&gt;  &lt;p&gt;Let’s face it. The reflection APIs in .NET suck. First of all, because I have to write APIs, and not API – I mean there’s System.Reflection, System.Reflection.Emit, CodeDOM, the Debugger API (what else is debugging if not reflecting over your code?), a separate API for F# reflection (and probably for any language that’s not C# or VB), Cecil, ReflectionOnlyLoad, Metadata reading in the F# PowerPack, and so on.&lt;/p&gt;  &lt;p&gt;This indicates insufficient abstraction of System.Reflection: if I’m playing with F# types, I&lt;em&gt;&amp;#160; cannot&lt;/em&gt; use GetType() – this exposes internal implementation details! The reflection API by itself cannot cope with other languages, or other types of reflection – hence the need for e.g. a separate debugging API, as it needs to cope with distributed debugging. Or for things like Cecil, to cope with situations where you don’t want to load an assembly and all its dependencies when you’re reflecting over it. Sadly, this sometimes makes it look like I'm learning the same old reflection API over and over again, except someone’s changed all the names. And don’t get me started on how many times&lt;a href="http://fortysix-and-two.blogspot.com/2008/03/reflection-type-unraveled.html"&gt; Type is overloaded&lt;/a&gt;. High cohesion, anyone?&lt;/p&gt;  &lt;p&gt;Enter m&lt;a href="http://bracha.org/mirrors.pdf"&gt;irror-based reflection&lt;/a&gt;, which is an idea that might solve these problems. Except of course, .NET does not have a library that uses this type of reflection. This is where you come in...for inspiration, &lt;a href="http://newspeaklanguage.org/"&gt;Newspeak&lt;/a&gt; has the beginnings of such an API. It should be possible to have a specific API that is clear in the limits of what it can do, while still sharing much of the concepts with very similar systems – imagine being able to use Cecil and System.Reflection but with the same names for everything possible. And if you ever need to reflect over a running program, you can use the debugging API, except you can leverage your existing knowledge. Obviously, the library should be pluggable so that people can plug their own reflection libraries in there.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Difficulty&lt;/strong&gt;: This may be a research problem. On the other hand, there are things to build on, and a motivated person or team could build, say, an introspection only API in a reasonable amount of time.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Work&lt;/strong&gt;: lots and lots, obviously. However, a proof of concept API that just does introspection of structure (not behaviour) would be enough to get more people on board and would already be useful.&lt;/p&gt;  &lt;h4&gt;Contribute to NuGet so it knows about F#&lt;/h4&gt;  &lt;p&gt;&lt;a href="http://nuget.codeplex.com"&gt;NuGet&lt;/a&gt; is a package manager for .NET . The current release does not work with F# – boo! However looks like David Fowler actually already went ahead and contributed some code to make this work! Excellent. However, keep voting &lt;a href="http://nuget.codeplex.com/workitem/374"&gt;the issue&lt;/a&gt; up so the NuGet team adds it to the next release :)&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Difficulty&lt;/strong&gt;: shouldn’t be all too hard – I gleaned at the source code and it looks like they’re using the Visual Studio Automation API. I know the F# project system’s implementation here is kind of shaky, so probably a bunch of workarounds is needed.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Work&lt;/strong&gt;: Not too much – mostly finding your way around the NuGet codebase and finding what works and what doesn’t in the F# language service..&lt;/p&gt;  &lt;h4&gt;Add snippets and organize usings support to the F# project system&lt;/h4&gt;  &lt;p&gt;I miss snippets. Sure, everything in F# is nice and short so the official story is that this isn’t needed as much as in C#, but still...oh, and while you’re at it, and now the compiler is open source (I love saying that – it makes everything look so easy) can we have organize usings too please? Bonus points for adding Refactor –&amp;gt; Rename.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Difficulty&lt;/strong&gt;: Straightforward. Only roadblock could be that the current F# language service is just not easily extensible for these kinds of things.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Work&lt;/strong&gt;: Reasonable. Finding your way around the Visual Studio language service extensibility model, and the F# compiler. Knowledge about this seems very useful to have, but I can’t deny it would take some time, obviously.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;That should give you enough to pass the time in 2011, I hope!&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 MSDN!" href="http://social.msdn.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2011/01/f-projects-someone-should-start.html&amp;amp;ttl=F# projects someone should start" target="_blank"&gt;&lt;img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/msdn.png" /&gt;MSDN!&lt;/a&gt;&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/2011/01/f-projects-someone-should-start.html&amp;amp;ttl=F# projects someone should start" 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/2011/01/f-projects-someone-should-start.html&amp;amp;;title=F# projects someone should start" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" /&gt;Del.icio.us!&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/2011/01/f-projects-someone-should-start.html&amp;amp;title=F# projects someone should start" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" /&gt;Digg!&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/2011/01/f-projects-someone-should-start.html&amp;amp;title=F# projects someone should start" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" /&gt;Dotnetkicks!&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/2011/01/f-projects-someone-should-start.html&amp;amp;title=F# projects someone should start" 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/2011/01/f-projects-someone-should-start.html&amp;amp;title=F# projects someone should start" 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-6958191686218372401?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/6958191686218372401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2011/01/f-projects-someone-should-start.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/6958191686218372401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/6958191686218372401'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2011/01/f-projects-someone-should-start.html' title='F# projects someone should start'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-8462105480361860034</id><published>2010-12-16T22:03:00.000Z</published><updated>2010-12-16T22:06:59.484Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='xunit'/><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><title type='text'>F#, xUnit theories and InlineData</title><content type='html'>&lt;p&gt;How do you know you haven’t blogged much lately? When you want to write a blog post and you forgot the name of the thing you’re actually writing it with. “Wait, it’s called Window Live something something…what did that icon look like again?”. Also, Windows Live Writer now has a ribbon! Good stuff.&lt;/p&gt;  &lt;p&gt;Anyway, just a short heads up to save people some time: in the &lt;a href="http://xunit.codeplex.com/"&gt;xUnit&lt;/a&gt; extensions, there is a Theory attribute which in combination with the InlineData attribute lets you specify a parameterized xUnit test. The InlineData attribute lets you specify the values the test should run with (you can’t test everything randomly with &lt;a href="http://fscheck.codeplex.com"&gt;FsCheck&lt;/a&gt;, you know). That and other xUnit extension goodies are explained &lt;a href="http://blog.benhall.me.uk/2008/01/introduction-to-xunitnet-extensions.html"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;My point is – this attribute does not work in F# (or managed C++), because the AttributeUsage attribute on the InlineData attribute is defined on its parent class, DataAttribute. It is correctly defined as Inherited = true; but only the C# compiler seems to honour this. More detailed explanation in &lt;a href="http://stackoverflow.com/questions/3116911/attribute-cannot-be-repeated-in-c-cli-but-ok-in-c"&gt;this stackoverflow post&lt;/a&gt;. If&amp;#160; you care about this, please &lt;a href="http://xunit.codeplex.com/workitem/9690"&gt;vote&lt;/a&gt; for the bug on the xUnit site!&lt;/p&gt;  &lt;p&gt;Luckily, the workaround is not too bad – just use the PropertyData attribute instead: &lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;symbolTestData = 
    [ &lt;span style="color: maroon"&gt;&amp;quot;an1 rest&amp;quot;&lt;/span&gt;,           &lt;span style="color: maroon"&gt;&amp;quot;an1&amp;quot;
      &amp;quot;?test bla&amp;quot;&lt;/span&gt;,          &lt;span style="color: maroon"&gt;&amp;quot;?test&amp;quot;
      &amp;quot;?+_est bla&amp;quot;&lt;/span&gt;,         &lt;span style="color: maroon"&gt;&amp;quot;?+_est&amp;quot;
      &amp;quot;+_123 bla&amp;quot;&lt;/span&gt;,          &lt;span style="color: maroon"&gt;&amp;quot;?+_123&amp;quot;
      &amp;quot;+._1.2.3 bla&amp;quot;&lt;/span&gt;,       &lt;span style="color: maroon"&gt;&amp;quot;+._1.2.3&amp;quot;
      &amp;quot;+_q1r-2g3! bla&amp;quot;&lt;/span&gt;,     &lt;span style="color: maroon"&gt;&amp;quot;+_q1r-2g3!&amp;quot;
      &amp;quot;abc.def.feg/q bla&amp;quot;&lt;/span&gt;,  &lt;span style="color: maroon"&gt;&amp;quot;abc.def.feg/q&amp;quot;
      &amp;quot;ab/cd? bla&amp;quot;&lt;/span&gt;,         &lt;span style="color: maroon"&gt;&amp;quot;ab/cd?&amp;quot;
    &lt;/span&gt;]
    |&amp;gt; Seq.map (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(a,b) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;[|a; b|])

[&amp;lt;Theory&amp;gt;]
[&amp;lt;PropertyData(&lt;span style="color: maroon"&gt;&amp;quot;symbolTestData&amp;quot;&lt;/span&gt;)&amp;gt;]
&lt;span style="color: blue"&gt;let &lt;/span&gt;``should parse symbol``(toParse:string, result:string) =
    Assert.Equal(result, run symbol result)&lt;/pre&gt;


&lt;p&gt;Note that xUnit actually expects a sequence of arrays, but I think the list of tuples looks better, at the small cost of an extra conversion step.&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:d5be2043-9637-4308-b6dc-31276abea777" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/xUnit" rel="tag"&gt;xUnit&lt;/a&gt;,&lt;a href="http://technorati.com/tags/F%23" rel="tag"&gt;F#&lt;/a&gt;,&lt;a href="http://technorati.com/tags/xUnit+Theory" rel="tag"&gt;xUnit Theory&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 MSDN!" href="http://social.msdn.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2010/12/f-xunit-theories-and-inlinedata.html&amp;amp;ttl=F#, xUnit theories and InlineData" target="_blank"&gt;&lt;img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/msdn.png" /&gt;&lt;/a&gt;&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/2010/12/f-xunit-theories-and-inlinedata.html&amp;amp;ttl=F#, xUnit theories and InlineData" 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/2010/12/f-xunit-theories-and-inlinedata.html&amp;amp;;title=F#, xUnit theories and InlineData" 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 Digg!" href="http://digg.com/submit?phase=2&amp;amp;url=http://fortysix-and-two.blogspot.com/2010/12/f-xunit-theories-and-inlinedata.html&amp;amp;title=F#, xUnit theories and InlineData" 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/2010/12/f-xunit-theories-and-inlinedata.html&amp;amp;title=F#, xUnit theories and InlineData" 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/2010/12/f-xunit-theories-and-inlinedata.html&amp;amp;title=F#, xUnit theories and InlineData" 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/2010/12/f-xunit-theories-and-inlinedata.html&amp;amp;title=F#, xUnit theories and InlineData" 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-8462105480361860034?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/8462105480361860034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2010/12/f-xunit-theories-and-inlinedata.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/8462105480361860034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/8462105480361860034'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2010/12/f-xunit-theories-and-inlinedata.html' title='F#, xUnit theories and InlineData'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-4182217485378532673</id><published>2010-07-10T17:26:00.000+01:00</published><updated>2010-07-10T17:29:45.536+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><category scheme='http://www.blogger.com/atom/ns#' term='code contracts'/><title type='text'>F# and Code Contracts: not quite there yet</title><content type='html'>&lt;p&gt;In this post I’ll show how you can get &lt;a href="http://msdn.microsoft.com/en-gb/devlabs/dd491992.aspx"&gt;Code Contracts&lt;/a&gt; sort of working for F#. From my very initial explorations, I would conclude that they seem basically usable for F# programming – but you’ll need some glue and tape, and not everything works as you’d expect. &lt;/p&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h4&gt;Code Contracts: the short story&lt;/h4&gt;  &lt;p&gt;Code contracts are a way to express pre- and postconditions and invariants for (theoretically) any CLR based programming language. This is a Very Good Thing, as such contracts are a great way to specify the expected behaviour of your program (i.e. your intent). &lt;/p&gt;  &lt;p&gt;Pragmatically, contracts are usually compiled into a debug build of a program, and checked at runtime. That’s how &lt;a href="http://www.eiffel.com/"&gt;Eiffel&lt;/a&gt; does it, where this whole contract thing got started. So every time your program runs, it’s actually being tested in a very deep way. That’s why a tool like Eiffel’s &lt;a href="http://se.inf.ethz.ch/people/ciupa/papers/icse08.pdf"&gt;ARTOO&lt;/a&gt;, which basically randomly constructs objects and calls method sequences on them, works well: you can find bugs by just executing your program randomly! Of course contracts are also good for documentation: no more looking in the code to find out what happens when you pass in 0 for a particular argument – the pre- and postcondition should tell you.&lt;/p&gt;  &lt;p&gt;In the .NET world Code Contracts delivers this kind of functionality by means of a rewriter. That is, you write your actual contracts in a contract language using the System.Diagnostics.Contracts namespace in .NET 4.0, but the methods you’re calling do not actually do much: instead the rewriter runs after the compilation phase on the resulting assembly, recognizes the calls and writes the actual contract checking code in the assembly. This is necessary for example because it’s very useful in a contract to be able to refer to the old value of a parameter, or to the result of the method. Without a rewriter, you’d basically just have something like Debug.Assert, which is not very expressive.&lt;/p&gt;  &lt;p&gt;MS research also has made a static checker for contracts, which tries to statically determine whether your contracts hold, and if so, is able to feed that information back to the rewriter so that statically checked contracts do not need to be checked at runtime. Personally I don’t think that is useful because it seems very imprecise. Time will tell – happy to be proven wrong.&lt;/p&gt;  &lt;p&gt;Since the rewriter works on the assemblies, you can just use the Contracts API from any .NET language, at least in theory. In practice, different compilers tend to output different representations of types or whatever construct they offer, so it’s not unthinkable that the rewriter gets confused. In fact, in the case of F# it gets confused when you try to write contracts in constructors, as we’ll see.&lt;/p&gt;  &lt;p&gt;So while nice in theory, this turns out to be another case of “It works for all .NET languages, as long as they’re exactly like C# or VB.” At least until the contracts folks get round to actually supporting F#, I guess.&lt;/p&gt;  &lt;h4&gt;The nuts and bolts&lt;/h4&gt;  &lt;p&gt;‘Nuff complaining. Let’s see how we get code contracts to work with F#.When you install the code contracts add-on, in C# you get a nice extra tab in your project properties. Not so in F# – but that’s the easy part. The whole rewriter thing is actually nicely abstracted away in some custom target file that the Code Contract folks have kindly provided, so we’ll just need some manual editing of the F# project file to get it to work. Here’s an example:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #a31515"&gt;xml &lt;/span&gt;&lt;span style="color: red"&gt;version&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;1.0&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;encoding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;utf-8&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;?&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Project &lt;/span&gt;&lt;span style="color: red"&gt;ToolsVersion&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;4.0&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;DefaultTargets&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Build&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;http://schemas.microsoft.com/developer/msbuild/2003&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;PropertyGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Configuration &lt;/span&gt;&lt;span style="color: red"&gt;Condition&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;'$(Configuration)' == '' &lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Debug&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Configuration&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Platform &lt;/span&gt;&lt;span style="color: red"&gt;Condition&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;'$(Platform)' == '' &lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;AnyCPU&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Platform&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ProductVersion&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;8.0.30703&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ProductVersion&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;SchemaVersion&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;2.0&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;SchemaVersion&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ProjectGuid&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;{dd086c3a-9cbd-4dc9-89d2-4386df7ee986}&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ProjectGuid&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;OutputType&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Exe&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;OutputType&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;RootNamespace&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;CodeContractsFs&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;RootNamespace&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;AssemblyName&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;CodeContractsFs&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;AssemblyName&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TargetFrameworkVersion&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;v4.0&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;TargetFrameworkVersion&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;CodeContractsFs&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
   &lt;strong&gt; &amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;&lt;span style="color: #a31515"&gt;CodeContractsAssemblyMode&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;1&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsAssemblyMode&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: blue"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;
  &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;PropertyGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;PropertyGroup &lt;/span&gt;&lt;span style="color: red"&gt;Condition&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;'$(Configuration)|$(Platform)' == 'Debug|AnyCPU' &lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;DebugSymbols&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;true&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;DebugSymbols&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;DebugType&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;full&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;DebugType&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Optimize&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;false&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Optimize&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Tailcalls&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;false&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Tailcalls&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;OutputPath&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;bin\Debug\&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;OutputPath&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;&lt;span style="color: #a31515"&gt;DefineConstants&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;TRACE;DEBUG;CONTRACTS_FULL&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;DefineConstants&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: blue"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;WarningLevel&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;3&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;WarningLevel&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;DocumentationFile&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;bin\Debug\CodeContractsFs.XML&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;DocumentationFile&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;&lt;span style="color: #a31515"&gt;CodeContractsEnableRuntimeChecking&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;True&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsEnableRuntimeChecking&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsRuntimeOnlyPublicSurface&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;False&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsRuntimeOnlyPublicSurface&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsRuntimeThrowOnFailure&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;True&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsRuntimeThrowOnFailure&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsRuntimeCallSiteRequires&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;False&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsRuntimeCallSiteRequires&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsRunCodeAnalysis&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;False&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsRunCodeAnalysis&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsNonNullObligations&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;False&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsNonNullObligations&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsBoundsObligations&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;False&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsBoundsObligations&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsArithmeticObligations&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;False&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsArithmeticObligations&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsRedundantAssumptions&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;False&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsRedundantAssumptions&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsRunInBackground&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;True&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsRunInBackground&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsShowSquigglies&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;False&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsShowSquigglies&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsUseBaseLine&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;False&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsUseBaseLine&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsEmitXMLDocs&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;False&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsEmitXMLDocs&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsCustomRewriterAssembly &lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsCustomRewriterClass &lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsLibPaths &lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsExtraRewriteOptions &lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsExtraAnalysisOptions &lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsBaseLineFile &lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsRuntimeCheckingLevel&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Full&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsRuntimeCheckingLevel&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsReferenceAssembly&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;%28none%29&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeContractsReferenceAssembly&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: blue"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;
  &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;PropertyGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;span style="color: blue"&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Reference &lt;/span&gt;&lt;span style="color: red"&gt;Include&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;mscorlib&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Reference &lt;/span&gt;&lt;span style="color: red"&gt;Include&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;FSharp.Core&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Reference &lt;/span&gt;&lt;span style="color: red"&gt;Include&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;System&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Reference &lt;/span&gt;&lt;span style="color: red"&gt;Include&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;System.Core&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Reference &lt;/span&gt;&lt;span style="color: red"&gt;Include&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;System.Numerics&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
  &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Compile &lt;/span&gt;&lt;span style="color: red"&gt;Include&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Module1.fs&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;None &lt;/span&gt;&lt;span style="color: red"&gt;Include&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Script.fsx&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
  &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Import &lt;/span&gt;&lt;span style="color: red"&gt;Project&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;Condition&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;!Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Import &lt;/span&gt;&lt;span style="color: red"&gt;Project&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;Condition&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Project&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;I’ve put the things to change from a vanilla F# project file in bold. I won’t go over all of them – you can experiment for yourself by playing with the UI in a C# project and checking what the effect is. The three important bits are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;CodeContractsAssemblyMode: per assembly, code contracts allows you to set it in either a compatibility mode (0) or the standard mode (1). For new assemblies, 1 is what you want.&lt;/li&gt;

  &lt;li&gt;CODECONTRACTS_FULL compile constant: if you don’t define this, the rewriter won’t write the contract checking methods in your assembly. So define this in you Debug configuration (or in a special Contracts configuration)&lt;/li&gt;

  &lt;li&gt;CodeContractsEnableRuntimeChecking: Otherwise the rewriter doesn’t kick in. Not sure why you’d need this and the constant, but there you go.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add this to your F# project and you should see the rewriter kick in after the build – it’s called ccrewrite.exe.&lt;/p&gt;

&lt;h4&gt;Let’s write some contracts&lt;/h4&gt;

&lt;p&gt;That was the easy part. Now, let’s try to convert the program given in the &lt;a href="http://download.microsoft.com/download/C/2/7/C2715F76-F56C-4D37-9231-EF8076B7EC13/userdoc.pdf"&gt;Code Contracts documentation&lt;/a&gt; to F#:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Rational(numerator,denominator) =
    &lt;span style="color: blue"&gt;do &lt;/span&gt;Contract.Requires( denominator &amp;lt;&amp;gt; 0 )
    [&amp;lt;ContractInvariantMethod&amp;gt;]
    &lt;span style="color: blue"&gt;let &lt;/span&gt;ObjectInvariant() = 
        Contract.Invariant ( denominator &amp;lt;&amp;gt; 0 )
    &lt;span style="color: blue"&gt;member &lt;/span&gt;x.Denominator =
        Contract.Ensures( Contract.Result&amp;lt;int&amp;gt;() &amp;lt;&amp;gt; 0 )
        denominator&lt;/pre&gt;

&lt;p&gt;So this is a simple rational type. It shows you basically how contracts work – you call methods on the Contract static class:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Contract.Requires to impose a precondition on arguments – in this case an argument of the constructor.&lt;/li&gt;

  &lt;li&gt;Contract.Ensures to express a postcondition – in this case a postcondition on the result of a getter, which is nicely accessible using Contract.Result.&lt;/li&gt;

  &lt;li&gt;ObjectInvariantMethodAttribute and Contract.Invariant to impose an invariant on a class – something that should hold after every execution of a method.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So far so good. Alas, when we try to build this, we get:&lt;/p&gt;

&lt;table border="1"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;
        &lt;pre&gt;warning CC1041: Invariant method must be private
error CC1011: This/Me cannot be used in Requires of a constructor
error CC1011: This/Me cannot be used in Requires of a constructor
error CC1011: This/Me cannot be used in Requires of a constructor
error CC1011: This/Me cannot be used in Requires of a constructor
error CC1038: Member 'Module1+Rational.denominator' has less visibility than the enclosing method 'Module1+Rational.#ctor(System.Object,System.Int32)'.: error CC1069: Detected expression statement evaluated for potential side-effect in contracts of method 'Module1+Rational.#ctor(System.Object,System.Int32)'. (Did you mean to put the expression into a Requires, Ensures, or Invariant call?) error CC1004: Malformed contract. Found Requires after assignment in method 'Module1+Rational.#ctor(System.Object,System.Int32)'.&lt;/pre&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;And it turns out that the rewriter is confused by F#’s representation of constructors. When we comment out the Contract.Requires in the constructor, everything works fine.&lt;/p&gt;

&lt;p&gt;The warning about the invariant method is because F# actually compiles private members as internal. The rewriter flags this using this warning, but it’s otherwise not much to worry about, I guess, though slightly annoying if you’re – like me – fairly obsessive about getting your code to compile without warnings.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;I’ve also checked code contracts with various pre-and postconditions to functions, and that seems to work fine. So overall it’s not a bad story, but it would be nice to see some better integration and to fix the bug(s).&lt;/p&gt;

&lt;p&gt;I haven’t checked other features of code contracts, like contract inheritance or expressing code contracts on interfaces, which needs a few tricks as well, so there is a chance that you’ll run into problems there.&lt;/p&gt;

&lt;p&gt;Finally, a tip: if you don’t like the C#-ish feel of the Contracts API, you can define your own inline functions that call into the actual API – given that they’re inlined, the rewriter will not see the difference.&lt;/p&gt;

&lt;p&gt;So close, but not quite there yet. I’ve &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/codecontracts/thread/dc7c8a56-0a80-4a5e-8413-31c7098833ad"&gt;asked a year ago&lt;/a&gt; if the situation was going to improve, and &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/codecontracts/thread/11b8c5e3-a25d-4770-a46d-14f24921e0a0"&gt;again a few weeks back&lt;/a&gt;, but it’s basically unchanged since then. So F#-ers: head over to the Code Contracts forum and ask for F# support! I’m feeling a bit alone in the desert there at the moment…&lt;/p&gt;

&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:b8790ac6-2d13-41be-9a59-542d0d7df7a2" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/F%23" rel="tag"&gt;F#&lt;/a&gt;,&lt;a href="http://technorati.com/tags/code+contracts" rel="tag"&gt;code contracts&lt;/a&gt;&lt;/div&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 MSDN!" href="http://social.msdn.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2010/07/f-and-code-contracts-not-quite-there.html&amp;amp;ttl=F# and Code Contracts:: not quite there yet" target="_blank"&gt;&lt;img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/msdn.png" /&gt;MSDN!&lt;/a&gt;&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/2010/07/f-and-code-contracts-not-quite-there.html&amp;amp;ttl=F# and Code Contracts:: not quite there yet" 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/2010/07/f-and-code-contracts-not-quite-there.html&amp;amp;;title=F# and Code Contracts:: not quite there yet" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" /&gt;Del.icio.us!&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/2010/07/f-and-code-contracts-not-quite-there.html&amp;amp;title=F# and Code Contracts:: not quite there yet" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" /&gt;Digg!&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/2010/07/f-and-code-contracts-not-quite-there.html&amp;amp;title=F# and Code Contracts:: not quite there yet" target="_blank"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" /&gt;Dotnetkicks!&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/2010/07/f-and-code-contracts-not-quite-there.html&amp;amp;title=F# and Code Contracts:: not quite there yet" 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/2010/07/f-and-code-contracts-not-quite-there.html&amp;amp;title=F# and Code Contracts:: not quite there yet" 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;span class="sbmLink"&gt;&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-4182217485378532673?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/4182217485378532673/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2010/07/f-and-code-contracts-not-quite-there.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/4182217485378532673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/4182217485378532673'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2010/07/f-and-code-contracts-not-quite-there.html' title='F# and Code Contracts: not quite there yet'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-3003708338896283695</id><published>2010-06-09T18:38:00.000+01:00</published><updated>2010-06-09T18:42:20.388+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><title type='text'>Thinking outside the Visual Studio box</title><content type='html'>&lt;p&gt;Visual Studio and .NET development go hand in hand. As far as I know, every .NET developer uses it. Compared to the Java IDE landscape, there isn’t even competition. And what little competition there is, is pretty much a carbon copy of the approach Visual Studio takes to development. Visual Studio is &lt;em&gt;incontournable&lt;/em&gt;, and there is little on the horizon that will change this situation.&lt;/p&gt;  &lt;h4&gt;What toothpicks and Visual Studio have in common&lt;/h4&gt;  &lt;p&gt;I did some Java development in &lt;a href="http://www.eclipse.org/"&gt;Eclipse&lt;/a&gt; over 3 years ago, and as I remember it, it worked better than Visual Studio 2010. Let me repeat that:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Eclipse 2007 (for Java) is a better IDE than Visual Studio 2010 (for C#).&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I don’t want to go into a feature by feature comparison. No doubt Visual Studio would win. I’m saying that for actual development, you know the thing you’re doing 95% of the time in an IDE, it’s just better. I believe these activities are compiling, testing, refactoring, browsing code and source control.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Compiling&lt;/strong&gt;. The most important feature of compilation is that you don’t see it. The incremental compilation in Eclipse is just way better. Even for medium sized projects, press Ctrl+S and your code is ready to run. Instantly. This is different from the incremental “compilation” Visual Studio does – while this updates intellisense info on the fly, it does not actually build your code. So if you want to test or run, you’ll have to wait.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Testing. &lt;/strong&gt;Eclipse comes with excellent JUnit integration out of the box. I guess there’s MSTest for Visual Studio, which is ok, but it doesn’t have that Red-Green-Refactor feel. Open source testing frameworks as far as I know don’t reach the same level of integration. If you want code coverage, be prepared pay some money for at least the Premium edition.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Refactoring. &lt;/strong&gt;The refactorings in Visual Studio pale in comparison to those in Eclipse. Hands down.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Browsing Code. &lt;/strong&gt;I think Visual Studio actually has many features in this area, but the UI doesn’t make them particularly discoverable. I’ve found that following references, finding overrides and such in Eclipse is faster and easier than in Visual Studio.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Source control. &lt;/strong&gt;If you fork out some money, you get integration with Team Foundation with Visual Studio. My feeling is that integration with other source control systems like &lt;a href="http://www.selenic.com/mercurial/wiki/"&gt;mercurial&lt;/a&gt; and &lt;a href="http://subversion.apache.org/"&gt;subversion&lt;/a&gt; is just not as good as the integration in Eclipse.&lt;/p&gt;  &lt;p&gt;Products like &lt;a href="http://www.jetbrains.com/resharper/index.html"&gt;Resharper&lt;/a&gt; and &lt;a href="http://testdriven.net/"&gt;Testdriven.NET&lt;/a&gt; mitigate the refactoring, browsing and testing issues for Visual Studio. But Eclipse comes with these things out of the box. It’s just there when you download it, which is first of all free and second, convenient.&lt;/p&gt;  &lt;p&gt;Then, Visual Studio just doesn’t have a good UI. I’m not excited that I can finally make code windows free floating. The solution explorer naturally makes you focus on the files and the file system – while this actually matters little for your day to day development activities. You want to focus on modules, classes, namespace instead (yes, I know about the class browser, but somehow I keep getting pulled back to the solution explorer by Visual Studio.) And then that annoyance among annoyances – the much hated Add Reference dialog. In 2010 they made it asynchronous, so we can now pretend that it is not as slow and painful as amputating your arm with a toothpick, &lt;em&gt;except that it’s worse! &lt;/em&gt;At least before you knew when you could start searching for a reference. Now you’re left to wonder – is my reference not there or is it still loading in the background?&lt;/p&gt;  &lt;h4&gt;What rocks and Visual Studio have in common&lt;/h4&gt;  &lt;p&gt;Both &lt;a href="http://www.icsharpcode.net/OpenSource/SD/"&gt;SharpDevelop&lt;/a&gt; and &lt;a href="http://monodevelop.com/"&gt;MonoDevelop&lt;/a&gt; seem to focus on conforming with Visual Studio. I guess the argument is that this makes it easier for people to migrate from Visual Studio. Wake up people: if it looks like Visual Studio, nobody is going to bother anyway. &lt;/p&gt;  &lt;p&gt;I don’t want to talk down to the developers of these projects. I’m sure they’re passionate about what they’re doing. But let’s face it – they’re not going to be able to compete on features, as long as Microsoft is throwing money at Visual Studio. On marketing alone, they’re overwhelmed. As far as I can see there is no buzz surrounding these projects at all. Nobody particularly likes or hates them. They’re boring. Because Visual Studio is. It’s just there. Like a rock. A boring, grey rock.&lt;/p&gt;  &lt;h4&gt;A call to arms&lt;/h4&gt;  &lt;p&gt;So, dear SharpDevelop or MonoDevelop developer, or whoever is looking to develop a new software project: here’s my call to arms for you.&lt;/p&gt;  &lt;p&gt;Dare to innovate! Forget about Visual Studio. It’s there, and it’s going to stay – but give use a ray of hope. Give us something to look forward to. Give us something that we can love, or hate – something that at least provokes some feelings.&lt;/p&gt;  &lt;p&gt;Need some ideas? &lt;/p&gt;  &lt;p&gt;Stop bothering with trying to be compatible with Visual Studio. Sure, the assemblies need to be compatible with .NET, but who really cares about MSBuild, and project files, and why even duplicate the solution-project-file based organization of Visual Studio - is there a better way? Can you finally free us from the tyranny of the file system and let us focus on the abstractions provided by the language – it’s called software development, not file shuffling.&lt;/p&gt;  &lt;p&gt;Can we make better compilers for C# or VB or &lt;a title="F# homepage" href="http://research.microsoft.com/fsharp/fsharp.aspx" target="_blank"&gt;F#&lt;/a&gt; that are incremental? Note I am talking about the compiler here, not the build system. The Eclipse Java compiler proves that incremental compilation can be pretty much as fast as no-compilation (as in dynamic languages). &lt;/p&gt;  &lt;p&gt;Source control – can we go beyond superficial integration with popular SCMs and really integrate &lt;em&gt;change tracking&lt;/em&gt; in the language and IDE? With the disk space currently available, is there even a use for the distinction between in memory undo/redo, saving a file to disk and committing a change in source control? Can’t I just type in my code and expect it to be saved, and undoable, and in source control? In addition, can we make “diff” tools language aware please – it’s silly that conflict resolution is line-based, while pretty much every coherent change to code spans multiple files and multiple lines. I’ve never heard of a line-based programming language. Let’s talk about modules and functions and objects and interfaces all the way through please.&lt;/p&gt;  &lt;p&gt;Have a look at a &lt;a href="http://www.smalltalk.org/main/"&gt;Smalltalk&lt;/a&gt; IDEs. They have a browser oriented perspective on development, and have had another view on code organization and source control for ages now. There are lots of good ideas there, and it’s about time they are finally acknowledged and brought to the mainstream. The Hopscotch browser for &lt;a href="http://newspeaklanguage.org/"&gt;Newspeak&lt;/a&gt; looks interesting too. &lt;/p&gt;  &lt;p&gt;As far as UI goes, &lt;a href="http://www.cs.brown.edu/people/acb/codebubbles_site.htm"&gt;Code Bubbles&lt;/a&gt; (built on Eclipse for Java) seems to have some very well thought out UI ideas on browsing, cooperating and debugging.&lt;/p&gt;  &lt;p&gt;I believe that any project that does just some of the above has the potential to become huge in the .NET space. Even with respect to mainstream Java IDEs which are nowhere near revolutionary, the .NET community seems to be behind the curve IDE-wise. Developers can see how computing devices all around them are becoming smarter, better integrated and user-oriented. Mainstream IDEs are lagging way behind. &lt;/p&gt;  &lt;p&gt;Time for a revolution?&lt;/p&gt;  &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:50a08764-c70c-468e-9bc2-cb9cc63464ed" class="wlWriterEditableSmartContent"&gt;Technorati: &lt;a href="http://technorati.com/tags/IDE" rel="tag"&gt;IDE&lt;/a&gt;,&lt;a href="http://technorati.com/tags/.NET" rel="tag"&gt;.NET&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Visual+Studio" rel="tag"&gt;Visual Studio&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Eclipse" rel="tag"&gt;Eclipse&lt;/a&gt;&lt;/div&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 Technet!" href="http://social.technet.microsoft.com/en-us/action/create/s/E/?url=http://fortysix-and-two.blogspot.com/2010/06/thinking-outside-visual-studio-box.html&amp;amp;ttl=Thinking outside the Visual Studio box" 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/2010/06/thinking-outside-visual-studio-box.html&amp;amp;;title=Thinking outside the Visual Studio box" 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/2010/06/thinking-outside-visual-studio-box.html&amp;amp;title=Thinking outside the Visual Studio box" 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/2010/06/thinking-outside-visual-studio-box.html&amp;amp;title=Thinking outside the Visual Studio box" 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/2010/06/thinking-outside-visual-studio-box.html&amp;amp;title=Thinking outside the Visual Studio box" 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/2010/06/thinking-outside-visual-studio-box.html&amp;amp;title=Thinking outside the Visual Studio box" 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/2010/06/thinking-outside-visual-studio-box.html&amp;amp;title=Thinking outside the Visual Studio box" 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-3003708338896283695?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/3003708338896283695/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2010/06/thinking-outside-visual-studio-box.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/3003708338896283695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/3003708338896283695'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2010/06/thinking-outside-visual-studio-box.html' title='Thinking outside the Visual Studio box'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-4018021672244052231</id><published>2010-06-04T21:40:00.000+01:00</published><updated>2010-06-04T21:46:57.754+01: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.7: Pleasure and Pain</title><content type='html'>&lt;p&gt;I just released &lt;a href="http://www.codeplex.com/fscheck" target="_blank"&gt;FsCheck&lt;/a&gt; 0.7&amp;#160; on the codeplex page. Whereas previous releases have been mostly incremental, this one is quite different. With the official release of &lt;a title="F# homepage" href="http://research.microsoft.com/fsharp/fsharp.aspx" target="_blank"&gt;F#&lt;/a&gt; 2.0 and all that it entails, I’ve &lt;strong&gt;refactored the FsCheck API from a usability perspective&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;The previous API was inherited from Haskell QuickCheck, which means that it wasn’t very .NET like. For example, once you opened the FsCheck namespace, all the relevant functions just came into scope. So you, dear user, had to rely mostly on your memory to find the function you need, and also you were not empowered to discover new functions. The new API is a much needed improvement on that situation: it is consistent with .NET idioms, works well with intellisense and the documentation should tell you all you need to know.&lt;/p&gt;  &lt;p&gt;I’ve also tried to improve FsCheck’s output, tried to improve the story with registering generators by type (which was a real pain before, and I hope it has now got at least a bit better), removed concepts that nobody seemed to understand (Hi, coarbitrary!) and generally improved the documentation and names of functions.&lt;/p&gt;  &lt;p&gt;That’s the good news – the bad news is that &lt;strong&gt;this release is not backwards compatible.&lt;/strong&gt; I’m afraid that was not possible given the breadth and depth of the refactoring that I wanted to do. I really believe that FsCheck is in a much better place now, also as far as plans for the future are concerned.&lt;/p&gt;  &lt;h4&gt;Short attention span?&lt;/h4&gt;  &lt;p&gt;Get a visually appealing (but much less detailed) overview in &lt;a href="http://prezi.com/dykys5bdnram/"&gt;this prezi&lt;/a&gt;.&lt;/p&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h4&gt;The whole truth&lt;/h4&gt;  &lt;p&gt;Well, at least as far as I can remember.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Factored API into three type and&amp;#160; module pairs – cfr e.g. the collection types in FSharp.Core. So there is now:&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;Gen&amp;lt;’a&amp;gt; type and the Gen module that contains utility functions to define your own random generators. This is essentially the same as before, except there have been many renames to make everything consistent both internally and with .NET, and understandable (e.g. vectorOf has been renamed to listOfLength, and fmapGen has been renamed to Gen.map). Also, where functions used to take a list as argument, they now take a more general and .NET-like seq instead.&lt;/li&gt;      &lt;li&gt;Arbitrary&amp;lt;’a&amp;gt; type and Arb module. Arbitrary, as before, packages up a generator and a shrinker. Coarbitrary was removed (without removing FsCheck’s functionality to generate functions). The Arb module is new, and plays a fairly central role in FsCheck now – a few useful functions that operate on a generator and a shrinker at the same time were added. &lt;/li&gt;      &lt;ul&gt;       &lt;li&gt;Arb.Default type contains the default generators and shrinkers that ship with FsCheck. I’ve cleaned up most of the mess, but am not completely finished yet. Anyway, you should find many useful Arbitrary instances here, and they are now easily accessible (I believe in the previous version you had to type something like Arbitrary.Arbitrary.String().Arbitrary – now it is Arb.Default.String)&lt;/li&gt;     &lt;/ul&gt;      &lt;li&gt;Property type and Prop module. Here is where all the functions to build the actual properties live. Not much changes here, except that Prop.forAll now takes an Arbitrary instance instead of a generator – I believe this is a first step in making FsCheck more easily extendable to other kinds of generators (e.g. file based or exhaustive generators) by abstracting away the Gen type from Property. (This is currently only skin-deep though)&lt;/li&gt;   &lt;/ul&gt;    &lt;li&gt;Similar refactoring with running tests. &lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;Instead of quickCheck, verboseCheck, and all the other functions, there is now a Check type with relevant static methods that do the same thing. This made it possible to overload method names, which was annoying about the functions – I felt like I had to make up meaningless names. Also, the various checking types that you can do are now discoverable using intellisense by typing Check.&amp;lt;intellisense&amp;gt;.&lt;/li&gt;      &lt;li&gt;Similarly, the default configurations have now been added as static members on the Config record type, which is were you would expect them to be.&lt;/li&gt;      &lt;li&gt;The Runner module has had some cleanup as well, with some new names for old friends, and the IRunner interface has been extended a bit. Like the other modules, it should only expose what is useful to you, so it should be fairly easy to figure out what you need from intellisense alone.&lt;/li&gt;   &lt;/ul&gt;    &lt;li&gt;Output has been improved in various places.&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;When registering generators, FsCheck now automatically overrides the previous generators, and also produces to some output where you can see what the new types that have been registered are, as well as what types were overridden. Hopefully this will help you fix those frustrating issues where types are not registered properly more easily.&lt;/li&gt;      &lt;li&gt;When checking all the members on a type or module, and an exception is thrown, the TargetInvocationExcception is now removed and you just get to see the actual exception, which reduces much of the noise.&lt;/li&gt;      &lt;li&gt;Various small output improvements.&lt;/li&gt;   &lt;/ul&gt;    &lt;li&gt;Size control has been changed in the Config. Instead of a function, you can now give a begin and end size and FsCheck will increase the size linearly between those two values. I did this to make the size independent of the number of test runs that you choose – the final size is always guaranteed to be the end size you ask for. So it is easy to change the number of tests while keeping the same size. I believe this is the least surprising result, as changing the number of tests should not directly influence the test size.&lt;/li&gt;    &lt;li&gt;Added many more tests, especially for the generators. I’m still not happy with the coverage, but we’re getting there.&lt;/li&gt;    &lt;li&gt;Wrote a simple documentation generator. I’m not very happy with it, but at least I reviewed all the documentation and at least the output shown in the documentation is now consistent with the actual output, and it is easy to keep that way.&lt;/li&gt;    &lt;li&gt;Cleaned up the examples a bit. The examples used in the documentation are now moved to the FsCheck.Documentation project (which also generated the codeplex formatted output).&lt;/li&gt;    &lt;li&gt;Typeclass simulation has had a pretty much bottom up rewrite. Hopefully this cleans up some nasty issues with static state I’ve seen, and also the API is I think much improved. Various bug fixes.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;That’s pretty much it. I’ve got more in store still, but not sure when it will materialize into something that I can release. My spare time is getting scarce…but do post a comment on the forum or on my blog if you get stuck in moving your old FsCheck code to the new API, or any other feedback you may have.&lt;/p&gt;  &lt;p&gt;Happy FsChecking!&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:521cae3f-b27b-4420-a04d-673c136ac72a" 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/f%23" rel="tag"&gt;f#&lt;/a&gt;,&lt;a href="http://technorati.com/tags/random+testing" rel="tag"&gt;random testing&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/2010/06/fscheck-07-pleasure-and-pain.html&amp;amp;ttl=FsCheck 0.7: Pleasure and Pain" 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/2010/06/fscheck-07-pleasure-and-pain.html&amp;amp;;title=FsCheck 0.7: Pleasure and Pain" 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/2010/06/fscheck-07-pleasure-and-pain.html&amp;amp;title=FsCheck 0.7: Pleasure and Pain" 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/2010/06/fscheck-07-pleasure-and-pain.html&amp;amp;title=FsCheck 0.7: Pleasure and Pain" 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/2010/06/fscheck-07-pleasure-and-pain.html&amp;amp;title=FsCheck 0.7: Pleasure and Pain" 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/2010/06/fscheck-07-pleasure-and-pain.html&amp;amp;title=FsCheck 0.7: Pleasure and Pain" 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/2010/06/fscheck-07-pleasure-and-pain.html&amp;amp;title=FsCheck 0.7: Pleasure and Pain" 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-4018021672244052231?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/4018021672244052231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2010/06/fscheck-07-pleasure-and-pain.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/4018021672244052231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/4018021672244052231'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2010/06/fscheck-07-pleasure-and-pain.html' title='FsCheck 0.7: Pleasure and Pain'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-7569364991658583686</id><published>2010-05-15T22:24:00.000+01:00</published><updated>2010-05-15T22:28:47.820+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><title type='text'>Accessing Visual Studio’s Automation API from F# Interactive</title><content type='html'>&lt;p&gt;Because why anyone would want to write VBA in the Visual Studio macro editor is beyond me. All the bits and pieces below are pretty much known, but I think the overall result is new. For the bewildered (I don’t blame you), what you’ll be able to do is, from F# Interactive, for example enumerating the current projects in the open solution:&lt;/p&gt;  &lt;pre&gt;&amp;gt; myDTE.Solution.Projects |&amp;gt; Seq.cast&amp;lt;Project&amp;gt; |&amp;gt; Seq.map (fun p -&amp;gt; p.FullName);;&lt;/pre&gt;

&lt;pre&gt;val it : seq&amp;lt;string&amp;gt; =
  seq
    [&amp;quot;C:\Users\Kurt\Projects\FsCheck\doc\FsCheck\FsCheck.fsproj&amp;quot;;
     &amp;quot;C:\Users\Kurt\Projects\FsCheck\doc\FsCheck.Examples\FsCheck.Examples.fsproj&amp;quot;;     &amp;quot;&amp;quot;;
     &amp;quot;C:\Users\Kurt\Projects\FsCheck\doc\FsCheck.Checker\FsCheck.Checker.fsproj&amp;quot;;     ...]&lt;/pre&gt;

&lt;p&gt;You get access to the &lt;a href="http://msdn.microsoft.com/en-us/library/za2b25t3%28v=VS.71%29.aspx"&gt;DTE top level automation object&lt;/a&gt; of the Visual Studio instance the current FSI is running under. This DTE is a COM interface that basically allows you to do programmatically what you can do using the Visual Studio UI interface – it’s the thing you get access to in the Macro IDE as well. So you can do pretty cool things – like add files, generate code, listen to build events, find dependencies of projects and such. &lt;/p&gt;

&lt;h4&gt;But…how?&lt;/h4&gt;

&lt;p&gt;The Macro IDE gives access to the DTE object automagically. But fsi is actually a separate process, that just happens to input and output through Visual Studio. So basically we need to get access to a Visual Studio instance’s DTE object from outside of Visual Studio. Luckily, each instance of Visual Studio registers its DTE object in the &lt;a href="http://msdn.microsoft.com/en-us/library/ms695276%28VS.85%29.aspx"&gt;Running Object Table&lt;/a&gt; (hereafter called ROT) with &lt;a href="http://msdn.microsoft.com/en-us/library/ms228755%28v=VS.80%29.aspx"&gt;two keys&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;As a string of the form “!VisualStudio.&amp;lt;VS version&amp;gt;.0:&amp;lt;processid&amp;gt;”. E.g. for VS2008 with process id 1234: !VisualStudio.9.0:1234&lt;/li&gt;

  &lt;li&gt;As the path to an open solution file, if any.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ll use the first option. That means we need to find out the process id of the Visual Studio instance the current FSI instance is running under. FSI is started as a child process of Visual Studio – each Visual Studio has its own FSI. &lt;/p&gt;

&lt;p&gt;Let’s tackle each of these in turn – first finding the process id of the current Visual Studio instance, then its DTE object via the ROT.&lt;/p&gt;

&lt;h4&gt;Step 1: Finding the Visual Studio process id&lt;/h4&gt;

&lt;p&gt;Not as straightforward as it sounds. System.Diagnostics.Process does not give you direct access to a process’ parent. There are at least two ways to go about it – using the Windows API or, maybe surprisingly, through performance counters. I used the latter because that didn’t require me to do interop.&lt;/p&gt;

&lt;p&gt;The code is pretty straightforward – remember the point is that this is being executed in F# interactive:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;open &lt;/span&gt;System
&lt;span style="color: blue"&gt;open &lt;/span&gt;System.Diagnostics

&lt;span style="color: blue"&gt;let &lt;/span&gt;getParentProcess (processId:int) =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;proc = Process.GetProcessById processId
    &lt;span style="color: blue"&gt;let &lt;/span&gt;myProcID = &lt;span style="color: blue"&gt;new &lt;/span&gt;PerformanceCounter(&lt;span style="color: maroon"&gt;&amp;quot;Process&amp;quot;&lt;/span&gt;, &lt;span style="color: maroon"&gt;&amp;quot;ID Process&amp;quot;&lt;/span&gt;, proc.ProcessName)
    &lt;span style="color: blue"&gt;let &lt;/span&gt;myParentID = &lt;span style="color: blue"&gt;new &lt;/span&gt;PerformanceCounter(&lt;span style="color: maroon"&gt;&amp;quot;Process&amp;quot;&lt;/span&gt;, &lt;span style="color: maroon"&gt;&amp;quot;Creating Process ID&amp;quot;&lt;/span&gt;, proc.ProcessName)
    myParentID.NextValue() |&amp;gt; int
    
&lt;span style="color: blue"&gt;let &lt;/span&gt;currentProcess = Process.GetCurrentProcess().Id

&lt;span style="color: blue"&gt;let &lt;/span&gt;myVS = getParentProcess currentProcess&lt;/pre&gt;

&lt;p&gt;You should just be able to paste that into an F# Interactive window and myVS will contain the process id of the Visual Studio instance it’s running under. (No doubt this will crash spectacularly when you’re running FSI standalone or something.)&lt;/p&gt;

&lt;h4&gt;Step 2: Getting the DTE object&lt;/h4&gt;

&lt;p&gt;This was a bit harder, as we’re now going to have to do some interop with OLE32. Code for this is floating around on the internet if you know where to &lt;a href="http://www.databaseforum.info/8/983730.aspx"&gt;look&lt;/a&gt; – I just translated it to F#. Here’s what we need:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;#r &lt;/span&gt;&lt;span style="color: maroon"&gt;&amp;quot;EnvDTE&amp;quot;
&lt;/span&gt;&lt;span style="color: blue"&gt;#r &lt;/span&gt;&lt;span style="color: maroon"&gt;&amp;quot;EnvDTE80.dll&amp;quot; 
&lt;/span&gt;&lt;span style="color: blue"&gt;#r &lt;/span&gt;&lt;span style="color: maroon"&gt;&amp;quot;EnvDTE90.dll&amp;quot; 

&lt;/span&gt;&lt;span style="color: blue"&gt;open &lt;/span&gt;EnvDTE
&lt;span style="color: blue"&gt;open &lt;/span&gt;EnvDTE80
&lt;span style="color: blue"&gt;open &lt;/span&gt;EnvDTE90&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;&lt;/span&gt;&lt;span style="color: blue"&gt;open &lt;/span&gt;System.Runtime.InteropServices
&lt;span style="color: blue"&gt;open &lt;/span&gt;System.Runtime.InteropServices.ComTypes

&lt;span style="color: blue"&gt;module &lt;/span&gt;Msdev =
    
    [&amp;lt;DllImport(&lt;span style="color: maroon"&gt;&amp;quot;ole32.dll&amp;quot;&lt;/span&gt;)&amp;gt;]  
    &lt;span style="color: blue"&gt;extern &lt;/span&gt;int GetRunningObjectTable([&amp;lt;In&amp;gt;]int reserved, [&amp;lt;Out&amp;gt;] IRunningObjectTable&amp;amp; prot)
 
    [&amp;lt;DllImport(&lt;span style="color: maroon"&gt;&amp;quot;ole32.dll&amp;quot;&lt;/span&gt;)&amp;gt;]  
    &lt;span style="color: blue"&gt;extern &lt;/span&gt;int CreateBindCtx([&amp;lt;In&amp;gt;]int reserved,  [&amp;lt;Out&amp;gt;]IBindCtx&amp;amp; ppbc)&lt;/pre&gt;

&lt;p&gt;These two interop functions allow us to enumerate the ROT and get the registered object with the key we want:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;tryFindInRunningObjectTable (name:string) =
    &lt;span style="color: green"&gt;//let result = new Dictionary&amp;lt;_,_&amp;gt;()
    &lt;/span&gt;&lt;span style="color: blue"&gt;let mutable &lt;/span&gt;rot = &lt;span style="color: blue"&gt;null
    if &lt;/span&gt;Msdev.GetRunningObjectTable(0,&amp;amp;rot) &amp;lt;&amp;gt; 0 &lt;span style="color: blue"&gt;then &lt;/span&gt;failwith &lt;span style="color: maroon"&gt;&amp;quot;GetRunningObjectTable failed.&amp;quot;
    &lt;/span&gt;&lt;span style="color: blue"&gt;let mutable &lt;/span&gt;monikerEnumerator = &lt;span style="color: blue"&gt;null
    &lt;/span&gt;rot.EnumRunning(&amp;amp;monikerEnumerator)
    monikerEnumerator.Reset()
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;numFetched = IntPtr.Zero
    &lt;span style="color: blue"&gt;let &lt;/span&gt;monikers = Array.init&amp;lt;ComTypes.IMoniker&amp;gt; 1 (&lt;span style="color: blue"&gt;fun &lt;/span&gt;_ &lt;span style="color: blue"&gt;-&amp;gt; null&lt;/span&gt;)
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;result = None
    &lt;span style="color: blue"&gt;while &lt;/span&gt;result.IsNone &amp;amp;&amp;amp; (monikerEnumerator.Next(1, monikers, numFetched) = 0) &lt;span style="color: blue"&gt;do
        let mutable &lt;/span&gt;ctx = &lt;span style="color: blue"&gt;null
        if &lt;/span&gt;Msdev.CreateBindCtx(0, &amp;amp;ctx) &amp;lt;&amp;gt; 0 &lt;span style="color: blue"&gt;then &lt;/span&gt;failwith &lt;span style="color: maroon"&gt;&amp;quot;CreateBindCtx failed&amp;quot;
            
        &lt;/span&gt;&lt;span style="color: blue"&gt;let mutable &lt;/span&gt;runningObjectName = &lt;span style="color: blue"&gt;null
        &lt;/span&gt;monikers.[0].GetDisplayName(ctx, &lt;span style="color: blue"&gt;null&lt;/span&gt;, &amp;amp;runningObjectName)
        
        &lt;span style="color: blue"&gt;if &lt;/span&gt;runningObjectName = name &lt;span style="color: blue"&gt;then
            let mutable &lt;/span&gt;runningObjectVal = &lt;span style="color: blue"&gt;null
            if &lt;/span&gt;rot.GetObject( monikers.[0], &amp;amp;runningObjectVal) &amp;lt;&amp;gt; 0 &lt;span style="color: blue"&gt;then &lt;/span&gt;failwith &lt;span style="color: maroon"&gt;&amp;quot;GetObject failed&amp;quot;
            &lt;/span&gt;result &amp;lt;- Some runningObjectVal
        
        &lt;span style="color: green"&gt;//result.[runningObjectName] &amp;lt;- runningObjectVal
    &lt;/span&gt;result&lt;/pre&gt;

&lt;p&gt;I won’t go into the virtues of this particular piece of code. Suffice to say it’s an acquired taste. (Bonus points for anyone who can write a function that returns the ROT as a nice, lazy seq&amp;lt;string*obj&amp;gt;. Yes I know it seems easy – but please try and prepare to be frustrated.). So we now have a function that returns the COM object in the ROT based on the name. If you put in the code in comments and change a few bits and pieces, it should be easy to get a function that outputs the ROT completely.&lt;/p&gt;

&lt;h4&gt;Putting two and two together&lt;/h4&gt;

&lt;p&gt;Armed with these functions, here’s the DTE object that you can use to call the Automation API:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;getVS2008ROTName id = 
    sprintf &lt;span style="color: maroon"&gt;&amp;quot;!VisualStudio.DTE.9.0:%i&amp;quot; &lt;/span&gt;id
    
&lt;span style="color: blue"&gt;let &lt;/span&gt;myDTE = (tryFindInRunningObjectTable (getVS2008ROTName myVS) |&amp;gt; Option.get) :?&amp;gt; DTE2&lt;/pre&gt;

&lt;p&gt;This is for Visual Studio 2008. For 2010, it should be as easy as changing the 9 to 10 in the ROT key string. It’s possible to make this more general if you can come up with a way to check whether the current process is .NET 4 or .NET 3.5 – the former would indicate an FSI running in VS2010, the latter in VS2008.&lt;/p&gt;

&lt;p&gt;And that’s it. Have a look around using Intellisense to see what is possible. Also check out the Macro IDE – it has some code examples in VBA that involve the DTE. Some ideas:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;myDTE.ExecuteCommand lets you execute any command – the things you can bind keyboard shortcuts to in the Options. For example, use ProjectandSolutionContextMenus.Item.MoveDown to move the currently selected item one place down.&lt;/li&gt;

  &lt;li&gt;myDTE.Events to register event handlers for all sort of Visual Studio events. For example, myDTE.Events.BuildEvents.add_OnBuildDone notifies you when a build is done. Nice for post-build steps that need to run after a solution is built (as opposed to after a particular project is built).&lt;/li&gt;

  &lt;li&gt;myDTE.Quit(). The l33t hax0r way to exit Visual Studio. You’ll be the envy of your less tech-savvy colleagues.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you find an imaginative use for this, please let me know.&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:1740c4bf-51a8-4254-922e-f56b63fbc480" class="wlWriterEditableSmartContent"&gt;Technorati: &lt;a href="http://technorati.com/tags/F%23+Interactive" rel="tag"&gt;F# Interactive&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Visual+Studio+Automation" rel="tag"&gt;Visual Studio Automation&lt;/a&gt;,&lt;a href="http://technorati.com/tags/DTE" rel="tag"&gt;DTE&lt;/a&gt;,&lt;a href="http://technorati.com/tags/F%23" rel="tag"&gt;F#&lt;/a&gt;,&lt;a href="http://technorati.com/tags/FSI" rel="tag"&gt;FSI&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/2010/05/accessing-visual-studios-automation-api.html&amp;amp;ttl=Accessing Visual Studio's Automation API from F# Interactive" 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/2010/05/accessing-visual-studios-automation-api.html&amp;amp;;title=Accessing Visual Studio's Automation API from F# Interactive" 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/2010/05/accessing-visual-studios-automation-api.html&amp;amp;title=Accessing Visual Studio's Automation API from F# Interactive" 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/2010/05/accessing-visual-studios-automation-api.html&amp;amp;title=Accessing Visual Studio's Automation API from F# Interactive" 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/2010/05/accessing-visual-studios-automation-api.html&amp;amp;title=Accessing Visual Studio's Automation API from F# Interactive" 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/2010/05/accessing-visual-studios-automation-api.html&amp;amp;title=Accessing Visual Studio's Automation API from F# Interactive" 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/2010/05/accessing-visual-studios-automation-api.html&amp;amp;title=Accessing Visual Studio's Automation API from F# Interactive" 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-7569364991658583686?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/7569364991658583686/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2010/05/accessing-visual-studios-automation-api.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/7569364991658583686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/7569364991658583686'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2010/05/accessing-visual-studios-automation-api.html' title='Accessing Visual Studio’s Automation API from F# Interactive'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-3254406850123955605</id><published>2010-04-09T22:20:00.000+01:00</published><updated>2010-04-09T22:31:48.042+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mercurial'/><category scheme='http://www.blogger.com/atom/ns#' term='fscheck'/><title type='text'>Moving FsCheck to Mercurial</title><content type='html'>&lt;p&gt;I’ve been using &lt;a href="http://www.selenic.com/mercurial/wiki/"&gt;Mercurial&lt;/a&gt; as my source control system of choice for a few years now, and I’ve been very&amp;#160; happy with it. The only problem I had was that codeplex, where &lt;a href="http://www.codeplex.com/fscheck" target="_blank"&gt;FsCheck&lt;/a&gt; is hosted, only supported SVN. I used Mercurial for daily development, and when a release was imminent I just copied the final snapshot to my local SVN checkout and updated codeplex from there. Needless to say, the SVN repository was out of date and didn’t represent the actual history.&lt;/p&gt;  &lt;p&gt;Well, no more! &lt;a href="http://blogs.msdn.com/codeplex/archive/2010/01/22/codeplex-now-supporting-native-mercurial.aspx"&gt;Codeplex now supports Mercurial&lt;/a&gt; as well. One email to the kind folks at codeplex support, and they wiped my SVN repository from codeplex and provided me with a shiny new hg repository. Great.&lt;/p&gt;  &lt;p&gt;That left me with a problem: since I was used to the hg repository being private, I also dumped some, well, private stuff in it. Before you start imagining things, there is nothing special there – just a few pdfs of papers and such, but nonetheless things I didn’t want to put in a public repository. If only because some authors prefer that they alone control dissemination of their work.&lt;/p&gt;  &lt;p&gt;And obviously Mercurial isn’t keen on letting you delete history.&lt;/p&gt;  &lt;p&gt;Luckily it has the excellent &lt;a href="http://mercurial.selenic.com/wiki/ConvertExtension"&gt;convert extension&lt;/a&gt;. This is usually used to convert SVN, CVS or other repositories to a Mercurial repository. But you can also convert a Mercurial repository to a new one, and rewrite and update history along the way. One of the things the convert extension lets you do is to specify files and folders that should not be migrated. It also lets you remove branches, and even splice a certain set of changesets on a parent in the new repository.&lt;/p&gt;  &lt;p&gt;I used the first two features to remove some superfluous history and files. I used the last because I’m used to clone my main repository to a bunch of feature repositories to work on specific features in relative isolation. I have a few of those in progress, but of course since I was converting my main repository to a new one the feature repositories couldn’t be used to push changes back to the new main. This makes them pretty much useless, unless they are converted as well.&lt;/p&gt;  &lt;p&gt;So here’s what I did:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Convert the old main repository to the new main, stripping out files and branches along the way.&lt;/li&gt;    &lt;li&gt;Clone the new repository for each feature I’m currently working on. Now I have a mirror image of my old folder where the old main and the old feature repositories are – except the changesets in the old feature repositories need to be migrated to the new feature repositories.&lt;/li&gt;    &lt;li&gt;Using hg convert’s splice feature, and the excellent &lt;a href="http://tortoisehg.bitbucket.org/"&gt;TortoiseHg&lt;/a&gt; repository explorer to find out the changeset numbers, I then additionally converted only the extra changesets from each old feature repository to its corresponding new feature repository. One thing to keep in mind is that hg convert uses the .hg/shamap file in the new repository to keep track of which changesets from the old repository it has already converted. This file is however not automatically copied when cloning – so I had to manually copy that over from the new main to the new feature repositories – otherwise convert would try to convert all of the changesets again.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Confused yet? Well, here’s my first &lt;a href="http://prezi.com/zznsmfwl7v9e/"&gt;Prezi&lt;/a&gt; to explain it all…&lt;/p&gt;  &lt;p&gt;You can check out the result in FsCheck’s source tab – although the main result is that there is now much less friction in my development process.&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:90d8df98-8b8d-4f70-854c-ed84a69f764a" class="wlWriterEditableSmartContent"&gt;Technorati: &lt;a href="http://technorati.com/tags/mercurial" rel="tag"&gt;mercurial&lt;/a&gt;,&lt;a href="http://technorati.com/tags/hg+convert" rel="tag"&gt;hg convert&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/codeplex" rel="tag"&gt;codeplex&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/2010/04/moving-fscheck-to-mercurial.html&amp;amp;ttl=Moving FsCheck to Mercurial" 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/2010/04/moving-fscheck-to-mercurial.html&amp;amp;;title=Moving FsCheck to Mercurial" 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/2010/04/moving-fscheck-to-mercurial.html&amp;amp;title=Moving FsCheck to Mercurial" 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/2010/04/moving-fscheck-to-mercurial.html&amp;amp;title=Moving FsCheck to Mercurial" 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/2010/04/moving-fscheck-to-mercurial.html&amp;amp;title=Moving FsCheck to Mercurial" 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/2010/04/moving-fscheck-to-mercurial.html&amp;amp;title=Moving FsCheck to Mercurial" 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/2010/04/moving-fscheck-to-mercurial.html&amp;amp;title=Moving FsCheck to Mercurial" 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-3254406850123955605?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/3254406850123955605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2010/04/moving-fscheck-to-mercurial.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/3254406850123955605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/3254406850123955605'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2010/04/moving-fscheck-to-mercurial.html' title='Moving FsCheck to Mercurial'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-316875756862098145</id><published>2010-02-15T20:08:00.000Z</published><updated>2010-02-15T20:09:44.817Z</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='http://fortysix-and-two.blogspot.com/2010/02/fscheck-063-for-visual-studio-2010-rc.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-4682904819737086709</id><published>2010-02-11T20:54:00.001Z</published><updated>2010-02-11T20:54:36.706Z</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='http://fortysix-and-two.blogspot.com/2010/02/visug-presentation-in-leuven-belgium-on.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-470284202826557193</id><published>2009-12-22T16:57:00.000Z</published><updated>2009-12-22T16:59:38.932Z</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='http://fortysix-and-two.blogspot.com/2009/12/on-understanding-data-abstraction.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-8106871407108772948</id><published>2009-12-08T19:51:00.000Z</published><updated>2009-12-08T19:55:11.040Z</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='http://fortysix-and-two.blogspot.com/2009/12/how-to-get-hg-git-working-with.html#comment-form' title='3 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-2253718114378551111</id><published>2009-10-26T10:10:00.000Z</published><updated>2009-10-26T10:22:45.318Z</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='http://fortysix-and-two.blogspot.com/2009/10/fscheck-062-f-october-2009-ctp2010-beta.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-2267112906835982001</id><published>2009-09-19T14:53:00.000+01:00</published><updated>2009-09-19T14:59:17.647+01: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='http://fortysix-and-two.blogspot.com/2009/09/simple-and-fair-backtracking.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-8168518752159805742</id><published>2009-06-27T12:32:00.000+01:00</published><updated>2009-06-27T12:34:48.491+01: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='http://fortysix-and-two.blogspot.com/2009/06/more-fun-with-data-structures.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-3158212243224204490</id><published>2009-06-24T21:00:00.000+01:00</published><updated>2009-06-24T21:12:55.107+01: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='http://fortysix-and-two.blogspot.com/2009/06/fun-with-data-structures-continuations.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-6519181874879423769</id><published>2009-06-13T15:25:00.000+01:00</published><updated>2009-06-14T10:17:25.555+01: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='http://fortysix-and-two.blogspot.com/2009/06/traversing-and-transforming-f.html#comment-form' title='8 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-7430979790558280803</id><published>2009-05-23T17:36:00.000+01:00</published><updated>2009-05-23T17:43:38.094+01: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='http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-061.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-5500259037381034725</id><published>2009-05-12T21:50:00.001+01:00</published><updated>2009-05-12T21:52:48.102+01: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='http://fortysix-and-two.blogspot.com/2009/05/how-to-test-dsls-and-fschecking-fscheck.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-8031068609563061314</id><published>2009-05-12T21:17:00.000+01:00</published><updated>2009-05-12T21:21:09.919+01: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='http://fortysix-and-two.blogspot.com/2009/05/announcing-fscheck-06-dot-is-new-pipe.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-1503614048149432705</id><published>2009-05-06T21:03:00.000+01:00</published><updated>2009-05-06T21:12:55.692+01: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='http://fortysix-and-two.blogspot.com/2009/05/tests-are-not-specifications.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-4177205617766265898</id><published>2009-03-13T15:37:00.000Z</published><updated>2009-03-13T20:22:17.548Z</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='http://fortysix-and-two.blogspot.com/2009/03/fschecking-dnanalytics-part-3.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-2964929970347139553</id><published>2009-03-06T20:14:00.000Z</published><updated>2009-03-06T20:15:39.873Z</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='http://fortysix-and-two.blogspot.com/2009/03/fscheck-on-ohloh.html#comment-form' title='2 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-5460577936984871285</id><published>2009-03-01T11:54:00.001Z</published><updated>2009-03-04T20:09:57.506Z</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='http://fortysix-and-two.blogspot.com/2009/03/fscheck-051.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-8693230923129170823</id><published>2009-02-27T23:10:00.000Z</published><updated>2009-02-27T23:25:07.893Z</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='http://fortysix-and-two.blogspot.com/2009/02/fschecking-dnanalytics-part-2.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-2292391042491882685</id><published>2009-02-23T22:06:00.000Z</published><updated>2009-02-23T22:10:07.987Z</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='http://fortysix-and-two.blogspot.com/2009/02/fschecking-dnanalytics.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-2415132589755783157</id><published>2009-02-19T21:19:00.000Z</published><updated>2009-02-19T21:19:00.788Z</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='http://fortysix-and-two.blogspot.com/2009/02/announcing-fscheck-05.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-8208141365690014787</id><published>2009-01-24T14:28:00.000Z</published><updated>2009-01-24T14:30:20.178Z</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='http://fortysix-and-two.blogspot.com/2009/01/how-to-deal-with-out-parameters-in-f.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-4688677127452201799</id><published>2009-01-14T22:18:00.000Z</published><updated>2009-01-14T22:35:08.249Z</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='http://fortysix-and-two.blogspot.com/2009/01/announcing-fscheck-04.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-6122047561001245374</id><published>2009-01-13T20:43:00.000Z</published><updated>2009-01-13T21:18:40.737Z</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='http://fortysix-and-two.blogspot.com/2009/01/poor-man-typeclass.html#comment-form' title='6 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-4038301181282714909</id><published>2008-12-20T16:54:00.001Z</published><updated>2008-12-20T16:54:19.949Z</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='http://fortysix-and-two.blogspot.com/2008/12/how-to-change-accessibility-of.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-608295331109105948</id><published>2008-12-03T22:28:00.000Z</published><updated>2008-12-05T11:35:00.206Z</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='http://fortysix-and-two.blogspot.com/2008/12/announcing-fscheck-03.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-8531321898948032867</id><published>2008-11-15T14:18:00.000Z</published><updated>2008-11-15T14:20:33.338Z</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='http://fortysix-and-two.blogspot.com/2008/11/future-plans-for-fscheck.html#comment-form' 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>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-7353458066979326784</id><published>2008-11-10T21:58:00.001Z</published><updated>2008-11-10T21:58:43.911Z</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 use named arguments in F#</title><content type='html'>&lt;p&gt;Named arguments are a little-known feature of F#, that is actually very useful when calling heavily overloaded members. The DateTime constructor is one such example: it has twelve overloads, and I can never remember what (in C#) DateTime d = new DateTime(2008,11,12) means. Is it December 11th or 11 November (as we would say it in Dutch)? Fortunately, in F# there is a nice solution for this: you can always use the names of the formal arguments to specify a named argument. This not only clarifies what overload you're calling, you can also easily change the order of the arguments. For example:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;d = &lt;span style="color: blue"&gt;new &lt;/span&gt;DateTime(month=12, day=11, year=2008)&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;makes it very clear that we're talking about December 11th here. If you're from the US, it even looks 'normal'. Europeans may like:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;d' = &lt;span style="color: blue"&gt;new &lt;/span&gt;DateTime(day=11, month=12, year=2008)&lt;/pre&gt;

&lt;p&gt;For F#, it's all the same.&lt;/p&gt;

&lt;p&gt;You can also mix positional with named arguments, and if the object has setters, you can use these to. For details, read &lt;a href="http://research.microsoft.com/fsharp/manual/spec2.aspx#_Toc207785699"&gt;Section 8.4.5&lt;/a&gt; in the F# (draft) language spec.&lt;/p&gt;

&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:8cac670b-dcab-426e-9142-4182f9d1a754" 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/named%20arguments" rel="tag"&gt;named arguments&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-7353458066979326784?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/7353458066979326784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/11/how-to-use-named-arguments-in-f.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/7353458066979326784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/7353458066979326784'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/11/how-to-use-named-arguments-in-f.html' title='How to use named arguments in F#'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-2941289064800578252</id><published>2008-10-11T17:35:00.000+01:00</published><updated>2008-10-11T17:42:57.927+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><title type='text'>Fun with units of measure</title><content type='html'>&lt;p&gt;Since the CTP, F# has a nice feature in its type system, called units of measure. Briefly, it allows you to specify a unit with any float, and the type system checks that your uses of units are consistent. For example, you can't add a float&amp;lt;m&amp;gt; to a float&amp;lt;ft&amp;gt;, which results in, among other things, &lt;a href="http://www.space.com/missionlaunches/launches/orbiter_errorupd_093099.htm"&gt;less crashes of spacecraft on Mars&lt;/a&gt;. I won't go into details, if you're interested but don't know what I'm talking about, read &lt;a href="http://blogs.msdn.com/andrewkennedy/default.aspx"&gt;Andrew Kennedy's blog&lt;/a&gt; before you continue.&lt;/p&gt;  &lt;p&gt;But anyway, using units for, well, tracking units is kind of boring - type systems are made to be abused after all. So here's my attempt to use units of measure to track the lengths of vectors, so that the compiler will for example detect that you try to add two vectors of unequal length. &lt;/p&gt;  &lt;p&gt;How can this be achieved? The basic idea is to encode the length of the vector as an exponent to a unit, that is kept in the 'safe vector' type as a unit of measure parameter. To do this, we first need a unit of measure and a 'safe vector' type that uses it:&lt;/p&gt;  &lt;pre class="code"&gt;[&amp;lt;Measure&amp;gt;] &lt;span style="color: blue"&gt;type &lt;/span&gt;length

&lt;span style="color: blue"&gt;type &lt;/span&gt;SVec&amp;lt;'a,[&amp;lt;Measure&amp;gt;]'l&amp;gt; = 
    SVec &lt;span style="color: blue"&gt;of &lt;/span&gt;list&amp;lt;'a&amp;gt; * float&amp;lt;'l&amp;gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;So, SVec is a vector containing elements of type 'a, and with a length encoded in 'l. We'll use the float to both encode the length of the string as a value and as a type; the idea is that SVec ([1,5], 2.0) has type SVec&amp;lt;int, length ^2&amp;gt;. Let's define some utility functions to make type safe vectors:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;nil = SVec ([],0.0)
&lt;span style="color: blue"&gt;let &lt;/span&gt;cons elem (SVec (xs,un:float&amp;lt;'l&amp;gt;)) : SVec&amp;lt;_,'l length&amp;gt; = 
        SVec (elem::xs, (un + 1.0&amp;lt;_&amp;gt;) * 1.0&amp;lt;length&amp;gt;)
&lt;span style="color: blue"&gt;let &lt;/span&gt;(=+=) = cons&lt;/pre&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;removeUnits f = f |&amp;gt; box |&amp;gt; unbox&amp;lt;float&amp;gt; &lt;/pre&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;length (SVec (_,c)) = removeUnits c |&amp;gt; int &lt;span style="color: green"&gt;
&lt;/span&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;from_list xs (l:float&amp;lt;'u&amp;gt;) : SVec&amp;lt;'a,'u&amp;gt; = 
    &lt;span style="color: blue"&gt;if &lt;/span&gt;List.length xs &amp;lt;&amp;gt; int (removeUnits l) &lt;span style="color: blue"&gt;then &lt;/span&gt;raise &amp;lt;| &lt;span style="color: blue"&gt;new &lt;/span&gt;ArgumentException(&lt;span style="color: maroon"&gt;&amp;quot;Actual length of list is not equal to given length&amp;quot;&lt;/span&gt;)
    &lt;span style="color: blue"&gt;else &lt;/span&gt;SVec (xs,l)&lt;/pre&gt;

&lt;p&gt;'nil' constructs an empty vector. It has type SVec&amp;lt;'a&amp;gt;,1&amp;gt;, denoting a list with zero elements. 'cons' adds an element to the front of the vector. To do this, it needs to do three things:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Add the actual element to the front of the list&lt;/li&gt;

  &lt;li&gt;Update the length&lt;em&gt;&amp;#160; value&lt;/em&gt; by adding 1&lt;/li&gt;

  &lt;li&gt;Update the length &lt;em&gt;type&lt;/em&gt; by multiplying with 1.0&amp;lt;length&amp;gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To get the length of a vector, we return the unit value, stripping of all static unit types. I tried this first by dividing by 1.0&amp;lt;'u&amp;gt;,&amp;#160; but it appears that you can't use a type argument as a unit of measure with a constant value. I'm not exactly sure why.&lt;/p&gt;

&lt;p&gt;'from_list' takes a list and turns it into a safe vector. You need to provide a list, with the length of the list correctly encoded in both value and type. The value is tested, the type is not: as far as I can see, this is impossible to check.&lt;/p&gt;

&lt;p&gt;Let's make a safe vector:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;l = 3 =+= (2 =+= (1 =+= nil))&lt;/pre&gt;

&lt;p&gt;The type of l is SVec&amp;lt;int,length^3&amp;gt;. Now we can define type-safe multiplication and addition:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;SVec&amp;lt;'a,[&amp;lt;Measure&amp;gt;]'l&amp;gt; = 
    SVec &lt;span style="color: blue"&gt;of &lt;/span&gt;list&amp;lt;'a&amp;gt; * float&amp;lt;'l&amp;gt;
        &lt;span style="color: blue"&gt;static member &lt;/span&gt;(+) (SVec (xs, l1): SVec&amp;lt;_,'l&amp;gt;, SVec (ys, l2): SVec&amp;lt;_,'l&amp;gt;) = 
            SVec (zip xs ys |&amp;gt; map (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(x,y) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;x + y), l1)
        &lt;span style="color: blue"&gt;static member &lt;/span&gt;(*) (SVec (xs, l1) : SVec&amp;lt;_,'l&amp;gt;, SVec (ys, l2): SVec&amp;lt;_,'l&amp;gt;)=
            zip xs ys |&amp;gt; sum_by (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(x,y) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;x*y)    &lt;/pre&gt;

&lt;p&gt;The interesting part is of course not the implementation, but the types: they statically enforce that when you add or multiply two vectors, they have the same length. So:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let sum&lt;/span&gt; = l + l&lt;/pre&gt;

&lt;p&gt;will typecheck fine, but&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;badsum = l + nil&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;will give a type error!&lt;/p&gt;

&lt;p&gt;That concludes my experiment. Some final thoughts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;This cannot be used to make a type safe head and tail operation, as far as I can see. We'd need an additional type to represent the empty list, and somehow make a head function that can transform between the two types - the kind of overloading necessary does not seem to be possible in F#.&lt;/li&gt;

  &lt;li&gt;Try to make a recursive function&amp;#160; with SVec: it's impossible, since generic recursion is impossible.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:b99fe374-6006-491d-b73a-c7e10f74726d" 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/units%20of%20measure" rel="tag"&gt;units of measure&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-2941289064800578252?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/2941289064800578252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/10/fun-with-units-of-measure.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/2941289064800578252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/2941289064800578252'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/10/fun-with-units-of-measure.html' title='Fun with units of measure'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-4148138498846433687</id><published>2008-10-07T10:10:00.000+01:00</published><updated>2008-10-07T10:25:04.598+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><category scheme='http://www.blogger.com/atom/ns#' term='Reflection'/><title type='text'>How to invoke a method with type parameters using reflection (in F#)</title><content type='html'>&lt;p&gt;Methods with type parameters arise naturally in F# code, for example:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Example =
    &lt;span style="color: blue"&gt;static member &lt;/span&gt;Test l = List.rev l&lt;/pre&gt;

&lt;p&gt;'Test' has one type parameter 'a, the type of the elements of the list that is being reversed.&lt;/p&gt;

&lt;p&gt;In F# you can call the Test method with a list of any type, and the compiler infers the type parameters for you:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;result = Example.Test [1;2;3]&lt;/pre&gt;

&lt;p&gt;The compiler infers that 'a must be an int. &lt;/p&gt;

&lt;p&gt;Mainstream languages such as C# and VB.NET only infer the type arguments at the call site. The programmer needs to declare all the type parameters of a method explicitly. Consider the type signature of the following method:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Example =
    &lt;span style="color: blue"&gt;static member &lt;/span&gt;Test2 (a,b) = (fst a = snd b)&lt;/pre&gt;

&lt;p&gt;Test2 has three type arguments: it takes two tuples a and b as its arguments, which is a total of four types. But since Test2 compares the first element of a with the second element of b, these two are inferred to have the same types. In C#, a programmer would have to infer this for herself, and write:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public static bool &lt;/span&gt;Test2&amp;lt;T, U, V&amp;gt;(Tuple&amp;lt;T, U&amp;gt; a, Tuple&amp;lt;V, T&amp;gt; b)
{
   &lt;span style="color: blue"&gt;return &lt;/span&gt;a.Fst == b.Snd;
}&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;(of course, assuming that a type Tuple would be defined in .NET, which is not the case if you're not using the F# core libraries)&lt;/p&gt;

&lt;p&gt;Because it is obvious that such type annotations require much more work by the programmer, in C# and VB.NET type arguments to methods are in my experience much less common, and much less complex, than what is written without a second thought in F#.&lt;/p&gt;

&lt;p&gt;However, recently I faced the problem of calling a number of static methods such as the above using reflection. I had the actual arguments to the method available, so for Test2 above I would have the (type-correct, of course) arguments (true,2.0) and (&amp;quot;whatever&amp;quot;, false) available. &lt;/p&gt;

&lt;p&gt;To call a method using reflection, you can use MethodInfo.Invoke, on a MethodInfo object obtained using typeof&amp;lt;Example&amp;gt;.GetMethod(&amp;quot;Test2&amp;quot;) or some such. Executing a non-generic method is easy - just call Invoke() with the actual arguments. However, System.Reflection refuses to call Invoke on a method with unspecified generic arguments (T,U and V for Test2) . You need to specify the actual arguments (bool, float and string for Test2 resp.) manually. So, I had to deduce these from the actual arguments given to the method. The following two functions demonstrate how to do this:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;resolve (a:Type) (f:Type) (acc:Dictionary&amp;lt;_,_&amp;gt;) =
    &lt;span style="color: blue"&gt;if &lt;/span&gt;f.IsGenericParameter &lt;span style="color: blue"&gt;then
        if &lt;/span&gt;not (acc.ContainsKey(f)) &lt;span style="color: blue"&gt;then &lt;/span&gt;acc.Add(f,a)
    &lt;span style="color: blue"&gt;else 
        &lt;/span&gt;Array.zip (a.GetGenericArguments()) (f.GetGenericArguments())
        |&amp;gt; Array.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(act,form) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;resolve act form acc)

&lt;span style="color: blue"&gt;let &lt;/span&gt;invokeMethod (m:MethodInfo) args =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;m = &lt;span style="color: blue"&gt;if &lt;/span&gt;m.ContainsGenericParameters &lt;span style="color: blue"&gt;then
                let &lt;/span&gt;typeMap = &lt;span style="color: blue"&gt;new &lt;/span&gt;Dictionary&amp;lt;_,_&amp;gt;()
                Array.zip args (m.GetParameters()) 
                |&amp;gt; Array.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(a,f) &lt;span style="color: blue"&gt;-&amp;gt; 
                    &lt;/span&gt;resolve (a.GetType()) f.ParameterType typeMap)  
                &lt;span style="color: blue"&gt;let &lt;/span&gt;actuals = 
                    m.GetGenericArguments() 
                    |&amp;gt; Array.map (&lt;span style="color: blue"&gt;fun &lt;/span&gt;formal &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;typeMap.[formal])
                m.MakeGenericMethod(actuals)
            &lt;span style="color: blue"&gt;else 
                &lt;/span&gt;m
    m.Invoke(&lt;span style="color: blue"&gt;null&lt;/span&gt;, args)&lt;/pre&gt;

&lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;
&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;The second function, invokeMethod, can be used as a replacement for MethodInfo.Invoke that also works for methods with generic arguments. The function above only works for static methods, but taking away this restriction should be straightforward.&lt;/p&gt;

&lt;p&gt;invokeMethod takes a MethodInfo m(which should be a static method) and the arguments you want to call the method with. First we check if m is a generic method. If not, nothing needs to be done and we can just call Invoke.&lt;/p&gt;

&lt;p&gt;If m is a generic method, we build a a typeMap which maps the formal type arguments to their actual types, for which we can use the signature of the method on the one hand (i.e. as given by the MethodInfo), and the types of the actual arguments args. The function 'resolve' does most of the heavy lifting here, building up the typeMap by comparing actual and formal arguments in a pairwise fashion. 'resolve' needs to be called recursively, since type arguments may be nested arbitrarily deeply. For example,&amp;#160;&amp;#160; the formal argument list&amp;lt;'a*option&amp;lt;'b&amp;gt;&amp;gt; should resolve with the actual argument list&amp;lt;int*option&amp;lt;bool&amp;gt;&amp;gt; by mapping 'a to int and 'b to bool.&lt;/p&gt;

&lt;p&gt;Once we've determined the actual type arguments to the generic method, System.Reflection lets us instantiate an invoke-able method using MethodInfo.MakeGenericMethod(), which takes an array of actual types that fill in the generic type arguments to the method. If we've determined the type arguments correctly, the result of MakeGenericMethod() is another MethodInfo object that can be invoked as usual.&lt;/p&gt;

&lt;p&gt;The interested reader can figure out the details.&lt;/p&gt;

&lt;p&gt;Some notes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;'resolve' is not tail-recursive. I just didn't bother since you would need to write some extremely convoluted method arguments to blow the stack. list&amp;lt;list&amp;lt;list&amp;lt;list&amp;lt;(repeat x 1000 000)&amp;gt;&amp;gt;&amp;gt;&amp;gt; anyone? Also for the same reason I didn't worry about performance - I don't actually expect to have very deeply nested types. (if type classes were ever added to F#, I guess I &lt;em&gt;would&lt;/em&gt;&amp;#160; need to start worrying about that...) &lt;/li&gt;

  &lt;li&gt;I dislike that I used a Dictionary in there, though it seemed to be the most elegant solution. I tried using a Map, but then I had to merge maps when the recursive call to resolve returned. It seemed easier with a (non-functional) Dictionary. If anyone can do better, I'd like to hear about it. &lt;/li&gt;
&lt;/ul&gt;

&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:cee46a49-35a2-4cc4-a617-c4f5fee45d26" 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/System.Reflection" rel="tag"&gt;System.Reflection&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-4148138498846433687?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/4148138498846433687/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/10/how-to-invoke-method-with-type.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/4148138498846433687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/4148138498846433687'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/10/how-to-invoke-method-with-type.html' title='How to invoke a method with type parameters using reflection (in F#)'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-3546642512062914960</id><published>2008-08-15T11:05:00.000+01:00</published><updated>2008-08-31T14:53:24.012+01: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.2</title><content type='html'>&lt;p&gt;[Update: I noticed that the download comes with a preliminary version of random.fs, which contained many mistakes! I've now updated the link. Sorry! I also added the link directly to this post as well.]&lt;/p&gt;  &lt;p&gt;[Update 2: I converted the old F# project to a shiny new .fsproj compatible with the F# September CTP which was released yesterday. Had to clean up and change some code as well, mostly due to renames and a different type signature of assert. New download link below.]&lt;/p&gt;  &lt;p&gt;Version 0.2 introduces the following changes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Ported the Haskell random implementation, which gives more dependable results when splitting seeds. &lt;/li&gt;    &lt;li&gt;Introduced lazy evaluation of properties to improve checking of conditional properties. The function &lt;em&gt;prop&lt;/em&gt; needs a lazy argument from now on; a shorthand &lt;em&gt;propl&lt;/em&gt; can be used if you don't need or want this. (Thanks to galen for bringing this to my attention) &lt;/li&gt;    &lt;li&gt;Tried lots of approaches to get rid of both &lt;em&gt;prop &lt;/em&gt;and &lt;em&gt;lazy &lt;/em&gt;when they are not needed. Also tried to get rid of the generators using reflection and quotations. Very few approaches were feasible, none were satisfactory. In the end, nothing changed. I'm hoping for type classes or some other way of overloading and/or implicit parameter passing, but I'll guess that'll be for F# 2.0 at the earliest. If anyone has any suggestions, please let me know. &lt;/li&gt;    &lt;li&gt;Added some examples in another style, where the property is separated from the actual generator, and added some convenience functions &lt;em&gt;qcheck&lt;/em&gt; and &lt;em&gt;vcheck &lt;/em&gt;to support this style. This improves readability of the actual properties, and makes them somewhat more reusable. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Breaking change: if you have some properties lying around, the easiest way to get them to work is to replace &lt;em&gt;prop&lt;/em&gt; by &lt;em&gt;propl.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Read the updated complete documentation in my &lt;a href="http://fortysix-and-two.blogspot.com/2008/05/fscheck-random-testing-for-f.html"&gt;previous post&lt;/a&gt;. My plan is to keep that post as the up to date and complete documentation of the latest version, and announcing new releases with changes in separate posts like this. &lt;/p&gt;  &lt;p&gt;Thanks for your interest, and do keep giving me feedback and suggestions!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://cid-f6a45280389d5d06.skydrive.live.com/self.aspx/Public/FsCheck%200.2.zip"&gt;Download FsCheck 0.2 source&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://cid-f6a45280389d5d06.skydrive.live.com/self.aspx/Public/FsCheck%200.2%20September%20CTP.zip"&gt;Download FsCheck 0.2 for the F# September CTP&lt;/a&gt;&lt;/p&gt;  &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:b3a3bdef-4bd0-42fa-8fd8-9941c51afb40" 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/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-3546642512062914960?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/3546642512062914960/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/08/announcing-fscheck-02.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/3546642512062914960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/3546642512062914960'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/08/announcing-fscheck-02.html' title='Announcing FsCheck 0.2'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-3425318829054054599</id><published>2008-05-10T22:56:00.001+01:00</published><updated>2008-11-11T18:38:11.761Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='fsyacc'/><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><category scheme='http://www.blogger.com/atom/ns#' term='parsing'/><category scheme='http://www.blogger.com/atom/ns#' term='fslex'/><title type='text'>Parsing Dot with F#: Part 4 - Conclusion</title><content type='html'>&lt;p&gt;In this very last part, I'll just show how to put everything together: the types, the lexer and the parser. First, we need to generate some F# files from the dotlexer.fsl&amp;#160; and the dotparser.fsy files. This is easily accomplished by running fslex and fsyacc, respectively. This creates dotlexer.fs, dotparser.fs and dotparser.fsi. If, like me, you're working in Visual Studio, you can add these files to your project, but take care that you put everything in the right order or it won't compile (I actually lost quite a bit of time with this): first the definition of the abstract syntax type, then the parser files, then the lexer file. Finally, you can call the parser:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;parseFromString(text) =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;lexbuf = Lexing.from_string text
    &lt;span style="color: blue"&gt;try
        &lt;/span&gt;DotParser.start DotLexer.token lexbuf
    &lt;span style="color: blue"&gt;with &lt;/span&gt;e &lt;span style="color: blue"&gt;-&amp;gt;
        let &lt;/span&gt;pos = lexbuf.EndPos
        printf &lt;span style="color: #a31515"&gt;&amp;quot;error near line %d, character %d\n%s\n&amp;quot; &lt;/span&gt;pos.Line pos.Column (e.ToString())
        Graph (&lt;span style="color: blue"&gt;new &lt;/span&gt;List&amp;lt;_&amp;gt;())&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;This is fairly straightforward: the Lexing module defines functions to create a lexing buffer from a string. Feed this buffer into the DotParser.start function generated by fsyacc. This function will return the expected type, as defined in the .fsy file.&lt;/p&gt;

&lt;p&gt;That's really all there is to it - the rest is some exception catching and printing an error for debugging purposes. One thing I'd like to warn you about is that debugging this stuff can be quite tedious, due to the fact that first the F# files are generated by the fsyacc and the fslex tools, and afterwards compiled. Although the compiler does a fairly good job of showing where the actual errors are in the fsy and fsl files, it is sometimes hard to track down what exactly is the problem.&lt;/p&gt;

&lt;p&gt;Finally, you can &lt;a href="http://cid-f6a45280389d5d06.skydrive.live.com/self.aspx/Public/Architude.Graphviz.zip"&gt;download the example project&lt;/a&gt;.&lt;/p&gt;

&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:7b1c3023-1565-4c3e-8518-ced1f4a6e39c" 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/parsing" rel="tag"&gt;parsing&lt;/a&gt;,&lt;a href="http://technorati.com/tags/fslex" rel="tag"&gt;fslex&lt;/a&gt;,&lt;a href="http://technorati.com/tags/fsyacc" rel="tag"&gt;fsyacc&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-3425318829054054599?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/3425318829054054599/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/05/parsing-dot-with-f-part-4-conclusion.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/3425318829054054599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/3425318829054054599'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/05/parsing-dot-with-f-part-4-conclusion.html' title='Parsing Dot with F#: Part 4 - Conclusion'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-6576576021817363843</id><published>2008-05-09T22:46:00.001+01:00</published><updated>2008-11-11T18:37:58.726Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='fsyacc'/><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><category scheme='http://www.blogger.com/atom/ns#' term='parsing'/><title type='text'>Parsing Dot with F#: Part 3 - The parser</title><content type='html'>&lt;p&gt;The parser is produced by fsyacc (yacc stands for Yet Another Compiler Compiler). Basically it turns the tokens produced by the lexer into a nice set of types that you can easily manipulate from within your program. Fsyacc can generate a parser based on a definition that looks pretty much the same as the simplified grammar for Dot that I discussed in &lt;a href="http://fortysix-and-two.blogspot.com/2008/04/parsing-dot-with-f-part-1.html" target="_blank"&gt;part 1&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Our dotparser.fsy file starts off with some preliminaries:&lt;/p&gt;  &lt;pre class="code"&gt;%{

open Ast
open System.Collections.Generic

%}&lt;/pre&gt;

&lt;p&gt;Same as the lexer, this code will eventually&amp;#160; be transformed into regular F# code. So here we can open some modules for use later, and potentially do other preliminaries.&lt;/p&gt;

&lt;p&gt;Then, some parser-related startup:&lt;/p&gt;

&lt;pre class="code"&gt;%start start

%token &amp;lt;string&amp;gt; ID
%token NODE EDGE DIGRAPH GRAPH DIEDGE UNEDGE QUOTE LACC RACC LPAREN RPAREN SEMI COMMA ASSIGN EOF 

%type &amp;lt; Ast.Graph &amp;gt; start&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;The first and last line indicate to fsyacc where to start parsing (at which rule, to be defined later), and the&amp;#160; type the complete parsing process will construct; if you remember our abstract syntax tree from part 1, we're trying to make a Graph type.&lt;/p&gt;

&lt;p&gt;The lines in between are just an enumeration of all the possible terminal tokens (i.e. tokens that needn't be parsed further), along with the type of data that they carry. You should recognize these from the lexer. In our parser, only the ID token carries information of type string.&lt;/p&gt;

&lt;p&gt;And finally, the part that makes this all tick:&lt;/p&gt;

&lt;pre class="code"&gt;start: Graph { $1 }

Graph: DIGRAPH ID LACC StmtList SEMI RACC    { ($4:List&amp;lt;_&amp;gt;).Reverse(); Graph $4 }

StmtList: Stmt            { let l = new List&amp;lt;Element&amp;gt;() in l.Add($1); l }
    | StmtList SEMI Stmt  { $1.Add($3); $1 }

Stmt: 
    | ID AttrListOpt             { Node($1,$2) } 
    | ID DIEDGE ID AttrListOpt   { Edge($1,$3,$4) }
    | GRAPH AttrListOpt          { GraphAttributeList($2) }
    | NODE AttrListOpt           { NodeAttributeList($2) }
    | EDGE AttrListOpt           { EdgeAttributeList($2) }

AttrListOpt:
    |                            { new Dictionary&amp;lt;string,string&amp;gt;() }
    | LPAREN AttrList RPAREN     { $2 }

Attr: ID ASSIGN ID               { new KeyValuePair&amp;lt;string,string&amp;gt;($1,$3) }

AttrList: Attr              { let attr = new Dictionary&amp;lt;string,string&amp;gt;() in attr.Add($1.Key,$1.Value); attr }
    | AttrList COMMA Attr   { $1.Add($3.Key, $3.Value); $1 }&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Notice that this is very similar to the grammar defined earlier. I guess with some experience one can derive this fsyacc spec from the grammar in a fairly straightforward way. Expect some bumps on the road the first time around though. Notice that with each rule we can again associate the transformation that needs to occur, similar as we did in the lexer. Only this time we're not producing tokens, we're producing the actual F# types that we need. The $n variables in the right part refer to the data that is carried by the nth token on the left.&lt;/p&gt;

&lt;p&gt;Some things to be aware of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If you need to parse a list of things, like the StmtList above, you need to do this &amp;quot;backwards&amp;quot;, i.e. the second option in StmtList is 'StmtList SEMI Stmt', not 'Stmt SEMI StmtList'. This also means I reverse the list once read in the Graph rule. This is simply a consequence of how the parser produced by fsyacc works under the hood - in this case a minor inconvenience. &lt;/li&gt;

  &lt;li&gt;I chose here to use regular .NET types as much as possible, since I intended to use this code from C#. If you use F# types like list, the code actually becomes a lot shorter. For example, 'let l = new List&amp;lt;Element&amp;gt;() in l.Add($1); l&amp;quot; just becomes '[$1]'. &lt;/li&gt;

  &lt;li&gt;I deliberately reversed the order of the rules Attr and AttrList, so that F# could infer the types of the arguments better. This is a result of the fact that F# parser top to bottom, left to right. If you get a lot of type inference errors, it pays off to experiment with the order of your statements, if you can reverse them. I try to avoid adding type annotations as much as possible, they make the code harder to read and to maintain. (in C# my use of the C# 'var' keyword has increased exponentially) &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it; next time, I'll show you how to put everything together and call the parser.&lt;/p&gt;

&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:58dfd7fd-0b92-40c3-aa86-2548e1145672" 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/fsyacc" rel="tag"&gt;fsyacc&lt;/a&gt;,&lt;a href="http://technorati.com/tags/graphviz" rel="tag"&gt;graphviz&lt;/a&gt;,&lt;a href="http://technorati.com/tags/parsing" rel="tag"&gt;parsing&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-6576576021817363843?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/6576576021817363843/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/05/parsing-dot-with-f-part-3-parser.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/6576576021817363843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/6576576021817363843'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/05/parsing-dot-with-f-part-3-parser.html' title='Parsing Dot with F#: Part 3 - The parser'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-5080716819153916052</id><published>2008-05-02T19:36:00.001+01:00</published><updated>2008-12-05T11:36:55.779Z</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: Random testing for F#</title><content type='html'>&lt;p&gt;[Updated for version 0.2]&lt;/p&gt;  &lt;p&gt;[Update: this documentation is no longer kept up to date as of FsCheck 0.3. Please check out &lt;a href="http://www.codeplex.com/fscheck"&gt;FsCheck&lt;/a&gt; on codeplex for up to date releases, information and what not.]&lt;/p&gt;  &lt;p&gt;FsCheck is an as-literal-as-possible port of Haskell's &lt;a href="http://www.cs.chalmers.se/~rjmh/QuickCheck/"&gt;QuickCheck&lt;/a&gt; 0.1. Using FsCheck, you define &lt;em&gt;properties&lt;/em&gt; that should hold for all your functions. FsCheck checks that those properties hold by generating random values for the parameters of the properties. While writing the properties, you are actually writing a testable specification of your program.&lt;/p&gt;  &lt;p&gt;This release is still a bit rough around the edges; basic things work, but there's for example no easy way to check all properties in a given file. Also parts of FsCheck itself are still untested (ah, the irony). I wrote FsCheck mainly as an exercise&amp;#160; - learn from the best, or suck like the rest, so Haskell seems like a good place to start.&lt;/p&gt;  &lt;p&gt;The next part of this post is&amp;#160; a manual for using FsCheck; most of it is almost literally &amp;quot;adapted&amp;quot; from the &lt;a href="http://www.cs.chalmers.se/~rjmh/QuickCheck/"&gt;QuickCheck&lt;/a&gt;&amp;#160;&lt;a href="http://www.cs.chalmers.se/~rjmh/QuickCheck/manual.html"&gt;manual&lt;/a&gt; and &lt;a href="http://www.md.chalmers.se/~koen/Papers/quick.ps"&gt;paper&lt;/a&gt;. Any errors and omissions are entirely my responsibility.&lt;/p&gt;  &lt;h4&gt;What is FsCheck?&lt;/h4&gt;  &lt;p&gt;FsCheck is a tool for testing F# programs automatically. The programmer provides a specification of the program, in the form of properties which functions should satisfy, and FsCheck then tests that the properties hold in a large number of randomly generated cases. 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;FsCheck is currently best used to test the functions in your F# programs. I may be experimenting in the future with using it to test classes and methods, in combination with existing .NET unit testing frameworks. The generator combinators can be used already in any testing framework to easily generate a number of random values for many types. Mostly these are F# specific at this point (tuples, option values, function values), but that should be easy to remedy.&lt;/p&gt;  &lt;h4&gt;A Simple Example&lt;/h4&gt;  &lt;p&gt;A simple example of a property definition is &lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_RevRev (xs:list&amp;lt;int&amp;gt;) = List.rev (List.rev xs) = xs  |&amp;gt; propl&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;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;This property asserts that the reverse of the reverse of a list of integers is the list itself. (the &lt;em&gt;propl&lt;/em&gt; function comes with FsCheck and is explained shortly) To check the property, we load this definition in F# interactive and then invoke &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: black"&gt;&amp;gt; q&lt;/span&gt;check (Gen.List(Gen.Int)) prop_RevRev&lt;span style="color: #00008b"&gt;;;
&lt;/span&gt;&lt;span style="color: black"&gt;Ok, passed 100 tests.
val it : unit = ()&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;As the example shows, you indicate to FsCheck the type to generate for the property (in this case, a list of ints).&lt;/p&gt;

&lt;p&gt;When a property fails, FsCheck displays a counter-example. For example, if we define &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_RevId xs = List.rev xs = xs |&amp;gt; propl&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;then checking it results in&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: black"&gt;&amp;gt; q&lt;/span&gt;check (Gen.List(Gen.Int)) prop_RevId&lt;span style="color: #00008b"&gt;;;
&lt;/span&gt;&lt;span style="color: black"&gt;Falsifiable, after 8 tests:
[&amp;quot;[-2; -4; -1]&amp;quot;]
val it : unit = ()
&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;h4&gt;Using FsCheck&lt;/h4&gt;

&lt;p&gt;To use FsCheck, you download the latest FsCheck solution at the very end of this post. Build and reference the assembly in any projects containing specifications or test data generators. You can then test properties by loading the module they are defined in into F# interactive, and calling 
  &lt;br /&gt;&lt;span style="color: #00008b"&gt;qcheck &amp;lt;generator&amp;gt; &amp;lt;property_name&amp;gt;;; &lt;/span&gt;

  &lt;br /&gt;or by running and writing a small console application that calls the qcheck function.&lt;/p&gt;

&lt;h4&gt;What do I do if a test loops or encounters an error?&lt;/h4&gt;

&lt;p&gt;In this case we know that the property does not hold, but &lt;span style="color: #00008b"&gt;&lt;em&gt;qcheck&lt;/em&gt;&lt;/span&gt; does not display the counter-example. There is another testing function provided for this situation. Repeat the test using &lt;/p&gt;

&lt;p&gt;&lt;span style="color: #00008b"&gt;vcheck &amp;lt;generator&amp;gt; &amp;lt;property_name&amp;gt;;; &lt;/span&gt;&lt;/p&gt;

&lt;p&gt;which displays each test case before running the test: the last test case displayed is thus the one in which the loop or error arises. &lt;/p&gt;

&lt;h4&gt;Properties&lt;/h4&gt;

&lt;p&gt;Properties are expressed as F# function definitions, with names beginning with prop_. Properties can be defined together with their generators, by universal quantification over their parameters using the function &lt;em&gt;forAll, &lt;/em&gt;which takes the form&lt;/p&gt;

&lt;pre class="code"&gt;forAll &amp;lt;generator&amp;gt; (&lt;span style="color: blue"&gt;fun &lt;/span&gt;arg &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;&amp;lt;property&amp;gt;)&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;The first argument of &lt;em&gt;forAll&lt;/em&gt; is a test data generator. The second argument is a function that takes as argument one value generated by the test data generator, and returns the property that needs to be checked. The values generated by the test data generator must be of the correct type for the argument, which is checked at compile time. For example,&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_RevRev = 
    forAll (Gen.List(Gen.Int)) (&lt;span style="color: blue"&gt;fun &lt;/span&gt;xs &lt;span style="color: blue"&gt;-&amp;gt; 
        &lt;/span&gt;List.rev (List.rev xs) = xs |&amp;gt; propl)&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;will generate a number of int lists for the argument xs, and evaluate the function using the generated value.&lt;/p&gt;

&lt;p&gt;The core of a property is an assertion function that returns a bool. Such a function should be made into a Property type by calling the function &lt;em&gt;propl&lt;/em&gt;. This allows you to use property combinators explained below.&lt;/p&gt;

&lt;p&gt;`Polymorphic' properties, such as the one above, are restricted to a particular type to be used for testing, which is done by specifying a generator. The anonymous function given to forAll can take only one argument: if a property needs more, they should be tupled using &lt;em&gt;Gen.Tuple&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Note: thanks to Haskell's type classes, QuickCheck does not force you to use &lt;em&gt;forAll&lt;/em&gt; or needs you to use &lt;em&gt;prop. &lt;/em&gt;I do realize it makes the properties in F# harder to read - at the moment I see no elegant ways around this. But in FsCheck you can separate the generators from the properties using &lt;em&gt;qcheck &lt;/em&gt;and &lt;em&gt;vcheck. &lt;/em&gt;In the examples you can find examples of both styles. For clarity, I'll use the &lt;em&gt;forAll&lt;/em&gt; function in the following.&lt;/p&gt;

&lt;h5&gt;Conditional Properties&lt;/h5&gt;

&lt;p&gt;Properties may take the form&lt;/p&gt;

&lt;pre class="code"&gt;&amp;lt;condition&amp;gt; ==&amp;gt; &amp;lt;property&amp;gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;For example, &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;ordered xs = &lt;span style="color: blue"&gt;match &lt;/span&gt;xs &lt;span style="color: blue"&gt;with
                     &lt;/span&gt;| [] &lt;span style="color: blue"&gt;-&amp;gt; true
                     &lt;/span&gt;| [x] &lt;span style="color: blue"&gt;-&amp;gt; true
                     &lt;/span&gt;| x::y::ys &lt;span style="color: blue"&gt;-&amp;gt;  &lt;/span&gt;(x &amp;lt;= y) &amp;amp;&amp;amp; ordered (y::ys)
&lt;span style="color: blue"&gt;let rec &lt;/span&gt;insert x xs = &lt;span style="color: blue"&gt;match &lt;/span&gt;xs &lt;span style="color: blue"&gt;with
                      &lt;/span&gt;| [] &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;[x]
                      | c::cs &lt;span style="color: blue"&gt;-&amp;gt; if &lt;/span&gt;x&amp;lt;=c &lt;span style="color: blue"&gt;then &lt;/span&gt;x::xs &lt;span style="color: blue"&gt;else &lt;/span&gt;c::(insert x cs)
&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_Insert = forAll (Gen.Tuple(Gen.Int, Gen.List(Gen.Int))) (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(x,xs) &lt;span style="color: blue"&gt;-&amp;gt; 
                    &lt;/span&gt;ordered xs ==&amp;gt; propl (ordered (insert x xs)))&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Such a property holds if the property after ==&amp;gt; holds whenever the condition does. &lt;/p&gt;

&lt;p&gt;Testing discards test cases which do not satisfy the condition. Test case generation continues until 100 cases which do satisfy the condition have been found, or until an overall limit on the number of test cases is reached (to avoid looping if the condition never holds). In this case a message such as 
  &lt;br /&gt;Arguments exhausted after 97 tests. 

  &lt;br /&gt;indicates that 97 test cases satisfying the condition were found, and that the property held in those 97 cases. &lt;/p&gt;

&lt;p&gt;Since F# has eager evaluation by default, the above property does more work than necessary: it evaluates the property at the right of the condition no matter what the outcome of the condition on the left. While only a performance consideration in the above example, this may limit the expressiveness of properties as well - consider:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_CheckLazy2 = forAll (Gen.Int) (&lt;span style="color: blue"&gt;fun &lt;/span&gt;a &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;a &amp;lt;&amp;gt; 0 ==&amp;gt; prop&lt;span style="color: blue"&gt;l &lt;/span&gt;(1/a = 1/a)))&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color: blue"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Will throw an exception. However, FsCheck also provides the function &lt;em&gt;prop&lt;/em&gt; which makes a lazy property, and so requires the F# keyword lazy to force the lazy evaluation of the condition:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_CheckLazy2 = forAll (Gen.Int) (&lt;span style="color: blue"&gt;fun &lt;/span&gt;a &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;a &amp;lt;&amp;gt; 0 ==&amp;gt; prop (&lt;span style="color: blue"&gt;lazy &lt;/span&gt;(1/a = 1/a)))&lt;/pre&gt;

&lt;p&gt;Works as expected. &lt;em&gt;propl&lt;/em&gt; is actually a shorthand for &lt;em&gt;prop (lazy ...)),&lt;/em&gt; but beware: the argument of &lt;em&gt;propl&lt;/em&gt; is evaluated eagerly!&lt;/p&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;h5&gt;Generators&lt;/h5&gt;

&lt;p&gt;There are number of generators for some common types, but by supplying a custom generator, instead of using the default generator for that type, it is possible to control the distribution of test data. In the following example, by supplying a custom generator for ordered lists, rather than filtering out test cases which are not ordered, we guarantee that 100 test cases can be generated without reaching the overall limit on test cases:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_Insert = forAll (Gen.Tuple(Gen.Int, orderedList(Gen.Int))) (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(x,xs) &lt;span style="color: blue"&gt;-&amp;gt; 
                    &lt;/span&gt;propl (ordered (insert x xs)))&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Combinators for defining generators are described below. &lt;/p&gt;

&lt;h4&gt;Observing Test Case Distribution&lt;/h4&gt;

&lt;p&gt;It is important to be aware of the distribution of test cases: if test data is not well distributed then conclusions drawn from the test results may be invalid. In particular, the ==&amp;gt; operator can skew the distribution of test data badly, since only test data which satisfies the given condition is used. &lt;/p&gt;

&lt;p&gt;FsCheck provides several ways to observe the distribution of test data. Code for making observations is incorporated into the statement of properties, each time the property is actually tested the observation is made, and the collected observations are then summarized when testing is complete. &lt;/p&gt;

&lt;h5&gt;Counting Trivial Cases&lt;/h5&gt;

&lt;p&gt;A property may take the form&lt;/p&gt;

&lt;pre class="code"&gt;trivial &amp;lt;condition&amp;gt; &amp;lt;property&amp;gt;&lt;/pre&gt;

&lt;p&gt;For example,&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color: blue"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_Insert = forAll (Gen.Tuple(Gen.Int, Gen.List(Gen.Int))) 
                    (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(x,xs) &lt;span style="color: blue"&gt;-&amp;gt; 
                    &lt;/span&gt;ordered xs ==&amp;gt; propl (ordered (insert x xs))
                    |&amp;gt; trivial (List.length xs = 0)) &lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Test cases for which the condition is true are classified as trivial, and the proportion of trivial test cases in the total is reported. In this example, testing produces&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: black"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color: #00008b"&gt;quickCheck prop_Insert;;
&lt;/span&gt;&lt;span style="color: black"&gt;Ok, passed 100 tests (46% trivial).
val it : unit = ()&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;h5&gt;Classifying Test Cases&lt;/h5&gt;

&lt;p&gt;A property may take the form&lt;/p&gt;

&lt;pre class="code"&gt;classify &amp;lt;condition&amp;gt; &amp;lt;string&amp;gt; &amp;lt;property&amp;gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;For example,&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;prop_Insert2 = 
    forAll (Gen.Tuple(Gen.Int, Gen.List(Gen.Int))) (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(x,xs) &lt;span style="color: blue"&gt;-&amp;gt; 
        &lt;/span&gt;ordered xs ==&amp;gt; propl (ordered (insert x xs))
        |&amp;gt; classify (ordered (x::xs)) &lt;span style="color: #a31515"&gt;&amp;quot;at-head&amp;quot;
        &lt;/span&gt;|&amp;gt; classify (ordered (xs @ [x])) &lt;span style="color: #a31515"&gt;&amp;quot;at-tail&amp;quot;&lt;/span&gt;)&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Test cases satisfying the condition are assigned the classification given, and the distribution of classifications is reported after testing. In this case the result is&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: black"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color: #00008b"&gt;quickCheck prop_Insert2;;
&lt;/span&gt;&lt;span style="color: black"&gt;Ok, passed 100 tests.
48% at-tail, at-head.
25% at-head.
21% at-tail.
val it : unit = ()
&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Note that a test case may fall into more than one classification. &lt;/p&gt;

&lt;h5&gt;Collecting Data Values&lt;/h5&gt;

&lt;p&gt;A property may take the form&lt;/p&gt;

&lt;pre class="code"&gt;collect &amp;lt;expression&amp;gt; &amp;lt;property&amp;gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;For example, &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_Insert3 = 
    forAll (Gen.Tuple(Gen.Int, Gen.List(Gen.Int))) (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(x,xs) &lt;span style="color: blue"&gt;-&amp;gt; 
        &lt;/span&gt;ordered xs ==&amp;gt; propl (ordered (insert x xs))
&lt;span style="color: #a31515"&gt;        &lt;/span&gt;|&amp;gt; collect (List.length xs))&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;The argument of collect is evaluated in each test case, and the distribution of values is reported. The type of this argument is printed using any_to_string. In the example above, the output is&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: black"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color: #00008b"&gt;quickCheck prop_Insert3;;
&lt;/span&gt;&lt;span style="color: black"&gt;Ok, passed 100 tests.
46% 0.
36% 1.
11% 2.
6% 3.
1% 4.
val it : unit = ()&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;h5&gt;Combining Observations&lt;/h5&gt;

&lt;p&gt;The observations described here may be combined in any way. All the observations of each test case are combined, and the distribution of these combinations is reported. For example, testing the property&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_Insert3 = 
    forAll (Gen.Tuple(Gen.Int, Gen.List(Gen.Int))) (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(x,xs) &lt;span style="color: blue"&gt;-&amp;gt; 
        &lt;/span&gt;ordered xs ==&amp;gt; propl (ordered (insert x xs))
        |&amp;gt; classify (ordered (x::xs)) &lt;span style="color: #a31515"&gt;&amp;quot;at-head&amp;quot;
        &lt;/span&gt;|&amp;gt; classify (ordered (xs @ [x])) &lt;span style="color: #a31515"&gt;&amp;quot;at-tail&amp;quot;
        &lt;/span&gt;|&amp;gt; collect (List.length xs))   &lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;produces&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: black"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color: #00008b"&gt;quickCheck prop_Insert3;;
&lt;/span&gt;&lt;span style="color: black"&gt;Ok, passed 100 tests.
46% 0, at-tail, at-head.
18% 1, at-head.
17% 1, at-tail.
6% 2, at-head.
3% 3.
2% 2.
2% 3, at-tail.
2% 2, at-tail.
1% 4.
1% 3, at-head.
1% 2, at-tail, at-head.
1% 1, at-tail, at-head.
val it : unit = ()
&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&amp;#160; &lt;br /&gt;from which we see that insertion at the beginning or end of a list has not been tested for lists of four elements.&lt;/p&gt;

&lt;h4&gt;Test Data Generators: The Type Gen&lt;/h4&gt;

&lt;p&gt;Test data is produced by test data generators. FsCheck defines default generators for some often used types, but you can use your own, and will need to define your own generators for any new types you introduce. &lt;/p&gt;

&lt;p&gt;Generators have types of the form &lt;em&gt;'a Gen&lt;/em&gt;; this is a generator for values of type a. The type Gen is a computation expression called &lt;em&gt;gen&lt;/em&gt;, so F#'s computation expression syntax can be used to define generators. &lt;/p&gt;

&lt;p&gt;Generators are built up on top of the function &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: black"&gt;val choose : (int * int -&amp;gt; int Gen)&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;which makes a random choice of a value from an interval, with a uniform distribution. For example, to make a random choice between the elements of a list, use &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;chooseFromList xs = gen { &lt;span style="color: blue"&gt;let! &lt;/span&gt;i = choose (0, List.length xs) 
                              &lt;span style="color: blue"&gt;return &lt;/span&gt;(List.nth xs i) }&lt;/pre&gt;

&lt;p&gt;Note that choose does not include the upper bound of the interval, so you can use List.length without deducting 1.&lt;/p&gt;

&lt;h5&gt;Choosing Between Alternatives&lt;/h5&gt;

&lt;p&gt;A generator may take the form &lt;/p&gt;

&lt;pre class="code"&gt;oneof &amp;lt;list of generators&amp;gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;which chooses among the generators in the list with equal probability. For example, &lt;/p&gt;

&lt;pre class="code"&gt;oneof [ gen { &lt;span style="color: blue"&gt;return true &lt;/span&gt;}; gen { &lt;span style="color: blue"&gt;return false &lt;/span&gt;} ]&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;generates a random boolean which is true with probability one half. &lt;/p&gt;

&lt;p&gt;We can control the distribution of results using the function &lt;/p&gt;

&lt;pre class="code"&gt;val frequency: (int * 'a Gen) list -&amp;gt; 'a Gen &lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;instead. Frequency chooses a generator from the list randomly, but weights the probability of choosing each alternative by the factor given. For example,&lt;/p&gt;

&lt;pre class="code"&gt;frequency [ (2, gen { &lt;span style="color: blue"&gt;return true &lt;/span&gt;}); (1, gen { &lt;span style="color: blue"&gt;return false &lt;/span&gt;})]&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;generates true two thirds of the time. &lt;/p&gt;

&lt;h5&gt;The Size of Test Data&lt;/h5&gt;

&lt;p&gt;Test data generators have an implicit size parameter; FsCheck begins by generating small test cases, and gradually increases the size as testing progresses. Different test data generators interpret the size parameter in different ways: some ignore it, while the list generator, for example, interprets it as an upper bound on the length of generated lists. You are free to use it as you wish to control your own test data generators. &lt;/p&gt;

&lt;p&gt;You can obtain the value of the size parameter using &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: black"&gt;val sized : ((int -&amp;gt; 'a Gen) -&amp;gt; 'a Gen)&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;em&gt;sized g&lt;/em&gt; calls g, passing it the current size as a parameter. For example, to generate natural numbers in the range 0 to size, use &lt;/p&gt;

&lt;pre class="code"&gt;sized &amp;lt;| &lt;span style="color: blue"&gt;fun &lt;/span&gt;s &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;choose (0,s)&lt;/pre&gt;

&lt;p&gt;The purpose of size control is to ensure that test cases are large enough to reveal errors, while remaining small enough to test fast. Sometimes the default size control does not achieve this. For example, towards the end of a test run arbitrary lists may have up to 50 elements, so arbitrary lists of lists may have up to 2500, which is too large for efficient testing. In such cases it can be useful to modify the size parameter explicitly. You can do so using &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: black"&gt;val resize : (int -&amp;gt; 'a Gen -&amp;gt; 'a Gen)&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;em&gt;resize n g&lt;/em&gt; invokes generator g with size parameter n. The size parameter should never be negative. For example, to generate a random matrix it might be appropriate to take the square root of the original size:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;matrix gn = sized &amp;lt;| &lt;span style="color: blue"&gt;fun &lt;/span&gt;s &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;resize (s|&amp;gt;float|&amp;gt;sqrt|&amp;gt;int) gn&lt;/pre&gt;

&lt;h5&gt;Generating Recursive Data Types&lt;/h5&gt;

&lt;p&gt;Generators for recursive data types are easy to express using &lt;em&gt;oneof&lt;/em&gt; or &lt;em&gt;frequency&lt;/em&gt; to choose between constructors, and F#'s standard computation expression syntax to form a generator for each case. There are also &lt;em&gt;liftGen&lt;/em&gt; functions for arity up to 4 (more are easy to add) to lift constructors and functions into the Gen type. For example, if the type of trees is defined by&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Tree = Leaf &lt;span style="color: blue"&gt;of &lt;/span&gt;int | Branch &lt;span style="color: blue"&gt;of &lt;/span&gt;Tree * Tree&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;then a generator for trees might be defined by&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;unsafeTree = 
    oneof [ liftGen (Leaf) Gen.Int; 
            liftGen2 (&lt;span style="color: blue"&gt;fun &lt;/span&gt;x y &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Branch (x,y)) unsafeTree unsafeTree]&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;However, there is always a risk that a recursive generator like this may fail to terminate, or produce very large results. In any case, the F# compiler generates an error for the above function for exactly this reason: the function calls itself. To avoid this, recursive generators should always use the size control mechanism. For example, &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;tree =
    &lt;span style="color: blue"&gt;let rec &lt;/span&gt;tree' s = 
        &lt;span style="color: blue"&gt;match &lt;/span&gt;s &lt;span style="color: blue"&gt;with
          &lt;/span&gt;| 0 &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;liftGen (Leaf) Gen.Int
          | 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;subtree = tree' (n/2) &lt;span style="color: blue"&gt;in
            &lt;/span&gt;oneof [ liftGen (Leaf) Gen.Int; 
                    liftGen2 (&lt;span style="color: blue"&gt;fun &lt;/span&gt;x y &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Branch (x,y)) subtree subtree]
    sized tree'&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Note that &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We guarantee termination by forcing the result to be a leaf when the size is zero. &lt;/li&gt;

  &lt;li&gt;We halve the size at each recursion, so that the size gives an upper bound on the number of nodes in the tree. We are free to interpret the size as we will. &lt;/li&gt;

  &lt;li&gt;The fact that we share the subtree generator between the two branches of a Branch does not, of course, mean that we generate the same tree in each case. &lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Useful Generator Combinators&lt;/h5&gt;

&lt;p&gt;If g is a generator for type t, then &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;two g&lt;/em&gt; generates a pair of t's, &lt;/li&gt;

  &lt;li&gt;&lt;em&gt;three g&lt;/em&gt; generates a triple of t's, &lt;/li&gt;

  &lt;li&gt;&lt;em&gt;four g&lt;/em&gt; generates a quadruple of t's, &lt;/li&gt;

  &lt;li&gt;&lt;em&gt;vector n g&lt;/em&gt; generates a list of n t's. &lt;/li&gt;

  &lt;li&gt;If xs is a list, then &lt;em&gt;elements xs&lt;/em&gt; generates an arbitrary element of xs. &lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Default Generators&lt;/h5&gt;

&lt;p&gt;FsCheck uses static members of the type Gen to define default test data generators for some types. FsCheck defines instances for the types (), bool, int, float, pairs, triples, quadruples, lists, and functions. You can define new ones by making new instances of &lt;em&gt;'a Gen.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To generate random functions of type 'a-&amp;gt;'b, you need to provide an instance of type &lt;em&gt;'a-&amp;gt; 'b Gen -&amp;gt; 'b Gen,&lt;/em&gt; which we'll call the cogenerator. The implementation of &lt;em&gt;('a-&amp;gt;'b) Gen&lt;/em&gt; uses a cogenerator for type a. If you only want to generate random values of a type, you need only to define a generator for that type, while if you want to generate random functions over the type also, then you should define a cogenerator as well. &lt;/p&gt;

&lt;p&gt;A cogenerator function interprets a value of type a as a generator transformer. It should be defined so that different values are interpreted as independent generator transformers. These can be programmed using the function&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: black"&gt;val variant : (int -&amp;gt; 'a Gen -&amp;gt; 'a Gen)&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;For different natural numbers i and j, &lt;em&gt;variant i g&lt;/em&gt; and &lt;em&gt;variant j g&lt;/em&gt; are independent generator transformers. The argument of variant must be non-negative, and, for efficiency, should be small. Cogenerators can be defined by composing together generator transformers constructed with variant. &lt;/p&gt;

&lt;p&gt;For example,for the type Tree defined above, a suitable instance of a cogenerator, allowing you to define functions &lt;em&gt;Tree -&amp;gt; 'a, &lt;/em&gt;can be defined as follows&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;cotree t = 
    &lt;span style="color: blue"&gt;match &lt;/span&gt;t &lt;span style="color: blue"&gt;with
       &lt;/span&gt;| (Leaf n) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;variant 0 &amp;lt;&amp;lt; Co.Int n
       | (Branch (t1,t2)) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;variant 1 &amp;lt;&amp;lt; cotree t1 &amp;lt;&amp;lt; cotree t2&lt;/pre&gt;

&lt;h5&gt;Properties of Functions&lt;/h5&gt;

&lt;p&gt;Since FsCheck can generate random function values, it can check properties of functions. For example, we can check associativity of function composition as follows:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;treegen = (Gen.Tuple(tree,three (Gen.Arrow(cotree,tree))))
&lt;span style="color: blue"&gt;let &lt;/span&gt;prop_Assoc gen = forAll gen (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(x,(f,g,h)) &lt;span style="color: blue"&gt;-&amp;gt; 
    &lt;/span&gt;propl ( ((f &amp;gt;&amp;gt; g) &amp;gt;&amp;gt; h) x = (f &amp;gt;&amp;gt; ( g &amp;gt;&amp;gt; h)) x ))&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;where we use the generator and cogenerator for trees defined above; we thus generate functions Tree -&amp;gt; Tree. If a counter-example is found, function values will be displayed as &amp;quot;&amp;lt;func&amp;gt;&amp;quot;.&lt;/p&gt;

&lt;h4&gt;FsCheck internals&lt;/h4&gt;

&lt;p&gt;FsCheck follows the &lt;a href="http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck/src/Test-QuickCheck.html"&gt;Haskell implementation of QuickCheck&lt;/a&gt; almost literally. For some explanation, read the &lt;a href="http://www.md.chalmers.se/~koen/Papers/quick.ps"&gt;original QuickCheck paper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the implementation, there are still a few issues that I'm unhappy with:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I ported Haskell's random implementation, but I'm still not 100% satisfied with it. &lt;/li&gt;

  &lt;li&gt;&lt;em&gt;decodeFloat&lt;/em&gt; is somewhat amateurish. Might even be wrong. I need to test the generator for floats more thoroughly. &lt;/li&gt;

  &lt;li&gt;It would be cool to have more standard generators, e.g. for strings and more .net oriented types, like Func&amp;lt;&amp;gt;, TimeSpan, DateTime and so on. &lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Download&lt;/h4&gt;

&lt;p&gt;Finally, download the latest Visual Studio solution from my Skydrive folder: &lt;a href="http://cid-f6a45280389d5d06.skydrive.live.com/self.aspx/Public/FsCheck%200.2.zip"&gt;FsCheck 0.2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Older releases:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&amp;#160;&lt;a href="http://cid-f6a45280389d5d06.skydrive.live.com/self.aspx/Public/FsCheck%200.1.zip" target="_blank"&gt;FsCheck 0.1&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:f8e9fcee-9620-49af-b42a-3fb5b9edcb6f" 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/random%20testing" rel="tag"&gt;random testing&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-5080716819153916052?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/5080716819153916052/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/05/fscheck-random-testing-for-f.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/5080716819153916052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/5080716819153916052'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/05/fscheck-random-testing-for-f.html' title='FsCheck: Random testing for F#'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-4082573400513443781</id><published>2008-04-11T22:59:00.001+01:00</published><updated>2008-11-11T18:37:46.489Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='WPF'/><title type='text'>WPF Pointers</title><content type='html'>&lt;p&gt;I recently went to a session at Microsoft Belgium for ISV's, where &lt;a href="http://blogs.msdn.com/tims/"&gt;Tim Sneath&lt;/a&gt; gave a packed session about WPF, answering some question but mainly giving a wealth of pointers of the WPF related information out there. Enjoy!&lt;/p&gt;  &lt;h6&gt;WPF/Silverlight reference applications&lt;/h6&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/jaimer/archive/2008/03/13/silverlight-in-financials-demonstrator.aspx"&gt;Silverlight in financials&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.vertigo.com/familyshow.aspx"&gt;Family.Show&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://adamkinney.com/blog/317/default.aspx"&gt;NBC Olympics in Silverlight&lt;/a&gt; (Tim showed a demo but it was local on his machine - don't think it is publicly available as the time of this writing)&lt;/p&gt;  &lt;p&gt;&lt;a title="http://memorabilia.hardrock.com/" href="http://memorabilia.hardrock.com/"&gt;Hard rock memorabilia&lt;/a&gt; (Tim also showed an application for actually making the deep zoom effect that you can see on the site, I guess it's included when with Silverlight 2 somehow?)&lt;/p&gt;  &lt;h6&gt;WPF Performance&lt;/h6&gt;  &lt;p&gt;&lt;a title="http://blogs.msdn.com/jgoldb/" href="http://blogs.msdn.com/jgoldb/"&gt;WPF performance blog&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://blogs.msdn.com/kiranku/archive/2006/10/30/wpf-performance-whitepaper.aspx" href="http://blogs.msdn.com/kiranku/archive/2006/10/30/wpf-performance-whitepaper.aspx"&gt;WPF Performance white paper&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://msdn2.microsoft.com/en-us/library/aa970683.aspx" href="http://msdn2.microsoft.com/en-us/library/aa970683.aspx"&gt;Optimizing WPF performance on MSDN&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://wpf.netfx3.com/files/folders/developer/tags/WPF+performance/default.aspx"&gt;WPF Performance suite download&lt;/a&gt;&lt;/p&gt;  &lt;h6&gt;WPF controls and dev tools&lt;/h6&gt;  &lt;p&gt;&lt;a href="http://work.j832.com/2008/03/bag-o-tricks-march-edition.html"&gt;Kevin's bag-o-tricks&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.kaxaml.com/"&gt;Kaxaml&lt;/a&gt; (XamlPad, but better)&lt;/p&gt;  &lt;p&gt;&lt;a href=" http://www.blendables.com/"&gt;Blendables&lt;/a&gt; (the only link in this list which is not free, but some nice samples in the blog, so worthwhile to visit even if you're not spending)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blois.us/Snoop/"&gt;Snoop&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://karlshifflett.wordpress.com/mole-for-visual-studio/"&gt;Mole&lt;/a&gt;&lt;/p&gt;  &lt;h6&gt;Neat Trick&lt;/h6&gt;  &lt;p&gt;Did you know that an .xps file is actually just a zip file with various files in them, and that one of those files contains a xaml dialect? This is really cool to export clip art from office. Tim just took a random Office piece of clip art, printed it to xps, renamed the file extension to .zip, unpack and pasted a part of one of the files in XamlPad. One or two adjustments for fonts later, and the clip art displayed in XamlPad. Nice to keep in mind!&lt;/p&gt;  &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:cacbaad5-5bea-4f8c-aaad-7c7a35060ef9" 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/WPF" rel="tag"&gt;WPF&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-4082573400513443781?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/4082573400513443781/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/04/wpf-pointers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/4082573400513443781'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/4082573400513443781'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/04/wpf-pointers.html' title='WPF Pointers'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-6007525138153902131</id><published>2008-04-09T22:04:00.001+01:00</published><updated>2008-11-11T18:37:33.807Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><category scheme='http://www.blogger.com/atom/ns#' term='parsing'/><category scheme='http://www.blogger.com/atom/ns#' term='fslex'/><title type='text'>Parsing Dot with F#: Part 2 - The lexer</title><content type='html'>&lt;p&gt;Now that &lt;a href="http://fortysix-and-two.blogspot.com/2008/04/parsing-dot-with-f-part-1.html"&gt;the preliminaries&lt;/a&gt; are over, we can get on with using the first part in the fslex/fsyacc tandem: the lexer. The lexer's responsibility is to break up the long input text into &lt;em&gt;tokens &lt;/em&gt;that are better manageable for the parser, which in turn will produce the actual abstract syntax tree. So, instead of having to deal with the string &amp;quot;digraph MyGraph {&amp;#160; 0 [label=&amp;quot;a string_{}&amp;quot;] }&amp;quot;, the lexer will turn this into a list of tokens, where each token can be attributed with some information. For the example, the output of our lexer is the following list of tokens: DIGRAPH ID[&amp;quot;MyGraph&amp;quot;] LACC ID[&amp;quot;0&amp;quot;] LBR ID[&amp;quot;label&amp;quot;] ASSIGN ID[&amp;quot;a string_{}&amp;quot;] RBR RACC.&amp;#160; As you can see, the only token with an attribute is the ID, in which all kinds of string names are parsed. Notice also that any ID string can contain &amp;quot;control characters&amp;quot; like { and }. The lexer's main job is to filter those kinds of things out so the parser's job is much easier.&lt;/p&gt;  &lt;p&gt;You can tell fslex how to tokenize a string by providing it with a list of rules. Each rule is a series of regular expressions-action pairs, each producing an (attributed) token. These rules are specified in a special format, which is pre-processed to an actual F# code file by the fslex tool. I'm not going to explain that in detail, there are &lt;a href="http://www.strangelights.com/fsharp/wiki/default.aspx/FSharpWiki/fslex.html"&gt;other sources&lt;/a&gt; for that.&lt;/p&gt;  &lt;p&gt;Our parser.fsl file starts with some preliminaries:&lt;/p&gt;  &lt;pre class="code"&gt;{
open System
open DotParser
open Lexing
}

let digit = ['0'-'9']
let whitespace = [' ' '\t' ]
let newline = ('\n' | '\r' '\n')
let letter = [ 'a'-'z' 'A'-'Z' '_']&lt;/pre&gt;

&lt;p&gt;Notice here that, besides opening the System and Lexing namespaces, the DotParser namespace is opened. That's because the type that defines the tokens (actually a regular discriminated union type) is defined in the fsyacc file. We'll come back to that in the next post. Then, some basic regular expressions that are useful for almost any parser, are defined. If you're at all familiar with regular expressions, this stuff should be easy. Notcie that these are just regular let variable bindings in F#. Fslex just translates this file to actual F# code, so you're free to use F# constructs as you see fit.&lt;/p&gt;

&lt;p&gt;Our actual parser consists of 2 rules. This is the first:&lt;/p&gt;

&lt;pre class="code"&gt;rule token = parse
| whitespace     { token lexbuf }
| ('\r' | '\t')  { token lexbuf }
| &amp;quot;digraph&amp;quot;      { DIGRAPH }
| &amp;quot;node&amp;quot;         { NODE }
| &amp;quot;edge&amp;quot;         { EDGE }
| &amp;quot;graph&amp;quot;        { GRAPH }
| &amp;quot;-&amp;gt;&amp;quot;           { DIEDGE }
| &amp;quot;--&amp;quot;           { UNEDGE }
| &amp;quot;\&amp;quot;&amp;quot;           { ID ( (string lexbuf.StartPos &amp;quot;&amp;quot; lexbuf) ) }
| '{'            { LACC }
| '}'            { RACC }
| '['            { LPAREN }
| ']'            { RPAREN }
| ';'            { SEMI }
| ','            { COMMA }
| '='            { ASSIGN }
| letter(letter|digit)*                { ID (lexeme lexbuf) }
| ['-']?('.'digit+ | digit+('.'digit*)? ) { ID (lexeme lexbuf) }
| newline        { lexbuf.EndPos &amp;lt;- lexbuf.EndPos.NextLine; token lexbuf }
| eof            { EOF }&lt;/pre&gt;

&lt;p&gt;On the left, written like a pattern match, are the regular expressions that will be matched against the input string. On the right, the tokens that are returned. As you can see in the line for lexing IDs, you can access the current lexeme, i.e. the currently-being-lexed part of the input string, by calling &lt;em&gt;lexeme lexbuf&lt;/em&gt;. Just skipping the current lexeme can be achieved by calling &lt;em&gt;token lexbuf&lt;/em&gt;. Also, it is useful if you keep track of the line number for debugging later. That's what the action in the &lt;em&gt;newline&lt;/em&gt; pattern does. &lt;/p&gt;

&lt;p&gt;One gotcha here is that the order of these regular expressions matter not only for lexing (a line higher up will take precedence over a lower line), but also for type inference. The above rule needed no type annotations, but try placing the newline rule at the top; after pre-processing, F# will complain during compilation that it needs some type annotations. It's not a big deal, but if the order does not matter for lexing, it is nicer and more flexible to change later if you don't need to put any type annotations.&lt;/p&gt;

&lt;p&gt;One line in the above sample may puzzle you:&lt;/p&gt;

&lt;pre class="code"&gt;| &amp;quot;\&amp;quot;&amp;quot;            { ID ( (string lexbuf.StartPos &amp;quot;&amp;quot; lexbuf) ) }&lt;/pre&gt;

&lt;p&gt;That's because this calls a second rule, called&lt;em&gt;&amp;#160; string&lt;/em&gt;, which parses a string,i.e. something between double quotes (&amp;quot;). We go into this second rule when we encounter an open double quotes in the input. Such multiple rules are useful when you have different contexts in the input string in which different lexing rules apply. For dot, a string can contain characters such as brackets, arrows, semicolons and such that have a particular meaning in the main dot file. But when they're between double quotes, the lexer is in another context, where these characters lose their meaning and should just be added to a string that is part of the name of some entity. So once we encounter a &amp;quot; in our main file, we start parsing with the second rule; once the second rule finds a &amp;quot;, we return the string parsed so far and continue in the main rule:&lt;/p&gt;

&lt;pre class="code"&gt;and string pos s = parse
| &amp;quot;\\&amp;quot;    { string pos s lexbuf }
| &amp;quot;\r&amp;quot;    { string pos s lexbuf }
| &amp;quot;\&amp;quot;&amp;quot;    { s }
| &amp;quot;\n&amp;quot;    { lexbuf.EndPos &amp;lt;- lexbuf.EndPos.NextLine;
            string pos s lexbuf }
| eof     { failwithf &amp;quot;end of file in string started at or near %A&amp;quot; pos }
| _       { string pos (s + (Lexing.lexeme lexbuf)) lexbuf }&lt;/pre&gt;

&lt;p&gt;As you can see, the string function takes the &lt;em&gt;pos&lt;/em&gt; of the start of the string (for debugging) and accumulates the string in its parameter &lt;em&gt;s&lt;/em&gt;. If the third pattern matches, the rule is finished: we've encountered the second &amp;quot;. The last pattern matches with anything that isn't matched by the previous lines, so we add it to the &lt;em&gt;s&lt;/em&gt; accumulator.&lt;/p&gt;

&lt;p&gt;The other matches, 1st 2nd and 4th match, are control characters that are simply skipped, and in the case of newline we update the line number. I did this because graphviz has the annoying habit of inserting a newline after a certain number of characters on one line. Presumably this is for readability, but why anyone would want to read dot files is beyond me. Anyway, Graphviz inserts a \ followed by \r in such cases, and this is what the two first rules filter out. This solved quite some pains afterwards when interpreting IDs (&amp;quot;230,345&amp;quot; is a much easier string to interpret than &amp;quot;230,3\\r45&amp;quot;, especially when you don't know if, when or where graphviz will insert a line break. Yes, it actually did this in the middle of numbers.).&lt;/p&gt;

&lt;p&gt;By the way, another typical example where it is useful to have multiple rules is when you would like to parse comments; also there the normal lexing rule does not apply. In fact, I adapted the above &lt;em&gt;string&lt;/em&gt; function from a similar function designed to parse comments in the excellent &lt;a title="Expert F#" href="http://www.apress.com/book/view/1590598504"&gt;Expert F#&lt;/a&gt; book.&lt;/p&gt;

&lt;p&gt;That's it for the lexer. Paste all the stuff from this post together, and you should have a working .fsl file. Not compilable yet I'm afraid, you need the token definitions which are produced by the parser (remember the &lt;em&gt;open DotParser&lt;/em&gt;?).&lt;/p&gt;

&lt;p&gt;You've made it halfway! Next post: the parser.&lt;/p&gt;

&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:88bc388d-9e3a-449c-a4c0-568803521cd6" 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/fslex" rel="tag"&gt;fslex&lt;/a&gt;,&lt;a href="http://technorati.com/tags/fsyacc" rel="tag"&gt;fsyacc&lt;/a&gt;,&lt;a href="http://technorati.com/tags/parsing" rel="tag"&gt;parsing&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-6007525138153902131?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/6007525138153902131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/04/parsing-dot-with-f-part-2-lexer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/6007525138153902131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/6007525138153902131'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/04/parsing-dot-with-f-part-2-lexer.html' title='Parsing Dot with F#: Part 2 - The lexer'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-5230111838504050928</id><published>2008-04-02T17:08:00.000+01:00</published><updated>2008-11-11T18:34:54.706Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='fsyacc'/><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><category scheme='http://www.blogger.com/atom/ns#' term='parsing'/><category scheme='http://www.blogger.com/atom/ns#' term='fslex'/><title type='text'>Parsing Dot with F#: Part 1</title><content type='html'>&lt;p&gt;&lt;a href="http://fortysix-and-two.blogspot.com/2008/03/graph-control-for-wpf.html"&gt;A while back&lt;/a&gt; I decided to write a parser for dot, the language used by &lt;a href="http://www.graphviz.org/"&gt;Graphviz&lt;/a&gt;. This is both my first real project in &lt;a title="F# homepage" href="http://research.microsoft.com/fsharp/fsharp.aspx"&gt;F#&lt;/a&gt;, and in parsing. I learned the basics from the excellent &lt;a title="Expert F#" href="http://www.apress.com/book/view/1590598504"&gt;Expert F#&lt;/a&gt; book. &lt;/p&gt;  &lt;p&gt;I'll try to explain my solution, using fslex and fsyacc, in the order that I tackled the problem.&amp;#160; There are a few more basic examples out there, explaining what parsing is, what a lexer and a parser are etc., However it seems the examples given are always small, typically parsing some expressions. Graphviz' dot definitely has more of a real world flavor, and I'll present it as a real world example of using fslex and fsyacc, without explaining much about those tools per se.&lt;/p&gt;  &lt;p&gt;This is how I see this mini-series play out:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Simplified dot grammar and abstract syntax tree &lt;/li&gt;    &lt;li&gt;The lexer &lt;/li&gt;    &lt;li&gt;The parser &lt;/li&gt;    &lt;li&gt;Putting it all together &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;This post is part 1.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="+0"&gt;Graphviz&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Graphviz is a command line tool that takes a description of a graph as input, and outputs a description (or an image) of a layout of the graph. For example, as input you can give:&lt;/p&gt;  &lt;pre class="code"&gt;digraph G {
0 [label=&amp;quot;Type1&amp;lt;&amp;gt;&amp;quot;, shape=box];
1 [label=&amp;quot;Type1&amp;lt;Type2&amp;gt;&amp;quot;, shape=box];
2 [label=&amp;quot;T&amp;quot;, shape=box];
3 [label=&amp;quot;Type2&amp;quot;, shape=box];
4 [label=&amp;quot;Type2[], Type2*, Type2&amp;amp;&amp;quot;, shape=box];
5 [label=&amp;quot;#Type2&amp;quot;, shape=box];
6 [label=&amp;quot;Type2.Type3&amp;quot;, shape=box];
0 -&amp;gt; 1 [ label=&amp;quot;MakeGenericType(Type2)&amp;quot;];
0 -&amp;gt; 2 [ label=&amp;quot;GetGenericArguments()&amp;quot;];
1 -&amp;gt; 0 [ label=&amp;quot;GetGenericTypeDefinition()&amp;quot;];
1 -&amp;gt; 3 [ label=&amp;quot;GetGenericArguments()&amp;quot;];
2 -&amp;gt; 0 [ label=&amp;quot;DeclaringType&amp;quot;];
3 -&amp;gt; 4 [ label=&amp;quot;MakeArrayType(), MakePointerType(), MakeByRefType()&amp;quot;];
3 -&amp;gt; 6 [ label=&amp;quot;GetNestedType(Type3.Name)&amp;quot;];
4 -&amp;gt; 3 [ label=&amp;quot;GetElementType()&amp;quot;];
5 -&amp;gt; 3 [ label=&amp;quot;BaseType&amp;quot;];
6 -&amp;gt; 3 [ label=&amp;quot;DeclaringType&amp;quot;];
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Basically, just a sequence of nodes and edges annotated with attributes. In the above example, only label and shape are used, but dot supports many, many more. Given such a file, graphviz outputs:&lt;/p&gt;

&lt;pre class="code"&gt;digraph G {
    node [label=&amp;quot;\N&amp;quot;];
    graph [bb=&amp;quot;0,0,1028,328&amp;quot;];
    0 [label=&amp;quot;Type1&amp;lt;&amp;gt;&amp;quot;, shape=box, pos=&amp;quot;502,302&amp;quot;, width=&amp;quot;1.03&amp;quot;, height=&amp;quot;0.50&amp;quot;];
    1 [label=&amp;quot;Type1&amp;lt;Type2&amp;gt;&amp;quot;, shape=box, pos=&amp;quot;380,210&amp;quot;, width=&amp;quot;1.61&amp;quot;, height=&amp;quot;0.50&amp;quot;];
    2 [label=T, shape=box, pos=&amp;quot;625,210&amp;quot;, width=&amp;quot;0.75&amp;quot;, height=&amp;quot;0.50&amp;quot;];
    3 [label=Type2, shape=box, pos=&amp;quot;568,118&amp;quot;, width=&amp;quot;0.78&amp;quot;, height=&amp;quot;0.50&amp;quot;];
    4 [label=&amp;quot;Type2[], Type2*, Type2&amp;amp;&amp;quot;, shape=box, pos=&amp;quot;249,26&amp;quot;, width=&amp;quot;2.61&amp;quot;, height=&amp;quot;0.50&amp;quot;];
    5 [label=&amp;quot;#Type2&amp;quot;, shape=box, pos=&amp;quot;703,210&amp;quot;, width=&amp;quot;0.92&amp;quot;, height=&amp;quot;0.50&amp;quot;];
    6 [label=&amp;quot;Type2.Type3&amp;quot;, shape=box, pos=&amp;quot;784,26&amp;quot;, width=&amp;quot;1.42&amp;quot;, height=&amp;quot;0.50&amp;quot;];
    0 -&amp;gt; 1 [label=&amp;quot;MakeGenericType(Type2)&amp;quot;, pos=&amp;quot;e,322,216 465,301 381,298 181,288 161,266 156,259 156,252 161,246 170,235 252,223 312,217&amp;quot;, lp=&amp;quot;263,256&amp;quot;];
    0 -&amp;gt; 2 [label=&amp;quot;GetGenericArguments()&amp;quot;, pos=&amp;quot;e,623,228 539,298 561,293 589,284 607,266 615,258 619,247 621,237&amp;quot;, lp=&amp;quot;708,256&amp;quot;];
    1 -&amp;gt; 0 [label=&amp;quot;GetGenericTypeDefinition()&amp;quot;, pos=&amp;quot;s,465,293 455,290 430,284 403,275 394,266 385,256 381,240 380,228&amp;quot;, lp=&amp;quot;504,256&amp;quot;];
    1 -&amp;gt; 3 [label=&amp;quot;GetGenericArguments()&amp;quot;, pos=&amp;quot;e,540,121 394,192 405,179 420,163 437,154 467,137 504,128 531,123&amp;quot;, lp=&amp;quot;528,164&amp;quot;];
    2 -&amp;gt; 0 [label=DeclaringType, pos=&amp;quot;s,539,300 548,300 628,295 785,284 802,266 807,259 807,252 802,246 781,222 691,237 661,228 658,227 655,226 652,225&amp;quot;, lp=&amp;quot;863,256&amp;quot;];
    3 -&amp;gt; 4 [label=&amp;quot;MakeArrayType(), MakePointerType(), MakeByRefType()&amp;quot;, pos=&amp;quot;e,155,36 540,117 432,114 50,100 32,82 26,75 27,68 32,62 40,53 93,44 145,37&amp;quot;, lp=&amp;quot;251,72&amp;quot;];
    3 -&amp;gt; 6 [label=&amp;quot;GetNestedType(Type3.Name)&amp;quot;, pos=&amp;quot;e,733,40 596,101 616,89 645,73 671,62 688,54 707,48 725,43&amp;quot;, lp=&amp;quot;781,72&amp;quot;];
    4 -&amp;gt; 3 [label=&amp;quot;GetElementType()&amp;quot;, pos=&amp;quot;s,540,110 532,107 515,100 495,92 480,82 470,75 472,67 461,62 441,51 390,42 343,36&amp;quot;, lp=&amp;quot;557,72&amp;quot;];
    5 -&amp;gt; 3 [label=BaseType, pos=&amp;quot;e,595,136 676,192 655,178 625,157 602,141&amp;quot;, lp=&amp;quot;692,164&amp;quot;];
    6 -&amp;gt; 3 [label=DeclaringType, pos=&amp;quot;s,596,117 605,117 687,113 875,103 894,82 915,58 873,43 835,34&amp;quot;, lp=&amp;quot;956,72&amp;quot;];
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p  ="&gt;&lt;p        "&gt;The basic structure of the file is the same: a sequence of nodes and edges, but Graphviz has added position, height, width and other layout info. This is actually the file that was used to draw the graph in &lt;a href="http://fortysix-and-two.blogspot.com/2008/03/reflection-type-unraveled.html"&gt;my previous post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p  =""&gt;&lt;strong&gt;&lt;font size="+0"&gt;The dot grammar&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When parsing using fslex and fsyacc, the first thing you should find or make is a grammar of the thing you're trying to parse. Everything else sort of flows from there. Luckily, the complete dot grammar can be found &lt;a href="http://www.graphviz.org/doc/info/lang.html"&gt;here&lt;/a&gt;. I thought it was a bit complicated for my purposes, so I simplified the grammar a bit:&lt;/p&gt;

&lt;p&gt;(in the following, terminals are shown in bold. Literal characters are given in single quotes. Parentheses ( and ) indicate grouping when needed. Square brackets [ and ] enclose optional items. Vertical bars | separate alternatives.)&lt;/p&gt;

&lt;pre class="code"&gt;graph    :    &lt;strong&gt;digraph&lt;/strong&gt; [ ID ] '{' stmt_list '}'
stmt_list:    [ stmt [ ';' ] [ stmt_list ] ]
stmt     :    node_stmt
         |    edge_stmt
         |    attr_stmt /*defines a default attribute*/
attr_stmt:    (&lt;strong&gt;graph&lt;/strong&gt; | &lt;strong&gt;node&lt;/strong&gt; | &lt;strong&gt;edge&lt;/strong&gt;) attr_list
attr_list:    '[' attr  [ ',' ] [ attr_list ] ']' 
atrtr    :    ID '=' ID  
edge_stmt:    node_id -&amp;gt; node_id [ attr_list ]
node_stmt:    node_id [ attr_list ]
node_id  :    INT&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;If you compare with the original dot grammar, I made the following simplifications:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;No node ports &lt;/li&gt;

  &lt;li&gt;No sub-graphs &lt;/li&gt;

  &lt;li&gt;No short definition of multiple edges (a -&amp;gt; b -&amp;gt; c) &lt;/li&gt;

  &lt;li&gt;no HTML IDs &lt;/li&gt;

  &lt;li&gt;only digraphs &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Basically this grammar says that a graph is &amp;quot;digraph name { bunch of node, edge or default statements }&amp;quot;. We've already seen node and edge statements; default statements basically just set an attribute on all the nodes and edges that follow. It is overridden by an attribute of the same name on a node or edge itself, or by a new default statement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;font size="+0"&gt;The abstract syntax tree&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Based on that grammar, I came up with the following abstract syntax tree using F# discriminated unions: &lt;/p&gt;

&lt;pre class="code"&gt;#light

&lt;span style="color: blue"&gt;open &lt;/span&gt;List
&lt;span style="color: blue"&gt;open &lt;/span&gt;System
&lt;span style="color: blue"&gt;open &lt;/span&gt;System.Collections.Generic

&lt;span style="color: blue"&gt;type &lt;/span&gt;Attributes = Dictionary&amp;lt;string,string&amp;gt;

&lt;span style="color: blue"&gt;type &lt;/span&gt;Element = 
    | Node &lt;span style="color: blue"&gt;of &lt;/span&gt;string * Attributes
    | Edge &lt;span style="color: blue"&gt;of &lt;/span&gt;string * string * Attributes
    | GraphAttributeList &lt;span style="color: blue"&gt;of &lt;/span&gt;Attributes
    | NodeAttributeList &lt;span style="color: blue"&gt;of &lt;/span&gt;Attributes
    | EdgeAttributeList &lt;span style="color: blue"&gt;of &lt;/span&gt;Attributes&lt;span style="color: #a31515"&gt;

&lt;/span&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Graph = Graph &lt;span style="color: blue"&gt;of &lt;/span&gt;List&amp;lt;Element&amp;gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;It's easiest to read this from bottom to top (unfortunately it needs to be defined the other way round, otherwise F# has difficulty parsing). A graph is a list of elements. An element can either be a node, an edge or a default attribute list for the graph, the subsequent nodes or the subsequent edges. Each of these elements can have a number of attributes. Attributes are simply presented as a Dictionary. The abstract syntax tree was fairly straightforward to build from the grammar; I expect the same for any well-written grammar.&lt;/p&gt;

&lt;p&gt;The abstract syntax tree is the parser's interface to the outside, so it's important that you think about how you're going to use the parser when making decisions about the representation of the abstract syntax tree. For example, I took care not to use any F# specific types in the above AST definition, so that client assemblies in other language would not need to reference F# specific assemblies. On that topic, don't forget to compile your F# assemblies with the --standalone flag, otherwise client assemblies will still need some F# specific libraries (e.g. discriminated unions implement IStructuralHash, so clients also need to know this interface).&lt;/p&gt;

&lt;p&gt;Another issue you should think about is how 'deep' you want to parse. For example, it would be theoretically possible to define separate cases for each of the different types of attributes that can be generated by Graphviz. This would also allow us to parse some of the arguments (e.g. the list of position coordinates could be parsed into a list of tuples). However, given the &lt;a href="http://www.graphviz.org/doc/info/attrs.html"&gt;large amount&lt;/a&gt; and frequent changes in Graphviz dot attributes, I choose not to take this route.&lt;/p&gt;

&lt;p&gt;Next episode: the lexer!&lt;/p&gt;

&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:2b78a798-ecce-487d-8ea1-525c847c3c64" 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/fslex" rel="tag"&gt;fslex&lt;/a&gt;,&lt;a href="http://technorati.com/tags/fsyacc" rel="tag"&gt;fsyacc&lt;/a&gt;,&lt;a href="http://technorati.com/tags/parsing" rel="tag"&gt;parsing&lt;/a&gt;,&lt;a href="http://technorati.com/tags/graphviz" rel="tag"&gt;graphviz&lt;/a&gt;&lt;/div&gt;
&lt;!-- Tag links generated by Zoundry Raven. Do not manually edit. http://www.zoundryraven.com --&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-5230111838504050928?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/5230111838504050928/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/04/parsing-dot-with-f-part-1.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/5230111838504050928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/5230111838504050928'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/04/parsing-dot-with-f-part-1.html' title='Parsing Dot with F#: Part 1'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-576043097317338481</id><published>2008-03-16T22:02:00.001Z</published><updated>2008-11-11T18:33:14.550Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Reflection'/><title type='text'>Reflection: Type unraveled</title><content type='html'>&lt;p&gt;The Type class in .NET is not the easiest to understand, I believe because of the many different "kinds of types" that are modeled by it: generic types, generic type parameters, reference types, pointer types, array types, etc. Furthermore, sometimes you have one kind of type (e.g. a generic type) and want to make another kind (i.e. "instantiate" a generic parameter with another type). The Type class offers all the necessary methods to do the feasible conversions; however it is not always easy to find. The following graph should help.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh3.google.com/kurt.schelfthout/R92a1QCU05I/AAAAAAAAABw/MbWa8vB4EX8/Reflection%20Type%20Graph.JPG" rel="lightbox"&gt;&lt;img src="http://lh3.google.com/kurt.schelfthout/R-A3TgCU06I/AAAAAAAAAB8/jGR5s8gEQbc/00000118c3d75e6500c000a8000200037b949b1a_tn.png" style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; WIDTH: 250px; BORDER-BOTTOM: 0px; HEIGHT: 138px" height="138" width="250"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The boxes show the different kinds of types that exist. An example of Type1&amp;lt;&amp;gt; is typeof(IList&amp;lt;&amp;gt;); Type1&amp;lt;Type2&amp;gt; is typeof(IList&amp;lt;string&amp;gt;) and so on. The arrows denote how you can obtain one kind of type from the other. For example, if you have a generic type definition (e.g. typeof(IList&amp;lt;&amp;gt;)) you can make this into an instantiatable type (typeof(IList&amp;lt;string&amp;gt;))by calling typeof(IList&amp;lt;&amp;gt;).MakeGenericType(typeof(string)). With "#Type2" I mean a subtype of Type2.&lt;/p&gt;
&lt;p&gt;Hope this helps someone.&lt;/p&gt;
&lt;p&gt;PS the graph was laid out by Graphviz's dot layout. It was rendered using a self-made WPF control. More on that later.&lt;/p&gt;
&lt;p xmlns="" class="zoundry_raven_tags"&gt;
  &lt;!-- Tag links generated by Zoundry Raven. Do not manually edit. http://www.zoundryraven.com --&gt;
  &lt;span class="ztags"&gt;&lt;span class="ztagspace"&gt;Technorati&lt;/span&gt; : &lt;a href="http://www.technorati.com/tag/.NET" class="ztag" rel="tag"&gt;.NET&lt;/a&gt;, &lt;a href="http://www.technorati.com/tag/Type" class="ztag" rel="tag"&gt;Type&lt;/a&gt;, &lt;a href="http://www.technorati.com/tag/reflection" class="ztag" rel="tag"&gt;reflection&lt;/a&gt;&lt;/span&gt;  &lt;br/&gt;
 &lt;span class="ztags"&gt;&lt;span class="ztagspace"&gt;Del.icio.us&lt;/span&gt; : &lt;a href="http://del.icio.us/tag/.NET" class="ztag" rel="tag"&gt;.NET&lt;/a&gt;, &lt;a href="http://del.icio.us/tag/Type" class="ztag" rel="tag"&gt;Type&lt;/a&gt;, &lt;a href="http://del.icio.us/tag/reflection" class="ztag" rel="tag"&gt;reflection&lt;/a&gt;&lt;/span&gt; 
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-576043097317338481?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/576043097317338481/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/03/reflection-type-unraveled.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/576043097317338481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/576043097317338481'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/03/reflection-type-unraveled.html' title='Reflection: Type unraveled'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-7804755584726123996</id><published>2008-03-15T22:37:00.001Z</published><updated>2008-11-11T18:33:01.150Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='graph control'/><category scheme='http://www.blogger.com/atom/ns#' term='WPF'/><title type='text'>A graph control for WPF</title><content type='html'>&lt;p&gt;Recently, I decided to write a WPF control that can display graphs (I mean, the kind with edges and nodes; not charts). This post describes the beginning of that little project. It does not contain many technical details, just a few hints and pointers for anyone who would like to start a similar project.&lt;/p&gt;
&lt;p&gt;I have the time nor the inclination to write a graph layout algorithm myself. Graph algorithms are complex and fairly specific, and I couldn't really find a good overview of the algorithms involved on the net. I found many references to papers, but it seems some papers are hard to get if you don't have a subscription to the ACM portal. (When I was still a PhD candidate this stuff was much easier). So much for free science.&lt;/p&gt;
&lt;p&gt;Maybe I can reuse a graph layout algorithm from some existing Winforms control? After some searching, it seems that .NET lacks a free graph layout control. A good graph algorithm library is &lt;a href="http://www.codeplex.com/quickgraph" title="Quickgraph"&gt;QuickGraph&lt;/a&gt; , but as far as I can see it does not offer any algorithm for layout. Another library is GLEE from Microsoft, but that's is not available for commercial usage (something I'd like for later when my imaginary startup will take over the world).&lt;/p&gt;
&lt;p&gt;Outside the .NET world then? After all, .NET has excellent interoperability.
&lt;br/&gt;
&lt;a href="http://www.graphviz.org/" title="Graphviz"&gt;Graphviz&lt;/a&gt; by AT&amp;amp;T is an excellent graph layout utility. Not only can it do beautiful hierarchical graphs (like GLEE does) it can also do spring layout and radial graphs, is fast and is highly configurable. Graphviz reads graphs in a proprietary format, called dot. It then layouts the graph, and can export to a variety of formats, of which attributed dot is one. Attributed dot is basically the same as the dot input file, but attributed with node, edge and label positions, as well as other layout info.&lt;/p&gt;
&lt;p&gt;Another C++ based alternative is &lt;a href="http://www.dynagraph.org/" title="Dynagraph"&gt;Dynagraph&lt;/a&gt; which is a daughter of Graphviz but is geared toward dynamical graph layout. Whereas Graphviz takes an input graph, does layout and produces an output graph, Dynagraph can add and delete nodes and edges incrementally, keeping existing positions the same as much as possible.&lt;/p&gt;
&lt;table width="593" style="WIDTH: 593px; HEIGHT: 543px" border="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td/&gt;
&lt;td&gt;&lt;strong&gt;Graphviz&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Dynagraph&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET interoperability&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;COM, using &lt;a href="http://wingraphviz.sourceforge.net/wingraphviz/"&gt;Wingraphviz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;dot in/any out&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;P/Invoke&lt;/li&gt;
&lt;li&gt;(COM)&lt;/li&gt;
&lt;li&gt;'incrface' in and out&lt;/li&gt;
&lt;li&gt;dot
&lt;br/&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintained&lt;/td&gt;
&lt;td&gt;Actively&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Hardly&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Incremental&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Algorithms&lt;/td&gt;
&lt;td&gt;Hierarchical, spring, radial, circular&lt;/td&gt;
&lt;td&gt;Hierarchical&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speed&lt;/td&gt;
&lt;td&gt;Fast, even for large graphs&lt;/td&gt;
&lt;td&gt;Noticeably slower than Graphviz for large graphs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;After some tinkering with Dynagraph, which I liked better at first because of its flexibility, and after some back and forth email with Gordon Woodhull, the maintainer of Dynagraph, it turned out that Dynagraph COM support is not completely implemented yet. By the time we came to that conclusion, I had already sort of given up and started on an interface for Graphviz using the Wingraphviz COM interface.&lt;/p&gt;
&lt;p&gt;It turns out that a few people before me had thought of that. Quickgraph can actually output a dot file to be consumed by Graphviz. Furthermore, &lt;a href="http://www.codeproject.com/KB/WPF/Dot2Wpf.aspx"&gt;D&lt;/a&gt; &lt;a href="http://www.codeproject.com/KB/WPF/Dot2Wpf.aspx"&gt;ot2Wpf&lt;/a&gt; is a WPF control that parses output from Graphviz.&lt;/p&gt;
&lt;p&gt;You'd think I'm done, right? So did I. However, there were a few more things I expected from my graph control than dot2wpf offered. For example, I'd like to change the color or line style of an edge without having to do a complete layout of the graph. So I figured I'd take the dot2wpf source and add some features. That didn't quite work out as planned.
&lt;br/&gt;
That's because dot2wpf actually parses the 'plain' output format of Graphviz. It is supposedly easier to parse than the dot output format, but loses some information. It turns out that it contains a flaw: for cyclic graphs, the plain format does not allow you to determine whether an arrow should be at the beginning or the end of an edge. Graphviz' hierarchical layout algorithm cannot handle cycles, so it reverses one edge in a cycle automatically for layout purposes. However, in the plain output format there is no indication of this reversal, and the points of the edge are given in the reverse direction. There's no way for dot2wpf to distinguish these reversed edges from normal edges in the plain output format, so it has no way to determine where to draw the arrow.&lt;/p&gt;
&lt;p&gt;That one took me a while to figure out.&lt;/p&gt;
&lt;p&gt;So it turns out that to make a faithful representation of a graph layout by Graphviz, I need to parse the (fairly complicated) dot output format of Graphviz. So my idea now is that the WPF graph control takes as input a string containing a dot representation of the graph it should draw (such a dot representation is easy to get from e.g. Quickgraph), passes this string to Graphviz which passes an annotated dot file back. The control parses it, and draws the visuals on the canvas.&lt;/p&gt;
&lt;p&gt;Since I've been wanting to learn F# for a while, and F# comes with a bunch of parsing tools (fslex and fsyacc), I thought it would be a good idea to use F# to write a dot parser - it could be useful for other things than the graph control. More on parsing with F# in a later post.&lt;/p&gt;
&lt;p xmlns="" class="zoundry_raven_tags"&gt;
  &lt;!-- Tag links generated by Zoundry Raven. Do not manually edit. http://www.zoundryraven.com --&gt;
  &lt;span class="ztags"&gt;&lt;span class="ztagspace"&gt;Technorati&lt;/span&gt; : &lt;a href="http://www.technorati.com/tag/.NET" class="ztag" rel="tag"&gt;.NET&lt;/a&gt;, &lt;a href="http://www.technorati.com/tag/WPF" class="ztag" rel="tag"&gt;WPF&lt;/a&gt;, &lt;a href="http://www.technorati.com/tag/dynagraph" class="ztag" rel="tag"&gt;dynagraph&lt;/a&gt;, &lt;a href="http://www.technorati.com/tag/graphviz" class="ztag" rel="tag"&gt;graphviz&lt;/a&gt;&lt;/span&gt;  &lt;br/&gt;
 &lt;span class="ztags"&gt;&lt;span class="ztagspace"&gt;Del.icio.us&lt;/span&gt; : &lt;a href="http://del.icio.us/tag/.NET" class="ztag" rel="tag"&gt;.NET&lt;/a&gt;, &lt;a href="http://del.icio.us/tag/WPF" class="ztag" rel="tag"&gt;WPF&lt;/a&gt;, &lt;a href="http://del.icio.us/tag/dynagraph" class="ztag" rel="tag"&gt;dynagraph&lt;/a&gt;, &lt;a href="http://del.icio.us/tag/graphviz" class="ztag" rel="tag"&gt;graphviz&lt;/a&gt;&lt;/span&gt; 
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-7804755584726123996?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/7804755584726123996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/03/graph-control-for-wpf.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/7804755584726123996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/7804755584726123996'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/03/graph-control-for-wpf.html' title='A graph control for WPF'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-3346002593502604452</id><published>2008-01-14T09:45:00.000Z</published><updated>2008-11-11T18:32:48.972Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><title type='text'>Comparing presentation styles</title><content type='html'> I recently watched a recorded presentation by Jim Hugunin and John Lam, entitled &lt;a href="http://sessions.visitmix.com/upperlayer.asp?event=&amp;session=&amp;id=1511&amp;year=All&amp;search=lam&amp;sortChoice=&amp;stype="&gt; "Just Glue It! Ruby and the DLR in Silverlight"&lt;/a&gt;.

&lt;p&gt;The presentation made me wish that more performers would be like Edsger W. Dijkstra, or at least make an effort towards imitating his style. &lt;a href="http://www.cs.utexas.edu/~EWD/video-audio/video-audio.html"&gt;See and listen for yourself&lt;/a&gt;, and I hope you'll share my preference. Unfortunately the "demo-oriented" presentation style, in which contrived demonstrations that require nor provide any insight are exchanged for content, is becoming  common.&lt;/p&gt;

&lt;p&gt;PS I would like to add that, judging from their blogs, both Jim Hugunin and John Lam are intelligent, creative and well-spoken human beings. Which makes their performance all the more saddening: it may be a cultural phenomenon.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-3346002593502604452?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/3346002593502604452/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/01/comparing-presentation-styles.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/3346002593502604452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/3346002593502604452'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2008/01/comparing-presentation-styles.html' title='Comparing presentation styles'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-2043114285801823166</id><published>2007-11-21T07:45:00.000Z</published><updated>2008-11-11T18:32:35.306Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>Writing WCF config files programmatically and dynamically</title><content type='html'>&lt;p&gt;OK, so I said I'd write a series of posts on WPF first, but this came up the other day.
&lt;br/&gt;
&lt;br/&gt;
&lt;span&gt;Problem&lt;/span&gt;
&lt;br/&gt;
&lt;br/&gt;
Suppose you need to write a wizard-type application where you allow a user to expose a service over WCF (maybe allowing the input of a port number and name). At the same time, you want to allow so-called power-users to just edit the app.config file and change WCF details, such as various binding parameters. (The same mechanism applies for the client side.)
&lt;br/&gt;
&lt;br/&gt;
So, what you need is to write a WCF configuration, let's say exposing a service, on the fly to the app.config file, and then opening a ServiceHost that uses the configuration that was just written.
&lt;br/&gt;
&lt;br/&gt;
&lt;span&gt;Solution&lt;/span&gt;
&lt;br/&gt;
&lt;br/&gt;
&lt;br/&gt;
Let's start of with a very simple example. First, the service contract.
&lt;br/&gt;
&lt;br/&gt;
&lt;code&gt;&lt;br/&gt;
[ServiceContract]
&lt;br/&gt;
internal interface ISimpleService
&lt;br/&gt;
{
&lt;br/&gt;
&lt;br/&gt;
[OperationContract]
&lt;br/&gt;
string AddWordToString( string input );
&lt;br/&gt;
&lt;br/&gt;
}
&lt;br/&gt;&lt;/code&gt;
&lt;br/&gt;
&lt;br/&gt;
Now, a service that implements this contract:
&lt;br/&gt;
&lt;br/&gt;
&lt;code&gt;&lt;br/&gt;
[ServiceBehavior( InstanceContextMode=InstanceContextMode.Single )]
&lt;br/&gt;
public class SimpleService : ISimpleService
&lt;br/&gt;
{
&lt;br/&gt;
&lt;br/&gt;
#region ISimpleService Members
&lt;br/&gt;
&lt;br/&gt;
public string AddWordToString( string input )
&lt;br/&gt;
{
&lt;br/&gt;
return input + " and a word";
&lt;br/&gt;
}
&lt;br/&gt;
&lt;br/&gt;
#endregion
&lt;br/&gt;
}
&lt;br/&gt;&lt;/code&gt;
&lt;br/&gt;
&lt;br/&gt;
So, what we want to do now is, in code, expose a SimpleService over WCF, while updating the app.config file so that it shows the configuration of the exposed service.
&lt;br/&gt;
&lt;br/&gt;
So, the idea is to first write to the WCF config file, and then use a standard ServiceHost call on the service type to allow WCF to read the configuration from app.config, and expose the service. The following code snippet achieves this:
&lt;br/&gt;
&lt;br/&gt;
&lt;br/&gt;
&lt;code&gt;&lt;br/&gt;
//first write the service config for the service
&lt;br/&gt;
WriteWCFConfig( typeof(SimpleService), typeof(ISimpleService) );
&lt;br/&gt;
&lt;br/&gt;
//now try to open the wcf service
&lt;br/&gt;
ServiceHost host = new ServiceHost( new SimpleService() );
&lt;br/&gt;
host.Open();
&lt;br/&gt;&lt;/code&gt;
&lt;br/&gt;
&lt;br/&gt;
For the WriteWCFConfig method (of course, the crux of the matter), I recommend reading &lt;a href="http://thespot4sap.com/SAPscript/re-20497_Is-there-an-easy-way-to-enumerate-the-bindings-listed-in-configuration.aspx"&gt;this blog post&lt;/a&gt;, which gives an overview of the object model for the WCF configuration sections (which is basically an implementation of System.Configuration).
&lt;br/&gt;
&lt;br/&gt;
&lt;code&gt;&lt;br/&gt;
private static int portNumber = 12000;
&lt;br/&gt;
&lt;br/&gt;
private static void WriteWCFConfig(Type serviceType, Type contractType)
&lt;br/&gt;
{
&lt;br/&gt;
//standard method from System.Configuration
&lt;br/&gt;
Configuration appConfig = ConfigurationManager.OpenExeConfiguration( ConfigurationUserLevel.None );
&lt;br/&gt;
&lt;br/&gt;
//the main section in the app.config file for WCF
&lt;br/&gt;
ServiceModelSectionGroup serviceModel = ServiceModelSectionGroup.GetSectionGroup( appConfig );
&lt;br/&gt;
&lt;br/&gt;
//the
&lt;services/&gt;section
&lt;br/&gt;
ServiceElementCollection serviceSection = serviceModel.Services.Services;
&lt;br/&gt;
&lt;br/&gt;
//a new configuration for a service
&lt;br/&gt;
ServiceElement newService = new ServiceElement( serviceType.FullName );
&lt;br/&gt;
&lt;br/&gt;
if ( !serviceSection.ContainsKey( serviceType.FullName ) )
&lt;br/&gt;
{
&lt;br/&gt;
ServiceEndpointElement endpoint
&lt;br/&gt;
= new ServiceEndpointElement( new Uri( "net.tcp://localhost:" + portNumber ), contractType.FullName );
&lt;br/&gt;
portNumber++;
&lt;br/&gt;
&lt;br/&gt;
endpoint.Binding = "netTcpBinding";
&lt;br/&gt;
newService.Endpoints.Add( endpoint );
&lt;br/&gt;
&lt;br/&gt;
serviceSection.Add( newService );
&lt;br/&gt;
&lt;br/&gt;
appConfig.Save();
&lt;br/&gt;
}
&lt;br/&gt;
}
&lt;br/&gt;&lt;/code&gt;
&lt;br/&gt;
&lt;br/&gt;
THe code above basically uses the System.Configuration API to get an object model for the exising app.config file, uses the API in System.ServiceModel.Configuration to build up the necessary configuration section for a new service, and then saves the config file back to disk. Once this is done, WCF can read the config file, and the code snippet above will work.
&lt;br/&gt;
&lt;br/&gt;
However, there is one catch: suppose that, after writing a config and opening a service using ServiceHost, you want to add a new service, like this:
&lt;br/&gt;
&lt;br/&gt;
&lt;code&gt;&lt;br/&gt;
//first write the service config for the service
&lt;br/&gt;
WriteWCFConfig( typeof(SimpleService), typeof(ISimpleService) );
&lt;br/&gt;
&lt;br/&gt;
//now try to open the wcf service
&lt;br/&gt;
ServiceHost host = new ServiceHost( new SimpleService() );
&lt;br/&gt;
host.Open();
&lt;br/&gt;
&lt;br/&gt;
//do this again with another service
&lt;br/&gt;
WriteWCFConfig( typeof( AnotherSimpleService ), typeof( ISimpleService ) );
&lt;br/&gt;
&lt;br/&gt;
ServiceHost host2 = new ServiceHost( new AnotherSimpleService() );
&lt;br/&gt;
host2.Open();
&lt;br/&gt;&lt;/code&gt;
&lt;br/&gt;
&lt;br/&gt;
This won't work, because WCF (or rather, System.Configuration which is used by WCF to read the app.config file) only reads the app.config file once, and then uses its cache. However, you can force System.Configuration to re-read a certain section of the app.config file from disk, using:
&lt;br/&gt;
&lt;br/&gt;
&lt;code&gt;&lt;br/&gt;
ConfigurationManager.RefreshSection( serviceModel.Services.SectionInformation.SectionName );
&lt;br/&gt;&lt;/code&gt;
&lt;br/&gt;
&lt;br/&gt;
Add this line to the obvious place in WriteWCFConfig, and all will work as planned. For the client side, an identical strategy can be used.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-2043114285801823166?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/2043114285801823166/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2007/11/writing-wcf-config-files.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/2043114285801823166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/2043114285801823166'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2007/11/writing-wcf-config-files.html' title='Writing WCF config files programmatically and dynamically'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4129300230262819780.post-2537277155850988142</id><published>2007-11-11T15:14:00.000Z</published><updated>2008-11-11T18:28:47.264Z</updated><title type='text'>First post</title><content type='html'>Hello world,

A first blog post, in what I hope to be a long series. The main topic of this blog is probably going to be .NET and related technologies, since I'm working with those daily. In time, I'd also like to blog about some more research oriented topics, most notably languages like Haskell and Spec#. Finally, I'm also particularly interested in the topic of software architecture.


Hope you will enjoy my blog...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4129300230262819780-2537277155850988142?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/2537277155850988142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fortysix-and-two.blogspot.com/2007/11/first-post.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/2537277155850988142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4129300230262819780/posts/default/2537277155850988142'/><link rel='alternate' type='text/html' href='http://fortysix-and-two.blogspot.com/2007/11/first-post.html' title='First post'/><author><name>Kurt Schelfthout</name><uri>http://www.blogger.com/profile/15625144753735495725</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
