
Hi. I have a question regarding type classes and FunDeps. Consider the following code :
class Class2 a b | a -> b
class IsFoo a data Bar a = Bar a
instance IsFoo a => Class2 a a instance IsFoo a => Class2 (Bar a) a
The last two instantiations will yield a 'Functional dependencies conflict error'. From what I understand, this is because (Bar a) *MAY* instantiate the type class isFoo, which would obviously lead to a conflict between the two instantiations. Is there anyway to get around this, knowing that (Bar a) won`t instantiate the isFoo class, or is the right answer simply to get rid of the FunDep ? Thanks /Joel

Joel Björnson wrote:
Hi. I have a question regarding type classes and FunDeps. Consider the following code :
class Class2 a b | a -> b
class IsFoo a data Bar a = Bar a
instance IsFoo a => Class2 a a instance IsFoo a => Class2 (Bar a) a
The last two instantiations will yield a 'Functional dependencies conflict error'. From what I understand, this is because (Bar a) *MAY* instantiate the type class isFoo, which would obviously lead to a conflict between the two instantiations.
The typeclass IsFoo is irrelevant to the fundep. The problem arises here: class Class2 a b | a -> b data Bar a = Bar a instance Class2 a a instance Class2 (Bar a) a because a and Bar a could be instantiated to two different types eg Bool and Bar Bool, yet the result type would be the same, but the fundep specifies that the 'a' type uniquely determines the 'b' type, hence the conflict.
Is there anyway to get around this, knowing that (Bar a) won`t instantiate the isFoo class, or is the right answer simply to get rid of the FunDep ?
If 'b' is not uniquely determined by 'a' in all instances of Class2 a b, then you'd need to get rid of the fundep. Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com

Brian Hulley wrote:
Joel Björnson wrote:
Hi. I have a question regarding type classes and FunDeps. Consider the following code :
class Class2 a b | a -> b
class IsFoo a data Bar a = Bar a
instance IsFoo a => Class2 a a instance IsFoo a => Class2 (Bar a) a
The last two instantiations will yield a 'Functional dependencies conflict error'. From what I understand, this is because (Bar a) *MAY* instantiate the type class isFoo, which would obviously lead to a conflict between the two instantiations.
The typeclass IsFoo is irrelevant to the fundep. The problem arises here:
class Class2 a b | a -> b
data Bar a = Bar a
instance Class2 a a instance Class2 (Bar a) a
because a and Bar a could be instantiated to two different types eg Bool and Bar Bool, yet the result type would be the same, but the fundep specifies that the 'a' type uniquely determines the 'b' type, hence the conflict.
Please ignore the above "explanation" cause it's wrong ;-) I must have had an attack of fundep dyslexia and read the arrow the wrong way... Regards, Brian.

Joel Björnson wrote:
Hi. I have a question regarding type classes and FunDeps. Consider the following code :
class Class2 a b | a -> b
class IsFoo a data Bar a = Bar a
instance IsFoo a => Class2 a a instance IsFoo a => Class2 (Bar a) a
The last two instantiations will yield a 'Functional dependencies conflict error'. From what I understand, this is because (Bar a) *MAY* instantiate the type class isFoo, which would obviously lead to a conflict between the two instantiations.
Possibly you meant to write: instance IsFoo a => Class2 a a instance Class2 (Bar a) a in which case the conflict does arise because (Bar a) could be an instance of IsFoo, but afaik there is no way to tell the compiler that (Bar a) can never be an instance of IsFoo, since all classes are "open" ie new instances can be defined later. Having said this it does seem to me rather strange that there is no way to specify that (Bar a) cannot ever be an instance of IsFoo, since fundeps themselves limit the allowable instances for a class so you'd think the fundep itself would be enough to tell the compiler that there can be no instances of IsFoo (Bar a) in the same way that: class Class3 a b | a -> b instance Class3 Bool Char instance Class3 Int Float tells the compiler there can't be any future instance such as Class3 Int Char etc, but perhaps it is necessary to keep the possible instances for each type class strictly independent of any other typeclass to avoid too much complexity. There is a proposal for Haskell' for closed classes but this is listed under the "probably no" section so it's unlikely this will be adopted. http://hackage.haskell.org/trac/haskell-prime/wiki/ClassSystem http://hackage.haskell.org/trac/haskell-prime/wiki/ClosedClasses Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com

Brian Hulley wrote :
Possibly you meant to write: instance IsFoo a => Class2 a a instance Class2 (Bar a) a
Yes, in principle that illustrates the idea. However I don't see the major difference from constraining the 'a' to the IsFoo class, as in instance IsFoo a => Class2 (Bar a) a This wont automatically imply 'Bar a' to instantiate IsFoo. As pointed out, the problem arises due to the fact that it is possible to write an instance for Bar a, which would then violate the FunDep constraint. So, since the compiler does not control this, I'll better remove the FunDep. Thanks /Joel
participants (3)
-
Brian Hulley
-
Joel Björnson
-
Joel Björnson