<?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: Hindley-Milner type inference in Scala</title>
	<atom:link href="http://dysphoria.net/2009/06/28/hindley-milner-type-inference-in-scala/feed/" rel="self" type="application/rss+xml" />
	<link>http://dysphoria.net/2009/06/28/hindley-milner-type-inference-in-scala/</link>
	<description>For long lost friends and stalkers</description>
	<lastBuildDate>Tue, 26 Jan 2010 05:09:24 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: Christian Klauser</title>
		<link>http://dysphoria.net/2009/06/28/hindley-milner-type-inference-in-scala/comment-page-1/#comment-34122</link>
		<dc:creator>Christian Klauser</dc:creator>
		<pubDate>Tue, 26 Jan 2010 05:09:24 +0000</pubDate>
		<guid isPermaLink="false">http://dysphoria.net/?p=246#comment-34122</guid>
		<description>I keep my source code in a repository at assembla:

http://www.assembla.com/wiki/show/tincal

It is not a working compiler and a lot of things are missing. I haven&#039;t settled on how to encode product and sum types which in turn determines how &quot;value deconstructors&quot; will be implemented. Those in turn are necessary for pattern matching.

At the moment, it is a personal project that I work on from time to time. Don&#039;t know how far I&#039;ll get.</description>
		<content:encoded><![CDATA[<p>I keep my source code in a repository at assembla:</p>
<p><a href="http://www.assembla.com/wiki/show/tincal" rel="nofollow">http://www.assembla.com/wiki/show/tincal</a></p>
<p>It is not a working compiler and a lot of things are missing. I haven&#8217;t settled on how to encode product and sum types which in turn determines how &#8220;value deconstructors&#8221; will be implemented. Those in turn are necessary for pattern matching.</p>
<p>At the moment, it is a personal project that I work on from time to time. Don&#8217;t know how far I&#8217;ll get.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Andrew</title>
		<link>http://dysphoria.net/2009/06/28/hindley-milner-type-inference-in-scala/comment-page-1/#comment-32831</link>
		<dc:creator>Andrew</dc:creator>
		<pubDate>Sun, 08 Nov 2009 21:09:35 +0000</pubDate>
		<guid isPermaLink="false">http://dysphoria.net/?p=246#comment-32831</guid>
		<description>Actually, let me retract that: ‘Type’ is not necessary coupled to the type inference algorithm, so, yes, a ‘bind’ method, which checks that the variable is not already bound (or which walks the list to the last unbound variable in the chain) before assigning ‘instance’ would make sense.</description>
		<content:encoded><![CDATA[<p>Actually, let me retract that: ‘Type’ is not necessary coupled to the type inference algorithm, so, yes, a ‘bind’ method, which checks that the variable is not already bound (or which walks the list to the last unbound variable in the chain) before assigning ‘instance’ would make sense.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Andrew</title>
		<link>http://dysphoria.net/2009/06/28/hindley-milner-type-inference-in-scala/comment-page-1/#comment-32830</link>
		<dc:creator>Andrew</dc:creator>
		<pubDate>Sun, 08 Nov 2009 21:01:19 +0000</pubDate>
		<guid isPermaLink="false">http://dysphoria.net/?p=246#comment-32830</guid>
		<description>Bill,

I see what you’re saying.

Though in actual fact, the missed call to prune was in ‘occursintype’ which is used in a couple of places, notably ‘fresh’ (which creates new type variables from generic ones if necessary), not just in ‘unify’.

The way the algorithm works, the assignment to ‘instance’ should never be performed on anything other than an unbound type variable. So your setter method could just &lt;code&gt;assert(instance == null); instance = newValue;&lt;/code&gt;. The ‘Type’ class is already tightly bound to the type inference algorithm, so you might as well implement ‘unify’ and ‘prune’ (and possibly some other functions) as methods on Type, instead of exposing ‘instance’ at all.

Cheers,

–Andrew</description>
		<content:encoded><![CDATA[<p>Bill,</p>
<p>I see what you’re saying.</p>
<p>Though in actual fact, the missed call to prune was in ‘occursintype’ which is used in a couple of places, notably ‘fresh’ (which creates new type variables from generic ones if necessary), not just in ‘unify’.</p>
<p>The way the algorithm works, the assignment to ‘instance’ should never be performed on anything other than an unbound type variable. So your setter method could just <code>assert(instance == null); instance = newValue;</code>. The ‘Type’ class is already tightly bound to the type inference algorithm, so you might as well implement ‘unify’ and ‘prune’ (and possibly some other functions) as methods on Type, instead of exposing ‘instance’ at all.</p>
<p>Cheers,</p>
<p>–Andrew</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Bill Hails</title>
		<link>http://dysphoria.net/2009/06/28/hindley-milner-type-inference-in-scala/comment-page-1/#comment-32825</link>
		<dc:creator>Bill Hails</dc:creator>
		<pubDate>Fri, 06 Nov 2009 11:37:16 +0000</pubDate>
		<guid isPermaLink="false">http://dysphoria.net/?p=246#comment-32825</guid>
		<description>Hi Andrew

&gt; Line 271 of the Perl code implements unifies a type variable with its
&gt; inferred value, so it’s quite essential :)

Absolutely agree, but... :-)

&gt; You could wrap it in an setter method if you like (is that what you
&gt; meant?), but that doesn’t change the behaviour of the algorithm.

Yes that&#039;s what I meant. My real argument is that it&#039;s dangerous *not* to wrap the assignment to a logic variable in a setter method.

In the standard(?) implementation of Logic Variables, they arrange themselves in chains. For instance assume some language with LVs:

# create an empty LV
declare A;
# result A-&gt;(empty)

# create another empty LV
declare B;
# result: B-&gt;(empty)

# unify A with B
A = B;
# result: A-&gt;B-&gt;(empty)

# unify A with 1
A = 1;
# result: A-&gt;B-&gt;1

The point then is that naive assignment directly to A here would not achieve the desired result, instead you would end up breaking the association of A and B giving

A-&gt;1
B-&gt;(empty)

The setter method must chain down the list from A to B until it finds a pointer to (empty) and assign there.

&quot;Pruning&quot; as I understand it is just that action of chaining down the list, but it is presented in the Perl algorithm at least as being a separate step from the assignment. So if as in the perl case it was forgotten, we get the bug you detected.</description>
		<content:encoded><![CDATA[<p>Hi Andrew</p>
<p>&gt; Line 271 of the Perl code implements unifies a type variable with its<br />
&gt; inferred value, so it’s quite essential :)</p>
<p>Absolutely agree, but&#8230; :-)</p>
<p>&gt; You could wrap it in an setter method if you like (is that what you<br />
&gt; meant?), but that doesn’t change the behaviour of the algorithm.</p>
<p>Yes that&#8217;s what I meant. My real argument is that it&#8217;s dangerous *not* to wrap the assignment to a logic variable in a setter method.</p>
<p>In the standard(?) implementation of Logic Variables, they arrange themselves in chains. For instance assume some language with LVs:</p>
<p># create an empty LV<br />
declare A;<br />
# result A-&gt;(empty)</p>
<p># create another empty LV<br />
declare B;<br />
# result: B-&gt;(empty)</p>
<p># unify A with B<br />
A = B;<br />
# result: A-&gt;B-&gt;(empty)</p>
<p># unify A with 1<br />
A = 1;<br />
# result: A-&gt;B-&gt;1</p>
<p>The point then is that naive assignment directly to A here would not achieve the desired result, instead you would end up breaking the association of A and B giving</p>
<p>A-&gt;1<br />
B-&gt;(empty)</p>
<p>The setter method must chain down the list from A to B until it finds a pointer to (empty) and assign there.</p>
<p>&#8220;Pruning&#8221; as I understand it is just that action of chaining down the list, but it is presented in the Perl algorithm at least as being a separate step from the assignment. So if as in the perl case it was forgotten, we get the bug you detected.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Andrew</title>
		<link>http://dysphoria.net/2009/06/28/hindley-milner-type-inference-in-scala/comment-page-1/#comment-32694</link>
		<dc:creator>Andrew</dc:creator>
		<pubDate>Mon, 02 Nov 2009 22:47:33 +0000</pubDate>
		<guid isPermaLink="false">http://dysphoria.net/?p=246#comment-32694</guid>
		<description>Hi Bill,

It’s been a while since I’ve looked at this, but I think I’m right in saying:

The core type inference algorithm certainly does not require a distinction between let and lamda. That is: you’re perfectly free to add in a rewrite step which transforms ‘let’ into ‘lambda’, and remove ‘let’ handling by the type inferencer completely. The included AST is just a little toy language to show off that the type inference works.

Line 271 of the Perl code implements unifies a type variable with its inferred value, so it’s quite essential :)

You could wrap it in an setter method if you like (is that what you meant?), but that doesn&#039;t change the behaviour of the algorithm.

If more generally you mean that you’d rather have an implementation which only used immutable objects, and did not have the mutation which you point out on line 271… that too is possible. As Christian Klauser points out above, it’s trickier in a pure functional environment, but quite possible; you just have to maintain a map of type variables to their bound types. The Cardelli paper calls this the ‘set of assumptions’ (page 13). However, the Perl implementation, and my Scala implementation, mutate the type variable objects instead of maintaining a separate map.

Hope this helps!

–A</description>
		<content:encoded><![CDATA[<p>Hi Bill,</p>
<p>It’s been a while since I’ve looked at this, but I think I’m right in saying:</p>
<p>The core type inference algorithm certainly does not require a distinction between let and lamda. That is: you’re perfectly free to add in a rewrite step which transforms ‘let’ into ‘lambda’, and remove ‘let’ handling by the type inferencer completely. The included AST is just a little toy language to show off that the type inference works.</p>
<p>Line 271 of the Perl code implements unifies a type variable with its inferred value, so it’s quite essential :)</p>
<p>You could wrap it in an setter method if you like (is that what you meant?), but that doesn&#8217;t change the behaviour of the algorithm.</p>
<p>If more generally you mean that you’d rather have an implementation which only used immutable objects, and did not have the mutation which you point out on line 271… that too is possible. As Christian Klauser points out above, it’s trickier in a pure functional environment, but quite possible; you just have to maintain a map of type variables to their bound types. The Cardelli paper calls this the ‘set of assumptions’ (page 13). However, the Perl implementation, and my Scala implementation, mutate the type variable objects instead of maintaining a separate map.</p>
<p>Hope this helps!</p>
<p>–A</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Bill Hails</title>
		<link>http://dysphoria.net/2009/06/28/hindley-milner-type-inference-in-scala/comment-page-1/#comment-32491</link>
		<dc:creator>Bill Hails</dc:creator>
		<pubDate>Sun, 25 Oct 2009 20:17:37 +0000</pubDate>
		<guid isPermaLink="false">http://dysphoria.net/?p=246#comment-32491</guid>
		<description>Hi.
I&#039;m also investigating HM type inference, trying to code it into a language I&#039;m developing as a hobby project. I&#039;m a little concerned that the &quot;prune&quot; operation figures in the algorithm at all to be honest. Pruning logic variables is an optimisation step, and if it affects the outcome in any way then there is a flaw somewhere else in the code.

In the Perl from Nikita Borisov, I *think* the flaw is in the direct assignment to a logic variable instance:

$type1-&gt;{instance} = $type2;

on line 271 in the code I found. Assigning to a logic variable is best done only by a logic variable method that can protect its own integrity.

I&#039;m also a bit disappointed having read the Cardelli paper (my maths is probably worse than yours) to find that the algorithm requires a distinction between let and lambda. I&#039;m already firmly in the Scheme camp where &quot;let x = y in z&quot; gets rewritten to &quot;fn (x) {z} (y)&quot; (i.e. let is just lambda) before the AST is even built.

Still, thanks very much for your implementation, I was getting hung up on the Perl one, and any thoughts about this?</description>
		<content:encoded><![CDATA[<p>Hi.<br />
I&#8217;m also investigating HM type inference, trying to code it into a language I&#8217;m developing as a hobby project. I&#8217;m a little concerned that the &#8220;prune&#8221; operation figures in the algorithm at all to be honest. Pruning logic variables is an optimisation step, and if it affects the outcome in any way then there is a flaw somewhere else in the code.</p>
<p>In the Perl from Nikita Borisov, I *think* the flaw is in the direct assignment to a logic variable instance:</p>
<p>$type1-&gt;{instance} = $type2;</p>
<p>on line 271 in the code I found. Assigning to a logic variable is best done only by a logic variable method that can protect its own integrity.</p>
<p>I&#8217;m also a bit disappointed having read the Cardelli paper (my maths is probably worse than yours) to find that the algorithm requires a distinction between let and lambda. I&#8217;m already firmly in the Scheme camp where &#8220;let x = y in z&#8221; gets rewritten to &#8220;fn (x) {z} (y)&#8221; (i.e. let is just lambda) before the AST is even built.</p>
<p>Still, thanks very much for your implementation, I was getting hung up on the Perl one, and any thoughts about this?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Peter Verswyvelen</title>
		<link>http://dysphoria.net/2009/06/28/hindley-milner-type-inference-in-scala/comment-page-1/#comment-31651</link>
		<dc:creator>Peter Verswyvelen</dc:creator>
		<pubDate>Sat, 26 Sep 2009 19:42:18 +0000</pubDate>
		<guid isPermaLink="false">http://dysphoria.net/?p=246#comment-31651</guid>
		<description>Hi Andrew &amp; Christian,

Great work!

I&#039;m also trying to understand HM type inference from a pragmatic point of view.

I only know Scala theoretically, but I have strong skills in C#.

So Christian, are you also sharing your C# implementation?

Thanks,
Peter</description>
		<content:encoded><![CDATA[<p>Hi Andrew &amp; Christian,</p>
<p>Great work!</p>
<p>I&#8217;m also trying to understand HM type inference from a pragmatic point of view.</p>
<p>I only know Scala theoretically, but I have strong skills in C#.</p>
<p>So Christian, are you also sharing your C# implementation?</p>
<p>Thanks,<br />
Peter</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Andrew</title>
		<link>http://dysphoria.net/2009/06/28/hindley-milner-type-inference-in-scala/comment-page-1/#comment-31479</link>
		<dc:creator>Andrew</dc:creator>
		<pubDate>Mon, 21 Sep 2009 12:30:37 +0000</pubDate>
		<guid isPermaLink="false">http://dysphoria.net/?p=246#comment-31479</guid>
		<description>Glad to be of help, Christian.

Yeah, took me a while (and the act of debugging my own implementation) before I started to really understand it.

Cheers,

–A</description>
		<content:encoded><![CDATA[<p>Glad to be of help, Christian.</p>
<p>Yeah, took me a while (and the act of debugging my own implementation) before I started to really understand it.</p>
<p>Cheers,</p>
<p>–A</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Christian Klauser</title>
		<link>http://dysphoria.net/2009/06/28/hindley-milner-type-inference-in-scala/comment-page-1/#comment-31010</link>
		<dc:creator>Christian Klauser</dc:creator>
		<pubDate>Mon, 07 Sep 2009 09:43:48 +0000</pubDate>
		<guid isPermaLink="false">http://dysphoria.net/?p=246#comment-31010</guid>
		<description>Hi,
I would like to thank you for publishing your implementation of the hindley-milner algorithm. It has been a great help!

I&#039;ve been playing around with the idea of using type-inference myself for a while now but couldn&#039;t make sense of Milner&#039;s original paper, in particular I didn&#039;t understand the unification step. (Even though it is actually quite simple in an impure environment)

I have since implemented my own version in C# (and yes, it is a pain to work without tuples, type inference, pattern matching and discriminated unions) and am now working &quot;more advanced&quot; features like pattern matching and case expressions.</description>
		<content:encoded><![CDATA[<p>Hi,<br />
I would like to thank you for publishing your implementation of the hindley-milner algorithm. It has been a great help!</p>
<p>I&#8217;ve been playing around with the idea of using type-inference myself for a while now but couldn&#8217;t make sense of Milner&#8217;s original paper, in particular I didn&#8217;t understand the unification step. (Even though it is actually quite simple in an impure environment)</p>
<p>I have since implemented my own version in C# (and yes, it is a pain to work without tuples, type inference, pattern matching and discriminated unions) and am now working &#8220;more advanced&#8221; features like pattern matching and case expressions.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
