GHC: Ticket #3197: disambiguating type family instances with qualified names not possible
http://ghc.haskell.org/trac/ghc/ticket/3197
<p>
While reading <a class="ext-link" href="http://www.haskell.org/pipermail/haskell-cafe/2009-April/060665.html"><span class="icon"></span>1</a>, it occured to me that type families could be used to parameterize modules by types. So I modified my example from <a class="ext-link" href="http://www.haskell.org/pipermail/haskell-cafe/2009-April/060324.html"><span class="icon"></span>2</a>, trying to parameterize two modules <tt>A</tt> and <tt>B</tt> with a shared type <tt>Label</tt> (sharing expressed in <tt>C)</tt>, but ran into a few issues:
</p>
<pre class="wiki">{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE EmptyDataDecls #-}
module LA where
data MyLabel
y = undefined::MyLabel
type family Label a
z = undefined::Label ()
</pre><pre class="wiki">{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE EmptyDataDecls #-}
module LB where
data MyLabel
y = undefined::MyLabel
type family Label a
z = undefined::Label ()
</pre><pre class="wiki">{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeFamilies #-}
module LC where
import LA
import LB
-- fails = [LA.y,LB.y]
-- express type sharing while leaving actual type open
type family Label a
type instance LA.Label a = LC.Label a
type instance LB.Label a = LC.Label a
ok2 = [LA.z,LB.z]
-- for testing only
-- type instance Label a = () -- can't use with or without qualifier:-(
</pre><p>
Issues:
</p>
<ul><li>is it really necessary for type families to have at least one index? Without that, type constants could be expressed directly
</li></ul><ul><li>uncommenting that last line demonstrates a couple of bugs:
</li></ul><ul><li>as it stands, the type instance is ambiguous, but the error message has an incorrect source location (<tt>1:0</tt>)
</li></ul><ul><li>trying to disambiguate by defining <tt>type instance LC.Label</tt> results in : "Qualified name in binding position: LC.Label" (note that this is permitted a couple of lines up, so it is related to whether the qualifier refers to the current module or an imported one)
</li></ul><p>
[the bug is not really in the type checker, but specific to type families..]
</p>
<p>
Bug aside, it works (<tt>length ok2</tt> gives two, not an error, as <tt>fail</tt> would).
</p>
<p>
This could be a useful type family programming pattern (it is probably implicit in the comparisons of SML functors vs Haskell type classes/families, I just don't recall it being made so explicit before, just focussing on type parameterization and sharing)!-)
</p>
en-usGHChttp://ghc.haskell.org/trac/ghc/chrome/site/ghc_logo.png
http://ghc.haskell.org/trac/ghc/ticket/3197
Trac 1.0.9clausWed, 29 Apr 2009 11:22:46 GMT
http://ghc.haskell.org/trac/ghc/ticket/3197#comment:1
http://ghc.haskell.org/trac/ghc/ticket/3197#comment:1
<p>
Another way to elicit the <tt>"Qualified name in binding position"</tt> part of this ticket:
</p>
<pre class="wiki">{-# LANGUAGE TypeFamilies #-}
module QTI where
type family TF a
</pre><pre class="wiki">{-# LANGUAGE TypeFamilies #-}
module Main where
import QTI()
type instance QTI.TF a = ()
</pre><p>
Instead of the expected <tt>"Not in scope"</tt> error, we get: <tt>"Qualified name in binding position: QTI.TF"</tt>. Removing the import restriction <tt>()</tt> makes the error go away, so this is definitely misleading.
</p>
TicketsimonpjWed, 29 Apr 2009 15:22:52 GMTdifficulty set
http://ghc.haskell.org/trac/ghc/ticket/3197#comment:2
http://ghc.haskell.org/trac/ghc/ticket/3197#comment:2
<ul>
<li><strong>difficulty</strong>
set to <em>Unknown</em>
</li>
</ul>
<p>
Yes that's definitely wrong, thanks. Will get to it.
</p>
<p>
However I don't understand what you mean by "is it really necessary for type families to have at least one index? Without that, type constants could be expressed directly". Ordinary Haskell 98 type synonyms are, in effect, a type family with zero indices.
</p>
<p>
Simon
</p>
TicketclausWed, 29 Apr 2009 15:57:41 GMT
http://ghc.haskell.org/trac/ghc/ticket/3197#comment:3
http://ghc.haskell.org/trac/ghc/ticket/3197#comment:3
<blockquote class="citation">
<p>
Ordinary Haskell 98 type synonyms are, in effect, a type family with zero indices.
</p>
</blockquote>
<p>
Until this example, I thought so, too. But there is still a difference: type synonyms have to be instantiated (given a right-hand side) immediately, type families can be instantiated later.
</p>
<p>
In the initial example above, <tt>type family Label a</tt> is defined in <tt>LA</tt>, but instantiated in <tt>LC</tt> (which imports <tt>LA</tt>) - that is how it comes close to parameterizing module <tt>LA</tt> by type <tt>Label a</tt> (see also <a class="ext-link" href="http://www.haskell.org/pipermail/haskell-cafe/2009-April/060673.html"><span class="icon"></span>3</a>).
</p>
<p>
If I had to replace <tt>type family Label a</tt> by <tt>type Label = ???</tt>, I wouldn't have anything to put in the right-hand side.
</p>
TicketsimonpjWed, 29 Apr 2009 16:12:34 GMT
http://ghc.haskell.org/trac/ghc/ticket/3197#comment:4
http://ghc.haskell.org/trac/ghc/ticket/3197#comment:4
<p>
I'm sorry, I don't understand. But I'll certainly look at the bug.
</p>
TicketiglooSat, 23 May 2009 20:38:26 GMTmilestone set
http://ghc.haskell.org/trac/ghc/ticket/3197#comment:5
http://ghc.haskell.org/trac/ghc/ticket/3197#comment:5
<ul>
<li><strong>milestone</strong>
set to <em>6.12.1</em>
</li>
</ul>
TicketchakThu, 02 Jul 2009 09:53:12 GMTstatus changed; resolution set
http://ghc.haskell.org/trac/ghc/ticket/3197#comment:6
http://ghc.haskell.org/trac/ghc/ticket/3197#comment:6
<ul>
<li><strong>status</strong>
changed from <em>new</em> to <em>closed</em>
</li>
<li><strong>resolution</strong>
set to <em>fixed</em>
</li>
</ul>
<p>
I fixed the bug, and I also permitted type families with no indices. I already wondered whether we should have them, but didn't see much use. You are saying there are useful and I don't think they create any problems (in the implementation, it was just a matter of removing the check).
</p>
Ticket