allow existential wrapper newtypes
Consider this OO-style thing, a class Compiler, and a most general instance MkCompiler:
class Compiler c where
getInstalledPackages :: c -> IO [String]
data GHC = GHC { }
data NHC = NHC { }
ghc :: GHC
ghc = GHC { }
nhc :: NHC
nhc = NHC { }
instance Compiler GHC
instance Compiler NHC
data MkCompiler where
MkCompiler :: Compiler c => c -> MkCompiler
instance Compiler MkCompiler where
getInstalledPackages (MkCompiler c) = getInstalledPackages c
compilers :: [MkCompiler]
compilers = [MkCompiler ghc, MkCompiler nhc]
There's two language features we want to make this really nice:
- Letting us call the data type
Compiler
rather thanMkCompiler
. That would mean separating the class and type namespaces. - Letting us derive the Compiler instance for
MkCompiler
.
For the latter we would want either:
newtype MkCompiler where
MkCompiler :: Compiler c => c -> MkCompiler
deriving Compiler
or
data MkCompiler where
MkCompiler :: Compiler c => c -> MkCompiler
deriving Compiler
The advantage of the first is that newtype deriving already exists as a concept so that's nice and consistent. The problem is we do not allow newtypes that use existentials. From an implementation point of view, it's clear that the representations cannot be equal because of the need to store the class dictionary. From a semantic point of view however it's not obvious that existentials with class contexts are illegitimate in newtypes. The underlying implementation would of course have to be an extra layer of boxing, so like data but with the pattern match behaviour newtype.
Trac metadata
Trac field | Value |
---|---|
Version | 6.10.4 |
Type | FeatureRequest |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |