Opened 13 years ago

Closed 7 years ago

Last modified 6 years 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 Test Case: N/A
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Change History (17)

comment:1 Changed 13 years ago by igloo

Milestone: _|_
Test Case: N/A

comment:2 Changed 12 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 11 years ago by Deewiant

Cc: Deewiant added

comment:4 Changed 11 years ago by simonmar

Architecture: UnknownUnknown/Multiple

comment:5 Changed 11 years ago by simonmar

Operating System: UnknownUnknown/Multiple

comment:8 Changed 10 years ago by igloo

Component: CompilerCompiler (Type checker)
Type of failure: None/Unknown

comment:9 Changed 9 years ago by simonpj

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


comment:10 Changed 9 years ago by gidyn

Cc: gideon@… added

comment:11 Changed 9 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


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 9 years ago by batterseapower

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

comment:13 Changed 9 years ago by simonpj

Description: modified (diff)

comment:14 Changed 9 years ago by simonpj

Description: modified (diff)

comment:15 Changed 8 years ago by bgamari

Cc: bgamari@… added

comment:16 Changed 7 years ago by anders_

Resolution: fixed
Status: newclosed

This is implemented by ConstraintKinds, right?

comment:17 Changed 6 years ago by gidyn

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