<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: What is Hindley-Milner?  (and why is it cool?)</title>
	<atom:link href="http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool/feed" rel="self" type="application/rss+xml" />
	<link>http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool</link>
	<description>(permanently in beta)</description>
	<lastBuildDate>Sun, 29 Aug 2010 20:01:44 -0700</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: Daniel Spiewak</title>
		<link>http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool/comment-page-1#comment-5098</link>
		<dc:creator>Daniel Spiewak</dc:creator>
		<pubDate>Sun, 04 Jul 2010 20:55:14 +0000</pubDate>
		<guid isPermaLink="false">http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool#comment-5098</guid>
		<description>@Jon

I am quite aware of that *now*.  Unfortunately, I wasn&#039;t too well versed in the distinction when I originally wrote this article.  I&#039;ve considered revising it, but the changes would be fairly extensive, and given the fact that it&#039;s a minor semantic point, I thought it best to leave things as they are.

There is also the fact that most people aren&#039;t going to make the distinction and so would be confused by the proliferation of terminology.  Generally, when someone says &quot;Hindley-Milner&quot;, they actually mean the type inference algorithm.  Should they use the term &quot;Damas-Milner&quot; instead?  Absolutely.  Is it worth quibbling?  Probably not.</description>
		<content:encoded><![CDATA[<p>@Jon</p>
<p>I am quite aware of that *now*.  Unfortunately, I wasn&#8217;t too well versed in the distinction when I originally wrote this article.  I&#8217;ve considered revising it, but the changes would be fairly extensive, and given the fact that it&#8217;s a minor semantic point, I thought it best to leave things as they are.</p>
<p>There is also the fact that most people aren&#8217;t going to make the distinction and so would be confused by the proliferation of terminology.  Generally, when someone says &#8220;Hindley-Milner&#8221;, they actually mean the type inference algorithm.  Should they use the term &#8220;Damas-Milner&#8221; instead?  Absolutely.  Is it worth quibbling?  Probably not.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jon Harrop</title>
		<link>http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool/comment-page-1#comment-5097</link>
		<dc:creator>Jon Harrop</dc:creator>
		<pubDate>Sun, 04 Jul 2010 19:43:40 +0000</pubDate>
		<guid isPermaLink="false">http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool#comment-5097</guid>
		<description>@Daniel: Strictly speaking, Hindley-Milner is the type system and Damas-Milner is the type inference algorithm, aka &quot;Algorithm W&quot;.</description>
		<content:encoded><![CDATA[<p>@Daniel: Strictly speaking, Hindley-Milner is the type system and Damas-Milner is the type inference algorithm, aka &#8220;Algorithm W&#8221;.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: anonymous</title>
		<link>http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool/comment-page-1#comment-4917</link>
		<dc:creator>anonymous</dc:creator>
		<pubDate>Wed, 23 Dec 2009 13:17:55 +0000</pubDate>
		<guid isPermaLink="false">http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool#comment-4917</guid>
		<description>@ Daniel Spiewak

This is an old argument but here it is anyway.

The problem with HM and OO is that this typing system does not have a property called principal typing. When a typing system has this property, and it is decidable, one can give the PT for the piece of code and any other typing for this piece can be obtained from this one. This allows you to have smart recompilation in your system. The lack of PT property has nothing to do with functional programming  itself, but with the typing system used with the most popular ones. 

There is a work going on with ML using intersection types instead of HM type system. Polymorphism by intersection is a promissing field, it list the multiple types instead of quantifying over it, as is done for HM.

Note that HM has principal TYPE property but no principal TYPING. The lack of modulatiry in the Dama/Milner algorithm can be notice that for &quot;let N in M&quot; program, one has to give a type for N and then for M. In a compositional type inference one can give type for N and M in parallel and check whether they can be related.</description>
		<content:encoded><![CDATA[<p>@ Daniel Spiewak</p>
<p>This is an old argument but here it is anyway.</p>
<p>The problem with HM and OO is that this typing system does not have a property called principal typing. When a typing system has this property, and it is decidable, one can give the PT for the piece of code and any other typing for this piece can be obtained from this one. This allows you to have smart recompilation in your system. The lack of PT property has nothing to do with functional programming  itself, but with the typing system used with the most popular ones. </p>
<p>There is a work going on with ML using intersection types instead of HM type system. Polymorphism by intersection is a promissing field, it list the multiple types instead of quantifying over it, as is done for HM.</p>
<p>Note that HM has principal TYPE property but no principal TYPING. The lack of modulatiry in the Dama/Milner algorithm can be notice that for &#8220;let N in M&#8221; program, one has to give a type for N and then for M. In a compositional type inference one can give type for N and M in parallel and check whether they can be related.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Daniel Spiewak</title>
		<link>http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool/comment-page-1#comment-4443</link>
		<dc:creator>Daniel Spiewak</dc:creator>
		<pubDate>Wed, 31 Dec 2008 19:04:22 +0000</pubDate>
		<guid isPermaLink="false">http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool#comment-4443</guid>
		<description>@James

Good point; I hadn&#039;t considered dependent types.  With that said, I tend to consider dependent types to be flirting a little too closely with a full-blown meta-language.  In fact, type systems with dependent types have a tendency toward intractability.  That doesn&#039;t make them any less valid, but it at least gives a better explanation for why I didn&#039;t even consider them in my example.  :-)

Regarding inference, I&#039;m pretty sure that it would be possible to infer the appropriate dependent type in examples as trivial as the one I gave.  The trick would be to imbue the CT-If* rules with awareness of Boolean dependent types (required anyway to make the system work).  However, in general, constraint-based inference for dependent types would certainly be undecidable.  Shame...</description>
		<content:encoded><![CDATA[<p>@James</p>
<p>Good point; I hadn&#8217;t considered dependent types.  With that said, I tend to consider dependent types to be flirting a little too closely with a full-blown meta-language.  In fact, type systems with dependent types have a tendency toward intractability.  That doesn&#8217;t make them any less valid, but it at least gives a better explanation for why I didn&#8217;t even consider them in my example.  <img src='http://www.codecommit.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Regarding inference, I&#8217;m pretty sure that it would be possible to infer the appropriate dependent type in examples as trivial as the one I gave.  The trick would be to imbue the CT-If* rules with awareness of Boolean dependent types (required anyway to make the system work).  However, in general, constraint-based inference for dependent types would certainly be undecidable.  Shame&#8230;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: James Iry</title>
		<link>http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool/comment-page-1#comment-4442</link>
		<dc:creator>James Iry</dc:creator>
		<pubDate>Wed, 31 Dec 2008 15:42:43 +0000</pubDate>
		<guid isPermaLink="false">http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool#comment-4442</guid>
		<description>@QuacoreZX,

Type systems are constraint logic programming, exactly.  And as Daniel says, for every type system there are true things it can&#039;t prove (see Godel).  But when we say that HM always finds one principle type we don&#039;t mean it will necessarily find a primitive type.  In Haskell for instance

id x = x -- A function that returns the value passed in unchanged

Gets inferred as 
id :: forall t. t -&gt; t

Meaning that the id function can take a value of any type and will return a value of that type.

Similarly
singletonList x = [x] -- a function that boxes a single value into a list

Haskell infers
singletonList :: forall t. t -&gt; [t]

Meaning if you pass in a value of any type &#039;t&#039; the function gives back a value of type List of &#039;t&#039;.

Finally, a more complicated example using Haskell type classes

f x y z = x &gt;&gt;= y &gt;&gt;= z
f :: forall a, a1, b . (Monad m) =&gt; m a -&gt; (a -&gt; m a1) -&gt; (a1 -&gt; m b) -&gt; m b

Which says that x must have a type &quot;m a&quot; where m is a special type constructor called a monad and &quot;a&quot; is some arbitrary type, y must have type &quot;a -&gt; m a1&quot;  where a1 is some other arbitrary type, and z has type &quot;a1 -&gt; m b&quot; where b is some arbitrary type.  It will then return a value of type &quot;m b&quot;.  

Hopefully this shows that principle types can be pretty sophisticated.

@Daniel,

Programs like what you wrote in Clojure above can be typed using dependent typing.  However, afaik, there&#039;s no way to infer dependent types.</description>
		<content:encoded><![CDATA[<p>@QuacoreZX,</p>
<p>Type systems are constraint logic programming, exactly.  And as Daniel says, for every type system there are true things it can&#8217;t prove (see Godel).  But when we say that HM always finds one principle type we don&#8217;t mean it will necessarily find a primitive type.  In Haskell for instance</p>
<p>id x = x &#8212; A function that returns the value passed in unchanged</p>
<p>Gets inferred as<br />
id :: forall t. t -&gt; t</p>
<p>Meaning that the id function can take a value of any type and will return a value of that type.</p>
<p>Similarly<br />
singletonList x = [x] &#8212; a function that boxes a single value into a list</p>
<p>Haskell infers<br />
singletonList :: forall t. t -&gt; [t]</p>
<p>Meaning if you pass in a value of any type &#8216;t&#8217; the function gives back a value of type List of &#8216;t&#8217;.</p>
<p>Finally, a more complicated example using Haskell type classes</p>
<p>f x y z = x &gt;&gt;= y &gt;&gt;= z<br />
f :: forall a, a1, b . (Monad m) =&gt; m a -&gt; (a -&gt; m a1) -&gt; (a1 -&gt; m b) -&gt; m b</p>
<p>Which says that x must have a type &#8220;m a&#8221; where m is a special type constructor called a monad and &#8220;a&#8221; is some arbitrary type, y must have type &#8220;a -&gt; m a1&#8243;  where a1 is some other arbitrary type, and z has type &#8220;a1 -&gt; m b&#8221; where b is some arbitrary type.  It will then return a value of type &#8220;m b&#8221;.  </p>
<p>Hopefully this shows that principle types can be pretty sophisticated.</p>
<p>@Daniel,</p>
<p>Programs like what you wrote in Clojure above can be typed using dependent typing.  However, afaik, there&#8217;s no way to infer dependent types.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Daniel Spiewak</title>
		<link>http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool/comment-page-1#comment-4441</link>
		<dc:creator>Daniel Spiewak</dc:creator>
		<pubDate>Wed, 31 Dec 2008 11:07:28 +0000</pubDate>
		<guid isPermaLink="false">http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool#comment-4441</guid>
		<description>@QuacoreZX

You can get surprisingly far with simple let-polymorphism.  Saying that HM is inferring *one* type implies that only a single nominal type will suffice, when really it is far more robust than that.  If you extend the algorithm to encompass intersect and union types, you get even more power.  Things aren&#039;t quite as bleak as you think.  :-)

However, generally speaking you are correct.  In any Turing Complete language, there will exist the possibility of code which is perfectly valid at runtime but not accepted by any type system, inference or no inference.  Consider the following Clojure tidbit:

&lt;pre&gt;(defn do-stuff [c x]
  (if c
    (:foo x)
    (:bar x)))

(do-stuff true (struct (create-struct :foo) 123))&lt;/pre&gt;

Even using every trick in the type systems book (structural types, intersect types, etc), there is no way to successfully type this snippet: the struct we are passing does not define a :bar property, meaning that it is *possible* that evaluation may fail.  Of course, at runtime, things work out just fine since the (:bar x) form is in a non-evaluated branch.  The type system doesn&#039;t know that though, and there is no way for it to reliably find out.  Dynamic languages are permanently safe in this regard.</description>
		<content:encoded><![CDATA[<p>@QuacoreZX</p>
<p>You can get surprisingly far with simple let-polymorphism.  Saying that HM is inferring *one* type implies that only a single nominal type will suffice, when really it is far more robust than that.  If you extend the algorithm to encompass intersect and union types, you get even more power.  Things aren&#8217;t quite as bleak as you think.  <img src='http://www.codecommit.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>However, generally speaking you are correct.  In any Turing Complete language, there will exist the possibility of code which is perfectly valid at runtime but not accepted by any type system, inference or no inference.  Consider the following Clojure tidbit:</p>
<pre>(defn do-stuff [c x]
  (if c
    (:foo x)
    (:bar x)))

(do-stuff true (struct (create-struct :foo) 123))</pre>
<p>Even using every trick in the type systems book (structural types, intersect types, etc), there is no way to successfully type this snippet: the struct we are passing does not define a :bar property, meaning that it is *possible* that evaluation may fail.  Of course, at runtime, things work out just fine since the (:bar x) form is in a non-evaluated branch.  The type system doesn&#8217;t know that though, and there is no way for it to reliably find out.  Dynamic languages are permanently safe in this regard.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: QuacoreZX</title>
		<link>http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool/comment-page-1#comment-4440</link>
		<dc:creator>QuacoreZX</dc:creator>
		<pubDate>Wed, 31 Dec 2008 10:48:28 +0000</pubDate>
		<guid isPermaLink="false">http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool#comment-4440</guid>
		<description>From the looks of it, it sure sounds like a simple Constraint Satisfaction Problem, solvable even with the most elementary artificial intelligence class.  Naturally, I assume this algorithm in particular is highly optimized for use, but at least from what I read here, it sounds like the algorithm is expecting to find ONE type for each variable -- highly unsatisfactory for generic functions such as those in Python or other such langauges.</description>
		<content:encoded><![CDATA[<p>From the looks of it, it sure sounds like a simple Constraint Satisfaction Problem, solvable even with the most elementary artificial intelligence class.  Naturally, I assume this algorithm in particular is highly optimized for use, but at least from what I read here, it sounds like the algorithm is expecting to find ONE type for each variable &#8212; highly unsatisfactory for generic functions such as those in Python or other such langauges.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Stephan Schmidt</title>
		<link>http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool/comment-page-1#comment-4438</link>
		<dc:creator>Stephan Schmidt</dc:creator>
		<pubDate>Tue, 30 Dec 2008 18:20:26 +0000</pubDate>
		<guid isPermaLink="false">http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool#comment-4438</guid>
		<description>Thanks a lot for your explaination Daniel. Peace -stephan</description>
		<content:encoded><![CDATA[<p>Thanks a lot for your explaination Daniel. Peace -stephan</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jason Cohen</title>
		<link>http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool/comment-page-1#comment-4437</link>
		<dc:creator>Jason Cohen</dc:creator>
		<pubDate>Tue, 30 Dec 2008 17:30:37 +0000</pubDate>
		<guid isPermaLink="false">http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool#comment-4437</guid>
		<description>@Aaron

Yup, brackets got smoked.

@Daniel

Yes of course polymorphism screws things too.  Simplest example is that of an interface -- by definition there&#039;s no code to infer from, therefore no types.

Still more support even at the IDE level in Java (or similar language) would be useful.  Sure if you know nothing about the types (or data), fine, but &lt;i&gt;when you do&lt;/i&gt;, how nice would it be for the IDE to tell you?

There&#039;s still plenty of code that calls non-polymorphic other code where this inference could help.

Of course this could also help at the runtime-VM or JIT layer, and in fact they already do simple things like that for e.g. removing array-out-of-bounds or null-pointer checks when it&#039;s clear that those errors are impossible.  Still I wonder if it could be made smarter through more inter-functional logic like this.</description>
		<content:encoded><![CDATA[<p>@Aaron</p>
<p>Yup, brackets got smoked.</p>
<p>@Daniel</p>
<p>Yes of course polymorphism screws things too.  Simplest example is that of an interface &#8212; by definition there&#8217;s no code to infer from, therefore no types.</p>
<p>Still more support even at the IDE level in Java (or similar language) would be useful.  Sure if you know nothing about the types (or data), fine, but <i>when you do</i>, how nice would it be for the IDE to tell you?</p>
<p>There&#8217;s still plenty of code that calls non-polymorphic other code where this inference could help.</p>
<p>Of course this could also help at the runtime-VM or JIT layer, and in fact they already do simple things like that for e.g. removing array-out-of-bounds or null-pointer checks when it&#8217;s clear that those errors are impossible.  Still I wonder if it could be made smarter through more inter-functional logic like this.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Aaron Davies</title>
		<link>http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool/comment-page-1#comment-4434</link>
		<dc:creator>Aaron Davies</dc:creator>
		<pubDate>Tue, 30 Dec 2008 01:27:37 +0000</pubDate>
		<guid isPermaLink="false">http://www.codecommit.com/blog/scala/what-is-hindley-milner-and-why-is-it-cool#comment-4434</guid>
		<description>@jason cohen: i think a generic type in your comment got eaten by the blogging engine, probably due to angle brackets.</description>
		<content:encoded><![CDATA[<p>@jason cohen: i think a generic type in your comment got eaten by the blogging engine, probably due to angle brackets.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
