
Hi all, I have played quite a bit with the ConstraintKinds extension, pretty cool. But I found a problem which I thought would be made better, plz correct me if I am wrong take a contrived example, class C B => B a where here B :: * -> Constraint, I think this definition is reasonable, since B does not appears in the first position of the context. Previously, we require acyclic class declarations since we don't have ConstraintKinds extension but now since type class could be abstracted, I think the definition above should be ok. the ghc-manual cited the program below is valid class C a where {op :: D b => a -> b -> b} class C a => D a where { ... } I think there are no reasons to reject class C B => B where (and this style is pretty useful in some cases) ... B :: * -> Constraint C :: (*->Constraint) -> Constraint Any comments are welcome -- Best, bob

On 18 October 2011 02:25, bob zhang
take a contrived example, class C B => B a where here B :: * -> Constraint, I think this definition is reasonable, since B does not appears in the first position of the context.
I think you are getting an error where GHC complains about a superclass cycle. I think this warning is necessary: after all, I could write the following definition for C: """ class c Int => C c where """ Now I really do have a cycle! You are right to say that *some* Cs are OK though. In particular, in a class "C c" if you don't mention c in the superclasses there can't be a cycle. In fact, the same observation might make sense for detecting type synonym cycles. Perhaps we could allow: """ type Foo a = Int type Bar = Foo Bar """ I could change the superclass-cycle check to only reject cycles that actually cause cycles after expansion. So with my proposed C: 1. Input: C B => B a. DontExpand = {B} 2. Substitute: B Int => B a. DontExpand = {B,C} We can't expand further. This is a real cycle and would be rejected. With a different C: """ class Eq Int => C c where """ 1. Input: C B => B a. DontExpand = {B} 2. Substitute: Eq Int => B a. DontExpand = {B,C} 3. Substitute: () => B a. DontExpand = {B, C, Eq} Again we can't expand further, but this time it is because we have reached (). B would not be rejected. I think relaxing the check in this manner would be safe. Would this change be enough for you to do what you need? Max

Hi, Max
Thanks for your reply.
I don't understand your proposal, or can you elaborate on it?
Let's double check,
In my contrived example the definition of class C is like this
class C c where { foo :: c Int => ....}
class C B => B a where { ...}
will this pass under your proposal?
It will bring much more power if this could pass.
plz let me know if it is committed into the source tree.
Many thanks
On Tue, Oct 18, 2011 at 2:42 AM, Max Bolingbroke wrote: On 18 October 2011 02:25, bob zhang take a contrived example,
class C B => B a where
here B :: * -> Constraint, I think this definition is reasonable,
since B does not appears in the
first position of the context. I think you are getting an error where GHC complains about a
superclass cycle. I think this warning is necessary: after all, I
could write the following definition for C: """
class c Int => C c where
""" Now I really do have a cycle! You are right to say that *some* Cs are OK though. In particular, in a
class "C c" if you don't mention c in the superclasses there can't be
a cycle. In fact, the same observation might make sense for detecting
type synonym cycles. Perhaps we could allow: """
type Foo a = Int
type Bar = Foo Bar
""" I could change the superclass-cycle check to only reject cycles that
actually cause cycles after expansion. So with my proposed C: 1. Input: C B => B a. DontExpand = {B}
2. Substitute: B Int => B a. DontExpand = {B,C} We can't expand further. This is a real cycle and would be rejected.
With a different C: """
class Eq Int => C c where
""" 1. Input: C B => B a. DontExpand = {B}
2. Substitute: Eq Int => B a. DontExpand = {B,C}
3. Substitute: () => B a. DontExpand = {B, C, Eq} Again we can't expand further, but this time it is because we have
reached (). B would not be rejected. I think relaxing the check in this manner would be safe. Would this
change be enough for you to do what you need? Max --
Best, bob

On 18 October 2011 13:49, bob zhang
In my contrived example the definition of class C is like this class C c where { foo :: c Int => ....} class C B => B a where { ...} will this pass under your proposal?
Yes I would allow this to pass. If this would be enough to support what you want to do I'm happy to make the change. Max

That would be great. Would you mind send me a patch, or commit it to the source tree. Actually I found in the paper SYB with classes also need such change, if you don't like overlapping instance. class Data cxt a => cxt a where On Thu, Oct 20, 2011 at 11:14 AM, Max Bolingbroke < batterseapower@hotmail.com> wrote:
On 18 October 2011 13:49, bob zhang
wrote: In my contrived example the definition of class C is like this class C c where { foo :: c Int => ....} class C B => B a where { ...} will this pass under your proposal?
Yes I would allow this to pass.
If this would be enough to support what you want to do I'm happy to make the change.
Max
-- Best, bob
participants (2)
-
bob zhang
-
Max Bolingbroke