FunDeps conflict

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

FunDeps conflict

Joel Björnson
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

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: FunDeps conflict

Brian Hulley
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 

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: FunDeps conflict

Brian Hulley
In reply to this post by Joel Björnson
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 

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: FunDeps conflict

Joel Björnson-2
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





_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: FunDeps conflict

Brian Hulley
In reply to this post by Brian Hulley
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.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe