Difference between revisions of "GHC/Type system"

From HaskellWiki
< GHC
Jump to navigation Jump to search
Line 5: Line 5:
   
 
== Type signatures and ambiguity ==
 
== Type signatures and ambiguity ==
  +
  +
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:
  +
<haskell>
  +
class C a b where
  +
foo :: a -> b
  +
  +
konst :: a -> Bool
  +
konst x = True
  +
  +
f :: (C a b) => a -> Bool
  +
f x = konst (foo x)
  +
</haskell>
  +
If you comment out the type signature <hask>f :: (C a b) => a -> Bool</hask>, the module will load fine into GHCi, and <tt>:t</tt> will report exactly this type for <tt>f</tt>. But if you leave the type signature in, 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? Without the type signature, GHC picks a 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 abouut <tt>b</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>. That would be OK if there was an instance like:
  +
<haskell>
  +
instance C Char b where ...
  +
</haskell>
   
 
== Overlapping instances ==
 
== Overlapping instances ==

Revision as of 14:25, 20 February 2007

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 observations, notes, and suggestions on them.

Type signatures and ambiguity

It's quite common for people to write a function definition without a type signature, load it into GHCi, use :t 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:

class C a b where
  foo :: a -> b

konst :: a -> Bool
konst x = True

f :: (C a b) => a -> Bool
f x = konst (foo x)

If you comment out the type signature f :: (C a b) => a -> Bool, the module will load fine into GHCi, and :t will report exactly this type for f. But if you leave the type signature in, you'll get this error:

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)

What's going on? Without the type signature, GHC picks a type for x, say x::a. Then applying foo means GHC must pick a return type for foo, say b, and generates the type constraint (C a b). The function konst just discards its argument, so nothing further is known abouut b. So GHC ends up saying that f :: (C a b) => a -> Bool.

This is probably a very stupid type. Suppose you called f thus: (f 'a'). Then you'd get a constraint (C Char b) where nothing is known about b. That would be OK if there was an instance like:

instance C Char b where ...

Overlapping instances

Here an interesting message about the interaction of existential types and overlapping instances.

Indexed data types and indexed newtypes

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 its source repository.

Stand-alone deriving clauses

Bjorn Bringert has recently implemented "stand-alone deriving" declarations.