Opened 8 years ago

Closed 22 months ago

Last modified 10 months ago

#788 closed feature request (fixed)

Implement class aliases and/or constraint synonyms

Reported by: simonpj Owned by:
Priority: normal Milestone:
Component: Compiler (Type checker) Version:
Keywords: Cc: Deewiant, bgamari@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Difficulty: Unknown
Test Case: N/A Blocked By:
Blocking: Related Tickets:

Change History (17)

comment:1 Changed 8 years ago by igloo

  • Milestone set to _|_
  • Test Case set to N/A

comment:2 Changed 6 years ago by SamB

Note that the class alias proposal seems to have some syntax errors. I found these in trying to implement class aliases in John's own compiler, JHC -- which I haven't given up on yet, but I am sidetracked fixing (->) for now...

comment:3 Changed 6 years ago by Deewiant

  • Cc Deewiant added

comment:4 Changed 6 years ago by simonmar

  • Architecture changed from Unknown to Unknown/Multiple

comment:5 Changed 6 years ago by simonmar

  • Operating System changed from Unknown to Unknown/Multiple

comment:8 Changed 4 years ago by igloo

  • Component changed from Compiler to Compiler (Type checker)
  • Type of failure set to None/Unknown

comment:9 Changed 3 years ago by simonpj

  • Description modified (diff)
  • Summary changed from Class aliases (as proposaed by John Meacham) to Implement class aliases and/or constraint synonyms

Anoter

comment:10 Changed 3 years ago by gidyn

  • Cc gideon@… added

comment:11 Changed 3 years ago by batterseapower

Superclass defaulting is another alternative. This is a proposal that has come up again recently on the mailing list. It is attractive because it would allow us to refactor class hierarchies (such as the infamous Monad) in a backwards-compatible manner.

The proposal would allow code like this:

class Functor f where
    fmap :: (a -> b) -> f a -> f b

class Functor m => Monad m where
    return :: a -> m a
    (>>=) :: m a -> (a -> m b) -> m b
    
    fmap f mx = mx >>= (return . f)

The change is that class declarations can include default methods not only for methods of that class, but also any of its superclasses. This allows us to add superclasses to an existing class but provide defaults for their methods. These defaults will be used to manufacture a superclass instance (like Functor) if one is not available at the point where we declare a class instance (like Monad), thus - mostly - avoiding breakage of user code.

Of course, user code will still break if we have orphan instances. For example this user code will break if we refactor Monad in this way:

module A where

instance Monad AType where
  ...

With:

module B where
import A

instance Functor AType where
  ...

Because the orphan Functor AType instance will not be available in module A, so superclass defaulting will manufacture a Functor instance there and then, which then overlaps with the one from module B. But abusers of orphans deserve what they get :-)

The first major problem I can think of (as with class aliases) is with code like this:

class Foo a where
    foo :: a -> String

class (Foo a, Foo b) => Bar a b where
    bar :: Either a b -> String
    
    foo = bar . Left

    foo = bar . Right

How should this be interpreted? It is clear that the user intended to provide superclass defaults for *both* Foo superclasses, but if we just parse it looks like a single foo method with two right hand sides. Even if we parse it as two different declarations then we have to use information about the inferred type of each default to decide which superclass instance it should contribute to.

One option would be to say you can only write one superclass default for any given superclass method, which lets us do Monads but defers treatment of the hard cases.

comment:12 Changed 3 years ago by batterseapower

I see that superclass defaulting has its own ticket: #2895

comment:13 Changed 3 years ago by simonpj

  • Description modified (diff)

comment:14 Changed 3 years ago by simonpj

  • Description modified (diff)

comment:15 Changed 2 years ago by bgamari

  • Cc bgamari@… added

comment:16 Changed 22 months ago by anders_

  • Resolution set to fixed
  • Status changed from new to closed

This is implemented by ConstraintKinds, right?

comment:17 Changed 10 months ago by gidyn

  • Cc gideon@… removed
Note: See TracTickets for help on using tickets.