Difference between revisions of "GHC/Type system"

From HaskellWiki
< GHC
Jump to navigation Jump to search
(Updated the link to the GHC user manual)
(5 intermediate revisions by 2 users not shown)
Line 2: Line 2:
 
<span style='font-size: x-large; font-weight: bold'>Type system extensions in GHC</span>
 
<span style='font-size: x-large; font-weight: bold'>Type system extensions in GHC</span>
   
GHC comes with a rather large collection of type-system extensions (beyond Haskell 98). They are all documented in the [http://www.haskell.org/ghc/docs/latest/html/users_guide/ghc-language-features.html user manual], but this page is a place to record observations, notes, and suggestions on them.
+
GHC comes with a rather large collection of type-system extensions (beyond Haskell 98). They are all documented in the [http://www.haskell.org/ghc/docs/latest/html/users_guide/ghc-language-features.html user manual], but this page is a place to record user-oriented observations, notes, and suggestions on how to use them.
   
  +
* '''[[GHC/Indexed_types|Indexed data types]]'''
== Type signatures and ambiguity ==
 
  +
* '''[[GHC/TypeHoles|Agda-like "holes" in GHC]]'''
 
 
* '''[[GHC/Stand-alone deriving declarations|"Stand-alone deriving" declarations]]'''
It's quite common for people to write a function definition without a type signature, load it into GHCi, use <tt>:t</tt> to see what type it has, and then cut-and-paste that type into the source code as a type signature. Usually this works fine, but alas not always. Perhaps this is a deficiency in GHC, but here's one way it can happen:
 
 
* '''[[GHC/TypeSigsAndAmbiguity|Type signatures and ambiguity]]'''
<haskell>
 
 
* '''Overlapping instances'''. GHC supports overlapping instances, with carefully specified rules. Make sure you read the [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-class-extensions.html#instance-decls relevant sections of the user manual]. Here is an appliation note about [[GHC/AdvancedOverlap|advanced use of overlapping instances]], combined with functional dependencies.
class C a b where
 
  +
* '''[[GHC/Coercible|Safe coercions using Coercible]]'''
foo :: a -> b
 
 
konst :: a -> Bool
 
konst x = True
 
 
f :: (C a b) => a -> Bool
 
f x = konst (foo x)
 
</haskell>
 
If you compile this code, you'll get this error:
 
<pre>
 
Foo1.hs:12:13:
 
Could not deduce (C a b1) from the context (C a b)
 
arising from use of `foo' at Foo1.hs:12:13-17
 
Possible fix: add (C a b1) to the type signature(s) for `f'
 
In the first argument of `konst', namely `(foo x)'
 
In the expression: konst (foo x)
 
In the definition of `f': f x = konst (foo x)
 
</pre>
 
What's going on? GHC knows, from the type signature that <tt>x::a</tt>. Then applying <tt>foo</tt> means GHC must pick a return type for <tt>foo</tt>, say <tt>b1</tt>, and generates the type constraint <tt>(C a b1)</tt>. The function <tt>konst</tt> just discards its argument, ''so nothing further is known about <tt>b1</tt>''.
 
 
Now GHC finished typechecking the right hand side of <tt>f</tt>, so next it checks that the constraints ''needed'' in the RHS, namely <tt>(C a b1)</tt>, can be satisfied from the constraints ''provided'' by the type signature, namely <tt>(C a b)</tt>. Alas there is nothing to tell GHC that <tt>b</tt> and <tt>b1</tt> should be identified together; hence the complaint. (Probably you meant to put a functional dependency in the class declaration, thus
 
<haskell>
 
class C a b | a->b where ...
 
</haskell>
 
but you didn't.)
 
 
The surprise is that if you comment out the type signature for <tt>f</tt>, the module will load fine into GHCi! Furthermore <tt>:t</tt> will report a type for <tt>f</tt> that is exactly the same as the type signature that was rejected!
 
 
Here's what's happening. Without the type signature, GHC picks an arbitrary type for <tt>x</tt>, say <tt>x::a</tt>. Then applying <tt>foo</tt> means GHC must pick a return type for <tt>foo</tt>, say <tt>b</tt>, and generates the type constraint <tt>(C a b)</tt>. The function <tt>konst</tt> just discards its argument, so nothing further is known about <tt>b</tt>. Finally, GHC gathers up all the constraints arising from the right hand side, namely <tt>(C a b)</tt>, and puts them into the inferred type of <tt>f</tt>. So GHC ends up saying that <hask>f :: (C a b) => a -> Bool</hask>.
 
 
This is probably a very stupid type. Suppose you called <tt>f</tt> thus: <tt>(f 'a')</tt>. Then you'd get a constraint <tt>(C Char b)</tt> where nothing is known about <tt>b</tt>. If the instances of <tt>C</tt> constrain both type parameters, you'd be in trouble:
 
<haskell>
 
instance C Char Bool where ...
 
</haskell>
 
The call gives a <tt>(C Char b)</tt> constraint, with absolutely no way to fix <tt>b</tt> to be <tt>Bool</tt>, or indeed anything else. We're back to very much the same situation as before; it's just that the error is deferred until we call <tt>f</tt>, rather than when we define it.
 
 
(However, notice that the call <tt>(f 'a')</tt> would be OK if there was an instance like:
 
<haskell>
 
instance C Char w where ...
 
</haskell>
 
Now the constraint <tt>(C Char b)</tt> matches the instance declaration, even though we know nothing about <tt>b</tt>.)
 
 
This behaviour isn't ideal. It really only arises in programs that are ambiguous anyway (that is, they could never really work), but it is undoubtedly confusing. But I don't know an easy way to improve it. Yet, anyway.
 
 
== Overlapping instances ==
 
 
GHC supports overlapping instances, with carefully specified rules. Make sure you read the [http://www.haskell.org/ghc/docs/latest/html/users_guide/type-class-extensions.html#instance-decls relevant sections of the user manual].
 
 
Here is an appliation note about [[GHC/AdvancedOverlap|advanced use of overlapping instances]], combined with functional dependencies.
 
 
== Indexed data types and indexed newtypes ==
 
 
[[GHC/Indexed_types|Indexed data types]] (including associated data types) are a very recent addition to GHC's type system extensions that is not yet included in the user manual. To use the extension, you need to obtain a version of GHC from [http://hackage.haskell.org/trac/ghc/wiki/Building/GettingTheSources its source repository].
 
 
== Stand-alone deriving clauses ==
 
 
Bjorn Bringert has recently implemented [[GHC/Stand-alone deriving declarations|"stand-alone deriving" declarations]].
 
-----------------------
 

Revision as of 08:57, 20 May 2014

Type system extensions in GHC

GHC comes with a rather large collection of type-system extensions (beyond Haskell 98). They are all documented in the user manual, but this page is a place to record user-oriented observations, notes, and suggestions on how to use them.