tag:blogger.com,1999:blog-41293002302628197802024-03-05T09:43:10.615+00:00Forty Six and TwoKurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.comBlogger57125tag:blogger.com,1999:blog-4129300230262819780.post-77729686972275590422014-05-24T11:52:00.000+01:002014-05-24T15:45:24.037+01:00FsCheck 0.9.4<p>Small update – some other generators have been hardened against the new null-generating string generator. Also, <a href="http://github.com/fsharp/FsCheck">FsCheck</a> is compiled against F# 3.1 now, FSharp.Core 4.3.1.0. As always, available on <a href="http://nuget.org">NuGet</a>.</p> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com0tag:blogger.com,1999:blog-4129300230262819780.post-1144514818350712412014-05-09T22:04:00.000+01:002014-05-09T22:05:57.453+01:00FsCheck 0.9.3 and FsCheck.Xunit 0.4.1 released<p><a href="http://github.com/fsharp/FsCheck">FsCheck</a> and <a href="http://nuget.org/packages/FsCheck.Xunit">Fscheck.Xunit</a> both have a new release on <a href="http://nuget.org">NuGet</a>. </p> <p>FsCheck has a breaking change – the string and object generates by default now generate and shrink nulls.</p> <p>FsCheck.Xunit has a workaround for an <a href="http://xunit.codeplex.com/">Xunit</a> bug, the bug itself is also fixed in a beta version of Xunit itself but I figured the workaround is worth it.</p> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com0tag:blogger.com,1999:blog-4129300230262819780.post-62180983673528966352014-04-24T20:51:00.000+01:002014-04-24T20:55:44.979+01:00NDepend to analyze F# code<p><em>Disclosure: Patrick Smacchia from NDepend kindly contacted me to offer an NDepend pro license for evaluation purposes.</em></p> <p>If you’ve been active in the .NET world I’m pretty sure you’ve heard about <a href="http://www.ndepend.com/">NDepend</a> before. It’s a pretty amazing code analysis tool that’s been kicking around for as long as I can remember – and I’m feeling pretty old today. It analyses IL code of one or more .NET assemblies and presents you with a very extensive range of metrics and graphics so you can “big data” the shit out of your code. If the predefined metrics are not enough for you, it also provides CQL (Code Query Language), which allows you to write custom analyses easily. Here’s an example:</p> <pre class="code"><span style="background: white; color: blue">warnif </span><span style="background: #e8e8ff; color: #000064">count</span><span style="background: white; color: black"> > </span><span style="background: #ffff99; color: black">0</span><span style="background: white; color: black"> </span><span style="background: white; color: blue">from </span><span style="background: white; color: black">m </span><span style="background: white; color: blue">in </span><span style="background: #e8e8ff; color: #000064">JustMyCode</span><span style="background: white; color: black">.Methods </span><span style="background: white; color: blue">where </span><span style="background: white; color: black">m.NbLinesOfCode > </span><span style="background: #ffff99; color: black">30
</span><span style="background: white; color: blue">orderby </span><span style="background: white; color: black">m.NbLinesOfCode </span><span style="background: white; color: blue">descending</span><span style="background: white; color: blue">
select new </span><span style="background: white; color: black">{ m, m.NbLinesOfCode, m.NbILInstructions }</span></pre>
<p>This checks for methods that have more than 30 lines of code and orders them by number of code. Pretty straightforward, NDepend even comes with an IDE that gives you intellisense on writing these queries. </p>
<p>All good and well, and I’ve had some fun over the years using NDepend off and on. In my experience, while using it you always learn something about your or your team’s code. But often tools that work well with C# code have trouble with the different style of IL generated by F#. So how does NDepend deal with F# code? Let’s find out. </p>
<p>By the way, here’ s another post about <a href="https://sergeytihon.wordpress.com/2014/01/03/ndepend-for-f-code-or-fsharp-compiler-service-code-review/">NDepend applied to the F# compiler</a> in case you want a second opinion. </p>
<p>For an initial impression with F#, I preferred using it on a project I know very well and that is also in the public domain. That doesn’t leave too many choices, obvious choice is of course <a href="http://github.com/fsharp/FsCheck">FsCheck</a>.</p>
<p>After choosing the projects to analyse I was greeted with the following screen:</p>
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg45fDzCJtzh0V7-PODW_zRzmNbs-eiSKf-i-6fDUNcqlLT6gfKHCKmHaZAKvDjc-ZvQ-QxA5ZyGEpXP0VhcXlE9xBgUQRcRGdrmCfKjFYu8R0AhGIWTA_YNHrFfcFqxC-Bj3YT8TUpl94i/s1600-h/image%25255B6%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEie1y3H3USdKKPVkdjD41yyfAcVQlPUD42T67e_MW0IOT9XwmPaGFvbGM6Ge6cYKQGDWbVNFqfRpP77-NQJrz1yE6ExgcV3q0-remAYLeClhkoI3-t3a7Yt12i7FV1hv279g_f-SJqJF9LH/?imgmax=800" width="1062" height="674" /></a></p>
<p>Sure it looks pretty intimidating, but there’s a lot of useful stuff there. And the UI really helps you out a lot with hints and popups.</p>
<p>In the bottom right for example there’s a bunch of predefined CQL queries that are generating warnings. Some of them are a nice reassuring green. Some of them have some read there, which means NDepend thinks they are “critical”.</p>
<p>The one’s that highlighted is methods with too many parameters. I’m not too bothered with that – about half of them seem to be closures anyway. It’s easy to change the CQL to exclude methods with names that contain @ – that reduces it to two methods. One of them  is the constructor of a record type. Not really critical. Filtering that out generally seems a bit harder (though probably still doable), but I’ll move on.</p>
<p>In the “Dead code” category (dead code is one of my favourite low hanging fruits to improve a code base. So great to just delete code with impunity.) There were a lot of methods that are just being called by reflection because of FsCheck’s generator registration mechanism that’s based on type – all these are not concerning to me but NDepend is certainly fair in highlighting these. I also found a couple of closures again, I wasn’t so sure about these. Maybe the F# compiler is sometimes generating a closure class when it really isn’t needed?</p>
<p>One last area I’ll discuss is the Purity – Immutability – Side effects category. You’d hope that an F# project would not throw up too many issues there, and indeed FsCheck doesn’t. NDepend does find all the cases where I used an array (i.e. a mutable type) as part of an immutable record type. It flags those because such types give the false impression that the type is immutable while really the array is mutable. Of course I realized that when I used arrays, making a conscious decision to not mutate them anyway, but it’s a pretty powerful example of the kind of analysis that you can do in a handful of lines of CQL. </p>
<h5>Conclusion</h5>
<p>NDepend is a really powerful tool to analyse your code base. A short overview like this doesn’t really do it justice, and despite some of the smaller niggles I mentioned above it’s absolutely usable for F#. Really all of the analyses are built on CQL, giving you at once every opportunity to refine them to make them more applicable to your own code base, as well as a great set of examples to build your own. </p> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com1tag:blogger.com,1999:blog-4129300230262819780.post-28243474329129796682013-06-19T03:36:00.000+01:002013-06-20T02:05:29.993+01:00FsCheck 0.9 Released and moved to GitHub<p><a href="http://github.com/fsharp/FsCheck">FsCheck</a> has a new home on GitHub. I wanted to move to GitHub for a while, because it’s where all the cool kids hang out, and @carstkoenig gave me the necessary push. I hope the barrier for contributions is now low enough to get you to chip in if you feel like it, and simplifies the life of existing contributors. (Not that I’m complaining. You’ve been great.)</p> <p>As for the long overdue release - a significant portion of contributions didn’t come from me.</p> <p>Here are the highlights of the change log:</p> <ul> <li>New generators for KeyValuePair, IList, ICollection, Action, Func, decimal (<a href="http://twitter.com/#!/mausch">@mausch</a>) and sbyte (@jackfoxy). </li> <li>Finally compiled against FSharp.Core 4.3 (no more binding redirect. Yay.) </li> <li><a href="http://nuget.org/packages/FsCheck.Xunit">FsCheck.Xunit</a> now allows you to replay a certain test by pasting in the seed from the output in the PropertyAttribute’s Replay property. This should help with debugging: <pre class="code"><span style="background: white; color: black">[<Property(Replay=</span><span style="background: white; color: maroon">"54321,67584"</span><span style="background: white; color: black">)>]</span></pre>
</li>
<li>FsCheck.Xunit also allows defining ArbitraryAttribute on an enclosing module or type now – the given Arbitrary instances are then available for all properties in the type or module. But you can still override them if you define one on a specific property.  <pre class="code"><span style="background: white; color: black"> [<Arbitrary(typeof<TestArbitrary2>)>]
</span><span style="background: white; color: blue">module </span><span style="background: white; color: black">ModuleWithArbitrary =
[<Property>]
</span><span style="background: white; color: blue">let </span><span style="background: white; color: black">``should use Arb instances from enclosing module``(underTest:float) =
underTest <= 0.0
[<Property( Arbitrary=[| typeof<TestArbitrary1> |] )>]
</span><span style="background: white; color: blue">let </span><span style="background: white; color: black">``should use Arb instance on method preferentially``(underTest:float) =
underTest >= 0.0</span></pre>
</li>
</ul>
<p>Hope you enjoy.</p>
<div id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:227ac7c4-ed15-4e36-b11a-cb7d4972b89e" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px">Technorati Tags: <a href="http://technorati.com/tags/fscheck" rel="tag">fscheck</a>,<a href="http://technorati.com/tags/xunit" rel="tag">xunit</a></div> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com0tag:blogger.com,1999:blog-4129300230262819780.post-15513498599181572082012-08-26T22:48:00.000+01:002013-06-20T02:14:01.936+01:00FsCheck 0.8.3 and FsCheck.Xunit 0.3<p>I’ve just uploaded new <a href="http://nuget.codeplex.com">NuGet</a> packages for <a href="http://github.com/fsharp/FsCheck">FsCheck</a> and <a href="http://nuget.org/packages/FsCheck.Xunit">FsCheck.Xunit</a>. </p> <p>The changes are minor:</p> <ul> <li>FsCheck.Xunit now works with instance methods. NCrunch, for example, reportedly only works with instance methods, so this means you can now use NCrunch for running FsCheck properties. </li> <li>Both NuGet packages now call Add-BindingRedirect on install. This will generate an app.config file in your test project if necessary, to spell out to the .NET loader that tests compiled with F#3.0 and so in all likelihood using FSharp.Core 4.3 should indeed use 4.3 instead of the older 4.0, which FsCheck is compiled with. </li> <li>Added symbols on <a href="http://www.symbolsource.org/">symbolsource.org</a>. </li> </ul> <p>Note that running “Add-BindingRedirect <project name>” in the NuGet package manager console should resolve any problems you may have running FsCheck in VS2012. Also, since <a href="http://xunit.codeplex.com/">xunit</a> is strongly signed, there are similar problems with FsCheck.Xunit – Add-BindingRedirect solves that one too.</p> <p>If you’re not into NuGet, add the following lines to your app.config file:</p> <pre class="code"><span style="background: white; color: blue"><?</span><span style="background: white; color: #a31515">xml </span><span style="background: white; color: red">version</span><span style="background: white; color: blue">=</span><span style="background: white; color: black">"</span><span style="background: white; color: blue">1.0</span><span style="background: white; color: black">" </span><span style="background: white; color: red">encoding</span><span style="background: white; color: blue">=</span><span style="background: white; color: black">"</span><span style="background: white; color: blue">utf-8</span><span style="background: white; color: black">"</span><span style="background: white; color: blue">?>
<</span><span style="background: white; color: #a31515">configuration</span><span style="background: white; color: blue">>
<</span><span style="background: white; color: #a31515">runtime</span><span style="background: white; color: blue">>
<</span><span style="background: white; color: #a31515">assemblyBinding </span><span style="background: white; color: red">xmlns</span><span style="background: white; color: blue">=</span><span style="background: white; color: black">"</span><span style="background: white; color: blue">urn:schemas-microsoft-com:asm.v1</span><span style="background: white; color: black">"</span><span style="background: white; color: blue">>
<</span><span style="background: white; color: #a31515">dependentAssembly</span><span style="background: white; color: blue">>
<</span><span style="background: white; color: #a31515">assemblyIdentity </span><span style="background: white; color: red">name</span><span style="background: white; color: blue">=</span><span style="background: white; color: black">"</span><span style="background: white; color: blue">FSharp.Core</span><span style="background: white; color: black">" </span><span style="background: white; color: red">publicKeyToken</span><span style="background: white; color: blue">=</span><span style="background: white; color: black">"</span><span style="background: white; color: blue">b03f5f7f11d50a3a</span><span style="background: white; color: black">" </span><span style="background: white; color: red">culture</span><span style="background: white; color: blue">=</span><span style="background: white; color: black">"</span><span style="background: white; color: blue">neutral</span><span style="background: white; color: black">" </span><span style="background: white; color: blue">/>
<</span><span style="background: white; color: #a31515">bindingRedirect </span><span style="background: white; color: red">oldVersion</span><span style="background: white; color: blue">=</span><span style="background: white; color: black">"</span><span style="background: white; color: blue">0.0.0.0-4.3.0.0</span><span style="background: white; color: black">" </span><span style="background: white; color: red">newVersion</span><span style="background: white; color: blue">=</span><span style="background: white; color: black">"</span><span style="background: white; color: blue">4.3.0.0</span><span style="background: white; color: black">" </span><span style="background: white; color: blue">/>
</</span><span style="background: white; color: #a31515">dependentAssembly</span><span style="background: white; color: blue">>
</</span><span style="background: white; color: #a31515">assemblyBinding</span><span style="background: white; color: blue">>
</</span><span style="background: white; color: #a31515">runtime</span><span style="background: white; color: blue">>
</</span><span style="background: white; color: #a31515">configuration</span><span style="background: white; color: blue">></span></pre>
<div id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:521a728b-0b77-440d-bfd8-794277c917d9" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px">Technorati Tags: <a href="http://technorati.com/tags/F%23" rel="tag">F#</a>,<a href="http://technorati.com/tags/FsCheck" rel="tag">FsCheck</a>,<a href="http://technorati.com/tags/xunit" rel="tag">xunit</a></div>
<span class="sbmLink">
<table cellspacing="1" cellpadding="1"><tbody>
<tr>
<td class="sbmText">Share this post : </td>
<td><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/08/fscheck-083-and-fscheckxunit-03.html&ttl=FsCheck 0.8.3 and FsCheck.Xunit 0.3" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/msdn.png" />MSDN!</a></td>
<td><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/08/fscheck-083-and-fscheckxunit-03.html&ttl=FsCheck 0.8.3 and FsCheck.Xunit 0.3" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" />Technet!</a></td>
<td><a title="Post it to Del.icio.us!" href="http://del.icio.us/post?url=http://fortysix-and-two.blogspot.com/2012/08/fscheck-083-and-fscheckxunit-03.html&;title=FsCheck 0.8.3 and FsCheck.Xunit 0.3" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" />Del.icio.us!</a></td>
<td><a title="Post it to Digg!" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2012/08/fscheck-083-and-fscheckxunit-03.html&title=FsCheck 0.8.3 and FsCheck.Xunit 0.3" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" />Digg!</a></td>
<td><a title="Post it to Dotnetkicks!" href="http://www.dotnetkicks.com/kick/?url=http://fortysix-and-two.blogspot.com/2012/08/fscheck-083-and-fscheckxunit-03.html&title=FsCheck 0.8.3 and FsCheck.Xunit 0.3" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" />Dotnetkicks!</a></td>
<td><a title="Post it to Reddit!" href="http://reddit.com/submit?url=http://fortysix-and-two.blogspot.com/2012/08/fscheck-083-and-fscheckxunit-03.html&title=FsCheck 0.8.3 and FsCheck.Xunit 0.3" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" />Reddit!</a></td>
<td><a title="Post it to Technorati!" href="http://technorati.com/faves/?add=http://fortysix-and-two.blogspot.com/2012/08/fscheck-083-and-fscheckxunit-03.html&title=FsCheck 0.8.3 and FsCheck.Xunit 0.3" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" />Technorati!</a></td>
</tr>
</tbody></table>
</span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com1tag:blogger.com,1999:blog-4129300230262819780.post-81931099621152781752012-06-26T03:06:00.000+01:002012-06-26T03:10:09.302+01:00FsCheck 0.8.1: The ecosystem release<p>Yesterday I’ve released a new version of <a href="http://fscheck.codeplex.com">FsCheck</a>. There are some minor changes, additions and bug fixes to FsCheck itself. The most important part of this release is that FsCheck is now integrated with <a href="http://xunit.codeplex.com/">Xunit</a> through the new FsCheck.Xunit assembly.</p> <p>For the impatient: <a href="http://nuget.codeplex.com">NuGet</a> packages for <a href="http://nuget.org/packages/FsCheck">FsCheck</a> and <a href="http://nuget.org/packages/FsCheck.Xunit">FsCheck.Xunit</a></p> <p>Here goes a more detailed overview.</p> <p><strong>Generators are now <a href="http://learnyouahaskell.com/functors-applicative-functors-and-monoids#applicative-functors">applicative</a></strong>. Or, without the general abstract nonsense: say you’ve got three generators </p> <pre class="code"><span style="color: blue">let </span>ga,gb,gc :Gen<_> * Gen<_> * Gen<_></pre>
<p>And you have a function of three arguments that you’d like to map over those. </p>
<pre class="code"><span style="color: blue">let </span>f = <span style="color: blue">fun </span>a b c <span style="color: blue">->
</span></pre>
<p>No problem, you can use Gen.map3 – right? But how many instances of map do you need? FsCheck currently defines 6. But now that Gen is applicative, we can write:</p>
<pre class="code"><span style="color: blue">let </span>result = f <!> ga <*> gb <*> gc</pre>
<p>Hey, doesn’t that almost read like function application? That’s the idea. The weird operators in between just make sure everything is applied properly. Besides being a bit nicer to use sometimes, you can also keep chaining this indefinitely, up to any arity.</p>
<p>And hey, if you still prefer map, FsCheck still has those.</p>
<p><strong>New generators.</strong> <a href="http://bugsquash.blogspot.com/">Mauricio Scheffer</a> contributed int64 and TimeSpan generators. I’ve also added an int16 generator, and DontSize wrappers for all of those – the default generators for int16, 32 and 64 will generate integers smaller than the test size, which is increased by FsCheck as the test progresses. The DontSize variants ignore the size and always pick from the whole range for the type.</p>
<p><strong>Xunit integration. </strong>Xunit is a very nice framework – very simple to use and extend. FsCheck integrates with Xunit by adding a PropertyAtttribute. To use it, just use Property instead of Fact, and you can now give your test arguments. These are randomly generated by FsCheck. You can also use all of the normal property combinators in the Prop namespace. A couple of examples:</p>
<pre class="code">[<Property>]
<span style="color: blue">let </span>``abs(v) % k equals abs(v % k)`` v (NonZeroInt k) =
(abs v) % k = abs(v % k)</pre>
<pre class="code">[<Property>]
<span style="color: blue">let </span>``divMod should satisfy definition`` (x:int) (y:int) =
y <> 0 ==> <span style="color: blue">lazy </span>(<span style="color: blue">let </span>(d,m) = divMod x y <span style="color: blue">in </span>d*y + m = x)</pre>
<h1></h1>
<p>Note that Property test methods, as opposed to Fact, don’t need to return unit – they can return anything that’s testable with FsCheck, including bool. But since a test fails in FsCheck when it throws an exception, you can still use the Assert class if you like. You can also use <a href="https://github.com/dmohl/FsUnit">FsUnit</a> or <a href="http://code.google.com/p/unquote/">Unquote</a> or whatever to write your assertions. FsCheck does not care – it does the hard work of generating random values and shrinking them if the test fails and generally tries to get out of your way for the rest.</p>
<p>You can also set various configuration parameters using the Property attribute, which then apply to that method only. Most of these are trivial (e.g. the number of tests), but an interesting one is that you can override the random generation for certain types on one test method only:</p>
<pre class="code"><span style="color: blue">type </span>TestArbitrary1 =
<span style="color: blue">static member </span>PositiveDouble() =
Arb.Default.Float()
|> Arb.mapFilter abs (<span style="color: blue">fun </span>t <span style="color: blue">-> </span>t >= 0.0)
[<Property( Arbitrary=[| typeof<TestArbitrary1> |] )>]
<span style="color: blue">let </span>``should register Arbitrary instances from Config in last to first order``(underTest:float) =
underTest >= 0.0</pre>
<p>Here the generator for float is overridden to generate only positive floats.</p>
<p>Finally, a special thanks to <a href="http://twitter.com/#!/mausch">@mausch</a> for contributing, integrating FsCheck with <a href="https://github.com/mausch/Fuchu">Fuchu</a>, and giving me a gentle nudge to get this release out the door at last!</p>
<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:686f50fe-7aad-43f0-8147-d732acff9327" class="wlWriterEditableSmartContent">Technorati Tags: <a href="http://technorati.com/tags/fscheck" rel="tag">fscheck</a>,<a href="http://technorati.com/tags/f%23" rel="tag">f#</a>,<a href="http://technorati.com/tags/xunit.net" rel="tag">xunit.net</a></div>
<span class="sbmLink">
<table cellspacing="1" cellpadding="1"><tbody>
<tr>
<td class="sbmText">Share this post : </td>
<td><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/06/fscheck-081-ecosystem-release.html&ttl=FsCheck 0.8.1: The ecosystem release" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/msdn.png" />MSDN!</a></td>
<td><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/06/fscheck-081-ecosystem-release.html&ttl=FsCheck 0.8.1: The ecosystem release" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" />Technet!</a></td>
<td><a title="Post it to Del.icio.us!" href="http://del.icio.us/post?url=http://fortysix-and-two.blogspot.com/2012/06/fscheck-081-ecosystem-release.html&;title=FsCheck 0.8.1: The ecosystem release" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" />Del.icio.us!</a></td>
<td><a title="Post it to Digg!" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2012/06/fscheck-081-ecosystem-release.html&title=FsCheck 0.8.1: The ecosystem release" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" />Digg!</a></td>
<td><a title="Post it to Dotnetkicks!" href="http://www.dotnetkicks.com/kick/?url=http://fortysix-and-two.blogspot.com/2012/06/fscheck-081-ecosystem-release.html&title=FsCheck 0.8.1: The ecosystem release" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" />Dotnetkicks!</a></td>
<td><a title="Post it to Reddit!" href="http://reddit.com/submit?url=http://fortysix-and-two.blogspot.com/2012/06/fscheck-081-ecosystem-release.html&title=FsCheck 0.8.1: The ecosystem release" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" />Reddit!</a></td>
<td><a title="Post it to Technorati!" href="http://technorati.com/faves/?add=http://fortysix-and-two.blogspot.com/2012/06/fscheck-081-ecosystem-release.html&title=FsCheck 0.8.1: The ecosystem release" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" />Technorati!</a></td>
</tr>
</tbody></table>
</span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com3tag:blogger.com,1999:blog-4129300230262819780.post-83335911387688355562012-05-26T02:57:00.000+01:002012-05-26T03:00:02.674+01:00Accessibility modifiers on F# record types<p>In the note to self category.</p> <pre class="code"><span style="color: blue">type internal </span>Internal = { Si : string }</pre>
<p>means that the class Internal will be internal. The constructor and properties are technically public, but that is meaningless since the enclosing class is internal. However, if the Internal type implements public interfaces, then the public methods it implements are visible and usable by clients outside the assembly (provided they get hold of an instance, of course – they can’t construct one since they can’t see the name of the class).</p>
<pre class="code"><span style="color: blue">type </span>IGet = <span style="color: blue">abstract </span>Get : string
<span style="color: blue">type internal </span>Internal =
{ Si : string }
<span style="color: blue">interface </span>IGet <span style="color: blue">with
member </span>x.Get = x.Si</pre>
<p>If an instance gets out as an obj, clients can still call HashCode and Equals because those are exposed as public overrides from obj or as public interfaces, e.g. IComparable.</p>
<pre class="code"><span style="color: blue">type </span>Internal = <span style="color: blue">internal </span>{ Si : string }</pre>
<p>means that the class Internal is public, but the constructor and properties are internal.</p>
<p>Both can be combined, and private of course works too. Similar accessibility modifiers can be given to discriminated unions – it is not possible to give a different accessibility to individual union cases, just like it isn’t possible to give different modifiers to different fields of a record.</p>
<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:f97cdbf1-36fc-42c0-9c5d-d311c3df0383" class="wlWriterEditableSmartContent">Technorati Tags: <a href="http://technorati.com/tags/F%23" rel="tag">F#</a>,<a href="http://technorati.com/tags/records" rel="tag">records</a>,<a href="http://technorati.com/tags/unions" rel="tag">unions</a>,<a href="http://technorati.com/tags/accessibility+modifiers" rel="tag">accessibility modifiers</a></div>
<span class="sbmLink">
<table cellspacing="1" cellpadding="1"><tbody>
<tr>
<td class="sbmText">Share this post : </td>
<td><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/05/accessibility-modifiers-on-f-record.html&ttl=Accessibility modifiers on F# record types" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/msdn.png" /></a></td>
<td><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/05/accessibility-modifiers-on-f-record.html&ttl=Accessibility modifiers on F# record types" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" /></a></td>
<td><a title="Post it to Del.icio.us!" href="http://del.icio.us/post?url=http://fortysix-and-two.blogspot.com/2012/05/accessibility-modifiers-on-f-record.html&;title=Accessibility modifiers on F# record types" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" /></a></td>
<td><a title="Post it to Digg!" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2012/05/accessibility-modifiers-on-f-record.html&title=Accessibility modifiers on F# record types" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" /></a></td>
<td><a title="Post it to Dotnetkicks!" href="http://www.dotnetkicks.com/kick/?url=http://fortysix-and-two.blogspot.com/2012/05/accessibility-modifiers-on-f-record.html&title=Accessibility modifiers on F# record types" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" /></a></td>
<td><a title="Post it to Reddit!" href="http://reddit.com/submit?url=http://fortysix-and-two.blogspot.com/2012/05/accessibility-modifiers-on-f-record.html&title=Accessibility modifiers on F# record types" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" /></a></td>
<td><a title="Post it to Technorati!" href="http://technorati.com/faves/?add=http://fortysix-and-two.blogspot.com/2012/05/accessibility-modifiers-on-f-record.html&title=Accessibility modifiers on F# record types" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" /></a></td>
</tr>
</tbody></table>
</span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com0tag:blogger.com,1999:blog-4129300230262819780.post-8803997242434765162012-05-07T02:24:00.001+01:002012-05-07T02:26:18.850+01:00Making F# reflection faster<p>I don’t really believe I’m the first one to do this, but I couldn’t find anything that’s publically available. If you know about a mature implementation, please leave a comment!</p> <p>I put up some code on <a href="https://bitbucket.org/kurt/fsreflect/wiki/Home">https://bitbucket.org/kurt/fsreflect/wiki/Home</a> that has a small API, mirroring <a href="http://msdn.microsoft.com/en-us/library/ee353505.aspx">FSharpValue’s</a> PreComputeXXX reflective construction and deconstruction methods for unions and records. It does the exact same thing as the original methods, only faster.</p> <p>As explained on the project page, the code uses two techniques. The first is on-the-fly IL code generation using <a href="http://msdn.microsoft.com/en-us/library/system.reflection.emit.dynamicmethod.aspx">DynamicMethod</a>. This is used for the fast record and union construction code. The second is using delegates instead of MethodInfo.Invoke for the record and union readers, using a <a href="https://msmvps.com/blogs/jon_skeet/archive/2008/08/09/making-reflection-fly-and-exploring-delegates.aspx">great trick introduced by Jon Skeet</a>. The former is explained in a lot of places – the latter is explained perfectly by Mr Skeet already.</p> <p>Anyway the code is pretty short and sweet, so if you’re interested please do have a browse.</p> <p>Here are some gratuitous micro-benchmarks.</p> <pre class="code">> repeat (<span style="color: blue">fun </span>i <span style="color: blue">-> </span>fastRecordCtor [| <span style="color: maroon">"2"</span>; i; 3. |] :?> MyRecord)</pre>
<pre class="code">Real: 00:00:00.198, CPU: 00:00:00.202, GC gen0: 73, gen1: 2, gen2: 1
val it : unit = ()
> repeat (<span style="color: blue">fun </span>i <span style="color: blue">-> </span>standardRecordCtor [| <span style="color: maroon">"2"</span>; i; 3. |] :?> MyRecord) </pre>
<pre class="code">Real: 00:00:02.811, CPU: 00:00:02.808, GC gen0: 115, gen1: 0, gen2: 0
val it : unit = ()
> repeat (<span style="color: blue">fun </span>i <span style="color: blue">-> </span>fastUnionCtor [| <span style="color: maroon">"3"</span>; i |] :?> MyUnion)
Real: 00:00:00.150, CPU: 00:00:00.156, GC gen0: 50, gen1: 0, gen2: 0
val it : unit = ()
> repeat (<span style="color: blue">fun </span>i <span style="color: blue">-> </span>standardUnionCtor [| <span style="color: maroon">"3"</span>; i |] :?> MyUnion)
Real: 00:00:02.551, CPU: 00:00:02.542, GC gen0: 72, gen1: 0, gen2: 0
val it : unit = ()
> repeat (<span style="color: blue">fun </span>i <span style="color: blue">-> </span>fastRecordReader { S = <span style="color: maroon">"2"</span>; i = i; f = 3.0 })
Real: 00:00:00.209, CPU: 00:00:00.218, GC gen0: 76, gen1: 0, gen2: 0
val it : unit = ()
> repeat (<span style="color: blue">fun </span>i <span style="color: blue">-> </span>standardRecordReader { S = <span style="color: maroon">"2"</span>; i = i; f = 3.0 })
Real: 00:00:05.390, CPU: 00:00:05.397, GC gen0: 77, gen1: 1, gen2: 0
val it : unit = ()
> repeat (<span style="color: blue">fun </span>i <span style="color: blue">-> </span>fastUnionReader (Two (<span style="color: maroon">"s"</span>,i)))
Real: 00:00:00.160, CPU: 00:00:00.171, GC gen0: 50, gen1: 0, gen2: 0
val it : unit = ()
> repeat (<span style="color: blue">fun </span>i <span style="color: blue">-> </span>standardUnionReader (Two (<span style="color: maroon">"s"</span>,i)))
Real: 00:00:03.477, CPU: 00:00:03.478, GC gen0: 49, gen1: 0, gen2: 0
val it : unit = ()</pre>
<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:f288833c-f55e-45cb-96e1-3cc3e4a14bcd" class="wlWriterEditableSmartContent">Technorati Tags: <a href="http://technorati.com/tags/F%23" rel="tag">F#</a>,<a href="http://technorati.com/tags/Reflection" rel="tag">Reflection</a>,<a href="http://technorati.com/tags/Performance" rel="tag">Performance</a></div>
<span class="sbmLink">
<table cellspacing="1" cellpadding="1"><tbody>
<tr>
<td class="sbmText">Share this post : </td>
<td><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/05/making-f-reflection-faster.html&ttl=Making F# Reflection faster" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/msdn.png" />MSDN!</a></td>
<td><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/05/making-f-reflection-faster.html&ttl=Making F# Reflection faster" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" />Technet!</a></td>
<td><a title="Post it to Del.icio.us!" href="http://del.icio.us/post?url=http://fortysix-and-two.blogspot.com/2012/05/making-f-reflection-faster.html&;title=Making F# Reflection faster" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" />Del.icio.us!</a></td>
<td><a title="Post it to Digg!" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2012/05/making-f-reflection-faster.html&title=Making F# Reflection faster" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" />Digg!</a></td>
<td><a title="Post it to Dotnetkicks!" href="http://www.dotnetkicks.com/kick/?url=http://fortysix-and-two.blogspot.com/2012/05/making-f-reflection-faster.html&title=Making F# Reflection faster" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" />Dotnetkicks!</a></td>
<td><a title="Post it to Reddit!" href="http://reddit.com/submit?url=http://fortysix-and-two.blogspot.com/2012/05/making-f-reflection-faster.html&title=Making F# Reflection faster" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" />Reddit!</a></td>
<td><a title="Post it to Technorati!" href="http://technorati.com/faves/?add=http://fortysix-and-two.blogspot.com/2012/05/making-f-reflection-faster.html&title=Making F# Reflection faster" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" />Technorati!</a></td>
</tr>
</tbody></table>
</span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com1tag:blogger.com,1999:blog-4129300230262819780.post-16874027764783020872012-01-04T01:46:00.000+00:002012-01-04T01:50:36.992+00:00API design: Record types and backwards compatibility<p>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.</p> <p>Let’s look at a couple of changes that you might want to make to a record type:</p> <ul> <li>Adding a new field. </li> <li>Changing the type of a field. </li> <li>Changing the order of the fields. </li> </ul> <p>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 <em>with </em>syntax, is a no-no. </p> <p>To make this abundantly clear – a record type definition and usage:</p> <pre class="code"><span style="color: blue">type </span>MyRecord =
{ Field : int
SecondField : string }
<span style="color: blue">let </span>instance = { Field = 3; SecondField = <span style="color: maroon">"3" </span>}</pre>
<p>Is translated by the F# compiler to:</p>
<pre class="code"><span style="color: blue">type </span>MyRecordTranslated(field:int,secondfield:string) =
<span style="color: blue">member </span>this.Field = field
<span style="color: blue">member </span>this.SecondField = secondfield
<span style="color: blue">let </span>instanceTranslated = <span style="color: blue">new </span>MyRecordTranslated(3,<span style="color: maroon">"3"</span>)</pre>
<p>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.</p>
<h4></h4>
<h4>Two solutions (sort of)</h4>
<p>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.</p>
<p>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:</p>
<pre class="code"><span style="color: blue">module </span>A_v0 =
<span style="color: blue">type </span>MyRecord =
<span style="color: blue">internal </span>{ _Field : int } <span style="color: blue">with
static member </span>Create(field:int) = { _Field = field }
<span style="color: blue">member </span>this.Field = this._Field
<span style="color: blue">member </span>this.With(?Field:int) = { this <span style="color: blue">with </span>_Field = defaultArg Field this.Field } </pre>
<p>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.</p>
<p>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.</p>
<p>Finally, using optional fields, we can regain some sort of with syntax. Here’s an example of usage:</p>
<pre class="code"><span style="color: blue">let </span>a = A_v0.MyRecord.Create(2).With(Field = 3).Field</pre>
<p>Now, suppose we want to add a new field. We can do that as follows, without breaking any clients:</p>
<pre class="code"><span style="color: blue">module </span>A_v1 =
<span style="color: blue">type </span>MyRecord =
<span style="color: blue">internal </span>{ _Field : int
_Foo : string } <span style="color: blue">with
static member </span>Create(field:int) = { _Field = field; _Foo = <span style="color: maroon">"default" </span>}
<span style="color: blue">static member </span>Create(field:int,foo:string) = { _Field = field; _Foo = foo }
<span style="color: blue">member </span>this.Field = this._Field
<span style="color: blue">member </span>this.Foo = this._Foo
<span style="color: blue">member </span>this.With(?Field:int) = { this <span style="color: blue">with </span>_Field = defaultArg Field this.Field }
<span style="color: blue">member </span>this.With(?Field:int,?Foo:string) = { this <span style="color: blue">with </span>_Field = defaultArg Field this.Field
_Foo = defaultArg Foo this.Foo }</pre>
<p>Note how we can now use overloading of both Create and With to our advantage.</p>
<p>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.</p>
<h4>Can F# v_next solve this?</h4>
<p>The  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. </p>
<p>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.</p>
<p>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.</p>
<p>A first idea would be to allow the declaration of “optional fields”, and compile those as overloaded constructors – say you could write:</p>
<pre class="code"><span style="color: blue">type </span>MyRecord =
{ Field : int
SecondField : string
?OptionalField = 5 }</pre>
<p>which would be compiled to:</p>
<pre class="code"><span style="color: blue">type </span>MyRecordTranslated(field:int,secondfield:string, optionalField:int) =
<span style="color: blue">new</span>(field:int,secondfield:string) = MyRecordTranslated(field,secondfield, 5)
<span style="color: blue">member </span>this.Field = field
<span style="color: blue">member </span>this.SecondField = secondfield
<span style="color: blue">member </span>this.OptionalField = optionalField</pre>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<h4></h4>
<h4>Conclusion</h4>
<p>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.</p>
<p>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.</p>
<p>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...).</p>
<span class="sbmLink">
<table cellspacing="1" cellpadding="1"><tbody>
<tr>
<td class="sbmText">Share this post : </td>
<td><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&ttl=API design: Record types and backwards compatibility" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/msdn.png" />MSDN!</a></td>
<td><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&ttl=API design: Record types and backwards compatibility" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" />Technet!</a></td>
<td><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&;title=API design: Record types and backwards compatibility" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" />Del.icio.us!</a></td>
<td><a title="Post it to Digg!" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2012/01/api-design-record-types-and-backwards.html&title=API design: Record types and backwards compatibility" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" />Digg!</a></td>
<td><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&title=API design: Record types and backwards compatibility" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" />Dotnetkicks!</a></td>
<td><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&title=API design: Record types and backwards compatibility" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" />Reddit!</a></td>
<td><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&title=API design: Record types and backwards compatibility" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" />Technorati!</a></td>
</tr>
</tbody></table>
</span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com9tag:blogger.com,1999:blog-4129300230262819780.post-6537599767050211982011-05-29T21:32:00.000+01:002011-05-29T21:35:25.235+01:00FsCheck 0.7.1: NuGet packaging<p>I’ve released a minor update to <a href="http://fscheck.codeplex.com">FsCheck</a>, mostly so it can now be downloaded as a <a href="http://nuget.codeplex.com">NuGet</a> package. It also comes with source server support, courtesy of <a href="http://www.symbolsource.org/">SymbolSource.org</a>. </p> <p>Furthermore, there are a couple of bug fixes.</p> <p>Enjoy.</p> <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">Technorati Tags: <a href="http://technorati.com/tags/fscheck" rel="tag">fscheck</a>,<a href="http://technorati.com/tags/random+testing" rel="tag">random testing</a></div> <span class="sbmLink"> <table cellspacing="1" cellpadding="1"><tbody> <tr> <td class="sbmText">Share this post : </td> <td><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&ttl=FsCheck 0.7.1: NuGet packaging" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/msdn.png" />MSDN!</a></td> <td><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&ttl=FsCheck 0.7.1: NuGet packaging" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" />Technet!</a></td> <td><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&;title=FsCheck 0.7.1: NuGet packaging" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" />Del.icio.us!</a></td> <td><a title="Post it to Digg!" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2011/05/fscheck-071-nuget-packaging.html&title=FsCheck 0.7.1: NuGet packaging" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" />Digg!</a></td> <td><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&title=FsCheck 0.7.1: NuGet packaging" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" />Dotnetkicks!</a></td> <td><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&title=FsCheck 0.7.1: NuGet packaging" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" />Reddit!</a></td> <td><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&title=FsCheck 0.7.1: NuGet packaging" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" />Technorati!</a></td> </tr> </tbody></table> </span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com0tag:blogger.com,1999:blog-4129300230262819780.post-69581916862183724012011-01-02T21:57:00.000+00:002011-01-02T22:00:03.853+00:00F# projects someone should start<p>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.</p> <h4>A usable documentation system</h4> <p>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.</p> <p>My main inspiration here is <a href="http://docs.racket-lang.org/scribble/">Scribble</a>, for <a href="http://racket-lang.org/">Racket</a> (formerly PLT Scheme). From the <a href="http://www.cs.utah.edu/plt/publications/icfp09-fbf.pdf">scribble paper’s</a> abstract:</p> <blockquote> <p>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 flexibility 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.</p> </blockquote> <p>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.</p> <p>I realize it is probably not possible to do this in F# in the same way due to the lack of macros. Maybe <a href="https://github.com/richhickey/clojure-clr">ClojureCLR</a> 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 <a href="http://www.agical.com/bumblebee/bumblebee_doc.html">BumbleBee</a>. Bonus points for Visual Studio integration. </p> <p><strong>Difficulty</strong>: 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.</p> <p><strong>Work</strong>: Lots. Getting all this stuff to work together reliably and preferably inside Visual Studio...that’ll take some time.</p> <h4>Mirror-based reflection library</h4> <p>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.</p> <p>This indicates insufficient abstraction of System.Reflection: if I’m playing with F# types, I<em>  cannot</em> 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<a href="http://fortysix-and-two.blogspot.com/2008/03/reflection-type-unraveled.html"> Type is overloaded</a>. High cohesion, anyone?</p> <p>Enter m<a href="http://bracha.org/mirrors.pdf">irror-based reflection</a>, 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, <a href="http://newspeaklanguage.org/">Newspeak</a> 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.</p> <p><strong>Difficulty</strong>: 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.</p> <p><strong>Work</strong>: 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.</p> <h4>Contribute to NuGet so it knows about F#</h4> <p><a href="http://nuget.codeplex.com">NuGet</a> 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 <a href="http://nuget.codeplex.com/workitem/374">the issue</a> up so the NuGet team adds it to the next release :)</p> <p><strong>Difficulty</strong>: 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.</p> <p><strong>Work</strong>: Not too much – mostly finding your way around the NuGet codebase and finding what works and what doesn’t in the F# language service..</p> <h4>Add snippets and organize usings support to the F# project system</h4> <p>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 –> Rename.</p> <p><strong>Difficulty</strong>: Straightforward. Only roadblock could be that the current F# language service is just not easily extensible for these kinds of things.</p> <p><strong>Work</strong>: 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.</p> <p> </p> <p>That should give you enough to pass the time in 2011, I hope!</p> <span class="sbmLink"> <table cellspacing="1" cellpadding="1"><tbody> <tr> <td class="sbmText">Share this post : </td> <td><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&ttl=F# projects someone should start" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/msdn.png" />MSDN!</a></td> <td><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&ttl=F# projects someone should start" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" />Technet!</a></td> <td><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&;title=F# projects someone should start" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" />Del.icio.us!</a></td> <td><a title="Post it to Digg!" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2011/01/f-projects-someone-should-start.html&title=F# projects someone should start" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" />Digg!</a></td> <td><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&title=F# projects someone should start" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" />Dotnetkicks!</a></td> <td><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&title=F# projects someone should start" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" />Reddit!</a></td> <td><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&title=F# projects someone should start" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" />Technorati!</a></td> </tr> </tbody></table> </span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com0tag:blogger.com,1999:blog-4129300230262819780.post-84621054803618600342010-12-16T22:03:00.000+00:002010-12-16T22:06:59.484+00:00F#, xUnit theories and InlineData<p>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.</p> <p>Anyway, just a short heads up to save people some time: in the <a href="http://xunit.codeplex.com/">xUnit</a> 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 <a href="http://fscheck.codeplex.com">FsCheck</a>, you know). That and other xUnit extension goodies are explained <a href="http://blog.benhall.me.uk/2008/01/introduction-to-xunitnet-extensions.html">here</a>.</p> <p>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 <a href="http://stackoverflow.com/questions/3116911/attribute-cannot-be-repeated-in-c-cli-but-ok-in-c">this stackoverflow post</a>. If  you care about this, please <a href="http://xunit.codeplex.com/workitem/9690">vote</a> for the bug on the xUnit site!</p> <p>Luckily, the workaround is not too bad – just use the PropertyData attribute instead: </p> <pre class="code"><span style="color: blue">let </span>symbolTestData =
[ <span style="color: maroon">"an1 rest"</span>, <span style="color: maroon">"an1"
"?test bla"</span>, <span style="color: maroon">"?test"
"?+_est bla"</span>, <span style="color: maroon">"?+_est"
"+_123 bla"</span>, <span style="color: maroon">"?+_123"
"+._1.2.3 bla"</span>, <span style="color: maroon">"+._1.2.3"
"+_q1r-2g3! bla"</span>, <span style="color: maroon">"+_q1r-2g3!"
"abc.def.feg/q bla"</span>, <span style="color: maroon">"abc.def.feg/q"
"ab/cd? bla"</span>, <span style="color: maroon">"ab/cd?"
</span>]
|> Seq.map (<span style="color: blue">fun </span>(a,b) <span style="color: blue">-> </span>[|a; b|])
[<Theory>]
[<PropertyData(<span style="color: maroon">"symbolTestData"</span>)>]
<span style="color: blue">let </span>``should parse symbol``(toParse:string, result:string) =
Assert.Equal(result, run symbol result)</pre>
<p>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.</p>
<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">Technorati Tags: <a href="http://technorati.com/tags/xUnit" rel="tag">xUnit</a>,<a href="http://technorati.com/tags/F%23" rel="tag">F#</a>,<a href="http://technorati.com/tags/xUnit+Theory" rel="tag">xUnit Theory</a></div>
<span class="sbmLink">
<table cellspacing="1" cellpadding="1"><tbody>
<tr>
<td class="sbmText">Share this post : </td>
<td><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&ttl=F#, xUnit theories and InlineData" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/msdn.png" /></a></td>
<td><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&ttl=F#, xUnit theories and InlineData" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" /></a></td>
<td><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&;title=F#, xUnit theories and InlineData" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" /></a></td>
<td><a title="Post it to Digg!" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2010/12/f-xunit-theories-and-inlinedata.html&title=F#, xUnit theories and InlineData" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" /></a></td>
<td><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&title=F#, xUnit theories and InlineData" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" /></a></td>
<td><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&title=F#, xUnit theories and InlineData" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" /></a></td>
<td><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&title=F#, xUnit theories and InlineData" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" /></a></td>
</tr>
</tbody></table>
</span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com0tag:blogger.com,1999:blog-4129300230262819780.post-41822174853785326732010-07-10T17:26:00.000+01:002010-07-10T17:29:45.536+01:00F# and Code Contracts: not quite there yet<p>In this post I’ll show how you can get <a href="http://msdn.microsoft.com/en-gb/devlabs/dd491992.aspx">Code Contracts</a> 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. </p> <h4></h4> <h4>Code Contracts: the short story</h4> <p>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). </p> <p>Pragmatically, contracts are usually compiled into a debug build of a program, and checked at runtime. That’s how <a href="http://www.eiffel.com/">Eiffel</a> 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 <a href="http://se.inf.ethz.ch/people/ciupa/papers/icse08.pdf">ARTOO</a>, 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.</p> <p>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.</p> <p>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.</p> <p>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.</p> <p>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.</p> <h4>The nuts and bolts</h4> <p>‘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:</p> <pre class="code"><span style="color: blue"><?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>"<span style="color: blue">1.0</span>" <span style="color: red">encoding</span><span style="color: blue">=</span>"<span style="color: blue">utf-8</span>"<span style="color: blue">?>
<</span><span style="color: #a31515">Project </span><span style="color: red">ToolsVersion</span><span style="color: blue">=</span>"<span style="color: blue">4.0</span>" <span style="color: red">DefaultTargets</span><span style="color: blue">=</span>"<span style="color: blue">Build</span>" <span style="color: red">xmlns</span><span style="color: blue">=</span>"<span style="color: blue">http://schemas.microsoft.com/developer/msbuild/2003</span>"<span style="color: blue">>
<</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">>
<</span><span style="color: #a31515">Configuration </span><span style="color: red">Condition</span><span style="color: blue">=</span>" <span style="color: blue">'$(Configuration)' == '' </span>"<span style="color: blue">></span>Debug<span style="color: blue"></</span><span style="color: #a31515">Configuration</span><span style="color: blue">>
<</span><span style="color: #a31515">Platform </span><span style="color: red">Condition</span><span style="color: blue">=</span>" <span style="color: blue">'$(Platform)' == '' </span>"<span style="color: blue">></span>AnyCPU<span style="color: blue"></</span><span style="color: #a31515">Platform</span><span style="color: blue">>
<</span><span style="color: #a31515">ProductVersion</span><span style="color: blue">></span>8.0.30703<span style="color: blue"></</span><span style="color: #a31515">ProductVersion</span><span style="color: blue">>
<</span><span style="color: #a31515">SchemaVersion</span><span style="color: blue">></span>2.0<span style="color: blue"></</span><span style="color: #a31515">SchemaVersion</span><span style="color: blue">>
<</span><span style="color: #a31515">ProjectGuid</span><span style="color: blue">></span>{dd086c3a-9cbd-4dc9-89d2-4386df7ee986}<span style="color: blue"></</span><span style="color: #a31515">ProjectGuid</span><span style="color: blue">>
<</span><span style="color: #a31515">OutputType</span><span style="color: blue">></span>Exe<span style="color: blue"></</span><span style="color: #a31515">OutputType</span><span style="color: blue">>
<</span><span style="color: #a31515">RootNamespace</span><span style="color: blue">></span>CodeContractsFs<span style="color: blue"></</span><span style="color: #a31515">RootNamespace</span><span style="color: blue">>
<</span><span style="color: #a31515">AssemblyName</span><span style="color: blue">></span>CodeContractsFs<span style="color: blue"></</span><span style="color: #a31515">AssemblyName</span><span style="color: blue">>
<</span><span style="color: #a31515">TargetFrameworkVersion</span><span style="color: blue">></span>v4.0<span style="color: blue"></</span><span style="color: #a31515">TargetFrameworkVersion</span><span style="color: blue">>
<</span><span style="color: #a31515">Name</span><span style="color: blue">></span>CodeContractsFs<span style="color: blue"></</span><span style="color: #a31515">Name</span><span style="color: blue">>
<strong> <</strong></span><strong><span style="color: #a31515">CodeContractsAssemblyMode</span><span style="color: blue">></span>1<span style="color: blue"></</span><span style="color: #a31515">CodeContractsAssemblyMode</span></strong><span style="color: blue"><strong>></strong>
</</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">>
<</span><span style="color: #a31515">PropertyGroup </span><span style="color: red">Condition</span><span style="color: blue">=</span>" <span style="color: blue">'$(Configuration)|$(Platform)' == 'Debug|AnyCPU' </span>"<span style="color: blue">>
<</span><span style="color: #a31515">DebugSymbols</span><span style="color: blue">></span>true<span style="color: blue"></</span><span style="color: #a31515">DebugSymbols</span><span style="color: blue">>
<</span><span style="color: #a31515">DebugType</span><span style="color: blue">></span>full<span style="color: blue"></</span><span style="color: #a31515">DebugType</span><span style="color: blue">>
<</span><span style="color: #a31515">Optimize</span><span style="color: blue">></span>false<span style="color: blue"></</span><span style="color: #a31515">Optimize</span><span style="color: blue">>
<</span><span style="color: #a31515">Tailcalls</span><span style="color: blue">></span>false<span style="color: blue"></</span><span style="color: #a31515">Tailcalls</span><span style="color: blue">>
<</span><span style="color: #a31515">OutputPath</span><span style="color: blue">></span>bin\Debug\<span style="color: blue"></</span><span style="color: #a31515">OutputPath</span><span style="color: blue">>
<strong><</strong></span><strong><span style="color: #a31515">DefineConstants</span><span style="color: blue">></span>TRACE;DEBUG;CONTRACTS_FULL<span style="color: blue"></</span><span style="color: #a31515">DefineConstants</span></strong><span style="color: blue"><strong>></strong>
<</span><span style="color: #a31515">WarningLevel</span><span style="color: blue">></span>3<span style="color: blue"></</span><span style="color: #a31515">WarningLevel</span><span style="color: blue">>
<</span><span style="color: #a31515">DocumentationFile</span><span style="color: blue">></span>bin\Debug\CodeContractsFs.XML<span style="color: blue"></</span><span style="color: #a31515">DocumentationFile</span><span style="color: blue">>
<strong><</strong></span><strong><span style="color: #a31515">CodeContractsEnableRuntimeChecking</span><span style="color: blue">></span>True<span style="color: blue"></</span><span style="color: #a31515">CodeContractsEnableRuntimeChecking</span></strong><strong><span style="color: blue">>
<</span><span style="color: #a31515">CodeContractsRuntimeOnlyPublicSurface</span><span style="color: blue">></span>False<span style="color: blue"></</span><span style="color: #a31515">CodeContractsRuntimeOnlyPublicSurface</span></strong><strong><span style="color: blue">>
<</span><span style="color: #a31515">CodeContractsRuntimeThrowOnFailure</span><span style="color: blue">></span>True<span style="color: blue"></</span><span style="color: #a31515">CodeContractsRuntimeThrowOnFailure</span></strong><strong><span style="color: blue">>
<</span><span style="color: #a31515">CodeContractsRuntimeCallSiteRequires</span><span style="color: blue">></span>False<span style="color: blue"></</span><span style="color: #a31515">CodeContractsRuntimeCallSiteRequires</span></strong><strong><span style="color: blue">>
<</span><span style="color: #a31515">CodeContractsRunCodeAnalysis</span><span style="color: blue">></span>False<span style="color: blue"></</span><span style="color: #a31515">CodeContractsRunCodeAnalysis</span></strong><strong><span style="color: blue">>
<</span><span style="color: #a31515">CodeContractsNonNullObligations</span><span style="color: blue">></span>False<span style="color: blue"></</span><span style="color: #a31515">CodeContractsNonNullObligations</span></strong><strong><span style="color: blue">>
<</span><span style="color: #a31515">CodeContractsBoundsObligations</span><span style="color: blue">></span>False<span style="color: blue"></</span><span style="color: #a31515">CodeContractsBoundsObligations</span></strong><strong><span style="color: blue">>
<</span><span style="color: #a31515">CodeContractsArithmeticObligations</span><span style="color: blue">></span>False<span style="color: blue"></</span><span style="color: #a31515">CodeContractsArithmeticObligations</span></strong><strong><span style="color: blue">>
<</span><span style="color: #a31515">CodeContractsRedundantAssumptions</span><span style="color: blue">></span>False<span style="color: blue"></</span><span style="color: #a31515">CodeContractsRedundantAssumptions</span></strong><strong><span style="color: blue">>
<</span><span style="color: #a31515">CodeContractsRunInBackground</span><span style="color: blue">></span>True<span style="color: blue"></</span><span style="color: #a31515">CodeContractsRunInBackground</span></strong><strong><span style="color: blue">>
<</span><span style="color: #a31515">CodeContractsShowSquigglies</span><span style="color: blue">></span>False<span style="color: blue"></</span><span style="color: #a31515">CodeContractsShowSquigglies</span></strong><strong><span style="color: blue">>
<</span><span style="color: #a31515">CodeContractsUseBaseLine</span><span style="color: blue">></span>False<span style="color: blue"></</span><span style="color: #a31515">CodeContractsUseBaseLine</span></strong><strong><span style="color: blue">>
<</span><span style="color: #a31515">CodeContractsEmitXMLDocs</span><span style="color: blue">></span>False<span style="color: blue"></</span><span style="color: #a31515">CodeContractsEmitXMLDocs</span></strong><strong><span style="color: blue">>
<</span><span style="color: #a31515">CodeContractsCustomRewriterAssembly </span></strong><strong><span style="color: blue">/>
<</span><span style="color: #a31515">CodeContractsCustomRewriterClass </span></strong><strong><span style="color: blue">/>
<</span><span style="color: #a31515">CodeContractsLibPaths </span></strong><strong><span style="color: blue">/>
<</span><span style="color: #a31515">CodeContractsExtraRewriteOptions </span></strong><strong><span style="color: blue">/>
<</span><span style="color: #a31515">CodeContractsExtraAnalysisOptions </span></strong><strong><span style="color: blue">/>
<</span><span style="color: #a31515">CodeContractsBaseLineFile </span></strong><strong><span style="color: blue">/>
<</span><span style="color: #a31515">CodeContractsRuntimeCheckingLevel</span><span style="color: blue">></span>Full<span style="color: blue"></</span><span style="color: #a31515">CodeContractsRuntimeCheckingLevel</span></strong><strong><span style="color: blue">>
<</span><span style="color: #a31515">CodeContractsReferenceAssembly</span><span style="color: blue">></span>%28none%29<span style="color: blue"></</span><span style="color: #a31515">CodeContractsReferenceAssembly</span></strong><span style="color: blue"><strong>></strong>
</</span><span style="color: #a31515">PropertyGroup</span><span style="color: blue">>
</span><span style="color: blue"> <</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">>
<</span><span style="color: #a31515">Reference </span><span style="color: red">Include</span><span style="color: blue">=</span>"<span style="color: blue">mscorlib</span>" <span style="color: blue">/>
<</span><span style="color: #a31515">Reference </span><span style="color: red">Include</span><span style="color: blue">=</span>"<span style="color: blue">FSharp.Core</span>" <span style="color: blue">/>
<</span><span style="color: #a31515">Reference </span><span style="color: red">Include</span><span style="color: blue">=</span>"<span style="color: blue">System</span>" <span style="color: blue">/>
<</span><span style="color: #a31515">Reference </span><span style="color: red">Include</span><span style="color: blue">=</span>"<span style="color: blue">System.Core</span>" <span style="color: blue">/>
<</span><span style="color: #a31515">Reference </span><span style="color: red">Include</span><span style="color: blue">=</span>"<span style="color: blue">System.Numerics</span>" <span style="color: blue">/>
</</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">>
<</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">>
<</span><span style="color: #a31515">Compile </span><span style="color: red">Include</span><span style="color: blue">=</span>"<span style="color: blue">Module1.fs</span>" <span style="color: blue">/>
<</span><span style="color: #a31515">None </span><span style="color: red">Include</span><span style="color: blue">=</span>"<span style="color: blue">Script.fsx</span>" <span style="color: blue">/>
</</span><span style="color: #a31515">ItemGroup</span><span style="color: blue">>
<</span><span style="color: #a31515">Import </span><span style="color: red">Project</span><span style="color: blue">=</span>"<span style="color: blue">$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets</span>" <span style="color: red">Condition</span><span style="color: blue">=</span>"<span style="color: blue">!Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')</span>" <span style="color: blue">/>
<</span><span style="color: #a31515">Import </span><span style="color: red">Project</span><span style="color: blue">=</span>"<span style="color: blue">$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets</span>" <span style="color: red">Condition</span><span style="color: blue">=</span>" <span style="color: blue">Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')</span>" <span style="color: blue">/>
</span><span style="color: blue"></</span><span style="color: #a31515">Project</span><span style="color: blue">>
</span></pre>
<p>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:</p>
<ul>
<li>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.</li>
<li>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)</li>
<li>CodeContractsEnableRuntimeChecking: Otherwise the rewriter doesn’t kick in. Not sure why you’d need this and the constant, but there you go.</li>
</ul>
<p>Add this to your F# project and you should see the rewriter kick in after the build – it’s called ccrewrite.exe.</p>
<h4>Let’s write some contracts</h4>
<p>That was the easy part. Now, let’s try to convert the program given in the <a href="http://download.microsoft.com/download/C/2/7/C2715F76-F56C-4D37-9231-EF8076B7EC13/userdoc.pdf">Code Contracts documentation</a> to F#:</p>
<pre class="code"><span style="color: blue">type </span>Rational(numerator,denominator) =
<span style="color: blue">do </span>Contract.Requires( denominator <> 0 )
[<ContractInvariantMethod>]
<span style="color: blue">let </span>ObjectInvariant() =
Contract.Invariant ( denominator <> 0 )
<span style="color: blue">member </span>x.Denominator =
Contract.Ensures( Contract.Result<int>() <> 0 )
denominator</pre>
<p>So this is a simple rational type. It shows you basically how contracts work – you call methods on the Contract static class:</p>
<ul>
<li>Contract.Requires to impose a precondition on arguments – in this case an argument of the constructor.</li>
<li>Contract.Ensures to express a postcondition – in this case a postcondition on the result of a getter, which is nicely accessible using Contract.Result.</li>
<li>ObjectInvariantMethodAttribute and Contract.Invariant to impose an invariant on a class – something that should hold after every execution of a method.</li>
</ul>
<p>So far so good. Alas, when we try to build this, we get:</p>
<table border="1"><tbody>
<tr>
<td>
<pre>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)'.</pre>
</td>
</tr>
</tbody></table>
<p> </p>
<p>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.</p>
<p>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.</p>
<h4>Conclusion</h4>
<p>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).</p>
<p>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.</p>
<p>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.</p>
<p>So close, but not quite there yet. I’ve <a href="http://social.msdn.microsoft.com/Forums/en-US/codecontracts/thread/dc7c8a56-0a80-4a5e-8413-31c7098833ad">asked a year ago</a> if the situation was going to improve, and <a href="http://social.msdn.microsoft.com/Forums/en-US/codecontracts/thread/11b8c5e3-a25d-4770-a46d-14f24921e0a0">again a few weeks back</a>, 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…</p>
<p>
<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">Technorati Tags: <a href="http://technorati.com/tags/F%23" rel="tag">F#</a>,<a href="http://technorati.com/tags/code+contracts" rel="tag">code contracts</a></div>
</p>
<span class="sbmLink">
<table cellspacing="1" cellpadding="1"><tbody>
<tr>
<td class="sbmText">Share this post : </td>
<td><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&ttl=F# and Code Contracts:: not quite there yet" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/msdn.png" />MSDN!</a></td>
<td><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&ttl=F# and Code Contracts:: not quite there yet" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" />Technet!</a></td>
<td><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&;title=F# and Code Contracts:: not quite there yet" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" />Del.icio.us!</a></td>
<td><a title="Post it to Digg!" href="http://digg.com/submit?phase=2&url=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" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" />Digg!</a></td>
<td><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&title=F# and Code Contracts:: not quite there yet" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" />Dotnetkicks!</a></td>
<td><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&title=F# and Code Contracts:: not quite there yet" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" />Reddit!</a></td>
<td><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&title=F# and Code Contracts:: not quite there yet" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" />Technorati!</a></td>
</tr>
</tbody></table>
</span><span class="sbmLink"></span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com2tag:blogger.com,1999:blog-4129300230262819780.post-30037083388962836952010-06-09T18:38:00.000+01:002010-06-09T18:42:20.388+01:00Thinking outside the Visual Studio box<p>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 <em>incontournable</em>, and there is little on the horizon that will change this situation.</p> <h4>What toothpicks and Visual Studio have in common</h4> <p>I did some Java development in <a href="http://www.eclipse.org/">Eclipse</a> over 3 years ago, and as I remember it, it worked better than Visual Studio 2010. Let me repeat that:</p> <blockquote> <p>Eclipse 2007 (for Java) is a better IDE than Visual Studio 2010 (for C#).</p> </blockquote> <p>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.</p> <p><strong>Compiling</strong>. 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.</p> <p><strong>Testing. </strong>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.</p> <p><strong>Refactoring. </strong>The refactorings in Visual Studio pale in comparison to those in Eclipse. Hands down.</p> <p><strong>Browsing Code. </strong>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.</p> <p><strong>Source control. </strong>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 <a href="http://www.selenic.com/mercurial/wiki/">mercurial</a> and <a href="http://subversion.apache.org/">subversion</a> is just not as good as the integration in Eclipse.</p> <p>Products like <a href="http://www.jetbrains.com/resharper/index.html">Resharper</a> and <a href="http://testdriven.net/">Testdriven.NET</a> 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.</p> <p>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, <em>except that it’s worse! </em>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?</p> <h4>What rocks and Visual Studio have in common</h4> <p>Both <a href="http://www.icsharpcode.net/OpenSource/SD/">SharpDevelop</a> and <a href="http://monodevelop.com/">MonoDevelop</a> 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. </p> <p>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.</p> <h4>A call to arms</h4> <p>So, dear SharpDevelop or MonoDevelop developer, or whoever is looking to develop a new software project: here’s my call to arms for you.</p> <p>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.</p> <p>Need some ideas? </p> <p>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.</p> <p>Can we make better compilers for C# or VB or <a title="F# homepage" href="http://research.microsoft.com/fsharp/fsharp.aspx" target="_blank">F#</a> 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). </p> <p>Source control – can we go beyond superficial integration with popular SCMs and really integrate <em>change tracking</em> 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.</p> <p>Have a look at a <a href="http://www.smalltalk.org/main/">Smalltalk</a> 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 <a href="http://newspeaklanguage.org/">Newspeak</a> looks interesting too. </p> <p>As far as UI goes, <a href="http://www.cs.brown.edu/people/acb/codebubbles_site.htm">Code Bubbles</a> (built on Eclipse for Java) seems to have some very well thought out UI ideas on browsing, cooperating and debugging.</p> <p>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. </p> <p>Time for a revolution?</p> <p> <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">Technorati: <a href="http://technorati.com/tags/IDE" rel="tag">IDE</a>,<a href="http://technorati.com/tags/.NET" rel="tag">.NET</a>,<a href="http://technorati.com/tags/Visual+Studio" rel="tag">Visual Studio</a>,<a href="http://technorati.com/tags/Eclipse" rel="tag">Eclipse</a></div> </p> <span class="sbmLink"> <table cellspacing="1" cellpadding="1"><tbody> <tr> <td class="sbmText">Share this post : </td> <td><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&ttl=Thinking outside the Visual Studio box" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" />Technet!</a></td> <td><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&;title=Thinking outside the Visual Studio box" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" />del.icio.us it!</a></td> <td><a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&address=http://fortysix-and-two.blogspot.com/2010/06/thinking-outside-visual-studio-box.html&title=Thinking outside the Visual Studio box" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" />del.iri.ous!</a></td> <td><a title="Post it to digg" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2010/06/thinking-outside-visual-studio-box.html&title=Thinking outside the Visual Studio box" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" />digg it!</a></td> <td><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&title=Thinking outside the Visual Studio box" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" />dotnetkicks it!</a></td> <td><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&title=Thinking outside the Visual Studio box" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" />reddit!</a></td> <td><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&title=Thinking outside the Visual Studio box" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" />technorati!</a></td> </tr> </tbody></table> </span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com0tag:blogger.com,1999:blog-4129300230262819780.post-40180216722440522312010-06-04T21:40:00.000+01:002010-06-04T21:46:57.754+01:00FsCheck 0.7: Pleasure and Pain<p>I just released <a href="http://www.codeplex.com/fscheck" target="_blank">FsCheck</a> 0.7  on the codeplex page. Whereas previous releases have been mostly incremental, this one is quite different. With the official release of <a title="F# homepage" href="http://research.microsoft.com/fsharp/fsharp.aspx" target="_blank">F#</a> 2.0 and all that it entails, I’ve <strong>refactored the FsCheck API from a usability perspective</strong>. </p> <p>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.</p> <p>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.</p> <p>That’s the good news – the bad news is that <strong>this release is not backwards compatible.</strong> 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.</p> <h4>Short attention span?</h4> <p>Get a visually appealing (but much less detailed) overview in <a href="http://prezi.com/dykys5bdnram/">this prezi</a>.</p> <h4></h4> <h4>The whole truth</h4> <p>Well, at least as far as I can remember.</p> <ul> <li>Factored API into three type and  module pairs – cfr e.g. the collection types in FSharp.Core. So there is now:</li> <ul> <li>Gen<’a> 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.</li> <li>Arbitrary<’a> 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. </li> <ul> <li>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)</li> </ul> <li>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)</li> </ul> <li>Similar refactoring with running tests. </li> <ul> <li>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.<intellisense>.</li> <li>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.</li> <li>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.</li> </ul> <li>Output has been improved in various places.</li> <ul> <li>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.</li> <li>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.</li> <li>Various small output improvements.</li> </ul> <li>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.</li> <li>Added many more tests, especially for the generators. I’m still not happy with the coverage, but we’re getting there.</li> <li>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.</li> <li>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).</li> <li>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.</li> </ul> <p>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.</p> <p>Happy FsChecking!</p> <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">Technorati: <a href="http://technorati.com/tags/fscheck" rel="tag">fscheck</a>,<a href="http://technorati.com/tags/f%23" rel="tag">f#</a>,<a href="http://technorati.com/tags/random+testing" rel="tag">random testing</a></div> <span class="sbmLink"> <table cellspacing="1" cellpadding="1"><tbody> <tr> <td class="sbmText">Share this post : </td> <td><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&ttl=FsCheck 0.7: Pleasure and Pain" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" />Technet!</a></td> <td><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&;title=FsCheck 0.7: Pleasure and Pain" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" />del.icio.us it!</a></td> <td><a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&address=http://fortysix-and-two.blogspot.com/2010/06/fscheck-07-pleasure-and-pain.html&title=FsCheck 0.7: Pleasure and Pain" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" />del.iri.ous!</a></td> <td><a title="Post it to digg" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2010/06/fscheck-07-pleasure-and-pain.html&title=FsCheck 0.7: Pleasure and Pain" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" />digg it!</a></td> <td><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&title=FsCheck 0.7: Pleasure and Pain" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" />dotnetkicks it!</a></td> <td><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&title=FsCheck 0.7: Pleasure and Pain" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" />reddit!</a></td> <td><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&title=FsCheck 0.7: Pleasure and Pain" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" />technorati!</a></td> </tr> </tbody></table> </span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com0tag:blogger.com,1999:blog-4129300230262819780.post-75693649916585836862010-05-15T22:24:00.000+01:002010-05-15T22:28:47.820+01:00Accessing Visual Studio’s Automation API from F# Interactive<p>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:</p> <pre>> myDTE.Solution.Projects |> Seq.cast<Project> |> Seq.map (fun p -> p.FullName);;</pre>
<pre>val it : seq<string> =
seq
["C:\Users\Kurt\Projects\FsCheck\doc\FsCheck\FsCheck.fsproj";
"C:\Users\Kurt\Projects\FsCheck\doc\FsCheck.Examples\FsCheck.Examples.fsproj"; "";
"C:\Users\Kurt\Projects\FsCheck\doc\FsCheck.Checker\FsCheck.Checker.fsproj"; ...]</pre>
<p>You get access to the <a href="http://msdn.microsoft.com/en-us/library/za2b25t3%28v=VS.71%29.aspx">DTE top level automation object</a> 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. </p>
<h4>But…how?</h4>
<p>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 <a href="http://msdn.microsoft.com/en-us/library/ms695276%28VS.85%29.aspx">Running Object Table</a> (hereafter called ROT) with <a href="http://msdn.microsoft.com/en-us/library/ms228755%28v=VS.80%29.aspx">two keys</a>:</p>
<ul>
<li>As a string of the form “!VisualStudio.<VS version>.0:<processid>”. E.g. for VS2008 with process id 1234: !VisualStudio.9.0:1234</li>
<li>As the path to an open solution file, if any.</li>
</ul>
<p>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. </p>
<p>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.</p>
<h4>Step 1: Finding the Visual Studio process id</h4>
<p>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.</p>
<p>The code is pretty straightforward – remember the point is that this is being executed in F# interactive:</p>
<pre class="code"><span style="color: blue">open </span>System
<span style="color: blue">open </span>System.Diagnostics
<span style="color: blue">let </span>getParentProcess (processId:int) =
<span style="color: blue">let </span>proc = Process.GetProcessById processId
<span style="color: blue">let </span>myProcID = <span style="color: blue">new </span>PerformanceCounter(<span style="color: maroon">"Process"</span>, <span style="color: maroon">"ID Process"</span>, proc.ProcessName)
<span style="color: blue">let </span>myParentID = <span style="color: blue">new </span>PerformanceCounter(<span style="color: maroon">"Process"</span>, <span style="color: maroon">"Creating Process ID"</span>, proc.ProcessName)
myParentID.NextValue() |> int
<span style="color: blue">let </span>currentProcess = Process.GetCurrentProcess().Id
<span style="color: blue">let </span>myVS = getParentProcess currentProcess</pre>
<p>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.)</p>
<h4>Step 2: Getting the DTE object</h4>
<p>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 <a href="http://www.databaseforum.info/8/983730.aspx">look</a> – I just translated it to F#. Here’s what we need:</p>
<pre class="code"><span style="color: blue">#r </span><span style="color: maroon">"EnvDTE"
</span><span style="color: blue">#r </span><span style="color: maroon">"EnvDTE80.dll"
</span><span style="color: blue">#r </span><span style="color: maroon">"EnvDTE90.dll"
</span><span style="color: blue">open </span>EnvDTE
<span style="color: blue">open </span>EnvDTE80
<span style="color: blue">open </span>EnvDTE90</pre>
<a href="http://11011.net/software/vspaste"></a>
<pre class="code"><span style="color: blue"></span><span style="color: blue">open </span>System.Runtime.InteropServices
<span style="color: blue">open </span>System.Runtime.InteropServices.ComTypes
<span style="color: blue">module </span>Msdev =
[<DllImport(<span style="color: maroon">"ole32.dll"</span>)>]
<span style="color: blue">extern </span>int GetRunningObjectTable([<In>]int reserved, [<Out>] IRunningObjectTable& prot)
[<DllImport(<span style="color: maroon">"ole32.dll"</span>)>]
<span style="color: blue">extern </span>int CreateBindCtx([<In>]int reserved, [<Out>]IBindCtx& ppbc)</pre>
<p>These two interop functions allow us to enumerate the ROT and get the registered object with the key we want:</p>
<pre class="code"><span style="color: blue">let </span>tryFindInRunningObjectTable (name:string) =
<span style="color: green">//let result = new Dictionary<_,_>()
</span><span style="color: blue">let mutable </span>rot = <span style="color: blue">null
if </span>Msdev.GetRunningObjectTable(0,&rot) <> 0 <span style="color: blue">then </span>failwith <span style="color: maroon">"GetRunningObjectTable failed."
</span><span style="color: blue">let mutable </span>monikerEnumerator = <span style="color: blue">null
</span>rot.EnumRunning(&monikerEnumerator)
monikerEnumerator.Reset()
<span style="color: blue">let mutable </span>numFetched = IntPtr.Zero
<span style="color: blue">let </span>monikers = Array.init<ComTypes.IMoniker> 1 (<span style="color: blue">fun </span>_ <span style="color: blue">-> null</span>)
<span style="color: blue">let mutable </span>result = None
<span style="color: blue">while </span>result.IsNone && (monikerEnumerator.Next(1, monikers, numFetched) = 0) <span style="color: blue">do
let mutable </span>ctx = <span style="color: blue">null
if </span>Msdev.CreateBindCtx(0, &ctx) <> 0 <span style="color: blue">then </span>failwith <span style="color: maroon">"CreateBindCtx failed"
</span><span style="color: blue">let mutable </span>runningObjectName = <span style="color: blue">null
</span>monikers.[0].GetDisplayName(ctx, <span style="color: blue">null</span>, &runningObjectName)
<span style="color: blue">if </span>runningObjectName = name <span style="color: blue">then
let mutable </span>runningObjectVal = <span style="color: blue">null
if </span>rot.GetObject( monikers.[0], &runningObjectVal) <> 0 <span style="color: blue">then </span>failwith <span style="color: maroon">"GetObject failed"
</span>result <- Some runningObjectVal
<span style="color: green">//result.[runningObjectName] <- runningObjectVal
</span>result</pre>
<p>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<string*obj>. 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.</p>
<h4>Putting two and two together</h4>
<p>Armed with these functions, here’s the DTE object that you can use to call the Automation API:</p>
<pre class="code"><span style="color: blue">let </span>getVS2008ROTName id =
sprintf <span style="color: maroon">"!VisualStudio.DTE.9.0:%i" </span>id
<span style="color: blue">let </span>myDTE = (tryFindInRunningObjectTable (getVS2008ROTName myVS) |> Option.get) :?> DTE2</pre>
<p>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.</p>
<p>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:</p>
<ul>
<li>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.</li>
<li>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).</li>
<li>myDTE.Quit(). The l33t hax0r way to exit Visual Studio. You’ll be the envy of your less tech-savvy colleagues.</li>
</ul>
<p>If you find an imaginative use for this, please let me know.</p>
<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">Technorati: <a href="http://technorati.com/tags/F%23+Interactive" rel="tag">F# Interactive</a>,<a href="http://technorati.com/tags/Visual+Studio+Automation" rel="tag">Visual Studio Automation</a>,<a href="http://technorati.com/tags/DTE" rel="tag">DTE</a>,<a href="http://technorati.com/tags/F%23" rel="tag">F#</a>,<a href="http://technorati.com/tags/FSI" rel="tag">FSI</a></div>
<span class="sbmLink">
<table cellspacing="1" cellpadding="1"><tbody>
<tr>
<td class="sbmText">Share this post : </td>
<td><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&ttl=Accessing Visual Studio's Automation API from F# Interactive" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" /></a></td>
<td><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&;title=Accessing Visual Studio's Automation API from F# Interactive" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" /></a></td>
<td><a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&address=http://fortysix-and-two.blogspot.com/2010/05/accessing-visual-studios-automation-api.html&title=Accessing Visual Studio's Automation API from F# Interactive" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" /></a></td>
<td><a title="Post it to digg" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2010/05/accessing-visual-studios-automation-api.html&title=Accessing Visual Studio's Automation API from F# Interactive" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" /></a></td>
<td><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&title=Accessing Visual Studio's Automation API from F# Interactive" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" /></a></td>
<td><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&title=Accessing Visual Studio's Automation API from F# Interactive" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" /></a></td>
<td><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&title=Accessing Visual Studio's Automation API from F# Interactive" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" /></a></td>
</tr>
</tbody></table>
</span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com1tag:blogger.com,1999:blog-4129300230262819780.post-32544068501239556052010-04-09T22:20:00.000+01:002010-04-09T22:31:48.042+01:00Moving FsCheck to Mercurial<p>I’ve been using <a href="http://www.selenic.com/mercurial/wiki/">Mercurial</a> as my source control system of choice for a few years now, and I’ve been very  happy with it. The only problem I had was that codeplex, where <a href="http://www.codeplex.com/fscheck" target="_blank">FsCheck</a> 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.</p> <p>Well, no more! <a href="http://blogs.msdn.com/codeplex/archive/2010/01/22/codeplex-now-supporting-native-mercurial.aspx">Codeplex now supports Mercurial</a> 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.</p> <p>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.</p> <p>And obviously Mercurial isn’t keen on letting you delete history.</p> <p>Luckily it has the excellent <a href="http://mercurial.selenic.com/wiki/ConvertExtension">convert extension</a>. 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.</p> <p>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.</p> <p>So here’s what I did:</p> <ol> <li>Convert the old main repository to the new main, stripping out files and branches along the way.</li> <li>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.</li> <li>Using hg convert’s splice feature, and the excellent <a href="http://tortoisehg.bitbucket.org/">TortoiseHg</a> 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.</li> </ol> <p>Confused yet? Well, here’s my first <a href="http://prezi.com/zznsmfwl7v9e/">Prezi</a> to explain it all…</p> <p>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.</p> <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">Technorati: <a href="http://technorati.com/tags/mercurial" rel="tag">mercurial</a>,<a href="http://technorati.com/tags/hg+convert" rel="tag">hg convert</a>,<a href="http://technorati.com/tags/fscheck" rel="tag">fscheck</a>,<a href="http://technorati.com/tags/codeplex" rel="tag">codeplex</a></div> <span class="sbmLink"> <table cellspacing="1" cellpadding="1"><tbody> <tr> <td class="sbmText">Share this post : </td> <td><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&ttl=Moving FsCheck to Mercurial" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" />Technet!</a></td> <td><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&;title=Moving FsCheck to Mercurial" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" />del.icio.us it!</a></td> <td><a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&address=http://fortysix-and-two.blogspot.com/2010/04/moving-fscheck-to-mercurial.html&title=Moving FsCheck to Mercurial" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" />del.iri.ous!</a></td> <td><a title="Post it to digg" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2010/04/moving-fscheck-to-mercurial.html&title=Moving FsCheck to Mercurial" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" />digg it!</a></td> <td><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&title=Moving FsCheck to Mercurial" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" />dotnetkicks it!</a></td> <td><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&title=Moving FsCheck to Mercurial" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" />reddit!</a></td> <td><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&title=Moving FsCheck to Mercurial" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" />technorati!</a></td> </tr> </tbody></table> </span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com0tag:blogger.com,1999:blog-4129300230262819780.post-3168757568620981452010-02-15T20:08:00.000+00:002010-02-15T20:09:44.817+00:00FsCheck 0.6.3 for Visual Studio 2010 RC and F# February 2010 CTP<p>A new release of <a title="F# homepage" href="http://research.microsoft.com/fsharp/fsharp.aspx" target="_blank">F#</a> means a new release of <a href="http://www.codeplex.com/fscheck" target="_blank">FsCheck</a>.</p> <ul> <li>Removed the dependency on the F# PowerPack. This makes FsCheck easier to use, especially since the PowerPack is now  separately distributed. Besides, it was only used to pretty print functions. </li> <li>Cleaned up reflective generators a bit. </li> <li>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.</li> </ul> <p>Enjoy.</p> <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">Technorati: <a href="http://technorati.com/tags/FsCheck" rel="tag">FsCheck</a>,<a href="http://technorati.com/tags/random+testing" rel="tag">random testing</a>,<a href="http://technorati.com/tags/F%23" rel="tag">F#</a></div> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com0tag:blogger.com,1999:blog-4129300230262819780.post-46829048197370867092010-02-11T20:54:00.001+00:002010-02-11T20:54:36.706+00:00Visug presentation in Leuven, Belgium on 8 Feb 2010<p>Thanks to everyone who attended – hope you got something out of it (besides the free food and drinks…).</p> <p>Here are the <a href="http://cid-f6a45280389d5d06.skydrive.live.com/self.aspx/Public/fsharp%20intro.pdf">slides</a> I used, as well as <a href="http://cid-f6a45280389d5d06.skydrive.live.com/self.aspx/Public/FSharpIntro.zip">the (completed) demo project</a>. 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.</p> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com0tag:blogger.com,1999:blog-4129300230262819780.post-4702842028265571932009-12-22T16:57:00.000+00:002009-12-22T16:59:38.932+00:00On Understanding Data Abstraction, Revisited<p>I’m not in the habit of posting links, but <a href="http://www.cs.utexas.edu/~wcook/Drafts/2009/essay.pdf">this essay by Willam R. Cook</a> 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.</p> <p>Enjoy.</p> <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">Technorati: <a href="http://technorati.com/tags/ADT" rel="tag">ADT</a>,<a href="http://technorati.com/tags/objects" rel="tag">objects</a>,<a href="http://technorati.com/tags/data+abstraction" rel="tag">data abstraction</a></div> <span class="sbmLink"> <table cellspacing="1" cellpadding="1"><tbody> <tr> <td class="sbmText">Share this post : </td> <td><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&ttl=On Understanding Data Abstraction, Revisited" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" /></a></td> <td><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&;title=On Understanding Data Abstraction, Revisited" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" /></a></td> <td><a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&address=http://fortysix-and-two.blogspot.com/2009/12/on-understanding-data-abstraction.html&title=On Understanding Data Abstraction, Revisited" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" /></a></td> <td><a title="Post it to digg" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2009/12/on-understanding-data-abstraction.html&title=On Understanding Data Abstraction, Revisited" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" /></a></td> <td><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&title=On Understanding Data Abstraction, Revisited" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" /></a></td> <td><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&title=On Understanding Data Abstraction, Revisited" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" /></a></td> <td><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&title=On Understanding Data Abstraction, Revisited" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" /></a></td> </tr> </tbody></table> </span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com0tag:blogger.com,1999:blog-4129300230262819780.post-81068714071087729482009-12-08T19:51:00.000+00:002009-12-08T19:55:11.040+00:00How to get hg-git working with Mercurial without installing Python on Windows<p>Sorry for the horrendous search keyword-driven title, but I’ve been trying to get this to work for ages.</p> <p>Here’s a step by step guide, along with some potential pitfalls.</p> <p>1) Download <a href="http://tortoisehg.bitbucket.org/">TortoiseHg</a>. I used 0.9.1.1. with Mercurial 1.4.1. Do not use the windows <a href="http://www.selenic.com/mercurial/wiki/">Mercurial</a> 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.</p> <p>2) Install TortoiseHg as usual.</p> <p>3) Download <a href="http://pypi.python.org/pypi/dulwich">dulwich 0.4.0</a>.</p> <p>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.</p> <p>5) Download the tip of an up to date hg-git fork. I used <a title="http://bitbucket.org/gwik/hg-git/" href="http://bitbucket.org/gwik/hg-git/">http://bitbucket.org/gwik/hg-git/</a>.</p> <p>6) Put the hg-git directory in the TortoiseHg directory.</p> <p>7) Add the following lines to your Mercurial.ini file:</p> <p><font face="con">bookmarks =</font></p> <p><font face="con">hggit = C:\Program Files\TortoiseHg\hg-git\hggit</font></p> <p>That’s it. I finally managed to clone the ClojureClr repository with the above install:</p> <pre>> 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</pre>
<p></p>
<p>And with this we’re back to functional programming languages ;)</p>
<p>I didn’t test this any further.</p>
<p>Good luck!</p>
<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"><p><span class="TagSite">Technorati:</span> <a href="http://technorati.com/tag/mercurial" rel="tag" class="tag">mercurial</a>, <a href="http://technorati.com/tag/hg" rel="tag" class="tag">hg</a>, <a href="http://technorati.com/tag/hg-git" rel="tag" class="tag">hg-git</a>, <a href="http://technorati.com/tag/git" rel="tag" class="tag">git</a><br /><!-- StartInsertedTags: mercurial,hg,hg-git,git :EndInsertedTags --></p></div>
<span class="sbmLink">
<table cellspacing="1" cellpadding="1"><tbody>
<tr>
<td class="sbmText">Share this post : </td>
<td><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&ttl=How to get hg-git working with Mercurial without installing Python on Windows" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" /></a></td>
<td><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&;title=How to get hg-git working with Mercurial without installing Python on Windows" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" /></a></td>
<td><a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&address=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" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" /></a></td>
<td><a title="Post it to digg" href="http://digg.com/submit?phase=2&url=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" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" /></a></td>
<td><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&title=How to get hg-git working with Mercurial without installing Python on Windows" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" /></a></td>
<td><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&title=How to get hg-git working with Mercurial without installing Python on Windows" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" /></a></td>
<td><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&title=How to get hg-git working with Mercurial without installing Python on Windows" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" /></a></td>
</tr>
</tbody></table>
</span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com3tag:blogger.com,1999:blog-4129300230262819780.post-22537181143785511112009-10-26T10:10:00.000+00:002009-10-26T10:22:45.318+00:00FsCheck 0.6.2: F# October 2009 CTP/2010 Beta 2<p><a href="http://fscheck.codeplex.com">FsCheck</a> is updated for the new F# release! Conversion was fairly straightforward, some name changes and indentation changes mostly. Furthermore, the following smaller changes: </p><ul><li>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.</li><li>Some more examples</li><li>registerInstances and overwriteInstances now throws an exception if it cannot find any instances in the given type.</li></ul><p>Happy FsChecking!
</p>Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com0tag:blogger.com,1999:blog-4129300230262819780.post-22671129068359820012009-09-19T14:53:00.000+01:002009-09-19T14:59:17.647+01:00Simple and Fair Backtracking Computations<p>Translated to <a title="F# homepage" href="http://research.microsoft.com/fsharp/fsharp.aspx" target="_blank">F#</a> from the <a href="http://okmij.org/ftp/Computation/monads.html#fair-bt-stream">fair and terminating backtracking monad and monad transformer</a> by Oleg Kiselyov. </p> <p>Sequence expressions in F# can be seen as backtracking computations. For example,</p> <pre class="code"><span style="color: blue">let </span>backtrack =
seq { <span style="color: blue">for </span>i <span style="color: blue">in </span>1..10 <span style="color: blue">do
for </span>j <span style="color: blue">in </span>1..10 <span style="color: blue">do
if </span>i*j > 10 <span style="color: blue">then yield </span>(i,j) }</pre>
<p><a href="http://11011.net/software/vspaste"></a>will yield one by one (i.e. lazily) all the tuples i,j that satisfy the guard i*j>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  – there is really a computation builder behind this that translates to something like </p>
<blockquote>
<p>1..10 >>= (fun i –> 1..10 >>= (fun j –> …))</p>
</blockquote>
<p>where (>>=) 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.</p>
<p>Unfortunately, this simplicity has some drawbacks.</p>
<pre class="code"><span style="color: blue">let </span>infinite =
seq { <span style="color: blue">for </span>i <span style="color: blue">in </span>1..10 <span style="color: blue">do
for </span>j <span style="color: blue">in </span>Seq.initInfinite id <span style="color: blue">do
if </span>i > 5 <span style="color: blue">then yield </span>(i,j) }</pre>
<p>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.</p>
<p>The thing to realize is that, if viewed as a backtracking computation, there are basically two operations that are important: <em>choice</em> and <em>bind. </em></p>
<p><em>Choice</em> 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…</p>
<p><em>Bind </em>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] <em>and </em>j should be chosen from [0,Infinity] <em>and </em>i should be > 5.</p>
<p>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.</p>
<p>So, can we make an alternative computation builder for which this kind of computation returns results?</p>
<h5>Fair streams</h5>
<p>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:</p>
<pre class="code"><span style="color: blue">type </span>Stream<'a> =
| Nil <span style="color: green">//empty
</span>| One <span style="color: blue">of </span>'a <span style="color: green">//one element
</span>| Choice <span style="color: blue">of </span>'a * Stream<'a> <span style="color: green">//one element, and maybe more
</span>| Incomplete <span style="color: blue">of </span>Lazy<Stream<'a>> <span style="color: green">//suspended stream
</span></pre>
<p> </p>
<p>Using this stream, we can code a fair choice function:</p>
<pre class="code"><span style="color: blue">let rec </span>choice r r' = <span style="color: green">
</span><span style="color: blue">match </span>r <span style="color: blue">with
</span>| Nil <span style="color: blue">-> </span>r' <span style="color: green">//first empty-> try the second
</span>| One a <span style="color: blue">-> </span>Choice (a,r') <span style="color: green">//Put in front of the new stream
</span>| Choice (a,rs) <span style="color: blue">-> </span>Choice (a,choice r' rs) <span style="color: green">//interleave r and r' here
</span>| Incomplete i <span style="color: blue">-></span><span style="color: green">
</span><span style="color: blue">match </span>r' <span style="color: blue">with
</span>| Nil <span style="color: blue">-> </span>r<span style="color: green">
</span>| One b <span style="color: blue">-> </span>Choice (b,r)<span style="color: green">
</span>| Choice (b,rs') <span style="color: blue">-> </span>Choice (b,choice r rs') <span style="color: green">
</span>| Incomplete j <span style="color: blue">-> </span>Incomplete (<span style="color: blue">lazy </span>(choice i.Value j.Value))</pre>
<p></p>
<p>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.</p>
<p>Bind is more straightforward:</p>
<pre class="code"><span style="color: blue">let rec </span>bind m f =
<span style="color: blue">match </span>m <span style="color: blue">with
</span>| Nil <span style="color: blue">-> </span>Nil
| One a <span style="color: blue">-> </span>(f a)
| Choice (a,r) <span style="color: blue">-> </span>choice (f a) (Incomplete (<span style="color: blue">lazy </span>bind r f))<span style="color: green">
</span>| Incomplete i <span style="color: blue">-> </span>Incomplete (<span style="color: blue">lazy </span>bind i.Value f)</pre>
<p>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.</p>
<p>We now have the important elements to make a computation builder:</p>
<pre class="code"><span style="color: blue">type </span>FairStream() =
<span style="color: blue">member </span>x.Return a = One a
<span style="color: blue">member </span>x.Yield a = One a
<span style="color: blue">member </span>x.Bind (m, f) = bind m f<span style="color: green">
</span><span style="color: blue">member </span>x.Zero() = Nil
<span style="color: blue">member </span>x.Combine (r,r') = choice r r'
<span style="color: blue">member </span>x.Delay (f:unit<span style="color: blue">-></span>Stream<_>) = Incomplete (Lazy.Create f)</pre>
<pre class="code">
<span style="color: blue">let </span>bt = FairStream()</pre>
<p></p>
<p>I called it bt, short for backtracking. Now we need a function to run our computation:</p>
<pre class="code"><span style="color: blue">let rec </span>run d st =
<span style="color: blue">match </span>(d,st) <span style="color: blue">with
</span>| _,Nil <span style="color: blue">-> </span>Seq.empty
| _,One a <span style="color: blue">-> </span>seq { <span style="color: blue">yield </span>a }
| _,Choice (a,r) <span style="color: blue">-> </span>seq { <span style="color: blue">yield </span>a; <span style="color: blue">yield! </span>run d r }
| Some 0,Incomplete i <span style="color: blue">-> </span>Seq.empty <span style="color: green">//exhausted depth
</span>| d,Incomplete (Lazy r) <span style="color: blue">-> let </span>d' = Option.map ((-) 1) d <span style="color: blue">in </span>run d' r</pre>
<p></p>
<p></p>
<a href="http://11011.net/software/vspaste"></a>
<p></p>
<p>The run function takes an optional parameter to bound the number of backtracking steps, which may be useful to help with termination.</p>
<h5>A few examples</h5>
<p>First, let’s define a stream of numbers [0,Infinity]:</p>
<pre class="code"><span style="color: blue">let rec </span>number() = bt { <span style="color: blue">yield </span>0
<span style="color: blue">let! </span>n = number() <span style="color: blue">in yield </span>n+1 }</pre>
<p><a href="http://11011.net/software/vspaste"></a>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 <em>left-recursive</em> function:</p>
<pre class="code"><span style="color: blue">let rec </span>number() = choice (bt { <span style="color: blue">let! </span>n = number() <span style="color: blue">in return </span>n+1 }) (bt {<span style="color: blue">return </span>0})</pre>
<p><a href="http://11011.net/software/vspaste"></a>Both number functions yield the same results.</p>
<p>Now for something a bit more spectacular. </p>
<pre class="code"><span style="color: blue">let </span>guard assertion =
bt { <span style="color: blue">if </span>assertion <span style="color: blue">then return </span>() }</pre>
<a href="http://11011.net/software/vspaste"></a>
<pre class="code"><span style="color: blue">let </span>pythagoreanTriples =
bt{ <span style="color: blue">let! </span>i = number()
<span style="color: blue">do! </span>guard (i > 0)<span style="color: green">
</span><span style="color: blue">let! </span>j = number()
<span style="color: blue">do! </span>guard (j > 0)
<span style="color: blue">let! </span>k = number()
<span style="color: blue">do! </span>guard (k > 0)
<span style="color: blue">do! </span>guard (i*i + j*j = k*k)
<span style="color: blue">return </span>(i,j,k) }</pre>
<a href="http://11011.net/software/vspaste"></a>
<p>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.</p>
<p>The discerning reader might wonder why we can’t write:</p>
<pre class="code"><span style="color: blue">let rec </span>number() =
bt { <span style="color: blue">let! </span>n = number() <span style="color: blue">in return </span>n+1
<span style="color: blue">return </span>0 }</pre>
<p><a href="http://11011.net/software/vspaste"></a>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 <a href="http://okmij.org/ftp/papers/LogicT.pdf">Backtracking, Interleaving, and Terminating Monad Transformers</a> by Kiselyov et al…</p>
<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">Technorati: <a href="http://technorati.com/tags/F%23" rel="tag">F#</a>,<a href="http://technorati.com/tags/computation+builder" rel="tag">computation builder</a>,<a href="http://technorati.com/tags/backtracking" rel="tag">backtracking</a>,<a href="http://technorati.com/tags/monads" rel="tag">monads</a></div>
<span class="sbmLink">
<table cellspacing="1" cellpadding="1"><tbody>
<tr>
<td class="sbmText">Share this post : </td>
<td><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&ttl=Simple and Fair Backtracking Computations" target="_blank"><img border="0" src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" />Technet!</a></td>
<td><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&;title=Simple and Fair Backtracking Computations" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" />del.icio.us it!</a></td>
<td><a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&address=http://fortysix-and-two.blogspot.com/2009/09/simple-and-fair-backtracking.html&title=Simple and Fair Backtracking Computations" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" />del.iri.ous!</a></td>
<td><a title="Post it to digg" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2009/09/simple-and-fair-backtracking.html&title=Simple and Fair Backtracking Computations" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" />digg it!</a></td>
<td><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&title=Simple and Fair Backtracking Computations" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" />dotnetkicks it!</a></td>
<td><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&title=Simple and Fair Backtracking Computations" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" />reddit!</a></td>
<td><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&title=Simple and Fair Backtracking Computations" target="_blank"><img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" />technorati!</a></td>
</tr>
</tbody></table>
</span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com2tag:blogger.com,1999:blog-4129300230262819780.post-81685187521598057422009-06-27T12:32:00.000+01:002009-06-27T12:34:48.491+01:00More fun with data structures, continuations and call/cc<p><a href="http://fortysix-and-two.blogspot.com/2009/06/fun-with-data-structures-continuations.html">Last time</a> 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:</p> <pre class="code"><span style="color: blue">let </span>insertExc x t =
<span style="color: blue">try
let rec </span>insertRec x t =
<span style="color: blue">match </span>t <span style="color: blue">with
</span>| Empty <span style="color: blue">-> </span>cont { <span style="color: blue">return </span>Elem(empty,x,empty) }
| Elem (left,e,right) <span style="color: blue">when </span>x < e <span style="color: blue">->
</span>cont { <span style="color: blue">let! </span>t' = insertRec x left
<span style="color: blue">return </span>Elem(t',e,right) }
| Elem (left,e,right) <span style="color: blue">when </span>x > e <span style="color: blue">->
</span>cont { <span style="color: blue">let! </span>t' = insertRec x right
<span style="color: blue">return </span>Elem(left,e,t') }
| Elem _ <span style="color: blue">-> </span>failwith <span style="color: maroon">"alreadyExists"
</span>insertRec x t id
<span style="color: blue">with </span>e –<span style="color: blue">> </span>t</pre>
<h4></h4>
<a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>
<h4>Performance shootout</h4>
<p>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:</p>
<pre class="code"><span style="color: blue">let </span>longList =
<span style="color: blue">let </span>r = <span style="color: blue">new </span>System.Random()
<span style="color: blue">let </span>l = 100000
[ <span style="color: blue">for </span>i <span style="color: blue">in </span>1..l <span style="color: blue">-> </span>r.Next(0,l) ]
<span style="color: blue">let </span>insertALot f nbRuns =
<span style="color: blue">for </span>i <span style="color: blue">in </span>1..nbRuns <span style="color: blue">do
</span>longList |> List.fold (<span style="color: blue">fun </span>t elem <span style="color: blue">-> </span>f elem t) empty</pre>
<p>How many duplicates are in the long list (i.e. how much can we expect to gain by using callCC/exceptions):</p>
<pre class="code">> longList |> Seq.distinct |> Seq.length;;
val it : int = 63362</pre>
<a href="http://11011.net/software/vspaste"></a>So about 35% duplicates. The results:
<pre>> insertALot insert 100;;
Real: 00:01:38.717, CPU: 00:01:37.516, GC gen0: 2247, gen1: 520, gen2: 8
val it : unit = ()
> insertALot insert' 100;;
Real: 00:01:44.583, CPU: 00:01:37.251, GC gen0: 4050, gen1: 1444, gen2: 18
val it : unit = ()
> insertALot insertM 100;;
Real: 00:02:35.101, CPU: 00:02:29.792, GC gen0: 12698, gen1: 1875, gen2: 24
val it : unit = ()
> insertALot insertCallCC 100;;
Real: 00:01:09.410, CPU: 00:01:02.540, GC gen0: 12149, gen1: 7, gen2: 0
val it : unit = ()
> insertALot insertExc 100;;
- Interrupt</pre>
<p>Observe that:</p>
<ul>
<li>the readability of computation expressions comes with a cost;</li>
<li>even with that cost, the callCC code is still significantly faster;</li>
<li>Exceptions are indeed horribly slow – I interrupted after about an hour.</li>
</ul>
<span class="sbmLink">
<table cellspacing="1" cellpadding="1"><tbody>
<tr>
<td class="sbmText">Share this post : </td>
<td><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&ttl=Mire fun with data structures, continuations and call/cc" target="_blank"><img src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" border="0" />Technet!</a></td>
<td><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&;title=Mire fun with data structures, continuations and call/cc" target="_blank"><img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" border="0" />del.icio.us it!</a></td>
<td><a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&address=http://fortysix-and-two.blogspot.com/2009/06/more-fun-with-data-structures.html&title=Mire fun with data structures, continuations and call/cc" target="_blank"><img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" border="0" />del.iri.ous!</a></td>
<td><a title="Post it to digg" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2009/06/more-fun-with-data-structures.html&title=Mire fun with data structures, continuations and call/cc" target="_blank"><img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" border="0" />digg it!</a></td>
<td><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&title=Mire fun with data structures, continuations and call/cc" target="_blank"><img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" border="0" />dotnetkicks it!</a></td>
<td><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&title=Mire fun with data structures, continuations and call/cc" target="_blank"><img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" border="0" />reddit!</a></td>
<td><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&title=Mire fun with data structures, continuations and call/cc" target="_blank"><img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" border="0" />technorati!</a></td>
</tr>
</tbody></table>
</span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com0tag:blogger.com,1999:blog-4129300230262819780.post-31582122432242044902009-06-24T21:00:00.000+01:002009-06-24T21:12:55.107+01:00Fun with data structures, continuations and call/cc<p>Prompted by exercise 2.3 in <a href="http://www.amazon.com/Purely-Functional-Structures-Chris-Okasaki/dp/0521663504">Purely Functional Data Structures</a>, by Chris Okasaki.</p> <pre class="code"><span style="color: blue">type </span>Tree<'a> = Empty | Elem <span style="color: blue">of </span>'a Tree * 'a * 'a Tree
<span style="color: blue">let </span>empty = Empty</pre>
<a href="http://11011.net/software/vspaste"></a>
<h5>Recursive</h5>
<pre class="code"><span style="color: blue">let rec </span>insert x t =
<span style="color: blue">match </span>t <span style="color: blue">with
</span>| Empty <span style="color: blue">-> </span>Elem(empty,x,empty)
| Elem (left,e,right) <span style="color: blue">when </span>x < e <span style="color: blue">-> </span>Elem (insert x left,e,right)
| Elem (left,e,right) <span style="color: blue">when </span>x > e <span style="color: blue">-> </span>Elem (left,e, insert x right)
| Elem _ –<span style="color: blue">> </span>t</pre>
<h5>Tail Recursive</h5>
<pre class="code"><span style="color: blue">let </span>insert' x t =
<span style="color: blue">let rec </span>cont x t k =
<span style="color: blue">match </span>t <span style="color: blue">with
</span>| Empty <span style="color: blue">-> </span>k (Elem(empty,x,empty))
| Elem (left,e,right) <span style="color: blue">when </span>x < e <span style="color: blue">-> </span>cont x left (<span style="color: blue">fun </span>t' <span style="color: blue">-> </span>k <| Elem (t',e,right))
| Elem (left,e,right) <span style="color: blue">when </span>x > e <span style="color: blue">-> </span>cont x right (<span style="color: blue">fun </span>t' <span style="color: blue">-> </span>k <| Elem (left,e,t'))
| Elem _ <span style="color: blue">-> </span>k t
cont x t id</pre>
<h5>Using a continuation monad</h5>
<pre class="code"><span style="color: blue">type </span>Cont<'a,'r> = ('a <span style="color: blue">-> </span>'r) <span style="color: blue">-> </span>'r
<span style="color: blue">type </span>ContBuilder() =
<span style="color: blue">member </span>x.Return (a):Cont<'a,'r> = <span style="color: blue">fun </span>k <span style="color: blue">-> </span>k a
<span style="color: blue">member </span>x.Bind (c:Cont<'a,'r>, f:'a <span style="color: blue">-> </span>Cont<'b,_>) =
(<span style="color: blue">fun </span>k <span style="color: blue">-> </span>c (<span style="color: blue">fun </span>a <span style="color: blue">-> </span>f a k))
<span style="color: blue">member </span>this.Delay(f) = f()
<span style="color: blue">let </span>cont = ContBuilder()</pre>
<a href="http://11011.net/software/vspaste"></a>
<pre class="code"><span style="color: blue">let </span>insertM x t =
<span style="color: blue">let rec </span>insertRecM x t =
<span style="color: blue">match </span>t <span style="color: blue">with
</span>| Empty <span style="color: blue">-> </span>cont { <span style="color: blue">return </span>Elem(empty,x,empty) }
| Elem (left,e,right) <span style="color: blue">when </span>x < e <span style="color: blue">->
</span>cont { <span style="color: blue">let! </span>t' = insertRecM x left
<span style="color: blue">return </span>Elem(t',e,right) }
| Elem (left,e,right) <span style="color: blue">when </span>x > e <span style="color: blue">->
</span>cont { <span style="color: blue">let! </span>t' = insertRecM x right
<span style="color: blue">return </span>Elem(left,e,t') }
| Elem _ <span style="color: blue">-> </span>cont { <span style="color: blue">return </span>t }
insertRecM x t id</pre>
<a href="http://11011.net/software/vspaste"></a>
<h5>Using call with current continuation</h5>
<pre class="code"><span style="color: blue">let </span>callCC (f:('a <span style="color: blue">-> </span>Cont<'b,'r>) <span style="color: blue">-> </span>Cont<'a,'r>) : Cont<'a,'r> = <span style="color: blue">fun </span>k <span style="color: blue">-> </span>f (<span style="color: blue">fun </span>a _ <span style="color: blue">-> </span>k a) k</pre>
<a href="http://11011.net/software/vspaste"></a>
<pre class="code"><span style="color: blue">let </span>insertCallCC x t =
callCC (<span style="color: blue">fun </span>alreadyExists <span style="color: blue">->
let rec </span>insertRecCallCC x t =
<span style="color: blue">match </span>t <span style="color: blue">with
</span>| Empty <span style="color: blue">-> </span>cont { <span style="color: blue">return </span>Elem(empty,x,empty) }
| Elem (left,e,right) <span style="color: blue">when </span>x < e <span style="color: blue">->
</span>cont { <span style="color: blue">let! </span>t' = insertRecCallCC x left
<span style="color: blue">return </span>Elem(t',e,right) }
| Elem (left,e,right) <span style="color: blue">when </span>x > e <span style="color: blue">->
</span>cont { <span style="color: blue">let! </span>t' = insertRecCallCC x right
<span style="color: blue">return </span>Elem(left,e,t') }
| Elem _ <span style="color: blue">-> </span>alreadyExists t
insertRecCallCC x t
) id</pre>
<a href="http://11011.net/software/vspaste"></a>
<p>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).</p>
<span class="sbmLink">
<table cellspacing="1" cellpadding="1"><tbody>
<tr>
<td class="sbmText">Share this post : </td>
<td><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&ttl=Fun with data structures, continuations and call/cc" target="_blank"><img src="http://www.dotnetscraps.com/dotnetscraps/samples/sbmtool/technet.png" border="0" />Technet!</a></td>
<td><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&;title=Fun with data structures, continuations and call/cc" target="_blank"><img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" border="0" />del.icio.us it!</a></td>
<td><a title="Post it to del.iri.ous!" href="http://de.lirio.us/bookmarks/sbmtool?action=add&address=http://fortysix-and-two.blogspot.com/2009/06/fun-with-data-structures-continuations.html&title=Fun with data structures, continuations and call/cc" target="_blank"><img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliriou4.png" border="0" />del.iri.ous!</a></td>
<td><a title="Post it to digg" href="http://digg.com/submit?phase=2&url=http://fortysix-and-two.blogspot.com/2009/06/fun-with-data-structures-continuations.html&title=Fun with data structures, continuations and call/cc" target="_blank"><img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" border="0" />digg it!</a></td>
<td><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&title=Fun with data structures, continuations and call/cc" target="_blank"><img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" border="0" />dotnetkicks it!</a></td>
<td><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&title=Fun with data structures, continuations and call/cc" target="_blank"><img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" border="0" />reddit!</a></td>
<td><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&title=Fun with data structures, continuations and call/cc" target="_blank"><img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" border="0" />technorati!</a></td>
</tr>
</tbody></table>
</span> Kurt Schelfthouthttp://www.blogger.com/profile/15625144753735495725noreply@blogger.com2