<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss version="2.0">
  <channel>
    <title>Planet F#</title>
    <description>Planet F#</description>
    <link>http://babelnova.net/planet</link>
    <docs>http://backend.userland.com/rss</docs>
    <generator>RSS.NET: http://www.rssdotnet.com/</generator>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/planet_fsharp" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
      <title>F# Discoveries This Week 11/09/2009</title>
      <description>&lt;p&gt;As momentum builds for the F# release with Visual Studio 2010, so too does the number of people blogging about the language.&amp;#160; This week we have a spec update, clarified comparisons, decision trees, porting gotchas and in depth explorations of the debug IL generated by F#.&amp;#160; Please do enjoy.&lt;/p&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;h3&gt;&lt;a rel="nofollow" target="_blank" href="https://www.clicktoattend.com/invitation.aspx?code=142886"&gt;Speaking on F# at the Connecticut .NET Developer’s Group&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;Tomorrow (Tuesday November 10th, 2009) I’ll be speaking on F# at the &lt;/em&gt;&lt;a rel="nofollow" target="_blank" href="http://ctdotnet.org/default.aspx"&gt;&lt;em&gt;Connecticut .NET Developer’s group&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&amp;#160; For more information check out the &lt;/em&gt;&lt;a rel="nofollow" target="_blank" href="https://www.clicktoattend.com/invitation.aspx?code=142886"&gt;&lt;em&gt;ClickToAttend event&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;h3&gt;&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/dsyme/archive/2009/11/04/f-1-9-7-language-specification-now-available.aspx"&gt;From Don Syme’s Blog - F# Spec Updated for the 1.9.7 Release&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;Many thanks to all those who sent so much helpful feedback on the specification during Beta1. And for those using 1.9.7 already, thanks for your patience in the last couple of weeks - it took us a little longer to get this out the door than we had planned, since a development deadline for Visual Studio 2010 intervened.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;h3&gt;&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/dsyme/archive/2009/11/08/equality-and-comparison-constraints-in-f-1-9-7.aspx"&gt;Don Syme’s Equality and Comparison Constraints in F#&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;F# 1.9.7 introduces two new constraints to the F# language to help uncover issues in your code when using equality and comparison operators. In this blog entry we'll take a look at these constraints in a bit more detail. &lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;The F# team has inherited quite a mess in terms of the lack of any kind of concrete definition of equality in the .NET framework.&amp;#160; It seems that they’ve been able to do much with it though.&lt;/p&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;h3&gt;Chris Smith’s Decision Trees &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/chrsmith/archive/2009/10/31/awesome-f-decision-trees-part-i.aspx"&gt;Part 1&lt;/a&gt; and &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/chrsmith/archive/2009/11/02/awesome-f-decision-trees-part-ii.aspx"&gt;Part 2&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;Now that we got all that painful math out of the way, let’s write some code! Here is an implementation of the algorithm in F#.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;I’m just dying to see this extended to Bayesian network.&amp;#160; Perhaps I’ll try and extend it myself.&lt;/p&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;h3&gt;&lt;a rel="nofollow" target="_blank" href="http://community.bartdesmet.net/blogs/bart/archive/2009/11/08/jumping-the-trampoline-in-c-stack-friendly-recursion.aspx"&gt;Bart De Smet’s Stack-Friendly Recursion&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;Recursion is a widely known technique to decompose a problem in smaller “instances” of the same problem. For example, performing tree operations (e.g. in the context of data structures, user interfaces, hierarchical stores, XML, etc) can be expressed in terms of a navigation strategy over the tree where one performs the same operation to subtrees.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;A detailed look at tail recursion optimization in F# and how to achieve something similar in C#.&lt;/p&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;h3&gt;&lt;a rel="nofollow" target="_blank" href="http://stackoverflow.com/questions/142985/is-a-program-f-any-more-efficient-execution-wise-than-c"&gt;On StackOverflow, is a program F# any more efficient (execution-wise) than C#?&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;I'm guessing that it is not because they both boil down to the same IL.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;It turns out that F# is in fact much faster in some cases.&amp;#160; For more on F# performance see &lt;a rel="nofollow" target="_blank" href="http://stackoverflow.com/questions/144227/c-f-performance-comparison"&gt;this roundup post&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;h3&gt;Steve Gilham’s F# under the covers parts &lt;a rel="nofollow" target="_blank" href="http://stevegilham.blogspot.com/2009/09/f-algebraic-types-under-covers.html"&gt;1&lt;/a&gt;, &lt;a rel="nofollow" target="_blank" href="http://stevegilham.blogspot.com/2009/09/more-f-under-covers.html"&gt;2&lt;/a&gt;, &lt;a rel="nofollow" target="_blank" href="http://stevegilham.blogspot.com/2009/09/f-under-covers-iii.html"&gt;3&lt;/a&gt;, &lt;a rel="nofollow" target="_blank" href="http://stevegilham.blogspot.com/2009/09/f-under-covers-iv-fxcop-noise.html"&gt;4&lt;/a&gt;, &lt;a rel="nofollow" target="_blank" href="http://stevegilham.blogspot.com/2009/09/f-under-covers-v.html"&gt;5&lt;/a&gt;, &lt;a rel="nofollow" target="_blank" href="http://stevegilham.blogspot.com/2009/10/f-under-covers-vi.html"&gt;6&lt;/a&gt;, and &lt;a rel="nofollow" target="_blank" href="http://stevegilham.blogspot.com/2009/11/f-under-covers-viii.html"&gt;8&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; &lt;p align="left"&gt;&lt;em&gt;I'm in the tidying up stages for the little project I've been working on lately, a set of FxCop rules, mainly aimed at providing some complementary features for nCover-style code coverage, including static analysis for trivial methods -- or compiler generated ones.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;In this series Steve takes a very careful approach to exploring the IL generated by the F# compiler in debug mode. &lt;/p&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;h3&gt;&lt;a rel="nofollow" target="_blank" href="http://www.mattssoftwareblog.com/?p=200"&gt;Matt Moloney’s Lessons Learned in Porting [from] C# to F# (WPF)&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;I encountered a ton of difficulties while porting code from C# to F#. Fortunately / unfortunately, so have many other people. Thankfully they took the time to write about these problems so my solutions were often only a quick search away. Here is a collection of some of the finds that were able to help me in my endeavors.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;An excellent post well worth reading for anyone getting ready to port to F#.&lt;/p&gt;
&lt;div class="shareblock"&gt;&lt;strong&gt;Share this post:&lt;/strong&gt; &lt;a rel="nofollow" target="_blank" href="mailto:?body=Thought you might like this: http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/09/f-discoveries-this-week-11-09-2009.aspx&amp;amp;;subject=F%23+Discoveries+This+Week+11%2f09%2f2009" title="Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/09/f-discoveries-this-week-11-09-2009.aspx"&gt;email it!&lt;/a&gt; | &lt;a rel="nofollow" target="_blank" href="http://del.icio.us/post?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/09/f-discoveries-this-week-11-09-2009.aspx&amp;amp;;title=F%23+Discoveries+This+Week+11%2f09%2f2009" title="Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/09/f-discoveries-this-week-11-09-2009.aspx"&gt;bookmark it!&lt;/a&gt; | &lt;a rel="nofollow" target="_blank" href="http://www.digg.com/submit?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/09/f-discoveries-this-week-11-09-2009.aspx&amp;amp;;phase=2" title="Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/09/f-discoveries-this-week-11-09-2009.aspx"&gt;digg it!&lt;/a&gt; | &lt;a rel="nofollow" target="_blank" href="http://reddit.com/submit?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/09/f-discoveries-this-week-11-09-2009.aspx&amp;amp;title=F%23+Discoveries+This+Week+11%2f09%2f2009" title="Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/09/f-discoveries-this-week-11-09-2009.aspx"&gt;reddit!&lt;/a&gt; | &lt;a rel="nofollow" target="_blank" href="http://www.dotnetkicks.com/submit/?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/09/f-discoveries-this-week-11-09-2009.aspx&amp;amp;;title=F%23+Discoveries+This+Week+11%2f09%2f2009" title="Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/09/f-discoveries-this-week-11-09-2009.aspx"&gt;kick it!&lt;/a&gt; | &lt;a rel="nofollow" target="_blank" href="https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;;mkt=en-us&amp;amp;;url=http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/09/f-discoveries-this-week-11-09-2009.aspx&amp;amp;;title=F%23+Discoveries+This+Week+11%2f09%2f2009&amp;amp;;top=1" title="Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/09/f-discoveries-this-week-11-09-2009.aspx"&gt;live it!&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.atalasoft.com/cs/aggbug.aspx?PostID=19686" width="1" height="1"&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257783899"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257783899" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/XEc-WyGnSEH1JV71E6l-1T3SU4w/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XEc-WyGnSEH1JV71E6l-1T3SU4w/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/XEc-WyGnSEH1JV71E6l-1T3SU4w/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XEc-WyGnSEH1JV71E6l-1T3SU4w/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=MpCjI_Al4vM:zif0JCSxEW8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=MpCjI_Al4vM:zif0JCSxEW8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=MpCjI_Al4vM:zif0JCSxEW8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=MpCjI_Al4vM:zif0JCSxEW8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=MpCjI_Al4vM:zif0JCSxEW8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=MpCjI_Al4vM:zif0JCSxEW8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=MpCjI_Al4vM:zif0JCSxEW8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/MpCjI_Al4vM" height="1" width="1"/&gt;</description>
      <link>http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/09/f-discoveries-this-week-11-09-2009.aspx</link>
      <pubDate>Mon, 09 Nov 2009 08:24:59 GMT</pubDate>
    </item>
    <item>
      <title>Lessons learned in porting C# to F# (WPF)</title>
      <description>&lt;p&gt;I encountered a ton of difficulties while porting code from C# to F#. Fortunately / unfortunately, so have many other people. Thankfully they took the time to write about these problems so my solutions were often only a quick search away. Here is a collection of some of the finds that were able to help me in my endeavors.&lt;/p&gt;
&lt;p&gt;I have done my best to attribute sources, and as always feedback is very much appreciated. Also, I will be updating my code viewer as soon as possible to stop it from embedding html smiley faces.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-200"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Data Templates&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Unfortunately the only way to build Data Templates in code is being deprecated, which means we have to resort to writing Data Templates in XAML as a string. This string is then loaded using XamlReader as per the following code.&lt;/p&gt;
&lt;pre&gt;
let loadFromString xaml = use sr = new StringReader(xaml) use xr = XmlReader.Create(sr) XamlReader.Load xr
&lt;/pre&gt;
&lt;p&gt;Steve Horsfeild has a good write up on this &lt;a rel="nofollow" target="_blank" href="http://stevehorsfield.wordpress.com/2009/08/26/example-programmatic-addition-of-wpf-data-template/"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Attached Dependency Properties&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For ages I tried to figure out why my attached properties were not showing up in the XAML intellisense. It turns out that I was missing the Get and Set functions for the property, as per below;&lt;/p&gt;
&lt;pre&gt; static let useHoverProperty = DependencyProperty.RegisterAttached( "UseHover", typeof&amp;lt;bool&amp;gt;, typeof&amp;lt;HoverInteractor&amp;gt;) static member public SetUseHover(d:DependencyObject, _use:bool) = d.SetValue(useHoverProperty, _use) static member public GetUseHover(d:DependencyObject) = d.GetValue(useHoverProperty) &lt;img src='http://www.mattssoftwareblog.com/wp-includes/images/smilies/icon_confused.gif' alt=':?' class='wp-smiley'/&gt; &amp;gt; bool
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;3. Using options instead of Null&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I use this when a attribute is begin set at runtime and I know that no function will call the attribute until after it has been set. (from &lt;a rel="nofollow" target="_blank" href="http://cs.hubfs.net/forums/thread/7729.aspx"&gt;here&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&amp;#8220;Nullable&amp;#8221; member&lt;/p&gt;
&lt;pre&gt; static let mutable draggedElt = None static member private DraggedElt with get() = match draggedElt with | Some(v) -&amp;gt; v | _ -&amp;gt; failwith "initialization fail" and set(x:UIElement) = draggedElt &amp;lt;- Some(x)
&lt;/pre&gt;
&lt;p&gt;Check for &amp;#8220;null&amp;#8221;:&lt;/p&gt;
&lt;pre&gt;
match scrollOwner with
| Some(v) -&amp;gt; v.InvalidateScrollInfo()
| None -&amp;gt; ()
&lt;/pre&gt;
&lt;p&gt;From &lt;a rel="nofollow" target="_blank" href="http://cs.hubfs.net/forums/thread/7729.aspx"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Removing event handlers&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;
let rec eventHandler = EventHandler(fun o e -&amp;gt; // Hide the Viewport this.viewport.Visibility &amp;lt;- Visibility.Hidden Panel.SetZIndex(this.backChildContainer, 0) // Show the FrontChild this.frontChildContainer.Visibility &amp;lt;- Visibility.Visible dockAnim.Completed.RemoveHandler(eventHandler) )
&lt;/pre&gt;
&lt;p&gt;However, sometimes you can&amp;#8217;t keep a reference to the delegate instance. Fortunately you don&amp;#8217;t have to. The following code works as the object passed into Remove() must match the associated signature, but not necessarily the actual delegate instance you wish to remove. (Apress: Pro C# 2008 and the .Net 3.5 Platform)&lt;/p&gt;
&lt;pre&gt; override this.StartListening(source:obj) = let evtSource = source &lt;img src='http://www.mattssoftwareblog.com/wp-includes/images/smilies/icon_confused.gif' alt=':?' class='wp-smiley'/&gt; &amp;gt; DataSource evtSource.DataChanged.AddHandler(Handler&amp;lt;EventArgs&amp;gt;(this.PrivateOnDataChanged)) override this.StopListening(source:obj) = let evtSource = source &lt;img src='http://www.mattssoftwareblog.com/wp-includes/images/smilies/icon_confused.gif' alt=':?' class='wp-smiley'/&gt; &amp;gt; DataSource evtSource.DataChanged.RemoveHandler(Handler&amp;lt;EventArgs&amp;gt;(this.PrivateOnDataChanged))
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;4. Property changed events&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is pretty straight forward (from &lt;a rel="nofollow" target="_blank" href="http://www.voyce.com/index.php/2009/03/02/implementing-inotifypropertychanged-with-fsharp/"&gt;here&lt;/a&gt;)&lt;/p&gt;
&lt;pre&gt;
let propertyChanged = Event&amp;lt;_,_&amp;gt;()
let notify obj s = propertyChanged.Trigger(obj, PropertyChangedEventArgs(s)) interface INotifyPropertyChanged with [&amp;lt;CLIEvent&amp;gt;] member this.PropertyChanged = propertyChanged.Publish
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;6. Runtime casting: &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The following is the equivilent for using as (C# keyword), and then checking for Null. (from &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/dd233220(VS.100).aspx"&gt;here&lt;/a&gt;)&lt;/p&gt;
&lt;pre&gt; match b1 with | &lt;img src='http://www.mattssoftwareblog.com/wp-includes/images/smilies/icon_confused.gif' alt=':?' class='wp-smiley'/&gt; Derived1 as derived1 -&amp;gt; derived1.F() | _ -&amp;gt; ()
&lt;/pre&gt;
&lt;p&gt;Other bits and pieces;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Accessing members in interfaces. It is a little odd but you have to cast the object to the interface type before you can call on the interface member: &amp;#8220;(mark :&amp;gt; CouchDBDocument).DocType&amp;#8221; (from &lt;a rel="nofollow" target="_blank" href="http://www.markhneedham.com/blog/2009/06/07/f-explicit-interface-implementation"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Pass ‘by ref’ into a function can be done by using the prefix ‘&amp;amp;” operator on a mutable (from &lt;a rel="nofollow" target="_blank" href="http://www.sturmnet.org/blog/2008/05/16/oddities-in-fc-interaction"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;
let mutable x = 1
if d.TryGetValue("foo", &amp;amp;amp;x) then... &lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;PropertyPath wouldn’t work with a string, it requires the actual property &amp;#8220;PropertyPath(UIElement.OpacityProperty)&amp;#8221; (from &lt;a rel="nofollow" target="_blank" href="http://jyliao.blogspot.com/2009/03/silverlight-with-f-background-thread.html"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257751797"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257751797" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/vUNtu-3dan-s3BjQ73zhnxTDn2Q/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vUNtu-3dan-s3BjQ73zhnxTDn2Q/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/vUNtu-3dan-s3BjQ73zhnxTDn2Q/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vUNtu-3dan-s3BjQ73zhnxTDn2Q/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=2BpVghGhANU:NpYL1Q5QSlA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=2BpVghGhANU:NpYL1Q5QSlA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=2BpVghGhANU:NpYL1Q5QSlA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=2BpVghGhANU:NpYL1Q5QSlA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=2BpVghGhANU:NpYL1Q5QSlA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=2BpVghGhANU:NpYL1Q5QSlA:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=2BpVghGhANU:NpYL1Q5QSlA:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/2BpVghGhANU" height="1" width="1"/&gt;</description>
      <link>http://www.mattssoftwareblog.com/?p=200</link>
      <pubDate>Sun, 08 Nov 2009 23:29:57 GMT</pubDate>
    </item>
    <item>
      <title>Motivating F# equality and comparison constraints</title>
      <description>&lt;p&gt;(I will return to the RSS Dashboard series soon; I needed to do this aside now to be timely.)&lt;/p&gt; &lt;p&gt;Don has just posted a great &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/dsyme/archive/2009/11/08/equality-and-comparison-constraints-in-f-1-9-7.aspx"&gt;blog entry&lt;/a&gt; describing the details of the equality and comparison constraints in the latest release of F#. I would like to take a moment to describe the higher-level view to motivate the feature. By reading this blog entry, the reader should learn&lt;/p&gt; &lt;ul&gt; &lt;li&gt;what structural equality and comparison are &lt;li&gt;what is the problem that F# equality/comparison constraints solve &lt;li&gt;why this problem cannot be solved without a specific language feature &lt;li&gt;when does a programmer need to care about this &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;If you want to know the details of the F# language feature and how to exercise fine control and specification of equality/comparison on your user-defined types, then you should go read &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/dsyme/archive/2009/11/08/equality-and-comparison-constraints-in-f-1-9-7.aspx"&gt;Don’s post&lt;/a&gt;. On the other hand, if you want an overview and more examples about the ‘why’, hopefully this blog entry will give you what you need. Some readers might find this blog entry is a useful ‘prequel’ to Don’s.&lt;/p&gt; &lt;p&gt;So let’s get started!&lt;/p&gt; &lt;h3&gt;What are structural equality and comparison?&lt;/h3&gt; &lt;p&gt;Consider this short code example:&lt;/p&gt;&lt;pre&gt;&lt;span style="color:blue;"&gt;let &lt;/span&gt;il1 : int list = [ 1; 2; 3 ]
&lt;span style="color:blue;"&gt;let &lt;/span&gt;il2 : int list = [ 2; 3; 1 ]
printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(il1 = il2) &lt;span style="color:green;"&gt;
&lt;/span&gt;printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(il1 &amp;lt; il2) &lt;/pre&gt;
&lt;p&gt;What would this print? If you said “false” and “true”, then you already have a good sense of structural equality and comparison. But let’s go through it in more detail.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Structural equality&lt;/em&gt; means that for &lt;em&gt;F# structural types&lt;/em&gt; (e.g. tuples, arrays, lists, options, records, and unions), we can get a default behavior for ‘equals’ that compares each individual element of the structure for equality. That is, one ‘int list’ is equal to another ‘int list’ if both lists have the same length and each of their individual elements are equal. (Contrast this to the default behavior of the .Equals() method of a class type, which defaults to reference equality.) Structural equality is commonly the semantic the author of a type would want anyway, and in F#, you can get semantic “for free” on any structural type. In my experience, most people have a good intuition for what structural equality means and see its utility. (Technical aside: “structural equality” applies to both the .Equals() and the .GetHashCode() methods of a type, as well as the F# (=) operator and “hash” function.)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Structural comparison &lt;/em&gt;is analogous to structural equality, except that it applies to the comparison operators (&amp;lt;, &amp;lt;=, &amp;gt;, &amp;gt;=, whose behavior involves calls to System.IComparable.CompareTo()). For some people, the behavior here is less intuitive – what does it mean to compare two integer lists with the less-than operator? To explain this, I appeal to a more familiar domain: dictionary order on strings. If I ask you what order the words “bad”, “ace”, “ad”, and “a” appear in the dictionary, I bet you could tell me. Thus you are probably not too surprised by the behavior of this F# code:&lt;/p&gt;&lt;pre&gt;&lt;span style="color:blue;"&gt;let &lt;/span&gt;words = [| &lt;span style="color:#a31515;"&gt;"bad"&lt;/span&gt;; &lt;span style="color:#a31515;"&gt;"ace"&lt;/span&gt;; &lt;span style="color:#a31515;"&gt;"ad"&lt;/span&gt;; &lt;span style="color:#a31515;"&gt;"a" &lt;/span&gt;|]
printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(Array.sort words)
&lt;span style="color:green;"&gt;// [|"a"; "ace"; "ad"; "bad"|]&lt;/span&gt;&lt;/pre&gt;&lt;a rel="nofollow" target="_blank" href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Dictionary order, sometimes called &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Lexicographic_order"&gt;lexicographical order&lt;/a&gt;, is a useful semantic for structural types. (Aside: you may recall that I relied on structural comparison in a &lt;a rel="nofollow" target="_blank" href="http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!548.entry"&gt;previous blog entry&lt;/a&gt; to get an automatic ordering of poker HandValuations.) With the previous code example in mind, I hope it is now less surprising how this F# code behaves:&lt;/p&gt;&lt;pre&gt;&lt;span style="color:blue;"&gt;let &lt;/span&gt;intLists = [| [2;1;4]; [1;3;5]; [1;4]; [1] |]
printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(Array.sort intLists)
&lt;span style="color:green;"&gt;// [|[1]; [1; 3; 5]; [1; 4]; [2; 1; 4]|]&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;All I did was change from strings, which ‘structurally’ are just lists of characters, to lists of integers (in this example, substituting a=1, b=2, …). &lt;/p&gt;
&lt;p&gt;So for example [1;2]&amp;lt;[2;1] because we can compare the first element and immediately see a difference, whereas [1;2]&amp;lt;[1;3] because we compare the first element and they are equal, so we move on to the next element until we find a difference. This same logic applies to other structural types, like tuples: (1,”bbb”)&amp;lt;(2,”aaa”) and (1,”aaa”)&amp;lt;(1,”bbb”); records: {field1=1;field2=”aaa”}&amp;lt;{field1=1;field2=”bbb”}; etc.&lt;/p&gt;
&lt;p&gt;To sum up then, structural equality and comparison define the most natural semantic for operations like (=) and (&amp;lt;) on structural types. In F#, you can get these semantic “for free” by default on structural types. (You can also opt out of these defaults, or choose to define your own equality/comparison behavior; for details see &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/dsyme/archive/2009/11/08/equality-and-comparison-constraints-in-f-1-9-7.aspx"&gt;Don’s post&lt;/a&gt;.) &lt;/p&gt;
&lt;p&gt;Now that we know what “structural equality” and “structural comparison” &lt;em&gt;mean&lt;/em&gt;, we can move on to…&lt;/p&gt;
&lt;h3&gt;What problem do F# equality/comparison constraints solve?&lt;/h3&gt;
&lt;p&gt;In the previous section, we learned about this behavior for lists of integers:&lt;/p&gt;&lt;pre&gt;&lt;span style="color:blue;"&gt;let &lt;/span&gt;il1 : int list = [ 1; 2; 3 ]
&lt;span style="color:blue;"&gt;let &lt;/span&gt;il2 : int list = [ 2; 3; 1 ]
printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(il1 = il2) &lt;span style="color:green;"&gt;// false
&lt;/span&gt;printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(il1 &amp;lt; il2) &lt;span style="color:green;"&gt;// true&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Now consider a couple more cases for lists of various types. What is the ideal behavior of equality/comparison on (Windows Forms) Controls?&lt;/p&gt;&lt;pre&gt;&lt;span style="color:blue;"&gt;open &lt;/span&gt;System.Windows.Forms &lt;span style="color:blue;"&gt;let &lt;/span&gt;cl1 : Control list = [ &lt;span style="color:blue;"&gt;new &lt;/span&gt;TextBox(); &lt;span style="color:blue;"&gt;new &lt;/span&gt;Button(); &lt;span style="color:blue;"&gt;new &lt;/span&gt;CheckBox() ]
&lt;span style="color:blue;"&gt;let &lt;/span&gt;cl2 : Control list = [ &lt;span style="color:blue;"&gt;new &lt;/span&gt;Button(); &lt;span style="color:blue;"&gt;new &lt;/span&gt;CheckBox(); &lt;span style="color:blue;"&gt;new &lt;/span&gt;TextBox() ]
printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(cl1 = cl2) &lt;span style="color:green;"&gt;
&lt;/span&gt;printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(cl1 &amp;lt; cl2) &lt;/pre&gt;&lt;a rel="nofollow" target="_blank" href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Or how about on F# function types?&lt;/p&gt;&lt;pre&gt;&lt;span style="color:blue;"&gt;let &lt;/span&gt;fl1 : (int &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;int) list = [ id; (+) 1; (&lt;span style="color:blue;"&gt;fun &lt;/span&gt;x &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;2*x) ]
&lt;span style="color:blue;"&gt;let &lt;/span&gt;fl2 : (int &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;int) list = [ (+) 1; (&lt;span style="color:blue;"&gt;fun &lt;/span&gt;x &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;2*x); id ]
printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(fl1 = fl2) &lt;span style="color:green;"&gt;
&lt;/span&gt;printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(fl1 &amp;lt; fl2) &lt;/pre&gt;
&lt;p&gt;Let’s consider each case in turn. For Controls, there is a useful equality semantic: reference equality. As a scenario example, you might hook up the same “click” event handler to a bunch of buttons, and then inside the handler test “if (sender=button1) then…” Indeed, the behavior of .Equals() on these .Net Framework types is reference equality. So an equality test on a list of Controls should return true if and only if each element of the first list .Equals() the corresponding element of the second list.&lt;/p&gt;
&lt;p&gt;What about comparison of Controls with the (&amp;lt;) operator? Here there is nothing reasonable to do. (Is a button less than a textbox? Is this button less than that one?) None of these type implement IComparable. Ideally we want this program not to compile; trying to compare a list of Controls with (&amp;lt;) is nonsense.&lt;/p&gt;
&lt;p&gt;How about the function types? Those few humans who have studied the F# spec in detail may recall that the result of calling System.Object.ReferenceEquals() on two F# function types is underspecified (see &lt;a rel="nofollow" target="_blank" href="http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html#_Toc245030880"&gt;6.10.22: Types with Under-specified Object and Type Identity&lt;/a&gt;&lt;span lang="EN-US"&gt;). Trying to compare two “function values” for (=) equality is bad news! Similarly, there is no reasonable “comparison” semantic for (&amp;lt;). So ideally, we would not like either of the function examples to compile.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span lang="EN-US"&gt;Happily, F# equality/comparison constraints give us exactly the behavior we want, as suggested by the comments:&lt;/span&gt;&lt;/p&gt;&lt;pre&gt;&lt;span style="color:blue;"&gt;let &lt;/span&gt;il1 : int list = [ 1; 2; 3 ]
&lt;span style="color:blue;"&gt;let &lt;/span&gt;il2 : int list = [ 2; 3; 1 ]
printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(il1 = il2) &lt;span style="color:green;"&gt;// false
&lt;/span&gt;printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(il1 &amp;lt; il2) &lt;span style="color:green;"&gt;// true &lt;/span&gt;&lt;span style="color:blue;"&gt;open &lt;/span&gt;System.Windows.Forms &lt;span style="color:blue;"&gt;let &lt;/span&gt;cl1 : Control list = [ &lt;span style="color:blue;"&gt;new &lt;/span&gt;TextBox(); &lt;span style="color:blue;"&gt;new &lt;/span&gt;Button(); &lt;span style="color:blue;"&gt;new &lt;/span&gt;CheckBox() ]
&lt;span style="color:blue;"&gt;let &lt;/span&gt;cl2 : Control list = [ &lt;span style="color:blue;"&gt;new &lt;/span&gt;Button(); &lt;span style="color:blue;"&gt;new &lt;/span&gt;CheckBox(); &lt;span style="color:blue;"&gt;new &lt;/span&gt;TextBox() ]
printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(cl1 = cl2) &lt;span style="color:green;"&gt;// false
&lt;/span&gt;printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(cl1 &amp;lt; cl2) &lt;span style="color:green;"&gt;// does not compile &lt;/span&gt;&lt;span style="color:blue;"&gt;let &lt;/span&gt;fl1 : (int &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;int) list = [ id; (+) 1; (&lt;span style="color:blue;"&gt;fun &lt;/span&gt;x &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;2*x) ]
&lt;span style="color:blue;"&gt;let &lt;/span&gt;fl2 : (int &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;int) list = [ (+) 1; (&lt;span style="color:blue;"&gt;fun &lt;/span&gt;x &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;2*x); id ]
printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(fl1 = fl2) &lt;span style="color:green;"&gt;// does not compile
&lt;/span&gt;printfn &lt;span style="color:#a31515;"&gt;"%A" &lt;/span&gt;(fl1 &amp;lt; fl2) &lt;span style="color:green;"&gt;// does not compile&lt;/span&gt;&lt;/pre&gt;&lt;a rel="nofollow" target="_blank" href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;If the operation is reasonable, the code compiles and gives the expected behavior. If the operation if unreasonable, the code fails to compile and you get a helpful diagnostic from the compiler.&lt;/p&gt;
&lt;p&gt;To sum up this section, hopefully I’ve provided a convincing argument that the behaviors described above are the ideal defaults. However this may leave you asking…&lt;/p&gt;
&lt;h3&gt;Does this really need a language feature?&lt;/h3&gt;
&lt;p&gt;As you may know, the CLI and languages like C# support a rich variety of ways to constraint class/method signatures so that the static type system can enforce that only sensible combinations of generics/object-hierarchies will typecheck. Surely we could use those existing mechanisms to get the ideal behavior described in the previous section?&lt;/p&gt;
&lt;p&gt;It turns out you cannot. (Some readers may wish to take a few minutes to try this themselves – try to author your own ‘list’ type (and possibly (=) and (&amp;lt;) operators) that give the same compile-time and run-time behavior as in the previous code example.) The static type system of the CLI or languages like C# are not powerful enough to express this behavior.&lt;/p&gt;
&lt;p&gt;To see why, consider just the comparison (&amp;lt;) aspect for a moment, and the ‘int’ versus ‘Control’ list example. I want to define a type List&amp;lt;T&amp;gt;. When I instantiate it with a comparable type like ‘int’, I want the resulting type “List&amp;lt;int&amp;gt;” to be an IComparable. But when I instantiate with a non-comparable type like ‘Control’ I want the resulting type “List&amp;lt;Control&amp;gt;” to &lt;em&gt;not &lt;/em&gt;be an IComparable. This amounts to needing a generic type to be able to &lt;em&gt;conditionally implement an interface&lt;/em&gt;, based on the generic argument. And you can’t do that. The nearest things you might try are C# code like&lt;/p&gt;&lt;pre&gt;&lt;span style="color:blue;"&gt;class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ListA&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style="color:#2b91af;"&gt;IComparable ...&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;or &lt;/p&gt;&lt;pre&gt;&lt;span style="color:blue;"&gt;class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ListB&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style="color:#2b91af;"&gt;IComparable &lt;/span&gt;&lt;span style="color:blue;"&gt;where &lt;/span&gt;T : &lt;span style="color:#2b91af;"&gt;IComparable ...&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;but neither does what we want. ListA allows lists of Controls, but also allows those lists to be comparable. ListB disallows comparing lists of Controls, but does so by throwing out the baby with the bathwater, you cannot even &lt;em&gt;create &lt;/em&gt;a list of Controls with ListB! What you really need is something like this imaginary syntax:&lt;/p&gt;&lt;pre&gt;&lt;span style="color:blue;"&gt;if &lt;/span&gt;T : IComparable &lt;span style="color:blue;"&gt;class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style="color:#2b91af;"&gt;IComparable &lt;/span&gt;{...}
&lt;span style="color:blue;"&gt;else class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; {...}&lt;/pre&gt;&lt;a rel="nofollow" target="_blank" href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;But this feature does not exist in C# or the CLI.&lt;/p&gt;
&lt;p&gt;The design methodology of F# here is to have features in the F# type system that are erased when the code is compiled. The same thing happens with &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/andrewkennedy/archive/2008/08/29/units-of-measure-in-f-part-one-introducing-units.aspx"&gt;units of measure&lt;/a&gt;; units are a feature that exist in the F# type system to enable a very useful kind of static type checking in F#, but this information is erased when compiled down to assemblies referenced by other .Net languages. So for instance, when F# looks at a particular F# assembly, it may see a method that returns “double&amp;lt;kg&amp;gt;”, but when C# looks at the same method, it will just see the return type as “double”. Similarly, F# equality &amp;amp; comparison constraints allow F# code to see what are effectively these ‘conditional interfaces’, whereas C# code would just see these interfaces unconditionally. The result is that the F# type system will catch some kinds of semantic errors at compile-time (like trying to add kilograms to meters, or trying to compare two functions values for equality), whereas the corresponding C# cannot (resulting in various unintended runtime semantics).&lt;/p&gt;
&lt;p&gt;Without this feature, F# would have to choose between either (1) disallowing equality and comparison on structural types like lists (meaning e.g. you could not compare two lists for equality), or (2) allowing equality and comparison on all structural types, even when it does not make sense (this is roughly where F# was prior to the release of Beta2). (In fact there are more points in the design space, but this paragraph summarizes the central choice.) These constraints enable equality/comparison only when it makes sense.&lt;/p&gt;
&lt;p&gt;To sum up this section: in order to get the desired behavior described in the previous section, we really do need a language feature. For details about the feature itself, see &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/dsyme/archive/2009/11/08/equality-and-comparison-constraints-in-f-1-9-7.aspx"&gt;Don’s blog&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now that you hopefully understand why the feature is necessary, you may say, ok, so…&lt;/p&gt;
&lt;h3&gt;When do I need to worry about any of this?&lt;/h3&gt;
&lt;p&gt;The good news is, amazingly, you almost never need to care about any of this. Almost all F# code that compiled and worked before continues to compile and work now the same way. The main difference is that the type system is providing an extra safety net to prevent you from doing meaningless things on certain types (such as trying to compare function values for equality). For the most part you get extra safety for free.&lt;/p&gt;
&lt;p&gt;The F# library has constraints mentioned on a few common types (like &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/ee353619(VS.100).aspx"&gt;Set&amp;lt;T&amp;gt;&lt;/a&gt;, which requires “T : comparison”) and functions (like &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/ee370445(VS.100).aspx"&gt;Seq.groupBy&lt;/a&gt;, which requires “Key : equality” (note: at time of this writing, there’s a doc bug on the groupBy web page that says “unknown constraint”)). So knowing these constraints is occasionally useful when reading documentation, to know for example that Set&amp;lt;T&amp;gt; only works for types T that support (&amp;lt;), and that groupBy can only group on keys that can be tested with (=).&lt;/p&gt;
&lt;p&gt;When you write code that uses equality/comparison constraints, it often gets inferred for you on your behalf. Consider this somewhat contrived example that finds the first element in a list ‘l’ that equals a certain value ‘e’:&lt;/p&gt;&lt;pre&gt;&lt;span style="color:blue;"&gt;let rec &lt;/span&gt;tryFindFirst e l = &lt;span style="color:blue;"&gt;match &lt;/span&gt;l &lt;span style="color:blue;"&gt;with &lt;/span&gt;| [] &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;None | x::xs &lt;span style="color:blue;"&gt;when &lt;/span&gt;x = e &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;Some(x) | x::xs &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;tryFindFirst e xs&lt;/pre&gt;
&lt;p&gt;Since (=) is used on the generic element type in the body of the function, the equality constraint is automatically inferred. Thus the behavior of this function for a few different calls is as seen here:&lt;/p&gt;&lt;pre&gt;tryFindFirst 3 [1;2;3;4] &lt;span style="color:green;"&gt;// Some(3)
&lt;/span&gt;tryFindFirst 5 [1;2;3;4] &lt;span style="color:green;"&gt;// None
&lt;/span&gt;tryFindFirst id [id;&lt;span style="color:blue;"&gt;fun &lt;/span&gt;x &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;x+1] &lt;span style="color:green;"&gt;// does not compile&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Notice that we get the ‘safety check’ for free. Our function only works on lists of elements for which the element types can be compared with (=), and we didn’t have to explicitly specify any constraint, it was automatically inferred.&lt;/p&gt;
&lt;p&gt;You will occasionally need to be explicit about equality/comparison constraints, if authoring algorithms with explicit type annotations that depend on these constraints, or authoring generic data types that depend on these constraints in non-obvious ways. For examples, see &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/dsyme/archive/2009/11/08/equality-and-comparison-constraints-in-f-1-9-7.aspx"&gt;Don’s blog&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To sum up: so long as you are aware of the existence of the “equality” and “comparison” constraints, and have some basic idea of what they mean (so as to grok them when seen in documentation or F# hover-tooltips in Visual Studio), you’re fine. You don’t need to understand the nitty-gritty details of the language mechanisms unless you are going to author types with ‘custom’ equality/comparison semantics, and those cases are relatively rare.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/oX-VYkk1NjX2K_fY0lN4zmanX10/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/oX-VYkk1NjX2K_fY0lN4zmanX10/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/oX-VYkk1NjX2K_fY0lN4zmanX10/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/oX-VYkk1NjX2K_fY0lN4zmanX10/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=mHgmqI5sZVM:fTrEAV_YK5M:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=mHgmqI5sZVM:fTrEAV_YK5M:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=mHgmqI5sZVM:fTrEAV_YK5M:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=mHgmqI5sZVM:fTrEAV_YK5M:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=mHgmqI5sZVM:fTrEAV_YK5M:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=mHgmqI5sZVM:fTrEAV_YK5M:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=mHgmqI5sZVM:fTrEAV_YK5M:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/mHgmqI5sZVM" height="1" width="1"/&gt;</description>
      <link>http://lorgonblog.spaces.live.com/Blog/cns!701679AD17B6D310!1621.entry</link>
      <pubDate>Sun, 08 Nov 2009 15:30:30 GMT</pubDate>
    </item>
    <item>
      <title>F# under the covers VIII</title>
      <description>&lt;p&gt;I'm in the tidying up stages for the little project I've been working on lately, a set of FxCop rules, mainly aimed at providing some complementary features for nCover-style code coverage, including static analysis for trivial methods -- or compiler generated ones. I've done the red -- add a set of methods that should give expected static analysis results -- and green -- write the simplest implementation that works when given the code base to analyse as a post-build activity. And now I'm on the refactor leg, abstracting out the common activities, taming sprawling methods into tighter ones, and reducing the level of imperative features (perhaps also making the code more idiomatic), even at times managing to delete whole methods.&lt;/p&gt; &lt;p&gt;And while I'm doing so, I'm running various tools over the code; FxCop and nCover over a small nUnit run every build, of course, but in turns Reflector and NDepend -- the results of which have been the inspiration for this series of posts.&lt;/p&gt; &lt;p&gt;And as we have seen, the code emitted by the F# compiler in its various iterations is unlike that coming from the more traditional .net langauges, in a way that doesn't always play nice with tools developed against C# or VB.net (and perhaps C++/CLI).&lt;/p&gt; &lt;p&gt;NDepend will deserve an essay of its own in due course -- part of the &lt;span style="font-style:italic;"&gt;quid pro quo&lt;/span&gt; for the copy that Patrick Smacchia has generously donated -- but today's point of interest is that some IL code generated from F# cannot (at least with current Reflector builds) be easily folded back into C# source.&lt;/p&gt; &lt;p&gt;Take this active pattern used to match a property getter method that just returns a backing field with a name related to the property name, which is at a current intermediate stage of refactoring&lt;/p&gt; &lt;pre&gt; let (|SimpleGetter|_|) (fn:Method) = if (not fn.IsAccessor) || (not (fn.Name.ToString() @ "get_")) then None else match MapToTypes fn.Body.Statements with | [NodeType.Block; NodeType.Block] -&amp;gt; match (fn.Body.Statements.[0], fn.Body.Statements.[1], fn) with | CSharpGetterInterior -&amp;gt; Some () | _ -&amp;gt; None | [NodeType.Block] -&amp;gt; match (fn.Body.Statements.[0], fn) with | SimpleGetterInterior -&amp;gt; Some() | _ -&amp;gt; None | _ -&amp;gt; None&lt;/pre&gt; &lt;p&gt;where &lt;code&gt;MapToTypes&lt;/code&gt; turns an FxCop &lt;code&gt;StatementCollection&lt;/code&gt; into a list of their corresponding &lt;code&gt;NodeType&lt;/code&gt;s, and &lt;code&gt;@&lt;/code&gt; wraps &lt;code&gt;String.StartsWith&lt;/code&gt; with ordinal comparison.&lt;/p&gt;
&lt;p&gt;Confronted with a request to decompile into C#, Reflector 5.1.6.0 asks me to file a bug report (which I have done) for an exception "Invalid branching statement for condition expression with target offset 002A."&lt;/p&gt;
&lt;p&gt;Now, as far as I can tell from the IL, this is part of line 2 where it is balking&lt;/p&gt; &lt;pre&gt; L_0000: nop L_0001: ldarg.0 L_0002: call instance bool [Microsoft.Cci]Microsoft.FxCop.Sdk.Method::get_IsAccessor() L_0007: brtrue.s L_000b L_0009: br.s L_000d L_000b: br.s L_0011 L_000d: ldc.i4.1 L_000e: nop L_000f: br.s L_002a L_0011: ldarg.0 L_0012: call instance class [Microsoft.Cci]Microsoft.FxCop.Sdk.Identifier [Microsoft.Cci]Microsoft.FxCop.Sdk.Member::get_Name() L_0017: callvirt instance string [mscorlib]System.Object::ToString() L_001c: ldstr "get_" L_0021: call bool Tinesware.Rules.Assist.Local::op_Append(string, string) L_0026: ldc.i4.0 L_0027: ceq L_0029: nop L_002a: brfalse.s L_002e L_002c: br.s L_0030 L_002e: br.s L_0032 L_0030: ldnull L_0031: ret ...&lt;/pre&gt; &lt;p&gt;Presumably -- I would have to build some equivalent C# code to validate -- the &lt;code&gt;brfalse.s&lt;/code&gt; is not one that C# (or any of the other languages Reflector knows of) would actually emit. Certainly it seems that the new F# CTP compiler is fond of emitting it, and it breaks Reflector every time it does.&lt;/p&gt;
&lt;p&gt;Another good reason for avoiding too many imperative constructs in your F# code, it would seem.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Later: this C# code that approximates the above F#&lt;/p&gt;
&lt;pre&gt; public static int? SimpleGetter(System.Reflection.MethodInfo fn) { if (!fn.IsSpecialName || !(fn.Name.StartsWith("get_"))) return null; return fn.Name.Length; }&lt;/pre&gt;
&lt;p&gt;compiles to&lt;/p&gt;
&lt;pre&gt; L_0000: nop L_0001: ldarg.0 L_0002: callvirt instance bool [mscorlib]System.Reflection.MethodBase::get_IsSpecialName() L_0007: brfalse.s L_001b L_0009: ldarg.0 L_000a: callvirt instance string [mscorlib]System.Reflection.MemberInfo::get_Name() L_000f: ldstr "get_" L_0014: callvirt instance bool [mscorlib]System.String::StartsWith(string) L_0019: br.s L_001c L_001b: ldc.i4.0 L_001c: stloc.1 L_001d: ldloc.1 L_001e: brtrue.s L_002c L_0020: ldloca.s CS$0$0002 L_0022: initobj [mscorlib]System.Nullable`1 L_0028: ldloc.2 L_0029: stloc.0 L_002a: br.s L_003f L_002c: ldarg.0 L_002d: callvirt instance string [mscorlib]System.Reflection.MemberInfo::get_Name() L_0032: callvirt instance int32 [mscorlib]System.String::get_Length() L_0037: newobj instance void [mscorlib]System.Nullable`1 ::.ctor(!0) L_003c: stloc.0 L_003d: br.s L_003f L_003f: ldloc.0 L_0040: ret &lt;/pre&gt;
&lt;p&gt;which indeed, as I suspected, uses a &lt;code&gt;brtrue.s&lt;/code&gt; for the final branch out of the &lt;code&gt;if&lt;/code&gt; statement (though there is a &lt;code&gt;brfalse.s&lt;/code&gt; to perform the short-circuiting.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5569894-3908086374790527025?l=stevegilham.blogspot.com'/&gt;&lt;/div&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257720780"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257720780" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/OEO2Cqa21TBHdwGRwx1dxu7J210/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OEO2Cqa21TBHdwGRwx1dxu7J210/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/OEO2Cqa21TBHdwGRwx1dxu7J210/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OEO2Cqa21TBHdwGRwx1dxu7J210/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=TLuJnYrnRfg:DArv-onMDYU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=TLuJnYrnRfg:DArv-onMDYU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=TLuJnYrnRfg:DArv-onMDYU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=TLuJnYrnRfg:DArv-onMDYU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=TLuJnYrnRfg:DArv-onMDYU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=TLuJnYrnRfg:DArv-onMDYU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=TLuJnYrnRfg:DArv-onMDYU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/TLuJnYrnRfg" height="1" width="1"/&gt;</description>
      <link>http://stevegilham.blogspot.com/2009/11/f-under-covers-viii.html</link>
      <author>Steve</author>
      <pubDate>Sun, 08 Nov 2009 14:53:00 GMT</pubDate>
    </item>
    <item>
      <title>Technical analysis indicators in F# – Part II</title>
      <description>This is the second part of a series of technical analysis indicators in F#.
We define some internal helper functions, and some basic indicators (math and statistics-related, moving averages etc.) Quick disclaimer : many of these indicators are not verified. And the code may very well be slower than in TA-Lib. The point was only to see [...] &lt;div id="related-posts"&gt; &lt;h3&gt;And also &amp;hellip;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/11/06/technical-analysis-indicators-in-f-part-i"&gt;Technical analysis indicators in F# &amp;#8211; Part I&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2008/04/22/redimensionneur-dimages"&gt;Batch image resizer&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/10/19/readwrite-requests-for-a-group-of-files"&gt;Read/Write requests for a group of files&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;
&lt;/div&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257718214"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257718214" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/taKsOFNy4_lWdOooBE_6O9sZDg4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/taKsOFNy4_lWdOooBE_6O9sZDg4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/taKsOFNy4_lWdOooBE_6O9sZDg4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/taKsOFNy4_lWdOooBE_6O9sZDg4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=jh4B3QgbSaA:1PQBRl_eXsM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=jh4B3QgbSaA:1PQBRl_eXsM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=jh4B3QgbSaA:1PQBRl_eXsM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=jh4B3QgbSaA:1PQBRl_eXsM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=jh4B3QgbSaA:1PQBRl_eXsM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=jh4B3QgbSaA:1PQBRl_eXsM:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=jh4B3QgbSaA:1PQBRl_eXsM:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/jh4B3QgbSaA" height="1" width="1"/&gt;</description>
      <link>http://lepensemoi.free.fr/index.php/2009/11/09/technical-analysis-indicators-in-f-part-ii</link>
      <pubDate>Sun, 08 Nov 2009 14:10:14 GMT</pubDate>
    </item>
    <item>
      <title>A Great Blog Series on Algorithmic Programming in F#</title>
      <description>&lt;p&gt;I've just discovered &lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/"&gt;Julien's&lt;/a&gt; amazingblog series on &lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/category/tech"&gt;algorithmic programming in F#&lt;/a&gt;. This is a fantastic resource! And if that doesn't whet your appetite, he also has a &lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/category/fooding"&gt;series on food&lt;/a&gt;&amp;nbsp;:-)&lt;/p&gt;
&lt;p&gt;Here are some of his recent posts:&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/11/06/technical-analysis-indicators-in-f-part-i"&gt;&lt;em&gt;Technical analysis indicators in F#&amp;nbsp;&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&amp;nbsp;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This is the first part of a series on &lt;/em&gt;&lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Technical_analysis"&gt;&lt;font color="#777777"&gt;&lt;em&gt;technical analysis&lt;/em&gt;&lt;/font&gt;&lt;/a&gt;&lt;em&gt; indicators in F#. We will define the basic object holding the data series which will be used to compute the indicators. We will also describe some functions to check the integrity of the said data (and which will be useful when defining the indicators).&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;span id="more-167"&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/11/02/an-immutable-range-library-in-f"&gt;&lt;em&gt;An immutable range&amp;nbsp;library in F#&lt;/em&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;span&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;An immutable range library in F# where a range is only defined by a minimum and a maximum value (hence, there is no step). &lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/span&gt;
&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/10/27/an-immutable-queue-library-in-f"&gt;&lt;em&gt;An immutable queue in F#&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;An immutable queue library in F#. The queue is divided into two lists : one for dequeueing, and one for enqueueing. All operations are based on the List module. &lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/10/25/a-bit-array-or-bitset-library-in-f"&gt;A bitset library in F#&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/10/19/readwrite-requests-for-a-group-of-files"&gt;ReadWrite Requests for groups of files&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;In this post, we shall use read/write requests from a group of files considered as a single entity. We will also look at verifying the data. In our model, the group of files is defined by the files, and pieces. A piece is a chunk of data with a standardized size so that read/write requests are consistent. Of course, the last piece of the files stream could see its size differ from others since if the cumulative size of the files is not a multiple of the piece length.&lt;br&gt;&lt;/p&gt;&lt;span id="more-139"&gt;&amp;nbsp;&lt;/span&gt;&lt;/em&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;span&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/10/16/implementing-two-way-traffic-control-in-f"&gt;Implementing Two-way TCP Traffic Control in F#&lt;/a&gt;&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;&lt;em&gt;&lt;span&gt;
&lt;blockquote&gt;&lt;em&gt;&lt;span&gt;
&lt;p&gt;This post describes how to implement two-way (TCP for instance) traffic control&amp;nbsp;in F# by modifying slightly a Trolltech article available at &lt;a rel="nofollow" target="_blank" href="http://doc.trolltech.com/qq/qq17-ratecontrol.html"&gt;http://doc.trolltech.com/qq/qq17-ratecontrol.html&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;And the list goes on!&lt;/p&gt;
&lt;div id="post-34" class="post-34 post hentry category-tech tag-dot-net tag-fsharp tag-programming tag-syntax-coloring tag-syntaxhighlighter"&gt;
&lt;div class="title"&gt;&lt;a rel="nofollow" title="Permanent Link to F# brush for Gorbatchev&amp;#x002019;s SyntaxHighlighter" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/10/05/f-brush-for-gorbatchevs-syntaxhighlighter"&gt;F# brush for Gorbatchev’s SyntaxHighlighter &lt;/a&gt;&lt;/div&gt;
&lt;div class="metadata"&gt;&lt;a rel="nofollow" title="Permanent Link to Dual quicksort in F#" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/09/22/quicksort"&gt;Dual quicksort in F# &lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div id="post-13" class="post-13 post hentry category-tech tag-dot-net tag-fsharp tag-programming tag-quicksort tag-sorting-algorithm"&gt;
&lt;div class="metadata"&gt;&lt;a rel="nofollow" title="Permanent Link to F# brush for Geshi" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/09/22/f-brush-for-geshi"&gt;F# brush for Geshi &lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div id="post-42" class="post-42 post hentry category-tech tag-dot-net tag-fsharp tag-geshi tag-programming tag-syntax-coloring"&gt;
&lt;div class="metadata"&gt;&lt;a rel="nofollow" title="Permanent Link to Batch image resizer" target="_blank" href="http://lepensemoi.free.fr/index.php/2008/04/22/redimensionneur-dimages"&gt;Batch image resizer &lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div id="post-1" class="post-1 post hentry category-tech tag-dot-net tag-fsharp tag-image tag-programming"&gt;&lt;a rel="nofollow" title="Permanent Link to Tries and Anagrams with F#" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/10/15/trie-and-anagrams-with-f"&gt;Tries and Anagrams with F#&amp;nbsp;&lt;/a&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class="post-1 post hentry category-tech tag-dot-net tag-fsharp tag-image tag-programming"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class="post-1 post hentry category-tech tag-dot-net tag-fsharp tag-image tag-programming"&gt;&lt;a rel="nofollow" title="Permanent Link to Cr&amp;#xe8;me p&amp;#xe2;tissi&amp;#xe8;re &amp;#x002013; Pierre Herm&amp;#xe9;, &amp;#x00201c;Larousse des desserts&amp;#x00201d;" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/10/15/creme-patissiere-pierre-herme-larousse-des-desserts"&gt;Crème pâtissière – Pierre Hermé, “Larousse des desserts” &lt;/a&gt;&lt;/div&gt;
&lt;div class="post-1 post hentry category-tech tag-dot-net tag-fsharp tag-image tag-programming"&gt;&lt;a rel="nofollow" title="Permanent Link to P&amp;#xe2;te &amp;#xe0; choux" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/10/15/pate-a-choux"&gt;Pâte à choux&lt;/a&gt;&lt;/div&gt;
&lt;div class="post-1 post hentry category-tech tag-dot-net tag-fsharp tag-image tag-programming"&gt;&lt;a rel="nofollow" title="Permanent Link to Le chocolat" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/10/20/le-chocolat"&gt;Le chocolat&amp;nbsp;&lt;/a&gt;&lt;/div&gt;
&lt;div class="post-1 post hentry category-tech tag-dot-net tag-fsharp tag-image tag-programming"&gt;&lt;a rel="nofollow" title="Permanent Link to P&amp;#xe2;te sucr&amp;#xe9;e &amp;#x002013; Pierre Herm&amp;#xe9;, &amp;#x00201c;Larousse des desserts&amp;#x00201d;" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/10/23/pate-sucree-version-pierre-herme"&gt;Pâte sucrée – Pierre Hermé, “Larousse des desserts”&amp;nbsp;&lt;/a&gt;&amp;nbsp;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/span&gt;&lt;/em&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;/em&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9919269" width="1" height="1"&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257704340"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257704340" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/I2ymTU8I2IQ6WWyvIxJlPjqPt5s/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/I2ymTU8I2IQ6WWyvIxJlPjqPt5s/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/I2ymTU8I2IQ6WWyvIxJlPjqPt5s/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/I2ymTU8I2IQ6WWyvIxJlPjqPt5s/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=NF97nE3Y6PA:HjZeWD1QAUE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=NF97nE3Y6PA:HjZeWD1QAUE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=NF97nE3Y6PA:HjZeWD1QAUE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=NF97nE3Y6PA:HjZeWD1QAUE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=NF97nE3Y6PA:HjZeWD1QAUE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=NF97nE3Y6PA:HjZeWD1QAUE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=NF97nE3Y6PA:HjZeWD1QAUE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/NF97nE3Y6PA" height="1" width="1"/&gt;</description>
      <link>http://blogs.msdn.com/dsyme/archive/2009/11/08/technical-programming-in-f.aspx</link>
      <author>dsyme</author>
      <pubDate>Sun, 08 Nov 2009 10:19:00 GMT</pubDate>
    </item>
    <item>
      <title>Equality and Comparison Constraints in F#</title>
      <description>&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;F# 1.9.7 introduces two new constraints to the F# language to help uncover issues in your code when using equality and comparison operators. In this blog entry we'll take a look at these constraints in a bit more detail. The topics in this blog post are&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;Tuples, Lists and other Structural Types&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;The Basic Equality and Comparison Operations in F#&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;What do the equality and comparison constraints mean?&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;Defining New Structural Types&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;Customizing Equality and Comparison&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;Safer Code: Suppressing Equality and Comparison on a Type &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;Safer Code: Safer Sets and Maps&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;Safer Code: Declaring Conditions for Equality over Container Types&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;Getting IEqualityComparer&amp;lt;’T&amp;gt; and IComparer&amp;lt;’T&amp;gt; Implementations which use F# Generic Equality&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;Using unchecked equality and comparison&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;Design Alternatives. Could interface constraints suffice? User defined constraints?&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;Summary&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;You can also find&amp;nbsp;the details in the draft &lt;/font&gt;&lt;/span&gt;&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/dsyme/archive/2009/11/04/f-1-9-7-language-specification-now-available.aspx"&gt;&lt;span style="FONT-FAMILY:'Arial', 'sans-serif';FONT-SIZE:10pt;"&gt;F# Language Specification&lt;/span&gt;&lt;/a&gt;&lt;span style=""&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;, where similar material is covered. &lt;span style=""&gt;&amp;nbsp;&lt;/span&gt;First, as usual, some background. &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;span style="FONT-FAMILY:'Arial', 'sans-serif';FONT-SIZE:10pt;"&gt;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;span style="FONT-FAMILY:'Arial', 'sans-serif';FONT-SIZE:10pt;"&gt;Tuples, Lists and other Structural Types&lt;/span&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;font face="Calibri"&gt;&lt;font size="3"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;font face="Calibri"&gt;&lt;font size="3"&gt;Functional programming in F# frequently involves the use of structural equality, hashing and comparison. For example:&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 6pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;(1,1+1) = (1,2)&lt;/font&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:#4f81bd;FONT-SIZE:10pt;"&gt; &lt;span lang="EN-US"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font face="Calibri"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;will return true&lt;/span&gt;&lt;span style="" lang="EN-US"&gt;, because tuple types support "structural" equality. Likewise these two function calls return identical values:&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;hash (1,1+1) &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;hash (1,2)&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="" lang="EN-US"&gt;&lt;font face="Calibri"&gt;Likewise an ordering on parts of a tuple induces an ordering on tuples themselves, so all the following evaluate to &lt;/font&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:#4f81bd;FONT-SIZE:12pt;" lang="EN-US"&gt;true&lt;/span&gt;&lt;/font&gt;&lt;span style="FONT-FAMILY:'Times New Roman', 'serif';FONT-SIZE:12pt;" lang="EN-US"&gt;:&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;(1,2) &amp;lt; (1,3) &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;(1,2) &amp;lt; (2,3) &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;(1,2) &amp;lt; (2,1) &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;(1,2) &amp;gt; (1,0) &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font face="Calibri"&gt;&lt;font size="3"&gt;The same applies to lists, options, arrays and user-defined record, union and struct types whose constituent field types permit structural equality, hashing and comparison.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Equality and comparison are a surprisingly important part of the experience of “programming with functional data” – it is difficult to imagine F# being F# if you can’t compare tuples for equality, or lists for equality, and likewise for other user-defined structural types. In each case, the behaviour of these operations depends on the equality properties of the constituent components. &lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font face="Calibri"&gt;&lt;font size="3"&gt;This in turn means that the “idea” of equality, hashing and comparison (including structural versions of these) is built in quite deeply into the F# language and core library – for example, several pages of the F# specification are devoted to defining what happens when you use equality with user-defined structural types.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font face="Calibri"&gt;&lt;font size="3"&gt;The Basic Equality and Comparison Operations in F#&lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Let’s take a look at the signatures of the equality, comparison and hashing operations in the F# library:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;(=)&amp;nbsp; : 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; bool &lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'T : equality &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;(&amp;lt;&amp;gt;) : 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; bool &lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'T : equality &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;hash : 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt;&amp;nbsp;int &lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'T : equality &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;(&amp;lt;)&amp;nbsp; : 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; bool &lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'T : comparison &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;(&amp;lt;=) : 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; bool &lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'T : comparison &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;(&amp;gt;)&amp;nbsp; : 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; bool &lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'T : comparison &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;(&amp;gt;=) : 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; bool &lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'T : comparison &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;compare : 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; int &lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'T : comparison &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;min&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; 'T &lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'T : comparison &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;max&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; 'T &lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'T : comparison&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;First note that these are &lt;i style=""&gt;generic&lt;/i&gt; operations – they can be used on objects of many different types. This can be seen by the use of &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;'T&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;&lt;span style=""&gt; &lt;/span&gt;in the signatures of these operations. These operations take one or two parameters of the same type. For example, you can apply the “=” operator to two &lt;/font&gt;&lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;Form&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt; objects, or two &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;System.DateTime&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt; objects, or two &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;System.Type&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt; objects, and something reasonable will happen.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Some other important derived generic types such as the immutable (persistent) &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;Set&amp;lt;_&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt; and &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;Map&amp;lt;_,_&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt; types in the F# library also use generic comparison on their key type:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; Set&amp;lt;'T &lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'T : comparison&amp;gt; = ...&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; Map&amp;lt;'Key, 'Value &lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'Key : comparison&amp;gt; = ...&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 14.2pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:#4f81bd;FONT-SIZE:10pt;" lang="EN-US"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;In common with many other basic generic operators in the F# library, the above operations are &lt;b style=""&gt;&lt;i style=""&gt;constrained&lt;/i&gt;&lt;/b&gt;, in this case by the &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;'T : equality &lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt;and &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;'T : comparison&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;&lt;span style=""&gt; &lt;/span&gt;constraints. The purpose of constraints on type parameters is to make sure the operations are only used on a reasonable set of types. For example, consider using equality and comparison on a &lt;/font&gt;&lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;System.Windows.Forms.Form&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt; object. Equality is permitted, because the default for nearly all .NET object types is reference equality:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt;let&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; form1 = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; System.Windows.Forms.Form()&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt;let&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; form2 = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; System.Windows.Forms.Form()&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;form1 = form1&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:green;"&gt;// true&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;form1 = form2&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:green;"&gt;// false&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:green;FONT-SIZE:10pt;"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;However comparison is not permitted: &lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt;let&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; form1 = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; System.Windows.Forms.Form()&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt;let&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; form2 = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; System.Windows.Forms.Form()&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;form1 &amp;lt;= form2&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:green;"&gt;// Error: The type 'System.Windows.Forms.Form' does not support the 'comparison' constraint. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:green;"&gt;// For example, it does not support the 'System.IComparable' interface&lt;span style=""&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;That’s good! There is no natural ordering for these object - you could define one, on a derived type, by implementing IComparable, but there is not natural ordering provided by the .NET libraries. &lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Now, unlike other operations in the F# core library, equality and comparison are &lt;b style=""&gt;&lt;i style=""&gt;conditional on the structure of types&lt;/i&gt;&lt;/b&gt;. For example, you can only use the above equality and comparison operators on a tuple if the constituent parts of the tuple also support equality and comparison. For example, using equality on a tuple of forms is permitted:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt;let&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; form1 = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; System.Windows.Forms.Form()&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt;let&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; form2 = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; System.Windows.Forms.Form()&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;(form1, form2) = (form1, form2) &lt;span style="COLOR:green;"&gt;// true&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;(form1, form2) = (form2, form1) &lt;span style="COLOR:green;"&gt;// false&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:green;FONT-SIZE:10pt;"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;But attempting to order a tuple involving forms is not:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;(form1, "Data for Form1") &amp;lt;= (form2, " Data for Form2")&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:green;"&gt;// Error: The type 'System.Windows.Forms.Form' does not support the 'comparison' constraint. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Again, that’s good – this ordering would be a bug in your code. &lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Many types in the .NET libraries come with custom equality and comparison implementations. For example, &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;System.DateTime&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt; has custom implementations of both equality and comparison. F# also allows you to define custom comparison and equality for new type definitions. We’ll be looking at how to customize equality and comparison implementations later in this blog post.&lt;b style=""&gt; &lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;What do the equality and comparison constraints mean?&lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Let’s summarize where we are so far:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoListParagraph"&gt;&lt;span style=""&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;-&lt;/font&gt;&lt;span style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt;For some types, equality is &lt;b style=""&gt;structural&lt;/b&gt;. For&lt;b style=""&gt; &lt;/b&gt;example, lists, options, tuples and user-defined structural types.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoListParagraph"&gt;&lt;span style=""&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;-&lt;/font&gt;&lt;span style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt;For some types, equality is &lt;b style=""&gt;reference based&lt;/b&gt;. These types do not tend to support comparison. For example, System.Windows.Forms.Form.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoListParagraph"&gt;&lt;span style=""&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;-&lt;/font&gt;&lt;span style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt;For some types, equality is &lt;b style=""&gt;customized&lt;/b&gt;, for example System.DateTime.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoListParagraph"&gt;&lt;span style=""&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;-&lt;/font&gt;&lt;span style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt;For some types, there is no sensible notion of equality and/or comparison. You can think of these types as being labelled &lt;b style=""&gt;no equality&lt;/b&gt; and &lt;b style=""&gt;no comparison.&lt;/b&gt; This case is only important for finding bugs in your code earlier rather than later.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt 18pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;The combination of these points underlies the decision to include equality and comparison constraints as first-class new, primary constraints in the F# language. &lt;span style=""&gt;&amp;nbsp;&lt;/span&gt;Later on in this blog post we consider other options in this design space. &lt;span style=""&gt;Now, let’s take a closer look at when &lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;equality&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt; and &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;comparison&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=""&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt; constraints are satisfied in F#.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;The essence of the rules is very simple:&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 18pt;" class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;font size="3" face="Calibri"&gt;The constraint &lt;/font&gt;&lt;/span&gt;&lt;font color="#4f81bd"&gt;&lt;font face="Consolas"&gt;&lt;span class="CodeInline"&gt;&lt;i style=""&gt;&lt;span style="FONT-SIZE:10pt;" lang="EN-US"&gt;type&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;" lang="EN-US"&gt; : equality&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;span style="" lang="EN-US"&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt; holds if:&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoListParagraph"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;-&lt;/font&gt;&lt;span style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="" lang="EN-US"&gt;&lt;font size="3" face="Calibri"&gt;the type definition for &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;i style=""&gt;&lt;span style="FONT-SIZE:10pt;" lang="EN-US"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;type&lt;/font&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="" lang="EN-US"&gt;&lt;font size="3" face="Calibri"&gt; doesn't have the &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;" lang="EN-US"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;NoEquality&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="" lang="EN-US"&gt;&lt;font face="Calibri"&gt;&lt;font size="3"&gt; attribute, &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="LINE-HEIGHT:130%;MARGIN:0cm 0cm 6pt 36pt;" class="MsoListParagraph"&gt;&lt;span class="CodeInline"&gt;&lt;span style="LINE-HEIGHT:130%;FONT-FAMILY:'Calibri', 'sans-serif';COLOR:windowtext;" lang="EN-US"&gt;&lt;span style=""&gt;&lt;font size="3"&gt;-&lt;/font&gt;&lt;span style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="" lang="EN-US"&gt;&lt;font size="3" face="Calibri"&gt;any &lt;span style=""&gt;&amp;nbsp;&lt;/span&gt;“equality dependencies” of the type also satisfy &lt;/font&gt;&lt;/span&gt;&lt;font color="#4f81bd"&gt;&lt;font face="Consolas"&gt;&lt;span class="CodeInline"&gt;&lt;i style=""&gt;&lt;span style="LINE-HEIGHT:130%;FONT-SIZE:10pt;" lang="EN-US"&gt;ty&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="LINE-HEIGHT:130%;FONT-SIZE:10pt;" lang="EN-US"&gt; : equality&lt;/span&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="LINE-HEIGHT:130%;FONT-FAMILY:'Calibri', 'sans-serif';COLOR:windowtext;" lang="EN-US"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 18pt;" class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;font size="3" face="Calibri"&gt;The constraint &lt;/font&gt;&lt;/span&gt;&lt;font color="#4f81bd"&gt;&lt;font face="Consolas"&gt;&lt;span class="CodeInline"&gt;&lt;i style=""&gt;&lt;span style="FONT-SIZE:10pt;" lang="EN-US"&gt;type&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;" lang="EN-US"&gt; : comparison&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;&lt;span style="" lang="EN-US"&gt; holds if:&lt;/span&gt;&lt;span style="FONT-FAMILY:'Arial', 'sans-serif';"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoListParagraph"&gt;&lt;span style=""&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;-&lt;/font&gt;&lt;span style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="" lang="EN-US"&gt;&lt;font size="3" face="Calibri"&gt;if the type is a named type, then the type definition doesn't have the &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;" lang="EN-US"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;NoComparison&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;&lt;span style="" lang="EN-US"&gt; attribute; and&lt;/span&gt;&lt;span style="FONT-FAMILY:'Arial', 'sans-serif';"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoListParagraph"&gt;&lt;span style=""&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;-&lt;/font&gt;&lt;span style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="" lang="EN-US"&gt;&lt;font size="3" face="Calibri"&gt;the type definition implements &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;" lang="EN-US"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;System.IComparable&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;&lt;span style="" lang="EN-US"&gt;; and&lt;/span&gt;&lt;span style="FONT-FAMILY:'Arial', 'sans-serif';"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="LINE-HEIGHT:130%;MARGIN:0cm 0cm 6pt 36pt;" class="MsoListParagraph"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;-&lt;/font&gt;&lt;span style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="" lang="EN-US"&gt;&lt;font size="3" face="Calibri"&gt;any “comparison dependencies” of the type also satisfy &lt;/font&gt;&lt;/span&gt;&lt;font color="#4f81bd"&gt;&lt;font face="Consolas"&gt;&lt;span class="CodeInline"&gt;&lt;i style=""&gt;&lt;span style="LINE-HEIGHT:130%;FONT-SIZE:10pt;" lang="EN-US"&gt;ty&lt;sub&gt;i&lt;/sub&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="LINE-HEIGHT:130%;FONT-SIZE:10pt;" lang="EN-US"&gt; : comparison&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;span style="" lang="EN-US"&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt; &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;These rules mean that an &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;" lang="EN-US"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;equality&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt; constraint is a relatively weak constraint, since nearly all CLI types satisfy this constraint.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Reference equality is pervasive in other CLI languages such as C# and this shows through in CLI libraries. Note that the an &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;" lang="EN-US"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;equality&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt; constraint also implies the ability to use the F# &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;hash&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=""&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt; function on an object.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;A &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;" lang="EN-US"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;comparison&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt; constraint is a stronger constraint, since it usually implies that a type must implement &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;System.IComparable&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=""&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;We’ve discussed the notion of “dependencies” above, e.g. &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;(int * string)&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt; is comparable because both &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;int&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt; and &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;string&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt; are comparable. Here, &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;int&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt; and &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;string&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=""&gt;&lt;font face="Calibri"&gt;&lt;font size="3"&gt; are dependencies of the tuple type. We’ll look at declaring new dependencies for a type further below.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font face="Calibri"&gt;&lt;font size="3"&gt;Defining New Structural Types&lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Structural type definitions are easy in F#:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; MyBox&amp;lt;'T&amp;gt; = MyBox &lt;span style="COLOR:blue;"&gt;of&lt;/span&gt; 'T&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;In this case, the type is given structural equality and comparison implementations, and F# infers that there is an equality and comparison dependency on ‘T. All done! &lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Sometimes you may want to assert that a structural type really MUST support structural equality, and you want an error at the definition of the type if it does not. You do this by adding the StructuralEquality or StructuralComparison attribute to the type&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;[&amp;lt;StructuralEquality;StructuralComparison&amp;gt;] &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; MyIntBox = MyIntBox &lt;span style="COLOR:blue;"&gt;of&lt;/span&gt; int&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;This simply adds extra checking.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;In the example below, the code gives an error at compile time, because the type can’t logically support automatic structural comparison, because one of the element types does not support structural comparison:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;[&amp;lt;StructuralEquality;StructuralComparison&amp;gt;] &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; MyData = MyBox &lt;span style="COLOR:blue;"&gt;of&lt;/span&gt; int * string * string * System.Windows.Forms.Form&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;More commonly, you may notice that F# function types do not support equality:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;[&amp;lt;StructuralEquality;StructuralComparison&amp;gt;] &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; MyData = MyBox &lt;span style="COLOR:blue;"&gt;of&lt;/span&gt; int * string * string * (int -&amp;gt; int)&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Again this will give an error, because function values are considered to be “no equality”&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;You can also declare that a structural type should use reference equality. &lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;[&amp;lt;ReferenceEquality&amp;gt;] &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; MyFormWrapper = MyFormWrapper &lt;span style="COLOR:blue;"&gt;of&lt;/span&gt; System.Windows.Forms.Form * (int -&amp;gt; int)&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;In summary, the following attributes control the comparison and equality semantics of types in the cases outlined earlier in this blog post&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoListParagraph"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoListParagraph"&gt;&lt;span style=""&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;-&lt;/font&gt;&lt;span style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;&lt;b style=""&gt;StructuralEquality&lt;/b&gt;,&lt;b style=""&gt;StructuralComparison&lt;/b&gt; &lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;– indicates a structural type MUST support equality and comaprison&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoListParagraph"&gt;&lt;span style=""&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;-&lt;/font&gt;&lt;span style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;&lt;b style=""&gt;ReferenceEquality&lt;/b&gt; &lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;– indicates a structural type supports only reference equality &lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoListParagraph"&gt;&lt;span style=""&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;-&lt;/font&gt;&lt;span style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;&lt;b style=""&gt;NoComparison&lt;/b&gt;, &lt;b style=""&gt;NoEquality&lt;/b&gt; &lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;– indicates a type doesn’t support equality or comparison at all&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoListParagraph"&gt;&lt;span style=""&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;-&lt;/font&gt;&lt;span style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;&lt;b style=""&gt;CustomEquality&lt;/b&gt;, &lt;b style=""&gt;CustomComparison&lt;/b&gt; &lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;– indicates a structural type supports custom equality and comparison&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Note there is no such thing as “reference comparison” (the object pointers used by .NET move around, so the ordering would change). You might implement that by using a unique tag and custom comparison.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;Customizing Equality and Comparison&lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;For some types it is often necessary to define your own comparison, equality and hashing semantics. For example, values of a type may carry a unique integer tag which can be used for this purpose. &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;&lt;span style=""&gt;In this case &lt;/span&gt;our recommendation is to take full control of your destiny and define custom comparison and equality operations on your type. For example, here is how you might compare based on a “stamp” integer value:&lt;span style=""&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="COLOR:#1f497d;"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:green;FONT-SIZE:10pt;"&gt;/// A type abbreviation indicating we’re using integers for unique stamps on objects &lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; stamp = int&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:green;FONT-SIZE:10pt;"&gt;/// A type containing a function that can’t be compared for equality&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&lt;/span&gt;[&amp;lt;CustomEquality; CustomComparison&amp;gt;]&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; MyThing = &lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{ Stamp: stamp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Behaviour: (int &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; int) }&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:green;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:green;FONT-SIZE:10pt;"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;override&lt;/span&gt; x.Equals(yobj) = &lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;match&lt;/span&gt; yobj &lt;span style="COLOR:blue;"&gt;with&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;| :? MyThing &lt;span style="COLOR:blue;"&gt;as&lt;/span&gt; y &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; (x.Stamp = y.Stamp)&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;| _ &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;false&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;override&lt;/span&gt; x.GetHashCode() = hash x.Stamp&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;interface&lt;/span&gt; System.IComparable &lt;span style="COLOR:blue;"&gt;with&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;member&lt;/span&gt; x.CompareTo yobj = &lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;match&lt;/span&gt; yobj &lt;span style="COLOR:blue;"&gt;with&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;| :? MyThing &lt;span style="COLOR:blue;"&gt;as&lt;/span&gt; y &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; compare x.Stamp y.Stamp&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;| _ &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; invalidArg &lt;span style="COLOR:maroon;"&gt;"yobj"&lt;/span&gt; &lt;span style="COLOR:maroon;"&gt;"cannot compare values of different types"&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;You might also find these helpful to add to your library of F# helpers:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="COLOR:#1f497d;"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; let&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; equalsOn f x (yobj:obj) = &lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="COLOR:blue;"&gt;match&lt;/span&gt; yobj &lt;span style="COLOR:blue;"&gt;with&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;| :? 'T &lt;span style="COLOR:blue;"&gt;as&lt;/span&gt; y &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; (f x = f y)&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;| _ &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;false&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; let&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; hashOn f x =&amp;nbsp; hash (f x)&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;FONT-SIZE:10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; let&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; compareOn f x (yobj: obj) = &lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="COLOR:blue;"&gt;match&lt;/span&gt; yobj &lt;span style="COLOR:blue;"&gt;with&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;| :? 'T &lt;span style="COLOR:blue;"&gt;as&lt;/span&gt; y &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; compare (f x) (f y)&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;| _ &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; invalidArg &lt;span style="COLOR:maroon;"&gt;"yobj"&lt;/span&gt; &lt;span style="COLOR:maroon;"&gt;"cannot compare values of different types"&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="COLOR:#1f497d;"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;This can then make your custom implementations more uniform. For example, here is a custom implementation for a union type:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; stamp = int&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;[&amp;lt;CustomEquality; CustomComparison&amp;gt;]&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; MyUnionType = &lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;| MyUnionType &lt;span style="COLOR:blue;"&gt;of&lt;/span&gt; stamp * (int &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; int)&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:green;"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:green;"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;member&lt;/span&gt; Stamp (MyUnionType (s,_)) = s&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;override&lt;/span&gt; x.Equals y = equalsOn MyUnionType.Stamp x y&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;override&lt;/span&gt; x.GetHashCode() = hashOn MyUnionType.Stamp x&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;interface&lt;/span&gt; System.IComparable &lt;span style="COLOR:blue;"&gt;with&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;member&lt;/span&gt; x.CompareTo y = compareOn MyUnionType.Stamp x y&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;You can also define custom equality and comparison implementations on other types.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Note: A bug in an error message in the 1.9.7 release of F# says “A type with CustomEquality must override Equals or implement IEquatable or IStructuralEquatable”. This is not the case: a type with CustomEquality must override Equals.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;Safer Code: Suppressing Equality and Comparison on a Type &lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;You can suppress equality on an F# defined type by using &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;[&amp;lt;NoEquality&amp;gt;]&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt; attribute on the definition of the type. This simply means that the type will not be considered to satisfy the equality constraint. Likewise, you can suppress comparison on an F# defined type by using &lt;/font&gt;&lt;/span&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;[&amp;lt;NoComparison&amp;gt;]&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=""&gt;&lt;font face="Calibri"&gt;&lt;font size="3"&gt; attribute on the definition of the type. This simply means that the type will not be considered to satisfy the comparison constraint.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;[&amp;lt;NoEquality; NoComparison&amp;gt;]&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; MyProjections = &lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;| MyProjections &lt;span style="COLOR:blue;"&gt;of&lt;/span&gt; (int * string) * (string &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; int)&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:green;"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;Adding these attributes to your library types makes client code safer, as it is less likely to inadvertently rely on equality and comparison over types where these operations make no sense.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;Safer Code: Safer Sets and Maps&lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;All previous versions of F# did not check equality and comparison constraints. We always planned to address this, but the details were only finalized in 1.9.7.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;One main motivation for checking these constraints is to make sure the F# Set and Map types, and other future F# immutable collections, are not misused. For example, consider the following:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 72pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:'Lucida Console';COLOR:blue;FONT-SIZE:10pt;"&gt;let&lt;/span&gt;&lt;span style="FONT-FAMILY:'Lucida Console';FONT-SIZE:10pt;"&gt; x1 = set [ (fun x -&amp;gt; x + 1); id ; (fun x -&amp;gt; x + 2) ] &lt;span style="COLOR:green;"&gt;// static error&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 72pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:'Lucida Console';COLOR:green;FONT-SIZE:10pt;"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 72pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:'Lucida Console';COLOR:blue;FONT-SIZE:10pt;"&gt;let&lt;/span&gt;&lt;span style="FONT-FAMILY:'Lucida Console';FONT-SIZE:10pt;"&gt; x2 = set [ obj(); obj(); obj() ] &lt;span style="COLOR:green;"&gt;// static error&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 72pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:'Lucida Console';COLOR:green;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 72pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:'Lucida Console';COLOR:blue;FONT-SIZE:10pt;"&gt;let&lt;/span&gt;&lt;span style="FONT-FAMILY:'Lucida Console';FONT-SIZE:10pt;"&gt; x3 = set [ typeof&amp;lt;int&amp;gt;; typeof&amp;lt;string&amp;gt; ] &lt;span style="COLOR:green;"&gt;// static error&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 72pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:'Lucida Console';COLOR:blue;FONT-SIZE:10pt;"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 72pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:'Lucida Console';FONT-SIZE:10pt;"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;In early versions of F# these gave runtime errors. As another example, consider trying to compare functions for equality:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 72pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:'Lucida Console';FONT-SIZE:10pt;"&gt;id = id &lt;span style="COLOR:green;"&gt;// static error&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;This returned “false” in early versions of F#, because two different closures were allocated for “id” on each side of the equation – this is valid, according to the F# specification, which says that the results of equality comparison on function values was undefined. This now gives a static error. These cases alone indicate the importance of addressing this issue.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;Safer Code: Declaring Conditions for Equality over Container Types&lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Programmers love defining new generic container types. This is done less often in .NET and F# programming than in other languages, but it's still important!&amp;nbsp;&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&lt;/font&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Equality and comparison play a role here. For example, it is common to have collections where some of the&amp;nbsp;values can be indexed using hashing, or compared for equality when searching, or compared using an ordering. For example, seeing a constraint on this signature on a library type would come as no surprise:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; Graph&amp;lt;'Node when 'Node : equality&amp;gt;() = ...&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:12pt;"&gt;&lt;font face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font face="Calibri"&gt;&lt;font size="3"&gt;Indeed the presence of the constraint is somewhat reassuring here, as the requirement on node types is made clearer.&lt;span style="FONT-SIZE:12pt;"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Now, sometimes it is also desirable to be able to compare “entire containers”, e.g. compare one set with another, or one map with another, or one graph with another. This is a lot like comparing tuples or lists. At a first approximation this is done by customizing equality and/or comparison for the container.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; Graph&amp;lt;'Node when 'Node : equality&amp;gt;() = &lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;override&lt;/span&gt; x.Equals(yobj) = ...&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;override&lt;/span&gt; x.GetHashCode() = ... &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;In this case, the node type already supports equality/hashing (for indexing inside the collection ) so the implementation of “Equals” is simple enough, following&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;the pattern laid out in the section “Customizing Equality and Comparison” above.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Sometimes, however, it is necessary to declare that equality (and comparison) over generic container values themselves is “dependent” on the type parameters of the container type. Just like F# list and tuple types. This is done by adding the &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;EqualityConditionalOn&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt; and &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;ComparisonConditionalOn&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font face="Calibri"&gt;&lt;font size="3"&gt; attributes to the type parameters of a generic type.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;As our example, we will use that beguilingly simple beast – a single-cell container that also supports equality and comparison over the container.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;You can define this easily in F# as follows:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; MyBox&amp;lt;'T&amp;gt; = MyBox &lt;span style="COLOR:blue;"&gt;of&lt;/span&gt; 'T&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:12pt;"&gt;&lt;font face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;In this case, this is a structural type definition, and F# infers that there is an equality and comparison dependency on ‘T. All done! You will be able to use MyBox&amp;lt;_&amp;gt; with values of any type, and you will only be able to do equality and comparison on MyBox values if the element type also supports equality and comparison – perfect!&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;However, what if MyBox is, for some reason, implemented as a class type, or with customized comparison and equality logic for the type? In this case you need to be more explicit, starting with the &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;EqualityConditionalOn&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt; and &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;ComparisonConditionalOn&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt; attributes on the type parameter: &lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;type&lt;/span&gt; MyBox&amp;lt;[&amp;lt;EqualityConditionalOn; ComparisonConditionalOn &amp;gt;]'T&amp;gt; = ...&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;With these attributes, &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;MyBox&amp;lt;A&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt; will only satisfy the &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;equality&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt; and &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;comparison&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt; constraints if &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;A&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt; satisfies these constraints. You will still be able to use &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;MyBox&amp;lt;_&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt; with any type.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Now, let’s look at the custom implementations for &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;Equals&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt;, &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;GetHashCode&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt; and &lt;/font&gt;&lt;span class="CodeInline"&gt;&lt;span style="FONT-SIZE:10pt;"&gt;&lt;font color="#4f81bd" face="Consolas"&gt;System.IComparable&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt;. Here’s a full example of a container type that also supports conditional equality and comparison over the containers themselves:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;type&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; MyBox&amp;lt;[&amp;lt;EqualityConditionalOn; ComparisonConditionalOn &amp;gt;]'T&amp;gt;(value : 'T) =&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;member&lt;/span&gt; x.Value = value&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;override&lt;/span&gt; x.Equals(yobj) = &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;match&lt;/span&gt; yobj &lt;span style="COLOR:blue;"&gt;with&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;| :? MyBox&amp;lt;'T&amp;gt; &lt;span style="COLOR:blue;"&gt;as&lt;/span&gt; y &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; Unchecked.equals x.Value y.Value&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;| _ &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;false&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;override&lt;/span&gt; x.GetHashCode() = Unchecked.hash x.Value&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;interface&lt;/span&gt; System.IComparable &lt;span style="COLOR:blue;"&gt;with&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;member&lt;/span&gt; x.CompareTo yobj = &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;match&lt;/span&gt; yobj &lt;span style="COLOR:blue;"&gt;with&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;| :? MyBox&amp;lt;'T&amp;gt; &lt;span style="COLOR:blue;"&gt;as&lt;/span&gt; y &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; Unchecked.compare x.Value y.Value&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;| _ &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; invalidArg &lt;span style="COLOR:maroon;"&gt;"yobj"&lt;/span&gt; &lt;span style="COLOR:maroon;"&gt;"cannot compare values of different types"&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 72pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:9pt;"&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Note that the implementation of the interfaces and overrides uses “unchecked equality and comparison”, something we’ll get to below. The need for unchecked equality here ultimately stems from the dual facts that &lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoListParagraph"&gt;&lt;span style=""&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;(a)&lt;/font&gt;&lt;span style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt;F# asks you to specify custom equality at the level of .NET overrides and interface implementations; and &lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoListParagraph"&gt;&lt;span style=""&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;(b)&lt;/font&gt;&lt;span style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="3" face="Calibri"&gt;.NET does not support conditional interface and override implementations (see discussion below). &lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;There are great advantages to (a) – it simplifies F# and means you don’t have to look up the F# manual to see what behaviour your objects will have when handed over to C#.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Fortunately, the use of unchecked equality is isolated and localized, and actually surprisingly hard to get wrong. In any case, you should unit test to check that your type really does support equality and comparison correctly.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font face="Calibri"&gt;&lt;font size="3"&gt;Getting IEqualityComparer&amp;lt;’T&amp;gt; and IComparer&amp;lt;’T&amp;gt; Implementations which use F# Generic Equality&lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;When using .NET libraries, it is very common to need an implementation of IEqualityComparer&amp;lt;'T&amp;gt; or IComparer&amp;lt;'T&amp;gt;.&lt;span style=""&gt;&amp;nbsp; &lt;/span&gt;Two F# core library functions are very useful for getting objects which implement these interfaces in a way that is consistent with F# equality and comparison:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;HashIdentity.Structural&amp;lt;'T&amp;gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;: IEqualityComparer&amp;lt;'T&amp;gt; &lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'T : equality&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;ComparisonIdentity.Structural&amp;lt;'T&amp;gt; : IComparer&amp;lt;'T&amp;gt;&lt;span style=""&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'T : comparable&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;These are most useful when instantiating .NET hash table and comparison operations. For example:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;open&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; System.Collections.Generic&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;let&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; hashTable = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; Dictionary&amp;lt;string,int&amp;gt;(HashIdentity.Structural&amp;lt;string&amp;gt;)&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;let&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; hashSet = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; HashSet&amp;lt;string&amp;gt;(HashIdentity.Structural&amp;lt;string&amp;gt;)&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;You can also omit some of the type annotations here and let inference do its work:&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;open&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; System.Collections.Generic&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;let&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; hashTable = Dictionary(HashIdentity.Structural)&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;let&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; hashSet = HashSet(HashIdentity.Structural)&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;hashTable.Add("three", 3)&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;hashSet.Add("three")&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;The great advantage of giving an explicit HashIdentity.* or ComparisonIdentity.* argument is that your code is more rigidly checked: the F# compiler checks if your inferred key type actually admits F# equality. For example, F# function types are considered to be “no equality” (i.e. hashing on an F# function values is not a good idea):&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;open&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; System.Collections.Generic&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;let&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; concatOne (s:string) = s + "1"&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;COLOR:blue;"&gt;let&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt; hashTable = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; Dictionary&amp;lt;_,_&amp;gt;(HashIdentity.Structural)&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;hashTable.Add(concatOne, 10) &lt;span style="COLOR:green;"&gt;// error: the type “string -&amp;gt; string” doesn’t support equality&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:12pt;"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Here the intended code was something like this:&lt;/font&gt;&lt;/p&gt;
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;hashTable.Add(concatOne "ten", 10) &lt;span style="COLOR:green;"&gt;// ok: the type “string” supports equality&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE:12pt;"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font face="Calibri"&gt;&lt;font size="3"&gt;Using unchecked equality and comparison&lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;As we saw above, it can occasionally it can be necessary to resort to “unchecked” equality and comparison on values. This doesn’t do any static checking, just like in earlier versions of F#.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;Unchecked.equals: 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; bool &lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;Unchecked.hash: 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; int&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;Unchecked.compare: 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; int&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;These are unconstrained operations, and work just the same way as the constrained operations – for example, they will also by optimized by the F# compiler if used on basic integer types. For Unchecked.equals and Unchecked.hash, they are semantically similar to converting to the type “obj” and doing equality over that static type.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font face="Calibri"&gt;&lt;font size="3"&gt;Design Alternatives. Could interface constraints suffice? What about type classes?&lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Readers familiar with C# may ask “Does F# really need a new kind of constraint here? How about using an interface constraint?”. For example, could we use this signature for comparison?&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;compare : 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; bool &lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'T : System.IComparable&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Or this one?&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt; &amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;compare : 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; 'T &lt;span style="COLOR:blue;"&gt;-&amp;gt;&lt;/span&gt; bool &lt;span style="COLOR:blue;"&gt;when&lt;/span&gt; 'T : System.IComparable&amp;lt;'T&amp;gt;&lt;/span&gt;&lt;span style="FONT-FAMILY:Consolas;"&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:12pt;"&gt;&lt;font face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;The problem with both is that they are too permissive: for example, if F# lists implement IComparable or IComparable&amp;lt;'T&amp;gt;, then the above signatures would let you use comparison on any two F# lists, &lt;i style=""&gt;regardless of whether the element type supports comparison&lt;/i&gt;. &lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;The underlying (and well known) problem is that interface implementation in .NET is &lt;i style=""&gt;unconditional&lt;/i&gt;&lt;span style=""&gt; – a type either supports an interface or it doesn’t. &lt;span style=""&gt;&amp;nbsp;&lt;/span&gt;This is a fundamental limitation of .NET generics. In F#, it is part of our design methodology to add additional, erased constraints to work around such limitations.&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;Equally it is also not possible to use a parameter constraint on the F# list type. For example, consider this option:&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:12pt;"&gt;&lt;font face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="TEXT-INDENT:36pt;MARGIN:0cm 0cm 0pt 36pt;" class="MsoNormal"&gt;&lt;span style="FONT-FAMILY:Consolas;FONT-SIZE:10pt;"&gt;type FSharpList&amp;lt;'T &lt;span style="COLOR:red;"&gt;when 'T : IComparable&amp;lt;'T&amp;gt;&lt;/span&gt;&amp;gt;() = ... // this leads the type to be over-constrained.&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="FONT-SIZE:12pt;"&gt;&lt;font face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;With this signature, lists become much less useful: you couldn’t create lists of objects that don’t support comparison!&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style=""&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;As a result, .NET interface constraints are not sufficient to allow us to tackle equality and comparison constraints in F#. This underlies the decision to include equality and comparison constraints as new, erased constraints in the F# language.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Readers familiar with Haskell and other functional languages will be well informed of all the issues relating to equality and comparison, since the issues are fundamental to equality and comparison in any typed language, but particularly functional languages. The mechanisms used to address these points in F# are reminiscent of a weak form of type classes, particularly in the way equality and comparison are dependent on the structure of types, and the way these dependencies can be declared for any type. Haskell also lets users define their own constraints, in a very rich (and sometimes fairly complicated!) way.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Now, equality and comparison are the &lt;i style=""&gt;only&lt;/i&gt; operations in the F# Core Library that are statically conditional on the structure of types. This raises the question as to why F# doesn’t allow user-defined constraints (beyond interface constraints), and why other constraints can’t be declared conditional. After all, it is well known that it can be useful to make other operations conditional on structure too, e.g. printing and serialization.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;The answer is two-fold. Firstly, in future versions of F# we may consider extending the mechanisms used to implement equality and comparison constraints to include user-defined constraints. &lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;Secondly, however, for many common used constraints (such as formatting and serializability), there are other ways to achieve the same thing in F# that are not particularly amenable to using constraints. Also, in each case there are serious interactions with .NET libraries and existing design practice to consider. Finally, some conditional constraints would require a “dictionary passing” implementation. This brings added difficulties. Equality and comparison constraints are not dictionary passing – they are ultimately implemented via interfaces and overrides. As a result, for F# in Visual Studio 2010, we concentrated on resolving the interactions with .NET for the critical cases of equality and comparison, rather than adding a completely general mechanism. &lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;b style=""&gt;&lt;font size="3"&gt;&lt;font face="Calibri"&gt;Summary&lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;F# equality and comparison constraints tighten up a key part of the F# language, they make user code safer and simpler.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;On the whole, F# code is surprisingly unaffected by these constraints – in our test trees we have a very large collection of sample F# code, and only a very small amount of that code needed to have equality or comparison constraints added. These constraints catch problems, but do not intrude. For example, we use structural and equality constraints throughout the F# compiler codebase and, in a couple of cases, it helped to identify lingering potential bugs.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;In 1.9.7 we also simplified some of the attributes used to control equality and comparison, notably removing the “true” and “false” arguments from StructuralEquality etc., and adding CustomEquality to help users declare exactly what is intended. If you need additional help to adjust your code for these changes, please let us know.&lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;We wish you many happy days of safer and more productive coding! &lt;/font&gt;&lt;/p&gt;
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt; 
&lt;p style="MARGIN:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;font size="3" face="Calibri"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9919259" width="1" height="1"&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/yvg2v-ImwH8f10j-E011tkebEWE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yvg2v-ImwH8f10j-E011tkebEWE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/yvg2v-ImwH8f10j-E011tkebEWE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yvg2v-ImwH8f10j-E011tkebEWE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=DUoGqerCOH4:3UgXs0rq5qc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=DUoGqerCOH4:3UgXs0rq5qc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=DUoGqerCOH4:3UgXs0rq5qc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=DUoGqerCOH4:3UgXs0rq5qc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=DUoGqerCOH4:3UgXs0rq5qc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=DUoGqerCOH4:3UgXs0rq5qc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=DUoGqerCOH4:3UgXs0rq5qc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/DUoGqerCOH4" height="1" width="1"/&gt;</description>
      <link>http://blogs.msdn.com/dsyme/archive/2009/11/08/equality-and-comparison-constraints-in-f-1-9-7.aspx</link>
      <author>dsyme</author>
      <pubDate>Sun, 08 Nov 2009 09:42:00 GMT</pubDate>
    </item>
    <item>
      <title>"Getting started" with NaturalSpec – (Updated 08.11.2009)</title>
      <description>&lt;p&gt;In my last article (&lt;a rel="nofollow" target="_blank" href="http://www.navision-blog.de/2009/02/23/introducing-naturalspec-a-dsl-for-testing-part-i/"&gt;Introducing NaturalSpec – A Domain-specific language (DSL) for testing&lt;/a&gt;) I used NaturalSpec in two small samples. This time I will show how we can set up a &lt;a rel="nofollow" target="_blank" href="http://code.google.com/p/natural/"&gt;NaturalSpec&lt;/a&gt; environment to write our first automatically testable scenarios.&lt;/p&gt;
&lt;h5&gt;1. Choosing an IDE&lt;/h5&gt;
&lt;p&gt;The first step is to choose an integrated development environment for NaturalSpec. At the current project status you should be able to use NaturalSpec with Visual Studio 2008, Visual Studio 2010 beta 2, the freely available &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/vsx2008/products/bb933751.aspx"&gt;Visual Studio 2008 Shell&lt;/a&gt; or the free IDE &lt;a rel="nofollow" target="_blank" href="http://www.icsharpcode.net/OpenSource/SD/"&gt;SharpDevelop 3.0&lt;/a&gt;.&lt;/p&gt;
&lt;h5&gt;2. Installing the testing framework&lt;/h5&gt;
&lt;p&gt;As NaturalSpec uses &lt;a rel="nofollow" target="_blank" href="http://www.nunit.org/index.php"&gt;NUnit&lt;/a&gt; as the underlying testing framework we have to install NUnit 2.5. I also recommend installing &lt;a rel="nofollow" target="_blank" href="http://testdriven.net/default.aspx"&gt;TestDriven.Net&lt;/a&gt; in order to get a Unit Test runner within Visual Studio.&lt;/p&gt;
&lt;h5&gt;3. Installing F#&lt;/h5&gt;
&lt;p&gt;NaturalSpec is completely written in &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/F_Sharp_programming_language"&gt;F#&lt;/a&gt; and all specs will also be written in F#. This doesn’t imply you have to learn programming in F# but we need the F# compiler to get things working. You can download the &lt;a rel="nofollow" target="_blank" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=b55f0532-ac3c-4106-918c-5586a953a7da&amp;amp;displaylang=en"&gt;F# October 2009 CTP&lt;/a&gt; from the &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/fsharp/default.aspx"&gt;Microsoft F# Developer Center&lt;/a&gt;.&lt;/p&gt;
&lt;h5&gt;4. Downloading the latest version of NaturalSpec&lt;/h5&gt;
&lt;p&gt;You can download a .zip with the &lt;a rel="nofollow" target="_blank" href="http://code.google.com/p/natural/"&gt;latest NaturalSpec libraries from GoogleCode&lt;/a&gt;.&lt;/p&gt;
&lt;h5&gt;5. Creating a spec&lt;/h5&gt;
&lt;p&gt;This part is written for using Visual Studio 2008. If you use SharpDevelop or Visual Studio 2008 Shell this might differ in some detail.&lt;/p&gt;
&lt;p&gt;Start Visual Studio 2008 and create a new F# class library.&lt;/p&gt;
&lt;p&gt;&lt;img class="bordered" title="Creating a spec project" border="0" alt="Creating a spec project" src="http://www.navision-blog.de/images/GettingstartedwithNaturalSpec_A7B1/image.png" width="500" height="354"/&gt;&lt;/p&gt;
&lt;p&gt;Rename &lt;em&gt;Module1.fs&lt;/em&gt; in &lt;em&gt;ListSpec.fs&lt;/em&gt; and delete &lt;em&gt;script.fsx&lt;/em&gt; from the project:&lt;/p&gt;
&lt;p&gt;&lt;img class="bordered" title="Solution explorer" border="0" alt="Solution explorer" src="http://www.navision-blog.de/images/GettingstartedwithNaturalSpec_A7B1/image_3.png" width="248" height="146"/&gt;&lt;/p&gt;
&lt;p&gt;Create a folder “Lib” and unzip the NaturalSpec libraries into it.&lt;/p&gt;
&lt;p&gt;Add &lt;em&gt;NaturalSpec.dll&lt;/em&gt; and &lt;em&gt;nunit.framework.dll&lt;/em&gt; as references to your project:&lt;/p&gt;
&lt;p&gt;&lt;img class="bordered" title="Adding project references" alt="Adding project references" src="http://www.navision-blog.de/images/GettingstartedwithNaturalSpec_A7B1/image_4.png" width="482" height="406"/&gt;&lt;/p&gt;
&lt;p&gt;Copy the following code into ListSpec.fs:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;module &lt;/span&gt;ListSpec&lt;/pre&gt;
&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;open &lt;/span&gt;NaturalSpec [&amp;lt;Scenario&amp;gt;]
&lt;span style="color:blue;"&gt;let &lt;/span&gt;When_removing_an_3_from_a_small_list_it_should_not_contain_3() = Given [1;2;3;4;5] |&amp;gt; When removing 3 |&amp;gt; It shouldn't contain 3 |&amp;gt; Verify&lt;/pre&gt;
&lt;p&gt;If you have TestDriven.Net installed you can run your spec via right click in the solution explorer:&lt;/p&gt;
&lt;p&gt;&lt;img class="bordered" title="Run spec with TestDriven.net" alt="Run spec with TestDriven.net" src="http://www.navision-blog.de/images/GettingstartedwithNaturalSpec_A7B1/image_5.png" width="295"/&gt;&lt;/p&gt;
&lt;p&gt;If you don’t like the TestDriven.Net test runner you might want to use the NUnit GUI runner. The output should look like:&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.navision-blog.de/images/GettingstartedwithNaturalSpec_A7B1/image_6.png"&gt;&lt;img class="bordered" title="NUnit Gui runner" border="0" alt="NUnit Gui runner" src="http://www.navision-blog.de/images/GettingstartedwithNaturalSpec_A7B1/image_thumb.png" width="500" height="264"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In addition the test runner should produce a Spec output file with the name “Spec.txt” within the same folder.&lt;/p&gt;
&lt;h5&gt;Summary&lt;/h5&gt;
&lt;p&gt;In a minimal environment you need &lt;a rel="nofollow" target="_blank" href="http://www.icsharpcode.net/OpenSource/SD/"&gt;SharpDevelop&lt;/a&gt;, the &lt;a rel="nofollow" target="_blank" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=b55f0532-ac3c-4106-918c-5586a953a7da&amp;amp;displaylang=en"&gt;F# compiler&lt;/a&gt;, &lt;a rel="nofollow" target="_blank" href="http://www.nunit.org/index.php"&gt;NUnit&lt;/a&gt; and the &lt;a rel="nofollow" target="_blank" href="http://code.google.com/p/natural/"&gt;NaturalSpec libraries&lt;/a&gt; for using NaturalSpec. &lt;/p&gt;
&lt;p&gt;In the next post I will show how you can &lt;a rel="nofollow" target="_blank" href="http://www.navision-blog.de/2009/02/23/using-naturalspec-to-create-spec-for-c-projects/"&gt;use NaturalSpec to create a spec for C# projects&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;copy;2009 &lt;a rel="nofollow" target="_blank" href="http://www.navision-blog.de"&gt;Rash thoughts about .NET, C#, F# and Dynamics NAV.&lt;/a&gt;. All Rights Reserved.&lt;/p&gt;.&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257673680"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257673680" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/BUZEgXxo_DDQ91aEYnYyEN4nQog/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BUZEgXxo_DDQ91aEYnYyEN4nQog/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/BUZEgXxo_DDQ91aEYnYyEN4nQog/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BUZEgXxo_DDQ91aEYnYyEN4nQog/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=7NgOXz6nDOY:E5hCyem0ga0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=7NgOXz6nDOY:E5hCyem0ga0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=7NgOXz6nDOY:E5hCyem0ga0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=7NgOXz6nDOY:E5hCyem0ga0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=7NgOXz6nDOY:E5hCyem0ga0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=7NgOXz6nDOY:E5hCyem0ga0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=7NgOXz6nDOY:E5hCyem0ga0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/7NgOXz6nDOY" height="1" width="1"/&gt;</description>
      <link>http://www.navision-blog.de/2009/11/08/getting-started-with-naturalspec/</link>
      <pubDate>Sun, 08 Nov 2009 01:48:00 GMT</pubDate>
    </item>
    <item>
      <title>Observing global hotkeys in C# / F#</title>
      <description>&lt;p&gt;I recently had the problem to register a global hotkey, but my “old” Win32-API calls didn’t work with WPF. I looked around the web and found the “&lt;a rel="nofollow" target="_blank" href="http://mwinapi.sourceforge.net/"&gt;Managed Windows API&lt;/a&gt;”, but I didn’t want to add another external dependency to my project, so I extracted the core functions for registering hotkeys and condensed the code to a new version. &lt;/p&gt;
&lt;p&gt;As the original “Managed Windows API” is licensed by the GNU Lesser General Public License (LGPL) I want to provide my modifications here.&lt;/p&gt;
&lt;p&gt;First we need a Window which can dispatch the window messages to our event handlers:&lt;/p&gt;
&lt;div style="font-family:courier new;background:white;color:black;font-size:10pt;"&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; A Win32 native window that delegates window messages to &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:green;"&gt;handlers. So several&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; components can use the same native window to save &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:green;"&gt;"USER resources". This class&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; is useful when writing your own components.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;sealed&lt;/span&gt; &lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;EventDispatchingNativeWindow&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;NativeWindow&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;{&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;readonly&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Object&lt;/span&gt; MyLock = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Object&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;EventDispatchingNativeWindow&lt;/span&gt; _instance;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; Create your own event dispatching window.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;public&lt;/span&gt; EventDispatchingNativeWindow()&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CreateHandle(&lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;CreateParams&lt;/span&gt;());&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; A global instance which can be used by components &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:green;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;that do not need&lt;/span&gt;&lt;span style="color:green;"&gt; their own window.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;EventDispatchingNativeWindow&lt;/span&gt; Instance&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;get&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;lock&lt;/span&gt; (MyLock)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;return&lt;/span&gt; &lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _instance ?? &lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (_instance = &lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;EventDispatchingNativeWindow&lt;/span&gt;());&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; Attach your event handlers here.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;event&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;WndProcEventHandler&lt;/span&gt; EventHandler;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; Parse messages passed to this window and send &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:gray;"&gt;&amp;#160;&amp;#160;&amp;#160; ///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:green;"&gt;them to the event handlers.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;param name="m"&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;A System.Windows.Forms.Message &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:gray;"&gt;&amp;#160;&amp;#160;&amp;#160; ///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:green;"&gt;that is associated with the &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; current Windows message.&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;protected&lt;/span&gt; &lt;span style="color:blue;"&gt;override&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; WndProc(&lt;span style="color:blue;"&gt;ref&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Message&lt;/span&gt; m)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; handled = &lt;span style="color:blue;"&gt;false&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (EventHandler != &lt;span style="color:blue;"&gt;null&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; EventHandler(&lt;span style="color:blue;"&gt;ref&lt;/span&gt; m, &lt;span style="color:blue;"&gt;ref&lt;/span&gt; handled);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (!handled)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;base&lt;/span&gt;.WndProc(&lt;span style="color:blue;"&gt;ref&lt;/span&gt; m);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Now we can write our global hotkey handler class:&lt;/p&gt;
&lt;div style="font-family:courier new;background:white;color:black;font-size:10pt;"&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; Specifies a class that creates a global keyboard hotkey.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;GlobalHotkey&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;{&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;readonly&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Object&lt;/span&gt; MyStaticLock = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Object&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;int&lt;/span&gt; _hotkeyCounter = 0xA000;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;readonly&lt;/span&gt; &lt;span style="color:blue;"&gt;int&lt;/span&gt; _hotkeyIndex;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;readonly&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IntPtr&lt;/span&gt; _hWnd;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; Initializes a new instance of this class.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;param name="keys"&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;The keys.&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;param name="ctrl"&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;if &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;c&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;true&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/c&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt; [CTRL].&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;param name="alt"&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;if &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;c&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;true&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/c&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt; [alt].&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;param name="shift"&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;if &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;c&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;true&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/c&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt; [shift].&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;param name="winKey"&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;if &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;c&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;true&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/c&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt; [win key].&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;public&lt;/span&gt; GlobalHotkey(&lt;span style="color:#2b91af;"&gt;Keys&lt;/span&gt; keys, &lt;span style="color:blue;"&gt;bool&lt;/span&gt; ctrl, &lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; alt, &lt;span style="color:blue;"&gt;bool&lt;/span&gt; shift, &lt;span style="color:blue;"&gt;bool&lt;/span&gt; winKey)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; KeyCode = keys;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Ctrl = ctrl;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Alt = alt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Shift = shift;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; WindowsKey = winKey;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#2b91af;"&gt;EventDispatchingNativeWindow&lt;/span&gt;.Instance.EventHandler &lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; += NwEventHandler;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;lock&lt;/span&gt; (MyStaticLock)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _hotkeyIndex = ++_hotkeyCounter;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _hWnd = &lt;span style="color:#2b91af;"&gt;EventDispatchingNativeWindow&lt;/span&gt;.Instance.Handle;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Enable();&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; The key code of the hotkey.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Keys&lt;/span&gt; KeyCode { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; Whether the shortcut includes the Control modifier.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; Ctrl { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; Whether this shortcut includes the Alt modifier.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; Alt { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; Whether this shortcut includes the shift modifier.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; Shift { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; Whether this shortcut includes the Windows key modifier.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:green;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; WindowsKey { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; ~GlobalHotkey()&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Disable();&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#2b91af;"&gt;EventDispatchingNativeWindow&lt;/span&gt;.Instance.EventHandler &lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; -= NwEventHandler;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; Enables the hotkey. When the hotkey is enabled, &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:gray;"&gt;&amp;#160;&amp;#160;&amp;#160; ///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:green;"&gt;pressing it causes a&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;c&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;HotkeyPressed&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/c&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt; event instead of being &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:gray;"&gt;&amp;#160;&amp;#160;&amp;#160; ///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:green;"&gt;handled by the active&lt;/span&gt;&lt;span style="color:green;"&gt; application.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; Enable()&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:green;"&gt;// register hotkey&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;int&lt;/span&gt; fsModifiers = 0;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (Shift) fsModifiers += ModShift;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (Ctrl) fsModifiers += ModControl;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (Alt) fsModifiers += ModAlt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (WindowsKey) fsModifiers += ModWin;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; success = &lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; RegisterHotKey(_hWnd, _hotkeyIndex, &lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; fsModifiers, (&lt;span style="color:blue;"&gt;int&lt;/span&gt;) KeyCode);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (!success)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;throw&lt;/span&gt; &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:#2b91af;"&gt;&lt;font color="#000000"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;Exception&lt;/span&gt;(&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:#a31515;"&gt;"Could not register hotkey (already in use)."&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; Disables this instance.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; Disable()&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:green;"&gt;// unregister hotkey&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; UnregisterHotKey(_hWnd, _hotkeyIndex);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; Occurs when the hotkey is pressed.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:gray;"&gt;///&lt;/span&gt;&lt;span style="color:green;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;event&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;EventHandler&lt;/span&gt; HotkeyPressed;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; NwEventHandler(&lt;span style="color:blue;"&gt;ref&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Message&lt;/span&gt; m, &lt;span style="color:blue;"&gt;ref&lt;/span&gt; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; handled)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (handled) &lt;span style="color:blue;"&gt;return&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (m.Msg != WmHotkey || &lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m.WParam.ToInt32() != _hotkeyIndex)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;return&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (HotkeyPressed != &lt;span style="color:blue;"&gt;null&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; HotkeyPressed(&lt;span style="color:blue;"&gt;this&lt;/span&gt;, &lt;span style="color:#2b91af;"&gt;EventArgs&lt;/span&gt;.Empty);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; handled = &lt;span style="color:blue;"&gt;true&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;#160;&amp;#160;&amp;#160; #region&lt;/span&gt; PInvoke Declarations&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;const&lt;/span&gt; &lt;span style="color:blue;"&gt;int&lt;/span&gt; ModAlt = 0&amp;#215;0001;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;const&lt;/span&gt; &lt;span style="color:blue;"&gt;int&lt;/span&gt; ModControl = 0&amp;#215;0002;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;const&lt;/span&gt; &lt;span style="color:blue;"&gt;int&lt;/span&gt; ModShift = 0&amp;#215;0004;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;const&lt;/span&gt; &lt;span style="color:blue;"&gt;int&lt;/span&gt; ModWin = 0&amp;#215;0008;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;const&lt;/span&gt; &lt;span style="color:blue;"&gt;int&lt;/span&gt; WmHotkey = 0&amp;#215;0312;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; [&lt;span style="color:#2b91af;"&gt;DllImport&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;"user32.dll"&lt;/span&gt;, SetLastError = &lt;span style="color:blue;"&gt;true&lt;/span&gt;)]&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;extern&lt;/span&gt; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; RegisterHotKey(&lt;span style="color:#2b91af;"&gt;IntPtr&lt;/span&gt; hWnd, &lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;int&lt;/span&gt; id, &lt;span style="color:blue;"&gt;int&lt;/span&gt; fsModifiers, &lt;span style="color:blue;"&gt;int&lt;/span&gt; vlc);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; [&lt;span style="color:#2b91af;"&gt;DllImport&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;"user32.dll"&lt;/span&gt;, SetLastError = &lt;span style="color:blue;"&gt;true&lt;/span&gt;)]&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;extern&lt;/span&gt; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; UnregisterHotKey(&lt;span style="color:#2b91af;"&gt;IntPtr&lt;/span&gt; hWnd, &lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color:blue;"&gt;int&lt;/span&gt; id);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;#160;&amp;#160;&amp;#160; #endregion&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Now we can easily register a global hotkey or use it as an observable in F#:&lt;/p&gt;
&lt;div style="font-family:courier new;background:white;color:black;font-size:10pt;"&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:green;"&gt;/// system-wide keyboard hook&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;let&lt;/span&gt; hotkey = &lt;span style="color:blue;"&gt;new&lt;/span&gt; GlobalHotkey(Keys.Q,&lt;span style="color:blue;"&gt;true&lt;/span&gt;,&lt;span style="color:blue;"&gt;false&lt;/span&gt;,&lt;span style="color:blue;"&gt;false&lt;/span&gt;,&lt;span style="color:blue;"&gt;false&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;let&lt;/span&gt; hookObserver =&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160; hotkey.HotkeyPressed&amp;#160; &lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; |&amp;gt; Observable.subscribe (&lt;span style="color:blue;"&gt;fun&lt;/span&gt; _ &lt;span style="color:blue;"&gt;-&amp;gt;&lt;/span&gt; printfn &lt;span style="color:maroon;"&gt;"Hotkey pressed"&lt;/span&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&amp;copy;2009 &lt;a rel="nofollow" target="_blank" href="http://www.navision-blog.de"&gt;Rash thoughts about .NET, C#, F# and Dynamics NAV.&lt;/a&gt;. All Rights Reserved.&lt;/p&gt;.
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/xsrXPskBWK9XCD2orS6pFzszZP0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xsrXPskBWK9XCD2orS6pFzszZP0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/xsrXPskBWK9XCD2orS6pFzszZP0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xsrXPskBWK9XCD2orS6pFzszZP0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=nXng1gFUSiM:hRu_pkiePww:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=nXng1gFUSiM:hRu_pkiePww:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=nXng1gFUSiM:hRu_pkiePww:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=nXng1gFUSiM:hRu_pkiePww:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=nXng1gFUSiM:hRu_pkiePww:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=nXng1gFUSiM:hRu_pkiePww:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=nXng1gFUSiM:hRu_pkiePww:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/nXng1gFUSiM" height="1" width="1"/&gt;</description>
      <link>http://www.navision-blog.de/2009/11/06/observing-global-shortcuts/</link>
      <pubDate>Fri, 06 Nov 2009 02:08:05 GMT</pubDate>
    </item>
    <item>
      <title>Technical analysis indicators in F# – Part I</title>
      <description>This is the first part of a series on technical analysis indicators in F#.
We will define the basic object holding the data series which will be used to compute the indicators. We will also describe some functions to check the integrity of the said data (and which will be useful when defining the indicators). Quick disclaimer [...] &lt;div id="related-posts"&gt; &lt;h3&gt;And also &amp;hellip;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/11/09/technical-analysis-indicators-in-f-part-ii"&gt;Technical analysis indicators in F# &amp;#8211; Part II&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2008/04/22/redimensionneur-dimages"&gt;Batch image resizer&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/10/19/readwrite-requests-for-a-group-of-files"&gt;Read/Write requests for a group of files&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;
&lt;/div&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257482821"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257482821" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/6T5kKn33gegsiRrgnrWa3nrq5O4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6T5kKn33gegsiRrgnrWa3nrq5O4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/6T5kKn33gegsiRrgnrWa3nrq5O4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6T5kKn33gegsiRrgnrWa3nrq5O4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=IM12ivsJH-0:qNhcN_e-i6w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=IM12ivsJH-0:qNhcN_e-i6w:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=IM12ivsJH-0:qNhcN_e-i6w:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=IM12ivsJH-0:qNhcN_e-i6w:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=IM12ivsJH-0:qNhcN_e-i6w:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=IM12ivsJH-0:qNhcN_e-i6w:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=IM12ivsJH-0:qNhcN_e-i6w:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/IM12ivsJH-0" height="1" width="1"/&gt;</description>
      <link>http://lepensemoi.free.fr/index.php/2009/11/06/technical-analysis-indicators-in-f-part-i</link>
      <pubDate>Thu, 05 Nov 2009 20:47:01 GMT</pubDate>
    </item>
    <item>
      <title>F# for Visualization 0.4.0.2 released</title>
      <description>A new release of our F# for Visualization library is now available to beta release subscribers. This release is designed to work with the new October 2009 CTP release of F#.&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257476100"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257476100" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/UJuMBFSPVUHu4Hq8E0T32Dx5ILE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UJuMBFSPVUHu4Hq8E0T32Dx5ILE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/UJuMBFSPVUHu4Hq8E0T32Dx5ILE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UJuMBFSPVUHu4Hq8E0T32Dx5ILE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=dg0ncsuGsRc:JFmae-9QjBY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=dg0ncsuGsRc:JFmae-9QjBY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=dg0ncsuGsRc:JFmae-9QjBY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=dg0ncsuGsRc:JFmae-9QjBY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=dg0ncsuGsRc:JFmae-9QjBY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=dg0ncsuGsRc:JFmae-9QjBY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=dg0ncsuGsRc:JFmae-9QjBY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/dg0ncsuGsRc" height="1" width="1"/&gt;</description>
      <link>http://fsharpnews.blogspot.com/2009/11/f-for-visualization-0402-released.html</link>
      <pubDate>Thu, 05 Nov 2009 18:55:00 GMT</pubDate>
    </item>
    <item>
      <title>Custom WPF Controls in F#</title>
      <description>&lt;p&gt;*Update: Custom WPF Controls in F# is now available on Codeplex at &lt;a rel="nofollow" target="_blank" href="http://wpffsharp.codeplex.com"&gt;http://wpffsharp.codeplex.com&lt;/a&gt;. You can still download the source from my site &lt;a rel="nofollow" target="_blank" href="http://www.mattssoftwareblog.com/asdflkjh/BookExplorerFSharp.zip"&gt;here&lt;/a&gt;. (Works best withVSTS2010 Beta1)&lt;/p&gt;
&lt;div id="attachment_197" class="wp-caption aligncenter" style="width:310px;"&gt;&lt;img class="size-medium wp-image-197" title="BookExplorerWPFControlDevelopment" src="http://www.mattssoftwareblog.com/wp-content/uploads/2009/11/BookExplorerWPFControlDevelopment-300x211.PNG" alt="Screen Shot" width="300" height="211"/&gt;&lt;p class="wp-caption-text"&gt;Screen Shot&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;It is a translation of &lt;a rel="nofollow" target="_blank" href="http://www.informit.com/store/product.aspx?isbn=0672330334"&gt;SAMS WPF Control Development Unleashed: Building Advanced User Interfaces&lt;/a&gt; written by Pavan Podila, and Kevin Hoffman to F#. I picked this book for translation as it covers many advanced topics that other books shy away from. I have been a reader of Pavan Podila’s blog &lt;a rel="nofollow" target="_blank" href="http://blog.pixelingene.com/"&gt;Pixel in Gene&lt;/a&gt; for some time, and I have also been waiting for a book dedicated advanced UIs, so when I heard that he was coming out with such a book I knew it was going to be exactly what I needed.&lt;/p&gt;
&lt;div class="wp-caption aligncenter" style="width:170px;"&gt;&lt;img title="WPF Control Development" src="http://www.informit.com/ShowCover.aspx?isbn=0672330334&amp;amp;type=f" alt="WPF Control Development Unleashed" width="160" height="209"/&gt;&lt;p class="wp-caption-text"&gt;WPF Control Development&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;The aim behind this project is to serve as an extensive collection non trivial examples of WPF/F# UI. As I introduce people to F#, one thing I am constantly asked is; can it do GUI. Now I can say yes, &amp;#8230; well sort of. So far I have only translated 3,500 lines of F# code, and I am still not finished.&lt;/p&gt;
&lt;p&gt;I’m doing this primarily as a learning experience and as a forcing function. I have already learned a lot about WPF and F#, and I plan on continuously improving the code as I learn more. Other contributions to the project would be very welcome, and if you spot mistakes or know of any better implementations please don’t hesitate to let me know.&lt;/p&gt;
&lt;p&gt;I hope that you find this code to be useful to your WPF and F# projects , and happy coding.&lt;/p&gt;
&lt;p&gt;-Matt&lt;/p&gt;
&lt;p&gt;Read on for a list of known bugs;&lt;/p&gt;
&lt;p&gt;&lt;span id="more-191"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A recent upgrade from VSTS 2010 Beta 1 to VSTS 2010 Beta 2 has unfortunately caused a whole lot of new bugs (on top of the ones that were already there).&lt;/p&gt;
&lt;p&gt;List of known bugs:&lt;/p&gt;
&lt;div id="_mcePaste" style="width:1px;height:1px;"&gt;Chapter 2 &amp;#8211; Media element doesn&amp;#8217;t play&lt;/div&gt;
&lt;div id="_mcePaste" style="width:1px;height:1px;"&gt;Chapter 9 - TransitionContainer (delegate blocked off from TransitionTester_Loaded)&lt;/div&gt;
&lt;div id="_mcePaste" style="width:1px;height:1px;"&gt;Chapter 10 &amp;#8211; ComponentResourceKey ?? Not sure what is happening here&lt;/div&gt;
&lt;div id="_mcePaste" style="width:1px;height:1px;"&gt;Chapter 10 &amp;#8211; Custom Chrome Window, no skin on window&lt;/div&gt;
&lt;div id="_mcePaste" style="width:1px;height:1px;"&gt;Chapter 11 &amp;#8211; GardenViewPanel3D and Interactive GardenViewPanel3D both register the same names (they work individually)&lt;/div&gt;
&lt;div id="_mcePaste" style="width:1px;height:1px;"&gt;Chapter 12 &amp;#8211; Issues with enums for 3D mesh&lt;/div&gt;
&lt;div id="_mcePaste" style="width:1px;height:1px;"&gt;Chapter 13 &amp;#8211; Dependency properties for SqueezeEffect and DisplacementEffect overlap? &amp;#8220;Input&amp;#8217; property was already registered by &amp;#8216;DisplacementEffect&amp;#8217;&amp;#8221;&lt;/div&gt;
&lt;div id="_mcePaste" style="width:1px;height:1px;"&gt;Chapter 14 &amp;#8211; WeekEvent / Command Source (Property SpikeControl.Command not found)&lt;/div&gt;
&lt;div id="_mcePaste" style="width:1px;height:1px;"&gt;Chapter 15 &amp;#8211; Media element doesn&amp;#8217;t play&lt;/div&gt;
&lt;div id="_mcePaste" style="width:1px;height:1px;"&gt;Chapter 17 &amp;#8211; Cannot find the static member &amp;#8216;WatermakrTextProperty&amp;#8217; on the type &amp;#8216;TextBoxWatermarkHelper&amp;#8217;&lt;/div&gt;
&lt;div id="_mcePaste" style="width:1px;height:1px;"&gt;
&lt;p&gt;Chapter 18 &amp;#8211; ComputedStartOffsetProperty on type RangeSelector&lt;/p&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Chapter 2 &amp;#8211; Media element doesn&amp;#8217;t play&lt;/li&gt;
&lt;li&gt;Chapter 9 - TransitionContainer (delegate blocked off from TransitionTester_Loaded)&lt;/li&gt;
&lt;li&gt;Chapter 10 &amp;#8211; ComponentResourceKey ?? Not sure what is happening here&lt;/li&gt;
&lt;li&gt;Chapter 10 &amp;#8211; Custom Chrome Window, no skin on window&lt;/li&gt;
&lt;li&gt;Chapter 11 &amp;#8211; GardenViewPanel3D and Interactive GardenViewPanel3D both register the same names (they work individually)&lt;/li&gt;
&lt;li&gt;Chapter 12 &amp;#8211; Issues with enums for 3D mesh&lt;/li&gt;
&lt;li&gt;Chapter 13 &amp;#8211; Dependency properties for SqueezeEffect and DisplacementEffect overlap? &amp;#8220;Input&amp;#8217; property was already registered by &amp;#8216;DisplacementEffect&amp;#8217;&amp;#8221;&lt;/li&gt;
&lt;li&gt;Chapter 14 &amp;#8211; WeekEvent / Command Source (Property SpikeControl.Command not found)&lt;/li&gt;
&lt;li&gt;Chapter 15 &amp;#8211; Media element doesn&amp;#8217;t play&lt;/li&gt;
&lt;li&gt;Chapter 17 &amp;#8211; Cannot find the static member &amp;#8216;WatermakrTextProperty&amp;#8217; on the type &amp;#8216;TextBoxWatermarkHelper&amp;#8217;&lt;/li&gt;
&lt;li&gt;Chapter 18 &amp;#8211; ComputedStartOffsetProperty on type RangeSelector&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257470097"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257470097" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/qfYEwO8QJPuJsei-5JrF6wOpvKw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qfYEwO8QJPuJsei-5JrF6wOpvKw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/qfYEwO8QJPuJsei-5JrF6wOpvKw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qfYEwO8QJPuJsei-5JrF6wOpvKw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=vuGV4xJNRoQ:0VCk-ZhgYOs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=vuGV4xJNRoQ:0VCk-ZhgYOs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=vuGV4xJNRoQ:0VCk-ZhgYOs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=vuGV4xJNRoQ:0VCk-ZhgYOs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=vuGV4xJNRoQ:0VCk-ZhgYOs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=vuGV4xJNRoQ:0VCk-ZhgYOs:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=vuGV4xJNRoQ:0VCk-ZhgYOs:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/vuGV4xJNRoQ" height="1" width="1"/&gt;</description>
      <link>http://www.mattssoftwareblog.com/?p=191</link>
      <pubDate>Thu, 05 Nov 2009 17:14:57 GMT</pubDate>
    </item>
    <item>
      <title>F# 1.9.7 Language Specification Now Available</title>
      <description>&lt;p&gt;The F# 1.9.7 Language Specification is now available, in &lt;a rel="nofollow" target="_blank" href="http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.pdf"&gt;PDF&lt;/a&gt; and &lt;a rel="nofollow" target="_blank" href="http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html"&gt;HTML&lt;/a&gt;, matching the recent release of &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/dsyme/archive/2009/10/19/visual-studio-2010-beta2-with-f-is-now-available-plus-matching-f-ctp-update-for-vs2008.aspx"&gt;F# in Visual Studio 2010 Beta2, with matching&amp;nbsp;CTP udpate for Mono and Visual Studio 2008&lt;/a&gt;.&amp;nbsp;The latest language specification can also always be found via &lt;a rel="nofollow" target="_blank" href="http://www.fsharp.net/"&gt;www.fsharp.net&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Many thanks to all those who sent so much helpful feedback on the specification during Beta1. And for those using 1.9.7 already, thanks for your patience in the last couple of weeks - it took us a little longer to get this out the door than we had planned, since a development deadline for Visual Studio 2010 intervened. &lt;/p&gt;
&lt;p&gt;We plan on making a second update to the 1.9.7 spec to polish some areas of the text in the next few weeks.&lt;/p&gt;
&lt;p&gt;thanks,&lt;/p&gt;
&lt;p&gt;don&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9917436" width="1" height="1"&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257356760"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257356760" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/CBDS8QcTSCsvoJLsDFpAX_HJ064/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CBDS8QcTSCsvoJLsDFpAX_HJ064/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/CBDS8QcTSCsvoJLsDFpAX_HJ064/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CBDS8QcTSCsvoJLsDFpAX_HJ064/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=wQWQrx-LV30:HUfHOxh5qWk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=wQWQrx-LV30:HUfHOxh5qWk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=wQWQrx-LV30:HUfHOxh5qWk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=wQWQrx-LV30:HUfHOxh5qWk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=wQWQrx-LV30:HUfHOxh5qWk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=wQWQrx-LV30:HUfHOxh5qWk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=wQWQrx-LV30:HUfHOxh5qWk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/wQWQrx-LV30" height="1" width="1"/&gt;</description>
      <link>http://blogs.msdn.com/dsyme/archive/2009/11/04/f-1-9-7-language-specification-now-available.aspx</link>
      <author>dsyme</author>
      <pubDate>Wed, 04 Nov 2009 09:46:00 GMT</pubDate>
    </item>
    <item>
      <title>F# under the covers VII</title>
      <description>&lt;p&gt;Working with nCover to examine the number of code-points represented by any given method, the October CTP made a large number of changes -- some up, some down -- to the code generated by the compiler.&lt;/p&gt;
&lt;p&gt;Most interesting is the change to attribute setters, which used to be NOP;assign;return and are now just assign;return. Also the name of the implicit backing field has changed to be the property name with an appended '@', rather than being a case-mangled version of the property name.&lt;/p&gt;
&lt;p&gt;(As always, talking about Debug builds).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5569894-3247237309816149534?l=stevegilham.blogspot.com'/&gt;&lt;/div&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257284040"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257284040" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/H90lCCJsuraBcF7xeTLXEIs00f8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/H90lCCJsuraBcF7xeTLXEIs00f8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/H90lCCJsuraBcF7xeTLXEIs00f8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/H90lCCJsuraBcF7xeTLXEIs00f8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=kL9XCOfw9w0:0_CGh0_bveA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=kL9XCOfw9w0:0_CGh0_bveA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=kL9XCOfw9w0:0_CGh0_bveA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=kL9XCOfw9w0:0_CGh0_bveA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=kL9XCOfw9w0:0_CGh0_bveA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=kL9XCOfw9w0:0_CGh0_bveA:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=kL9XCOfw9w0:0_CGh0_bveA:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/kL9XCOfw9w0" height="1" width="1"/&gt;</description>
      <link>http://stevegilham.blogspot.com/2009/11/f-under-covers-vii.html</link>
      <author>Steve</author>
      <pubDate>Tue, 03 Nov 2009 13:34:00 GMT</pubDate>
    </item>
    <item>
      <title>Discriminated Unions in F#</title>
      <description>&lt;img src="http://ecn.channel9.msdn.com/o9/ch9/3/8/8/3/0/5/DiscriminatedUnions_85_ch9.png" border="0"/&gt;&lt;p&gt;In this video, programming writer, Gordon Hogenson explains and gives examples of discriminated unions in F#. &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;You can also learn more in the topic &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/dd233226(VS.100).aspx"&gt;Discriminated Unions (F#)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Kathleen McGrath&lt;br /&gt;
Visual Studio User Education&lt;br /&gt;
&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/kathleen"&gt;http://blogs.msdn.com/kathleen&lt;/a&gt;&lt;br /&gt;
&lt;a rel="nofollow" target="_blank" href="http://go.microsoft.com/fwlink/?LinkID=102169"&gt;Visual Studio and .NET Framework Content Survey&lt;/a&gt;&lt;/p&gt;&lt;img src="http://channel9.msdn.com/503883/WebViewBug.aspx?EVT=0" height="1" width="1" alt=""/&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257268800"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257268800" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/lVI1MZ0rSen-X7AOPtEVX9EMPsE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lVI1MZ0rSen-X7AOPtEVX9EMPsE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/lVI1MZ0rSen-X7AOPtEVX9EMPsE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lVI1MZ0rSen-X7AOPtEVX9EMPsE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=8EQEsAhxie8:Js_ki4-joww:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=8EQEsAhxie8:Js_ki4-joww:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=8EQEsAhxie8:Js_ki4-joww:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=8EQEsAhxie8:Js_ki4-joww:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=8EQEsAhxie8:Js_ki4-joww:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=8EQEsAhxie8:Js_ki4-joww:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=8EQEsAhxie8:Js_ki4-joww:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/8EQEsAhxie8" height="1" width="1"/&gt;</description>
      <link>http://channel9.msdn.com/posts/kmcgrath/Discriminated-Unions-in-FSharp/</link>
      <pubDate>Tue, 03 Nov 2009 09:20:00 GMT</pubDate>
    </item>
    <item>
      <title>An RSS Dashboard in F#, part one</title>
      <description>&lt;p&gt;As you may know, I am quite active answering questions on forums like &lt;a rel="nofollow" target="_blank" href="http://stackoverflow.com/"&gt;StackOverflow&lt;/a&gt; and &lt;a rel="nofollow" target="_blank" href="http://cs.hubfs.net/forums/TopicsActive.aspx"&gt;hubfs&lt;/a&gt;. I want F# users to get prompt and useful answers to their questions (and yes, I also wanted to be the first person to earn the &lt;a rel="nofollow" target="_blank" href="http://stackoverflow.com/badges/74/f"&gt;F# badge on SO&lt;/a&gt;). But of course I cannot afford to spend all my time hitting the refresh button in my web browser, just waiting to pounce on new questions. So I need a tool to make it easy for me to keep abreast of forum topics. while still getting my other work done. I’ve created such a tool for myself, which I’ll describe in this blog series.&lt;/p&gt; &lt;h3&gt;Setting goal for the app&lt;/h3&gt; &lt;p&gt;Any reasonable web forum will be publishing an &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Rss_feed"&gt;RSS feed&lt;/a&gt; (or &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Atom_feed"&gt;Atom feed&lt;/a&gt;) of its posts, so it’s easy to get the data I wanted. The only thing I needed to do was figure out an effective way to present the information. The requirements I set up for myself were&lt;/p&gt; &lt;ul&gt; &lt;li&gt;I wanted a &lt;strong&gt;“dashboard”-style app&lt;/strong&gt;. That is, I wanted to be able to view a summary of all the forum topics I care about on a single screen. &lt;li&gt;Of course I needed to be able to &lt;strong&gt;control the set of forum feeds/topics&lt;/strong&gt; the app listens to. &lt;li&gt;I wanted the ability to get &lt;strong&gt;audio notification for new posts&lt;/strong&gt; on interesting topics. This way I can leave the app running in the background during the day while I’m doing other work, but still be able to react quickly to new questions. &lt;li&gt;I wanted to easily &lt;strong&gt;visualize the “diff”&lt;/strong&gt; over longer periods of time. For example, when I get in on Monday morning, I want to quickly be able to see “what’s new and different” since the last time I looked at the forums from the weekend.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Now, perhaps there is already a great tool out there which I could download that already meets all those requirements. But like many developers, I personally set a few more (selfish) requirements, namely&lt;/p&gt; &lt;ul&gt; &lt;li&gt;I wanted to built it myself in F#, &lt;li&gt;so I could experiment with some new-to-me technologies I don’t typically use in my day job, &lt;li&gt;and so I could blog about it.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;So without further ado, I present…&lt;/p&gt; &lt;h3&gt;Brian’s RSS Dashboard&lt;/h3&gt; &lt;p&gt;Here’s a screenshot of the app, which tells half the story by itself (sometimes a picture really is worth a thousand words):&lt;/p&gt; &lt;p&gt;&lt;a rel="nofollow" target="_blank" href="https://oljksa.bay.livefilestore.com/y1mZA5MmFWuTuwRKBPR0_B214KYHs0OueB2C8g2b0crw-TfbjQ0UXuaIlgMyScxB9gmgnU5T7eBaDMhuUp5sdsWsh_T6p9UrOHO21WBNJjT75UO_nWEpQ5D6z_84k4AAhQQppGrHtPeubnMOq3REgts9g/RssDashboardScreenshot[7].png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="RssDashboardScreenshot" border="0" alt="RssDashboardScreenshot" src="https://oljksa.bay.livefilestore.com/y1mku9Q2daIbOdhFa46hV3ZVAmn3ioBRSy20aMeNj5v4ejgSeWvtcjhLDByAFRZv4_ReIPbzX7bq9bo2i2vuGrTUFGno4OAk2d0PilBoQWcQCRuV-kMhd3pM91bhylVKMKmPHFWN_cA2eu8IO_6bU6rfg/RssDashboardScreenshot_thumb[5].png" width="784" height="483"/&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;The window is divided up into a grid where each cell is a different topic/forum. Within each cell are the six threads with the most recent activity, sorted in order of recency. Each thread displays its title (long titles are truncated with an ellipsis) and how long ago the thread began. The threads are hyperlinks, so if I click one it opens the corresponding thread in my web browser.&lt;/p&gt; &lt;p&gt;The app polls the various RSS feeds periodically for new activity. When new activity is detected, a few things happen:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;a new entry appears in the listing for the corresponding topic (or, if the thread was already displayed in the list, it gets moved to the top) &lt;li&gt;the thread gets a yellow highlight so that it visually stands out as new &lt;li&gt;(optionally) the title is read aloud over the speakers using the text-to-speech built in to Windows&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The audio is great for when I’m at my desk working on something else. If I’m in “flow” with whatever I’m working on, I just ignore the audio (my brain seems to tune it out automatically), but otherwise if I can take a break or afford a distraction, I’ll go have a look. This helps me provide quick replies to questions, which makes for happy customers and good StackOverflow reputation points. I only have the “audio” option turned on for a select few feeds (to minimize distraction).&lt;/p&gt; &lt;p&gt;The yellow highlight is great for when I return after being away from my desk for a while. When I log on in the morning, first thing I’ll do is glance at the dashboard to see what’s new (yellow). I click on any threads I’m interested in reading (and perhaps responding to) to go visit them in my browser. And then when I’m caught up, I click the big button at the top labeled “Mark all as seen”, which just erases all the yellow highlights.&lt;/p&gt; &lt;p&gt;That’s pretty much it! It’s a simple app, nothing fancy, but I’m very pleased with it, because it makes it super-easy for me to keep track of a number of different forums on different web sites.&lt;/p&gt; &lt;h3&gt;Technology overview&lt;/h3&gt; &lt;p&gt;In subsequent blog entries I’ll walk through all the F# code. Today I’ll just give an overview of the breakdown of the app and the various technologies/APIs that underlie each portion. The app conceptually has four main pieces:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;Observable Feeds&lt;/strong&gt;. I already know plenty about RSS/Atom feeds, seeing as I was part of the team that created the &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/system.servicemodel.syndication.syndicationfeed.aspx"&gt;SyndicationFeed class&lt;/a&gt; in .Net Framework 3.5. &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/dd990377(VS.100).aspx"&gt;IObservable&amp;lt;T&amp;gt;&lt;/a&gt; (the push-vs.-pull dual of &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/9eekhta0.aspx"&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/a&gt;) is, on the other hand, new technology that I wanted an excuse to play around with. For this app, an important piece of the code is about making feeds be IObservables. &lt;li&gt;&lt;strong&gt;Speech.&lt;/strong&gt; Though the .Net &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/system.speech.synthesis.aspx"&gt;speech synthesis APIs&lt;/a&gt; are dirt-simple to use, there’s still a bit of futzing around to do here if, for example, you want your computer to pronounce “GUI” like “gooey”. &lt;li&gt;&lt;strong&gt;Getting link-coloring info from Internet Explorer.&lt;/strong&gt; I really wanted the links in my app to be the same color as the links in my browser. But I also wanted my entire UI to be hand-coded WPF (I didn’t want to create HTML and host that in browser, that is not fun/interesting to me). So I needed a way to get IE to tell me what color each link should be. Perhaps there is a simple(r) way to do this, but I did find a way that involved hosting an invisible IE control that browses some HTML-and-Javascript my app serves to get the info it needs. It’s one of those hacks that you know is awful, but you nevertheless grin about, because it works. (I’d never written a line of Javascript before this – more unexpected new technology. Score!) &lt;li&gt;&lt;strong&gt;The WPF UI.&lt;/strong&gt; This is undoubtedly the most complex UI I’ve ever created on my own. Since the app is basically a grid of text and a single button, you would be correct to infer that my prior UI experience is practically zero. :) When you have no UI experience, it is easy to be tickled pink when you first get your pretty icons or yellow highlights to appear on the screen. I enjoyed this bit.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;And of course for any UI app, even though there is various background work going on (speech/audio, polling feeds, …) we want to ensure the UI stays up-to-date and responsive. Of course my code never mentions “Thread” or “BackgroundWorker”; instead it’s F# &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/ee370232(VS.100).aspx"&gt;async&lt;/a&gt;, &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/ee370357(VS.100).aspx"&gt;MailboxProcessor&lt;/a&gt;, and .Net &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx"&gt;SynchronizationContext&lt;/a&gt; FTW! I was very pleased how easy that part was.&lt;/p&gt; &lt;h3&gt;For next time…&lt;/h3&gt; &lt;p&gt;If you’re not yet familiar with IObservable, might I suggest that you watch a &lt;a rel="nofollow" target="_blank" href="http://channel9.msdn.com/shows/Going+Deep/E2E-Erik-Meijer-and-Wes-Dyer-Reactive-Framework-Rx-Under-the-Hood-1-of-2/"&gt;video&lt;/a&gt; &lt;a rel="nofollow" target="_blank" href="http://channel9.msdn.com/shows/Going+Deep/E2E-Erik-Meijer-and-Wes-Dyer-Reactive-Framework-Rx-Under-the-Hood-2-of-2/"&gt;or&lt;/a&gt; &lt;a rel="nofollow" target="_blank" href="http://channel9.msdn.com/shows/Going+Deep/Kim-Hamilton-and-Wes-Dyer-Inside-NET-Rx-and-IObservableIObserver-in-the-BCL-VS-2010/"&gt;three&lt;/a&gt;? It’s cool stuff; a simple set of interfaces for a powerful reactive eventing model.&lt;/p&gt; &lt;p&gt;Hopefully you’re aware of RSS feeds (and you’re subscribed to my blog’s feed :), right?), but if not, at least read the paragraph summary on &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Rss_feed"&gt;wikipedia&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Next time we’ll jump into the code for observable feeds. Fun stuff ahead!&lt;/p&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257234482"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257234482" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4hDE2hlPTzUvgVF1YJn9MVL7FoA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4hDE2hlPTzUvgVF1YJn9MVL7FoA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4hDE2hlPTzUvgVF1YJn9MVL7FoA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4hDE2hlPTzUvgVF1YJn9MVL7FoA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=ypIXv97Eu48:74HWQKvFpXU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=ypIXv97Eu48:74HWQKvFpXU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=ypIXv97Eu48:74HWQKvFpXU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=ypIXv97Eu48:74HWQKvFpXU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=ypIXv97Eu48:74HWQKvFpXU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=ypIXv97Eu48:74HWQKvFpXU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=ypIXv97Eu48:74HWQKvFpXU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/ypIXv97Eu48" height="1" width="1"/&gt;</description>
      <link>http://lorgonblog.spaces.live.com/Blog/cns!701679AD17B6D310!1612.entry</link>
      <pubDate>Mon, 02 Nov 2009 23:48:02 GMT</pubDate>
    </item>
    <item>
      <title>Awesome F# - Decision Trees – Part II</title>
      <description>&lt;p&gt;In my &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/chrsmith/"&gt;previous post&lt;/a&gt; I went over the theory behind the &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/ID3_algorithm"&gt;ID3 algorithm&lt;/a&gt;. Now that we got all that painful math out of the way, let’s write some code! Here is an implementation of the algorithm in F#. (It is also attached to this blog post, download it via the link at the bottom.) &lt;/p&gt; &lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;open &lt;/span&gt;System &lt;span style="color:blue;"&gt;type &lt;/span&gt;Record = { Outlook : string Temperature : string Humidity : string Wind : string PlayTennis : bool } &lt;span style="color:green;"&gt;/// Given an attribute name return its value &lt;/span&gt;&lt;span style="color:blue;"&gt;member &lt;/span&gt;this.GetAttributeValue(attrName) = &lt;span style="color:blue;"&gt;match &lt;/span&gt;attrName &lt;span style="color:blue;"&gt;with &lt;/span&gt;| &lt;span style="color:maroon;"&gt;"Outlook" &lt;/span&gt;&lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;this.Outlook | &lt;span style="color:maroon;"&gt;"Temperature" &lt;/span&gt;&lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;this.Temperature | &lt;span style="color:maroon;"&gt;"Humidity" &lt;/span&gt;&lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;this.Humidity | &lt;span style="color:maroon;"&gt;"Wind" &lt;/span&gt;&lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;this.Wind | _ &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;failwithf &lt;span style="color:maroon;"&gt;"Invalid attribute name '%s'" &lt;/span&gt;attrName &lt;span style="color:green;"&gt;/// Make the %o format specifier look all pretty like &lt;/span&gt;&lt;span style="color:blue;"&gt;override &lt;/span&gt;this.ToString() = sprintf &lt;span style="color:maroon;"&gt;"{Outlook = %s, Temp = %s, Humidity = %s, Wind = %s, PlayTennis = %b}" &lt;/span&gt;this.Outlook this.Temperature this.Humidity this.Wind this.PlayTennis &lt;span style="color:blue;"&gt;type &lt;/span&gt;DecisionTreeNode = &lt;span style="color:green;"&gt;// Attribute name and value / child node list &lt;/span&gt;| DecisionNode &lt;span style="color:blue;"&gt;of &lt;/span&gt;string * (string * DecisionTreeNode) seq &lt;span style="color:green;"&gt;// Decision and corresponding evidence &lt;/span&gt;| Leaf &lt;span style="color:blue;"&gt;of &lt;/span&gt;bool * Record seq &lt;span style="color:green;"&gt;// ---------------------------------------------------------------------------- /// Return the total true, total false, and total count for a set of Records
&lt;/span&gt;&lt;span style="color:blue;"&gt;let &lt;/span&gt;countClassifications data = Seq.fold (&lt;span style="color:blue;"&gt;fun &lt;/span&gt;(t,f,c) item &lt;span style="color:blue;"&gt;-&amp;gt; match &lt;/span&gt;item.PlayTennis &lt;span style="color:blue;"&gt;with &lt;/span&gt;| &lt;span style="color:blue;"&gt;true -&amp;gt; &lt;/span&gt;(t + &lt;span style="color:brown;"&gt;1&lt;/span&gt;, f, c + &lt;span style="color:brown;"&gt;1&lt;/span&gt;) | &lt;span style="color:blue;"&gt;false -&amp;gt; &lt;/span&gt;(t, f + &lt;span style="color:brown;"&gt;1&lt;/span&gt;, c + &lt;span style="color:brown;"&gt;1&lt;/span&gt;)) (&lt;span style="color:brown;"&gt;0&lt;/span&gt;, &lt;span style="color:brown;"&gt;0&lt;/span&gt;, &lt;span style="color:brown;"&gt;0&lt;/span&gt;) data &lt;span style="color:green;"&gt;// ---------------------------------------------------------------------------- /// Return the theoretical number of bits required to classify the information.
/// If a 50/50 mix, returns 1, if 100% true or false returns 0.
&lt;/span&gt;&lt;span style="color:blue;"&gt;let &lt;/span&gt;entropy data = &lt;span style="color:blue;"&gt;let &lt;/span&gt;(trueValues, falseValues, totalCount) = countClassifications data &lt;span style="color:blue;"&gt;let &lt;/span&gt;probTrue = (float trueValues) / (float totalCount) &lt;span style="color:blue;"&gt;let &lt;/span&gt;probFalse = (float falseValues) / (float totalCount) &lt;span style="color:green;"&gt;// Log2(1.0) = infinity, short circuiting this part &lt;/span&gt;&lt;span style="color:blue;"&gt;if &lt;/span&gt;trueValues = totalCount || falseValues = totalCount &lt;span style="color:blue;"&gt;then &lt;/span&gt;&lt;span style="color:brown;"&gt;0.0 &lt;/span&gt;&lt;span style="color:blue;"&gt;else &lt;/span&gt;-probTrue * Math.Log(probTrue, &lt;span style="color:brown;"&gt;2.0&lt;/span&gt;) + -probFalse * Math.Log(probFalse, &lt;span style="color:brown;"&gt;2.0&lt;/span&gt;) &lt;span style="color:green;"&gt;/// Given a set of data, how many bits do you save if you know the provided attribute.
&lt;/span&gt;&lt;span style="color:blue;"&gt;let &lt;/span&gt;informationGain (data : Record seq) attr = &lt;span style="color:green;"&gt;// Partition the data into new sets based on each unique value of the given attribute // e.g. [ where Outlook = rainy ], [ where Outlook = overcast], [ ... ] &lt;/span&gt;&lt;span style="color:blue;"&gt;let &lt;/span&gt;divisionsByAttribute = data |&amp;gt; Seq.groupBy(&lt;span style="color:blue;"&gt;fun &lt;/span&gt;item &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;item.GetAttributeValue(attr)) &lt;span style="color:blue;"&gt;let &lt;/span&gt;totalEntropy = entropy data &lt;span style="color:blue;"&gt;let &lt;/span&gt;entropyBasedOnSplit = divisionsByAttribute |&amp;gt; Seq.map(&lt;span style="color:blue;"&gt;fun &lt;/span&gt;(attributeValue, rowsWithThatValue) &lt;span style="color:blue;"&gt;-&amp;gt; let &lt;/span&gt;ent = entropy rowsWithThatValue &lt;span style="color:blue;"&gt;let &lt;/span&gt;percentageOfTotalRows = (float &amp;lt;| Seq.length rowsWithThatValue) / (float &amp;lt;| Seq.length data) -&lt;span style="color:brown;"&gt;1.0 &lt;/span&gt;* percentageOfTotalRows * ent) |&amp;gt; Seq.sum totalEntropy + entropyBasedOnSplit &lt;span style="color:green;"&gt;// ---------------------------------------------------------------------------- /// Give a list of attributes left to branch on and training data,
/// construct a decision tree node.
&lt;/span&gt;&lt;span style="color:blue;"&gt;let rec &lt;/span&gt;createTreeNode data attributesLeft = &lt;span style="color:blue;"&gt;let &lt;/span&gt;(totalTrue, totalFalse, totalCount) = countClassifications data &lt;span style="color:green;"&gt;// If we have tested all attributes, then label this node with the // most often occuring instance; likewise if everything has the same value. &lt;/span&gt;&lt;span style="color:blue;"&gt;if &lt;/span&gt;List.length attributesLeft = &lt;span style="color:brown;"&gt;0 &lt;/span&gt;|| totalTrue = &lt;span style="color:brown;"&gt;0 &lt;/span&gt;|| totalFalse = &lt;span style="color:brown;"&gt;0 &lt;/span&gt;&lt;span style="color:blue;"&gt;then let &lt;/span&gt;mostOftenOccuring = &lt;span style="color:blue;"&gt;if &lt;/span&gt;totalTrue &amp;gt; totalFalse &lt;span style="color:blue;"&gt;then true else false &lt;/span&gt;Leaf(mostOftenOccuring, data) &lt;span style="color:green;"&gt;// Otherwise, create a proper decision tree node and branch accordingly &lt;/span&gt;&lt;span style="color:blue;"&gt;else let &lt;/span&gt;attributeWithMostInformationGain = attributesLeft |&amp;gt; List.map(&lt;span style="color:blue;"&gt;fun &lt;/span&gt;attrName &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;attrName, (informationGain data attrName)) |&amp;gt; List.maxBy(&lt;span style="color:blue;"&gt;fun &lt;/span&gt;(attrName, infoGain) &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;infoGain) |&amp;gt; fst &lt;span style="color:blue;"&gt;let &lt;/span&gt;remainingAttributes = attributesLeft |&amp;gt; List.filter ((&amp;lt;&amp;gt;) attributeWithMostInformationGain) &lt;span style="color:green;"&gt;// Partition that data base on the attribute's values &lt;/span&gt;&lt;span style="color:blue;"&gt;let &lt;/span&gt;partitionedData = Seq.groupBy (&lt;span style="color:blue;"&gt;fun &lt;/span&gt;(r : Record) &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;r.GetAttributeValue(attributeWithMostInformationGain)) data &lt;span style="color:green;"&gt;// Create child nodes &lt;/span&gt;&lt;span style="color:blue;"&gt;let &lt;/span&gt;childNodes = partitionedData |&amp;gt; Seq.map (&lt;span style="color:blue;"&gt;fun &lt;/span&gt;(attrValue, subData) &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;attrValue, (createTreeNode subData remainingAttributes)) DecisionNode(attributeWithMostInformationGain, childNodes)&lt;/pre&gt;
&lt;a rel="nofollow" target="_blank" href="http://11011.net/software/vspaste"&gt;&lt;/a&gt; &lt;p&gt;The entropy and informationGain functions were covered in my last post, so let’s walk through how the actual decision tree gets constructed. There’s a little work to calculating the optimal decision tree split, but with F# you can express it quite beautifully.&lt;/p&gt; &lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;let &lt;/span&gt;attributeWithMostInformationGain = attributesLeft |&amp;gt; List.map(&lt;span style="color:blue;"&gt;fun &lt;/span&gt;attrName &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;attrName, (informationGain data attrName)) |&amp;gt; List.maxBy(&lt;span style="color:blue;"&gt;fun &lt;/span&gt;(attrName, infoGain) &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;infoGain) |&amp;gt; fst&lt;/pre&gt; &lt;p&gt;First, it takes all the potential attributes left to split on…&lt;/p&gt; &lt;pre class="code"&gt;attributesLeft &lt;/pre&gt;
&lt;a rel="nofollow" target="_blank" href="http://11011.net/software/vspaste"&gt;&lt;/a&gt; &lt;p&gt;… and then maps that attribute name to a new attribute name / information gain tuple …&lt;/p&gt; &lt;pre class="code"&gt;|&amp;gt; List.map(&lt;span style="color:blue;"&gt;fun &lt;/span&gt;attrName &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;attrName, (informationGain data attrName))&lt;/pre&gt;
&lt;a rel="nofollow" target="_blank" href="http://11011.net/software/vspaste"&gt;&lt;/a&gt; &lt;p&gt;… then from the newly generated list, pick out the tuple with the highest information gain …&lt;/p&gt; &lt;pre class="code"&gt;|&amp;gt; List.maxBy(&lt;span style="color:blue;"&gt;fun &lt;/span&gt;(attrName, infoGain) &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;infoGain)&lt;/pre&gt;
&lt;a rel="nofollow" target="_blank" href="http://11011.net/software/vspaste"&gt;&lt;/a&gt; &lt;p&gt;…finally returning the first element of that tuple, which is the attribute with the highest information gain.&lt;/p&gt; &lt;pre class="code"&gt;|&amp;gt; fst&lt;/pre&gt; &lt;p&gt;Once you can construct a decision tree in memory, how do get it out? The simplest way is to print it to the console.&lt;/p&gt; &lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartII_84F5/image_2.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartII_84F5/image_thumb.png" width="551" height="293"/&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;The code is very straight forward. Note the use of ‘padding parameter’, so that recursive calls get indented more and more. This is a very helpful technique when printing tree-like data structures to the console.&lt;/p&gt; &lt;pre class="code"&gt;&lt;span style="color:green;"&gt;/// Print the decision tree to the console
&lt;/span&gt;&lt;span style="color:blue;"&gt;let rec &lt;/span&gt;printID3Result indent node = &lt;span style="color:blue;"&gt;let &lt;/span&gt;padding = &lt;span style="color:blue;"&gt;new &lt;/span&gt;System.String(&lt;span style="color:maroon;"&gt;' '&lt;/span&gt;, indent) &lt;span style="color:blue;"&gt;match &lt;/span&gt;node &lt;span style="color:blue;"&gt;with &lt;/span&gt;| Leaf(classification, data) &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color:maroon;"&gt;"&amp;#92;tClassification = %b" &lt;/span&gt;classification &lt;span style="color:green;"&gt;// data |&amp;gt; Seq.iter (fun item -&amp;gt; printfn "%s-&amp;gt;%s" padding &amp;lt;| item.ToString()) &lt;/span&gt;| DecisionNode(attribute, childNodes) &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color:maroon;"&gt;"" &lt;/span&gt;&lt;span style="color:green;"&gt;// Finish previous line &lt;/span&gt;printfn &lt;span style="color:maroon;"&gt;"%sBranching on attribute [%s]" &lt;/span&gt;padding attribute childNodes |&amp;gt; Seq.iter (&lt;span style="color:blue;"&gt;fun &lt;/span&gt;(attrValue, childNode) &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;printf &lt;span style="color:maroon;"&gt;"%s-&amp;gt;With value [%s]..." &lt;/span&gt;padding attrValue printID3Result (indent + &lt;span style="color:brown;"&gt;4&lt;/span&gt;) childNode)&lt;/pre&gt;
&lt;a rel="nofollow" target="_blank" href="http://11011.net/software/vspaste"&gt;&lt;/a&gt; &lt;p&gt;However, it’s almost the year 2010. So in lieu of flying cars perhaps we can at least do better than printing data to the console. Ideally, we want to generate some sexy image like this:&lt;/p&gt; &lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartII_84F5/image_4.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartII_84F5/image_thumb_1.png" width="403" height="295"/&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;You &lt;em&gt;could &lt;/em&gt;painstakingly construct the decision tree using &lt;a rel="nofollow" target="_blank" href="http://office.microsoft.com/en-us/visio/FX100487861033.aspx"&gt;Microsoft Visio&lt;/a&gt; but fortunately there are tools to do this for you. AT&amp;amp;T Research has produced a great tool called &lt;a rel="nofollow" target="_blank" href="http://www.graphviz.org/"&gt;GraphViz&lt;/a&gt;. While the end result doesn’t quite have &lt;em&gt;sizzle&lt;/em&gt;, it’s very easy enough to get going.&lt;/p&gt; &lt;p&gt;The following function dumps the decision tree into a format that GraphViz can plot. (Just copy the printed text into the tool and plot it using the default settings.)&lt;/p&gt; &lt;pre class="code"&gt;&lt;span style="color:green;"&gt;/// Prints the tree in a format amenable to GraphViz
/// See http://www.graphviz.org/ for more format
&lt;/span&gt;&lt;span style="color:blue;"&gt;let &lt;/span&gt;printInGraphVizFormat node = &lt;span style="color:blue;"&gt;let rec &lt;/span&gt;printNode parentName name node = &lt;span style="color:blue;"&gt;match &lt;/span&gt;node &lt;span style="color:blue;"&gt;with &lt;/span&gt;| DecisionNode(attribute, childNodes) &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;&lt;span style="color:green;"&gt;// Print the decision node &lt;/span&gt;printfn &lt;span style="color:maroon;"&gt;"&amp;#92;"%s&amp;#92;" [ label = &amp;#92;"%s&amp;#92;" ];" &lt;/span&gt;(parentName + name) attribute &lt;span style="color:green;"&gt;// Print link from parent to this node (unless it's the root) &lt;/span&gt;&lt;span style="color:blue;"&gt;if &lt;/span&gt;parentName &amp;lt;&amp;gt; &lt;span style="color:maroon;"&gt;"" &lt;/span&gt;&lt;span style="color:blue;"&gt;then &lt;/span&gt;printfn &lt;span style="color:maroon;"&gt;"&amp;#92;"%s&amp;#92;" -&amp;gt; &amp;#92;"%s&amp;#92;" [ label = &amp;#92;"%s&amp;#92;" ];" &lt;/span&gt;parentName (parentName + name) name childNodes |&amp;gt; Seq.iter(&lt;span style="color:blue;"&gt;fun &lt;/span&gt;(attrValue, childNode) &lt;span style="color:blue;"&gt;-&amp;gt; &lt;/span&gt;printNode (parentName + name) attrValue childNode) | Leaf(classification, _) &lt;span style="color:blue;"&gt;-&amp;gt; let &lt;/span&gt;label = &lt;span style="color:blue;"&gt;match &lt;/span&gt;classification &lt;span style="color:blue;"&gt;with &lt;/span&gt;| &lt;span style="color:blue;"&gt;true -&amp;gt; &lt;/span&gt;&lt;span style="color:maroon;"&gt;"Yes" &lt;/span&gt;| &lt;span style="color:blue;"&gt;false -&amp;gt; &lt;/span&gt;&lt;span style="color:maroon;"&gt;"No" &lt;/span&gt;&lt;span style="color:green;"&gt;// Print the decision node &lt;/span&gt;printfn &lt;span style="color:maroon;"&gt;"&amp;#92;"%s&amp;#92;" [ label = &amp;#92;"%s&amp;#92;" ];" &lt;/span&gt;(parentName + name) label &lt;span style="color:green;"&gt;// Print link from parent to this node &lt;/span&gt;printfn &lt;span style="color:maroon;"&gt;"&amp;#92;"%s&amp;#92;" -&amp;gt; &amp;#92;"%s&amp;#92;" [ label = &amp;#92;"%s&amp;#92;" ];" &lt;/span&gt;parentName (parentName + name) name printfn &lt;span style="color:maroon;"&gt;"digraph g {" &lt;/span&gt;printNode &lt;span style="color:maroon;"&gt;"" "root" &lt;/span&gt;node printfn &lt;span style="color:maroon;"&gt;"}"&lt;/span&gt;&lt;/pre&gt; &lt;p&gt;So there you have it, ID3 in F#. With a little bit of mathematics and some clever output you can construct decision trees for all your machine learning needs. Think of the ID3 algorithm in the future the next time you want to mine customer transactions, analyze server logs, or program your killer robot to find Sarah Conner.&lt;/p&gt; &lt;p&gt;&amp;lt;TotallyShamelessPlug&amp;gt; If you would like to learn more about F#, check out &lt;a rel="nofollow" target="_blank" href="http://www.amazon.com/Programming-Animal-Guide-Chris-Smith/dp/0596153643"&gt;Programming F#&lt;/a&gt; by O’Reilly. Available on &lt;a rel="nofollow" target="_blank" href="http://www.amazon.com/Programming-Animal-Guide-Chris-Smith/dp/0596153643"&gt;Amazon&lt;/a&gt; and at other fine retailers. &amp;lt;/TotallyShamelessPlug&amp;gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9916536" width="1" height="1"&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257216960"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257216960" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/fmUgWNdJ4GObIQ1uG9LLohgYnOQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fmUgWNdJ4GObIQ1uG9LLohgYnOQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/fmUgWNdJ4GObIQ1uG9LLohgYnOQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fmUgWNdJ4GObIQ1uG9LLohgYnOQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=b01VUUVDDu0:-LzyQ9qnqus:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=b01VUUVDDu0:-LzyQ9qnqus:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=b01VUUVDDu0:-LzyQ9qnqus:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=b01VUUVDDu0:-LzyQ9qnqus:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=b01VUUVDDu0:-LzyQ9qnqus:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=b01VUUVDDu0:-LzyQ9qnqus:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=b01VUUVDDu0:-LzyQ9qnqus:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/b01VUUVDDu0" height="1" width="1"/&gt;</description>
      <link>http://blogs.msdn.com/chrsmith/archive/2009/11/02/awesome-f-decision-trees-part-ii.aspx</link>
      <pubDate>Mon, 02 Nov 2009 18:56:00 GMT</pubDate>
    </item>
    <item>
      <title>F# Discoveries This Week 11/02/2009</title>
      <description>&lt;p&gt;F# events are popping up all over the place and so I’ve included a separate section for them today.&amp;#160; As far as posts go I’ve stumbled across immutable queue and range libraries,&amp;#160; a post on the underlying implementation of discriminated unions, using the reactive framework and finally, a Microsoft research project: F7 Refinement Types.&lt;/p&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;h1 align="center"&gt;-- Events --&lt;/h1&gt; &lt;h3&gt;&lt;a rel="nofollow" target="_blank" href="http://www.nevb.com/"&gt;Talbott Crowell is Presenting at the New England Visual Basic Professionals, November 5th&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;Introducing F#&lt;/strong&gt; at 6:15pm &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;h3&gt;&lt;a rel="nofollow" target="_blank" href="http://fwcodecamp2009.eventbrite.com/?ref=eivte&amp;amp;invite=MjI0NzU2L1JpY2suTWluZXJpY2hAYXRhbGFzb2Z0LmNvbS8w%0A&amp;amp;utm_source=eb_email&amp;amp;utm_medium=email&amp;amp;utm_campaign=invite"&gt;I am Presenting at Fairfield / Westchester Code Camp 2009 on November 7th&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;em&gt;&lt;strong&gt;Why F#&lt;/strong&gt;&lt;/em&gt; at 11:15am in Track 2 &lt;/li&gt; &lt;li&gt;&lt;strong&gt;&lt;em&gt;F# for Testing and Analysis&lt;/em&gt;&lt;/strong&gt; at 2:40pm in Track 4 &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;h3&gt;&lt;a rel="nofollow" target="_blank" href="http://www.nashdotnet.org/archive/2009/10/28/37.aspx"&gt;NashDotNet - F# Firestarter in Franklin, TN on November 14th&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;Come with an open mind and a laptop. Be prepared to learn, share, and chat. No prior knowledge or experience with F# is expected.&lt;/em&gt; &lt;/p&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;h1 align="center"&gt;-- Posts --&lt;/h1&gt; &lt;h3&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/11/02/an-immutable-range-library-in-f"&gt;Julien’s An Immutable Range Library in F#&lt;/a&gt;&amp;#160;&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;An immutable range library in F# where a range is only defined by a minimum and a maximum value (hence, there is no step).&lt;/em&gt; &lt;/p&gt; &lt;/blockquote&gt; &lt;h3&gt;and &lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/10/27/an-immutable-queue-library-in-f"&gt;Julien’s An immutable Queue Library in F#&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;An immutable queue library in F#. The queue is divided into two lists : one for dequeueing, and one for enqueueing. All operations are based on the List module.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;I hope that Julien considers contributing these gems to the F# Power Pack.&lt;/p&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;h3&gt;&lt;a rel="nofollow" target="_blank" href="http://research.microsoft.com/en-us/downloads/c0c4ed53-cfd8-4b9c-b780-74946bd1337e/default.aspx"&gt;F7: Refinement Types for F#&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;F7 is an enhanced type checker for the F# programming language. F7 supports static checking of properties expressed with refinement types. Our motivation is to check various security properties of F# implementation code by typing.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;I took a peek at the included samples and found myself quite lost.&amp;#160; It would be great if a walkthrough on how to use F7 were to pop up.&lt;/p&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;h3&gt;&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/jaredpar/default.aspx"&gt;Using F# Discriminated Unions in C# (VS2010 Beta 2)&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;While updating my VsVim editor extensions for Beta2 [1] I got hit by a change in the way F# exposed discriminated unions in metadata.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;A quick romp through how discriminated unions work under the hood and how you use them from C#.&lt;/p&gt; &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;h3&gt;&lt;a rel="nofollow" target="_blank" href="http://www.navision-blog.de/2009/10/20/iobservableiobserver-using-the-reactive-framework-with-f/"&gt;IObservable/IObserver – Using the Reactive Framework with F#&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;One of the nice new features in .NET 4.0 beta 2 is the IObservable&amp;lt;T&amp;gt;/IObserver&amp;lt;T&amp;gt; support from the Reactive Framework (“Rx Framework” or sometimes “LinqToEvents”). It is a really powerful way to use reactive programming in .NET and especially in F# developed by Erik Meijer and his team.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;div class="shareblock"&gt;&lt;strong&gt;Share this post:&lt;/strong&gt; &lt;a rel="nofollow" target="_blank" href="mailto:?body=Thought you might like this: http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/02/f-discoveries-this-week-11-02-2009.aspx&amp;amp;;subject=F%23+Discoveries+This+Week+11%2f02%2f2009" title="Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/02/f-discoveries-this-week-11-02-2009.aspx"&gt;email it!&lt;/a&gt; | &lt;a rel="nofollow" target="_blank" href="http://del.icio.us/post?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/02/f-discoveries-this-week-11-02-2009.aspx&amp;amp;;title=F%23+Discoveries+This+Week+11%2f02%2f2009" title="Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/02/f-discoveries-this-week-11-02-2009.aspx"&gt;bookmark it!&lt;/a&gt; | &lt;a rel="nofollow" target="_blank" href="http://www.digg.com/submit?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/02/f-discoveries-this-week-11-02-2009.aspx&amp;amp;;phase=2" title="Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/02/f-discoveries-this-week-11-02-2009.aspx"&gt;digg it!&lt;/a&gt; | &lt;a rel="nofollow" target="_blank" href="http://reddit.com/submit?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/02/f-discoveries-this-week-11-02-2009.aspx&amp;amp;title=F%23+Discoveries+This+Week+11%2f02%2f2009" title="Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/02/f-discoveries-this-week-11-02-2009.aspx"&gt;reddit!&lt;/a&gt; | &lt;a rel="nofollow" target="_blank" href="http://www.dotnetkicks.com/submit/?url=http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/02/f-discoveries-this-week-11-02-2009.aspx&amp;amp;;title=F%23+Discoveries+This+Week+11%2f02%2f2009" title="Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/02/f-discoveries-this-week-11-02-2009.aspx"&gt;kick it!&lt;/a&gt; | &lt;a rel="nofollow" target="_blank" href="https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;;mkt=en-us&amp;amp;;url=http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/02/f-discoveries-this-week-11-02-2009.aspx&amp;amp;;title=F%23+Discoveries+This+Week+11%2f02%2f2009&amp;amp;;top=1" title="Post http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/02/f-discoveries-this-week-11-02-2009.aspx"&gt;live it!&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.atalasoft.com/cs/aggbug.aspx?PostID=19634" width="1" height="1"&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257174322"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257174322" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/nJAJjZqYbtehf44YIHWtbSVUoQM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nJAJjZqYbtehf44YIHWtbSVUoQM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/nJAJjZqYbtehf44YIHWtbSVUoQM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nJAJjZqYbtehf44YIHWtbSVUoQM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=vJUtIw3iWS0:sap0f2DUpJc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=vJUtIw3iWS0:sap0f2DUpJc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=vJUtIw3iWS0:sap0f2DUpJc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=vJUtIw3iWS0:sap0f2DUpJc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=vJUtIw3iWS0:sap0f2DUpJc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=vJUtIw3iWS0:sap0f2DUpJc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=vJUtIw3iWS0:sap0f2DUpJc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/vJUtIw3iWS0" height="1" width="1"/&gt;</description>
      <link>http://www.atalasoft.com/cs/blogs/rickm/archive/2009/11/02/f-discoveries-this-week-11-02-2009.aspx</link>
      <pubDate>Mon, 02 Nov 2009 07:05:22 GMT</pubDate>
    </item>
    <item>
      <title>Turning AutoCAD into a Spirograph using F#</title>
      <description>&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257172960"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257172960" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/71WJfSqkSEuXkPIPJmEZHgxdwaM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/71WJfSqkSEuXkPIPJmEZHgxdwaM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/71WJfSqkSEuXkPIPJmEZHgxdwaM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/71WJfSqkSEuXkPIPJmEZHgxdwaM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=t6hetwz2apo:2g7ICpp7akk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=t6hetwz2apo:2g7ICpp7akk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=t6hetwz2apo:2g7ICpp7akk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=t6hetwz2apo:2g7ICpp7akk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=t6hetwz2apo:2g7ICpp7akk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=t6hetwz2apo:2g7ICpp7akk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=t6hetwz2apo:2g7ICpp7akk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/t6hetwz2apo" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/typepad/walmsleyk/through_the_interface/~3/G6Mg-uUsE8s/turning-autocad-into-a-spirograph-using-f.html</link>
      <author>Kean Walmsley</author>
      <pubDate>Mon, 02 Nov 2009 06:42:40 GMT</pubDate>
    </item>
    <item>
      <title>Thinking about ECNs, WF, Oslo State Machine, F# and Task</title>
      <description>&lt;div class='snap_preview'&gt;&lt;br /&gt;&lt;ul&gt;
&lt;li&gt;I&amp;#8217;m not sure how many times people can blog about design patterns, anyway here is another with a Silverlight &lt;a rel="nofollow" target="_blank" href="http://www.robbagby.com/silverlight/patterns-based-silverlight-development-blog-screencast-series-index/"&gt;spin&lt;/a&gt;. You better watch &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/bobfamiliar/archive/2009/10/30/mike-taulty-video-series-on-prism-for-silverlight-3.aspx"&gt;these&lt;/a&gt; video&amp;#8217;s as well if your new to this old world.&lt;/li&gt;
&lt;li&gt;WF 4.0 &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/xiaowen/archive/2009/10/31/wf-4-0-scheduler.aspx"&gt;Scheduler&lt;/a&gt; &amp;#8211; under the hood details&lt;/li&gt;
&lt;li&gt;Reflection &lt;a rel="nofollow" target="_blank" href="http://www.wintellect.com/CS/blogs/jprosise/archive/2009/10/30/reflection-shader-for-silverlight-3.aspx"&gt;Shader&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The impact of &lt;a rel="nofollow" target="_blank" href="http://www.automatedtrader.net/online-exclusive/521/catching-up-with-technology-the-impact-of-regulatory-changes-on-ecnsmtfs-part-2"&gt;regulatory&lt;/a&gt; changes on ECNs/MTFs&lt;/li&gt;
&lt;li&gt;Oslo: State Machine Editor in &lt;a rel="nofollow" target="_blank" href="http://new.efficientcoder.net/2009/10/oslo-state-machine-editor-in.html"&gt;Silverlight&lt;/a&gt; &amp;#8211; interesting article, and probably a good foundation if your thinking about RFQ&amp;#8217;s.&lt;/li&gt;
&lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/wriju/archive/2009/10/30/parallel-computing-the-new-task-api.aspx"&gt;Task&lt;/a&gt; the &lt;a rel="nofollow" target="_blank" href="http://www.danielmoth.com/Blog/2009/10/parallelizing-loop-with-tasks-avoiding.html"&gt;new&lt;/a&gt; thread?&lt;/li&gt;
&lt;li&gt;Awesome &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/chrsmith/archive/2009/10/31/awesome-f-decision-trees-part-i.aspx"&gt;F#&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt; &lt;a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/mdavey.wordpress.com/2402/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mdavey.wordpress.com/2402/"/&gt;&lt;/a&gt; &lt;a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godelicious/mdavey.wordpress.com/2402/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mdavey.wordpress.com/2402/"/&gt;&lt;/a&gt; &lt;a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gostumble/mdavey.wordpress.com/2402/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mdavey.wordpress.com/2402/"/&gt;&lt;/a&gt; &lt;a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/godigg/mdavey.wordpress.com/2402/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mdavey.wordpress.com/2402/"/&gt;&lt;/a&gt; &lt;a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/goreddit/mdavey.wordpress.com/2402/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mdavey.wordpress.com/2402/"/&gt;&lt;/a&gt; &lt;img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mdavey.wordpress.com&amp;blog=18454&amp;post=2402&amp;subd=mdavey&amp;ref=&amp;feed=1"/&gt;&lt;/div&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257150657"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257150657" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Z8TflzI-dD-EDksD0i0_JZYKjcY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Z8TflzI-dD-EDksD0i0_JZYKjcY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Z8TflzI-dD-EDksD0i0_JZYKjcY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Z8TflzI-dD-EDksD0i0_JZYKjcY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=YNro2y8KBdE:6dMKMV6C_I8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=YNro2y8KBdE:6dMKMV6C_I8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=YNro2y8KBdE:6dMKMV6C_I8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=YNro2y8KBdE:6dMKMV6C_I8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=YNro2y8KBdE:6dMKMV6C_I8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=YNro2y8KBdE:6dMKMV6C_I8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=YNro2y8KBdE:6dMKMV6C_I8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/YNro2y8KBdE" height="1" width="1"/&gt;</description>
      <link>http://mdavey.wordpress.com/2009/11/02/thinking-about-ecns-wf-oslo-state-machine-f-and-task/</link>
      <pubDate>Mon, 02 Nov 2009 00:30:57 GMT</pubDate>
    </item>
    <item>
      <title>An immutable range library in F#</title>
      <description>An immutable range library in F# where a range is only defined by a minimum and a maximum value (hence, there is no step). Source type Range&amp;#60;'a when 'a:comparison&amp;#62; = { Min : 'a Max : 'a } override x.ToString() = sprintf &amp;#34;Range [...] &lt;div id="related-posts"&gt; &lt;h3&gt;And also &amp;hellip;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2008/04/22/redimensionneur-dimages"&gt;Batch image resizer&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/09/22/quicksort"&gt;Dual quicksort in F#&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lepensemoi.free.fr/index.php/2009/10/25/a-bit-array-or-bitset-library-in-f"&gt;A bit array (or bitset) library in F#&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;
&lt;/div&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257140129"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257140129" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ZufUPtZUVTj5O7G6DnR4OMtp6nA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZufUPtZUVTj5O7G6DnR4OMtp6nA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ZufUPtZUVTj5O7G6DnR4OMtp6nA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZufUPtZUVTj5O7G6DnR4OMtp6nA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=McOKEgWE5pI:YI3WNh0c-xU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=McOKEgWE5pI:YI3WNh0c-xU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=McOKEgWE5pI:YI3WNh0c-xU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=McOKEgWE5pI:YI3WNh0c-xU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=McOKEgWE5pI:YI3WNh0c-xU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=McOKEgWE5pI:YI3WNh0c-xU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=McOKEgWE5pI:YI3WNh0c-xU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/McOKEgWE5pI" height="1" width="1"/&gt;</description>
      <link>http://lepensemoi.free.fr/index.php/2009/11/02/an-immutable-range-library-in-f</link>
      <pubDate>Sun, 01 Nov 2009 21:35:29 GMT</pubDate>
    </item>
    <item>
      <title>Some quick F# notes…</title>
      <description>&lt;p&gt;I am lining up a blog series, but in the meantime, here are a few quick notes and links to keep you occupied. :)&lt;/p&gt; &lt;p&gt;First, I forgot to mention that the &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/ee353567(VS.100).aspx"&gt;documentation for the F# runtime&lt;/a&gt; (FSharp.Core.dll) is now online on MSDN. Previously these docs were only available from the F# website on research.microsoft.com. The F# docs keep getting better and better, as well as more fleshed out (and I really like the new look and improved usability of the MSDN site overall). So: don’t forget the docs, they’re a valuable resource.&lt;/p&gt; &lt;p&gt;For those of you just getting started with F#, here’s a summary of my most useful introductory/reference links:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!1325.entry"&gt;Brian's favorite online content for learning F#&lt;/a&gt; – a summary of good links to docs/videos/etc&lt;/li&gt; &lt;li&gt;A three-part overview of the syntax of the language: &lt;/li&gt; &lt;ul&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!887.entry"&gt;The basic syntax of F# - keywords and constructs&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!894.entry"&gt;The basic syntax of F# - classes, interfaces, and members&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!1077.entry"&gt;The basic syntax of F# - types&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!725.entry"&gt;What does this C# code look like in F#?&lt;/a&gt; – a comparative “here is some C#, here is the corresponding F#” reference&lt;/li&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!169.entry"&gt;F# function types: fun with tuples and currying&lt;/a&gt; – overview of tuples, curried functions, and partial application&lt;/li&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!165.entry"&gt;Pipelining in F#&lt;/a&gt; – a discussion on the pipeline operator (|&amp;gt;)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Teaser: Regarding what’s coming up, I intend to do a blog series about a little app I wrote that I find useful. It is a nice example that emphasizes the connectedness of F# with the rest of the .Net platform, in that the app uses F# (including some advanced features like async and MailboxProcessors) along with a variety of other technologies: WPF, IObservables, SyndicationFeeds, Speech APIs, SynchronizationContexts, and COM interop. To do something useful! (This is not just another “calculate factorials” example!) All in just 500 lines of code. So that will be fun to discuss; I’m looking forward to writing it up.&lt;/p&gt; &lt;p&gt;Please keep sending your feedback to the F# team! Since the Beta2 release we’ve received lots of useful feedback and bug reports. Keep it coming! We’re glad to hear from you at &lt;a rel="nofollow" target="_blank" href="mailto:fsbugs@microsoft.com"&gt;fsbugs@microsoft.com&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Until next time…&lt;/p&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257119625"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257119625" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/uAbh5_lInU-tqgIVgRvXJ0HW0OM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uAbh5_lInU-tqgIVgRvXJ0HW0OM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/uAbh5_lInU-tqgIVgRvXJ0HW0OM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uAbh5_lInU-tqgIVgRvXJ0HW0OM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=CrgEoUu3WDU:qCIUnDV5-L0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=CrgEoUu3WDU:qCIUnDV5-L0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=CrgEoUu3WDU:qCIUnDV5-L0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=CrgEoUu3WDU:qCIUnDV5-L0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=CrgEoUu3WDU:qCIUnDV5-L0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=CrgEoUu3WDU:qCIUnDV5-L0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=CrgEoUu3WDU:qCIUnDV5-L0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/CrgEoUu3WDU" height="1" width="1"/&gt;</description>
      <link>http://lorgonblog.spaces.live.com/Blog/cns!701679AD17B6D310!1603.entry</link>
      <pubDate>Sun, 01 Nov 2009 15:53:45 GMT</pubDate>
    </item>
    <item>
      <title>Awesome F# - Decision Trees – Part I</title>
      <description>&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.amazon.com/Programming-Animal-Guide-Chris-Smith/dp/0596153643"&gt;Programming F#&lt;/a&gt; is out! Meaning you can, and should, go to the store and pick up a copy today. &lt;/p&gt; &lt;p&gt;&lt;img src="http://t0.gstatic.com/images?q=tbn:jBwkMzLaDw2U-M:http://covers.oreilly.com/images/9780596153656/lrg.jpg"/&gt;&lt;/p&gt; &lt;p&gt;With&lt;em&gt; Programming F#&lt;/em&gt; serving as a solid guide for the F# Language, I’d like to start posting less about &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/chrsmith/archive/2008/02/21/Introduction-to-F_2300_-Active-Patterns.aspx"&gt;language&lt;/a&gt; &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/chrsmith/archive/2009/04/08/f-and-the-pfx-round-1.aspx"&gt;features&lt;/a&gt; and more about applications. That is, what can you &lt;em&gt;do&lt;/em&gt; with this awesome language.&lt;/p&gt; &lt;p&gt;This is the first blog post in a series titled &lt;strong&gt;Awesome F#&lt;/strong&gt;. These posts will provide advanced, real-world applications of the F# language to do awesome things. This post is about Decision Trees and the &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/ID3_algorithm"&gt;ID3 algorithm&lt;/a&gt;, motivated by &lt;a rel="nofollow" target="_blank" href="http://stackoverflow.com/questions/1418829/help-needed-creating-a-binary-tree-given-truth-table"&gt;this question&lt;/a&gt; on &lt;a rel="nofollow" target="_blank" href="http://stackoverflow.com"&gt;StackOverflow.com&lt;/a&gt;. &lt;/p&gt; &lt;p&gt;If you want to learn more about data mining and machine learning &lt;strong&gt;THE BOOK&lt;/strong&gt; you need to get is &lt;a rel="nofollow" target="_blank" href="http://www.amazon.com/Machine-Learning-Tom-M-Mitchell/dp/0070428077"&gt;&lt;em&gt;Machine Learning&lt;/em&gt; by Tom Mitchell&lt;/a&gt;. I’ll give a warning however, it is the most academically rigorous and dense book I’ve ever read. Seriously, not for the faint of heart!&lt;/p&gt; &lt;p&gt;&lt;img alt="cover" src="http://www.cs.cmu.edu/~tom/mlbook.gif" width="130" height="194"/&gt;&lt;/p&gt; &lt;h3&gt;Defining the Problem&lt;/h3&gt; &lt;p&gt;So what does the ID3 algorithm do? It is a technique for creating decision trees much like the following used for determining whether or not to play tennis. Starting at the topmost node, if the outlook is overcast then you should play tennis. If it is rainy however, you should play tennis only if the wind is weak.&lt;/p&gt; &lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/image_3.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/image_thumb.png" width="379" height="281"/&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;In addition to helping plan your sports activities, decision trees are an easy way to gather &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Business_intelligence"&gt;&lt;strong&gt;&lt;em&gt;business intelligence&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;. Imagine you run mid-sized paper company in Scranton, Pennsylvania. You have a database filled with IP addresses of people who have visited your site, special deals you’ve offered them on your products, and whether or not they ended up purchasing some paper. &lt;/p&gt; &lt;p&gt;This is a situation where you want to apply &lt;em&gt;&lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Data_mining"&gt;&lt;strong&gt;data mining&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; &lt;/strong&gt;&lt;/em&gt;to extract meaning from the data. In this case, how to optimize your sales. &lt;/p&gt; &lt;p&gt;There are many different data mining algorithms based on the type of data you have and what you are looking for. In this blog post I will be covering &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Decision_tree_learning"&gt;&lt;em&gt;&lt;strong&gt;decision trees&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;, which is a machine learning technique for predicting a &lt;strong&gt;&lt;em&gt;concept &lt;/em&gt;&lt;/strong&gt;based on data. (For example, given a browser session predict if the user will purchase something.)&lt;/p&gt; &lt;p&gt;More formally: given a set of instances represented as name/value pairs - where the values are discrete - create a decision tree to most accurately classify any new instances. In the example above the name value pairs were Outlook : {Sunny, Rainy, Overcast} and the classification was ‘should you plan tennis’.&lt;/p&gt; &lt;h3&gt;The Approach&lt;/h3&gt; &lt;p&gt;The simplest way to do this is to generate tree branches greedily. Given your training data, find the best branch first and then moving on with more specific subsets of rules on reduced data sets. For example, if trying to determine if someone will purchase a product from your website whether or not they are a returning customer is probably the most significant piece of information.&lt;/p&gt; &lt;p&gt;To find the ‘best split’ we will use an approach known as &lt;em&gt;&lt;strong&gt;&lt;a rel="nofollow" target="_blank" href="http://www.cs.cmu.edu/afs/cs/Web/People/awm/tutorials/infogain11.pdf"&gt;information again&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;. But first, let’s look at a concept from information theory called &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Information_entropy"&gt;&lt;em&gt;&lt;strong&gt;entropy&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;. Imagine you want to create a decision tree to determine if someone is an evil genius. Each datum may contain information such as gender and whether or not they had a Ph.D.&lt;/p&gt; &lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/image_6.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/image_thumb_2.png" width="240" height="270"/&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Entropy and information gain are metrics for calculating how much you &lt;em&gt;learned&lt;/em&gt; from taking a given branch. If exactly 50% of evil geniuses are men, then you have learned nothing by branching on gender. (Since the same number of evil geniuses will be on the left side of the tree as the right side of the tree.) However, for determining evil geniuses education is likely very important – since we can assume the majority of evil geniuses have a Ph.D. in malevolence. In that case the decision tree branch is very effective at whittling down the data into a homogenous group: evil genius or not.&lt;/p&gt; &lt;h3&gt;Enter the Mathematics&lt;/h3&gt; &lt;p&gt;While information gain and entropy are simple concepts, the math is a bit intimidating. Let’s carry on with the ‘is an evil genius’ predictor using the following data:&lt;/p&gt; &lt;table border="0" cellspacing="0" cellpadding="0"&gt;&lt;tbody&gt; &lt;tr&gt; &lt;td width="68"&gt;&lt;strong&gt;Gender&lt;/strong&gt;&lt;/td&gt; &lt;td width="83"&gt;&lt;strong&gt;Education&lt;/strong&gt;&lt;/td&gt; &lt;td width="110"&gt;&lt;strong&gt;Is Evil Genius?&lt;/strong&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Female&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Male&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Male&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Female&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Female&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Male&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Male&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Female&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Female&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;em&gt;Male&lt;/em&gt;&lt;/td&gt; &lt;td&gt;&lt;em&gt;No Ph.D.&lt;/em&gt;&lt;/td&gt; &lt;td&gt;&lt;em&gt;Yes&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;em&gt;Male&lt;/em&gt;&lt;/td&gt; &lt;td&gt;&lt;em&gt;No Ph.D.&lt;/em&gt;&lt;/td&gt; &lt;td&gt;&lt;em&gt;Yes&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Female&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Female&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Male&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Male&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Female&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Female&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Male&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Male&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Female&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Female&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Male&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Male&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Female&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Female&lt;/td&gt; &lt;td&gt;No Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;em&gt;Male&lt;/em&gt;&lt;/td&gt; &lt;td&gt;&lt;em&gt;Ph.D.&lt;/em&gt;&lt;/td&gt; &lt;td&gt;&lt;em&gt;Yes&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;em&gt;Male&lt;/em&gt;&lt;/td&gt; &lt;td&gt;&lt;em&gt;Ph.D.&lt;/em&gt;&lt;/td&gt; &lt;td&gt;&lt;em&gt;Yes&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;em&gt;Female&lt;/em&gt;&lt;/td&gt; &lt;td&gt;&lt;em&gt;Ph.D.&lt;/em&gt;&lt;/td&gt; &lt;td&gt;&lt;em&gt;Yes&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;em&gt;Female&lt;/em&gt;&lt;/td&gt; &lt;td&gt;&lt;em&gt;Ph.D.&lt;/em&gt;&lt;/td&gt; &lt;td&gt;&lt;em&gt;Yes&lt;/em&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Male&lt;/td&gt; &lt;td&gt;Ph.D.&lt;/td&gt; &lt;td&gt;No&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;h4&gt;Entropy&lt;/h4&gt; &lt;p&gt;Given a set of data, S, which can be divided c ways with the probability of each division being p the entropy of that set is given by:&lt;/p&gt; &lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/clip_image002_2.gif"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="clip_image002" border="0" alt="clip_image002" src="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/clip_image002_thumb.gif" width="186" height="51"/&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;For example, if out of a set of six evil geniuses only four are men what is the entropy of that set?&lt;/p&gt; &lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/clip_image002%5B16%5D.gif"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="clip_image002[16]" border="0" alt="clip_image002[16]" src="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/clip_image002%5B16%5D_thumb.gif" width="200" height="36"/&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Or 0.9182. Now, if out of that set of five people with Ph.D.s, four were evil geniuses. What is the entropy there?&lt;/p&gt; &lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/clip_image002%5B18%5D.gif"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="clip_image002[18]" border="0" alt="clip_image002[18]" src="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/clip_image002%5B18%5D_thumb.gif" width="200" height="36"/&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;Or 0.6883. That lower number means that it requires less information to encode that the evil geniuses of the log have a Ph.D. If you run the math for entropy, it will be zero when everything in a set has the same type and exactly 1 when its a 50/50 split. Looking something like this:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www2.wolframalpha.com/Calculate/MSP/MSP23851982e45a932e00f500004864hbh23hb56gf3?MSPStoreType=image/gif&amp;amp;s=9"/&gt;&lt;/p&gt; &lt;p&gt;(Image generated from &lt;a rel="nofollow" target="_blank" href="http://www.wolframalpha.com/input/?i=graph+y%3D-x+*+log(2,+x)+%2B+-(1-x)+*+log(2,+(1-x))+from+0+to+1"&gt;Wolfram Alpha&lt;/a&gt;.)&lt;/p&gt; &lt;p&gt;So the entropy for a homogenous set is lower than that of a mixed set. This is important because in our decision tree we want to narrow the data into more specific values – so we can make predictions more accurately.&lt;/p&gt; &lt;h4&gt;Information Gain&lt;/h4&gt; &lt;p&gt;Now that we know how to measure how homogenous a set of data is, how do we go about deciding the best attribute to branch on? That is, do we branch on gender, has a Ph.D., or some other attribute? To calculate this we can use the &lt;em&gt;&lt;strong&gt;information gain &lt;/strong&gt;&lt;/em&gt;function defined as:&lt;/p&gt; &lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/clip_image002%5B12%5D.gif"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="clip_image002[12]" border="0" alt="clip_image002[12]" src="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/clip_image002%5B12%5D_thumb.gif" width="364" height="49"/&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Given a set of values, S, and an attribute of each datum in that set, A, determine how much information has been gained by branching on that attribute. Note that Sv is the subset of values S where each element has attribute value v.&lt;/p&gt; &lt;p&gt;So what is the information gained by putting our root branch at ‘has a Ph.D'.’ or not?&lt;/p&gt; &lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/clip_image002%5B1%5D.gif"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="clip_image002[1]" border="0" alt="clip_image002[1]" src="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/clip_image002%5B1%5D_thumb.gif" width="633" height="43"/&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/clip_image002%5B3%5D.gif"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="clip_image002[3]" border="0" alt="clip_image002[3]" src="http://blogs.msdn.com/blogfiles/chrsmith/WindowsLiveWriter/AwesomeFDecisionTreesPartI_131F5/clip_image002%5B3%5D_thumb.gif" width="271" height="34"/&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Or 0.2002. If we calculated the information gain from branching on gender, the result is –0.0513. So the math backs up our assertion that Ph.D. is a more significant factor in determining evil genius than gender. (Which makes sense since 4/5ths of the Ph.D.s are evil, whereas only 2/25ths of the non Ph.D.s are evil.)&lt;/p&gt; &lt;p&gt;Putting it Together&lt;/p&gt; &lt;p&gt;In Part II we’ll implement the ID3 algorithm in F#, which generally goes through the following process:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Find the attribute that leads to the most information gain.&lt;/li&gt; &lt;li&gt;Add a branch for that attribute.&lt;/li&gt; &lt;li&gt;For each child node, repeat until all the data have the same classification.&lt;/li&gt; &lt;/ol&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9915736" width="1" height="1"&gt;&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257026480"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257026480" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/YCqmrSTq0Yo9vHK0pr4tkLZGCVI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/YCqmrSTq0Yo9vHK0pr4tkLZGCVI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/YCqmrSTq0Yo9vHK0pr4tkLZGCVI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/YCqmrSTq0Yo9vHK0pr4tkLZGCVI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=ijDQm2lb3qU:pNfx_vksQmQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=ijDQm2lb3qU:pNfx_vksQmQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=ijDQm2lb3qU:pNfx_vksQmQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=ijDQm2lb3qU:pNfx_vksQmQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=ijDQm2lb3qU:pNfx_vksQmQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=ijDQm2lb3qU:pNfx_vksQmQ:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=ijDQm2lb3qU:pNfx_vksQmQ:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/ijDQm2lb3qU" height="1" width="1"/&gt;</description>
      <link>http://blogs.msdn.com/chrsmith/archive/2009/10/31/awesome-f-decision-trees-part-i.aspx</link>
      <pubDate>Sat, 31 Oct 2009 15:01:20 GMT</pubDate>
    </item>
    <item>
      <title>The Visual Studio 2010 and .NET Framework 4 Training resources</title>
      <description>NET Framework 4 Training Course includes videos and hands-on-labs designed to help you learn how to utilize the Visual Studio 2010 features and a variety of framework technologies including: C# 4.0, Visual Basic 10, &lt;b&gt;F#&lt;/b&gt;, ...&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.pheedo.com/click.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257016353"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=60c11b8469e54dfba87cebc201b448d0&amp;u=planetfsharp1257016353" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/uq7EMXtE2VWqh5ZfWoSfy2AHXe0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uq7EMXtE2VWqh5ZfWoSfy2AHXe0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/uq7EMXtE2VWqh5ZfWoSfy2AHXe0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uq7EMXtE2VWqh5ZfWoSfy2AHXe0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=FvUVi8KJ_G0:ZGw4X1dwv8g:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=FvUVi8KJ_G0:ZGw4X1dwv8g:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=FvUVi8KJ_G0:ZGw4X1dwv8g:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=FvUVi8KJ_G0:ZGw4X1dwv8g:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=FvUVi8KJ_G0:ZGw4X1dwv8g:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/planet_fsharp?a=FvUVi8KJ_G0:ZGw4X1dwv8g:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/planet_fsharp?i=FvUVi8KJ_G0:ZGw4X1dwv8g:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/planet_fsharp/~4/FvUVi8KJ_G0" height="1" width="1"/&gt;</description>
      <link>http://geekswithblogs.net/jalexander/archive/2009/10/31/the-visual-studio-2010-and-.net-framework-4-training-resources.aspx</link>
      <pubDate>Sat, 31 Oct 2009 12:12:33 GMT</pubDate>
    </item>
  </channel>
</rss>
