Problem with functional dependencies
Simon Peyton-Jones
simonpj@microsoft.com
Wed, 20 Dec 2000 03:11:44 -0800
I think you can simplify the example. Given
class HasFoo a b | a -> b where
foo :: a -> b
instance HasFoo Int Bool where ...
Is this legal?
f :: HasFoo Int b => Int -> b
f x = foo x
You might think so, since
HasFoo Int b => Int -> b
is a substitution instance of
HasFoo a b => a -> b
but if we infer the type (HasFoo Int b => Int -> b)
for f's RHS, we can then "improve" it using the instance
decl to (HasFoo Int Bool => Int -> Bool), and now the signature
isn't a substitution insance of the type of the RHS. Indeed,
this is just what will happen if you try with GHC, because
GHC takes advantage of type signatures when typechecking a
function defn, rather than first typechecking the defn and only
then comparing with the signature.
I don't know what the answers are here, but there's more to this
functional dependency stuff than meets the eye. Even whether
one type is more general than another has changed!
Simon
| -----Original Message-----
| From: qrczak@knm.org.pl [mailto:qrczak@knm.org.pl]
| Sent: 17 December 2000 19:30
| To: haskell@haskell.org
| Subject: Problem with functional dependencies
|
|
| The following module is rejected by both
| ghc -fglasgow-exts -fallow-undecidable-instances
| and
| hugs -98
|
| --------------------------------------------------------------
| ----------
| class HasFoo a foo | a -> foo where
| foo :: a -> foo
|
| data A = A Int
| data B = B A
|
| instance HasFoo A Int where
| foo (A x) = x
|
| instance HasFoo A foo => HasFoo B foo where
| foo (B a) = foo a
| --------------------------------------------------------------
| ----------
|
| The error messsage says that the type inferred for foo in B's instance
| is not general enough: the rhs has type "HasFoo B Int => B ->
| Int", but
| "HasFoo B foo => B -> foo" was expected.