GHC 8.2.x Migration Guide
This guide summarises the changes you may need to make to your code to migrate from GHC 8.0 to GHC 8.2. This guide complements the GHC 8.2.x release notes which should be consulted as well.
Compiler changes
DefaultSignatures
is pickier
There a new validity check for default class method implementations using -XDefaultSignatures
. In particular, if you have a class Foo
:
class Foo a where bar :: C => a -> b -> b
and you add a default type signature for bar
, it must be of the form:
default bar :: C' => a -> b -> b
That is, the right-hand sides of the type signatures must be the same, but the contexts C
and C'
are allowed to be different. That means that these default type signatures for bar
:
default bar :: C' => b -> a -> b default bar :: C' => b -> b -> a default bar :: C' => a -> b -> b -> b
will all be rejected.
These will also be rejected:
default bar :: C' => a -> Int -> Int default bar :: C' => a -> TF b -> TF b
(where TF
is a type family). But it's possible to rearrange these into equivalent forms that GHC accepts: just use type equalities!
default bar :: (C', b ~ Int) => a -> b -> b default bar :: (C', b ~ TF c) => a -> b -> b
As shown in the TF
example, you might have to create new type variables (e.g., c
) to make the type equalities work out.
Associated type family instances are pickier
There is also a new validity check for associated type family instances. That is, if you have a class with an associated type family:
class C a b where type T a x b
And you create and instance of C
:
instance C ty1 ty2 where ...
Then the associated T
instance must look exactly like:
type T ty1 v ty2 = ... -- 'ty1' for 'a' -- 'ty2' for 'b', and -- some type `v` for 'x'
As a concrete example, this code, which would have been allowed before GHC 8.2, is now disallowed:
class Foo a where type Bar a instance Foo (Either a b) where type Bar (Either c d) = d -> c
To fix this instance, simply use the same type variables in the Bar
instance as in the instance head:
instance Foo (Either a b) where type Bar (Either a b) = b -> a
Instances for class synonyms are now disallowed
Previously, GHC silently accepted nonsense instance declarations like this:
type ReadShow a = (Read a, Show a) instance Read Foo instance Show Foo instance ReadShow Foo
It's not even clear what this is supposed to mean, since ReadShow
isn't a class in and of itself. To disallow this, GHC now prevents all instances of the form instance (...) => Syn (...)
, where Syn
is a type synonym.
This check is a bit conservative, as it bars you from writing this as well:
type MyShow = Show instance MyShow Foo
The workaround is to define the instance using Show
instead of MyShow
.
Kind generalization and MonoLocalBinds
The MonoLocalBinds
extension, which places limitations on when the type of a term is generalized, also affects when the kind of a type signature of generalized. Prior to GHC 8.2, there were certain scenarios when kinds signatures were incorrectly generalized in the presence of MonoLocalBinds
. This bug has now been fixed, but as a consequence, there are a handful of programs which will fail to typecheck without explicit kind signatures. Here is a known example:
{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE MonoLocalBinds #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeInType #-} data Proxy a = Proxy newtype Tagged s b = Tagged b class C b where c :: forall (s :: k). Tagged s b instance C (Proxy a) where c :: forall s. Tagged s (Proxy a) c = Tagged Proxy
This compiles in GHC 8.0, but in GHC 8.2, it gives this error:
• Couldn't match type ‘k0’ with ‘k1’ because type variable ‘k1’ would escape its scope This (rigid, skolem) type variable is bound by the type signature for: c :: forall k1 (s :: k1). Tagged s (Proxy a) at Bug.hs:13:8-35 Expected type: Tagged s (Proxy a) Actual type: Tagged s (Proxy a) • When checking that instance signature for ‘c’ is more general than its signature in the class Instance sig: forall (s :: k0). Tagged s (Proxy a) Class sig: forall k1 (s :: k1). Tagged s (Proxy a) In the instance declaration for ‘C (Proxy a)’
The reason for this error is that the type signature for c
captures a
, an outer-scoped type variable, which means the type signature is not closed. Therefore, with MonoLocalBinds
enabled, the inferred kind for s
will not be generalized, and as a result, it will fail to unify with the kind variable k
which is specified in the declaration of c
.
This can be worked around by specifying an explicit kind variable for s
, e.g.,
instance C (Proxy a) where c :: forall (s :: k). Tagged s (Proxy a) c = Tagged Proxy
Library changes
base-4.10.0.0
Type-indexed Typeable
changes
- The
Data.Typeable.Internal
module has been removed entirely. Much of theTypeable
internals now live in the newType.Reflection
module. Data.Typeable.TypeRep
is now a type synonym (so you may needTypeSynonymInstances
to create an instance for it, unless you switch it to useType.Reflection.SomeTypeRep
)mkFunTy
,mkAppTy
,mkTyConApp
, andhave been removed. If you use these then you might instead consider looking at the new type-indexed interfaces found in
Type.Reflection
.mkTyCon3
andmkTyConApp
are no longer exported byData.Typeable
. They are instead exported byType.Reflection.Unsafe
.Data.Dynamic
no longer re-exports all ofData.Typeable
(only theTypeable
class).
fromLabel
type signature change
The type signature of fromLabel
has changed:
fromLabel :: Proxy# x -> a -- old type signature fromLabel :: a -- new type signature
The new
fromLabel
can be accommodated usingTypeApplications
:
fromLabel (proxy# :: Proxy# "foo") :: alpha -- old style fromLabel @"foo" :: alpha -- new style
GHC.Generics
is more polykinded
The Generic1
class, as well related classes and data types from GHC.Generics
, are now poly-kinded. Here are the kind signatures of these types before base-4.10.0.0
:
class Generic1 (f :: * -> *) where type Rep1 f :: * -> * from1 :: f a -> Rep1 f a to1 :: Rep1 f a -> f a class Datatype (d :: k) where datatypeName :: t d (f :: * -> *) (a :: k1) -> [Char] moduleName :: t d (f :: * -> *) (a :: k1) -> [Char] packageName :: t d (f :: * -> *) (a :: k1) -> [Char] isNewtype :: t d (f :: * -> *) (a :: k1) -> Bool class Constructor (c :: k) where conName :: t c (f :: * -> *) (a :: k1) -> [Char] conFixity :: t c (f :: * -> *) (a :: k1) -> Fixity conIsRecord :: t c (f :: * -> *) (a :: k1) -> Bool class Selector (s :: k) where selName :: t s (f :: * -> *) (a :: k1) -> [Char] selSourceUnpackedness :: t s (f :: * -> *) (a :: k1) -> SourceUnpackedness selSourceStrictness :: t s (f :: * -> *) (a :: k1) -> SourceStrictness selDecidedStrictness :: t s (f :: * -> *) (a :: k1) -> DecidedStrictness data V1 (p :: *) data U1 (p :: *) = U1 newtype Par1 p = Par1 p newtype Rec1 (f :: * -> *) (p :: *) = Rec1 (f p) newtype K1 i c (p :: *) = K1 c newtype M1 i c (f :: * -> *) (p :: *) = M1 (f p) data (:+:) (f :: * -> *) (g :: * -> *) (p :: *) = L1 (f p) | R1 (g p) data (:*:) (f :: * -> *) (g :: * -> *) (p :: *) = f p :*: g p newtype (:.:) (f :: * -> *) (g :: * -> *) (p :: *) = Comp1 (f (g p)) data family URec a (p :: *)
And here are their kind signatures now:
class Generic1 (f :: k -> *) where type Rep1 f :: k -> * from1 :: f a -> Rep1 f a to1 :: Rep1 f a -> f a class Datatype (d :: k) where datatypeName :: t d (f :: k1 -> *) (a :: k1) -> [Char] moduleName :: t d (f :: k1 -> *) (a :: k1) -> [Char] packageName :: t d (f :: k1 -> *) (a :: k1) -> [Char] isNewtype :: t d (f :: k1 -> *) (a :: k1) -> Bool class Constructor (c :: k) where conName :: t c (f :: k1 -> *) (a :: k1) -> [Char] conFixity :: t c (f :: k1 -> *) (a :: k1) -> Fixity conIsRecord :: t c (f :: k1 -> *) (a :: k1) -> Bool class Selector (s :: k) where selName :: t s (f :: k1 -> *) (a :: k1) -> [Char] selSourceUnpackedness :: t s (f :: k1 -> *) (a :: k1) -> SourceUnpackedness selSourceStrictness :: t s (f :: k1 -> *) (a :: k1) -> SourceStrictness selDecidedStrictness :: t s (f :: k1 -> *) (a :: k1) -> DecidedStrictness data V1 (p :: k) data U1 (p :: k) = U1 newtype Par1 p = Par1 p newtype Rec1 (f :: k -> *) (p :: k) = Rec1 (f p) newtype K1 i c (p :: k) = K1 c newtype M1 i c (f :: k -> *) (p :: k) = M1 (f p) data (:+:) (f :: k -> *) (g :: k -> *) (p :: k) = L1 (f p) | R1 (g p) data (:*:) (f :: k -> *) (g :: k -> *) (p :: k) = f p :*: g p newtype (:.:) (f :: k2 -> *) (g :: k1 -> k2) (p :: k1) = Comp1 (f (g p)) data family URec a (p :: k)
It's possible that you might experience some typechecker errors due to this change. If so, a probable fix is to add explicit kind signatures in the right places.
template-haskell-2.12.0.0
- The
DataD
,NewtypeD
,DataInstD
, andNewtypeInstD
constructors now take a[DerivCxtQ]
instead of aCxtQ
to representderiving
clauses (#10598). This change was necessary because:- Due to the introduction of deriving strategies, data types can now accept multiple deriving clauses (hence the need for
[DerivCxtQ]
instead ofDerivCxtQ
). - Each deriving clause now allows an optional strategy keyword, so a new
DerivClause
data type was introduced that contains aMaybe DerivStrategy
in addition to the usualCxt
.
- Due to the introduction of deriving strategies, data types can now accept multiple deriving clauses (hence the need for
Similarly, the
StandaloneDerivD
constructor now also takes an additionalMaybe DerivStrategy
argument, since deriving strategy keywords can also be used with standalonederiving
declarations. ThestandaloneDerivD
function's type signature remains unchanged, as it will produce a standalone deriving declaration with no strategy keyword. If you want to use an explicit keyword, usestandaloneDerivWithStrategyD
.
Tool changes
GHC API changes
- The
StaticFlags
module has been removed, as all static flags have been converted to dynamic ones in GHC 8.2.