GHC 8.4.x Migration Guide
This guide summarises the changes you may need to make to your code to migrate from GHC 8.2 to GHC 8.4. This guide complements the GHC 8.4.x release notes which should be consulted as well.
Compiler changes
Type variable order in GADT constructors
The order in which type variables are quantified in GADT constructor type signatures has changed. Before, if you had MkT
as below:
data T a where MkT :: forall b a. b -> T a
Then the type of MkT
would (counterintuitively) be forall a b. b -> T a
! Now, GHC quantifies the type variables in the order that the users writes them, so the type of MkT
is now forall b a. b -> T a
(this matters for TypeApplications
).
TypeInType
is pickier
Some code which previously typechecked in earlier versions of GHC without the use of the TypeInType
extension will now require it in 8.4. For example:
myError :: forall (r :: RuntimeRep) . forall (a :: TYPE r) . String -> a myError = error
In spirit, this function has always required the TypeInType
extension, since the type variable r
is also used as a kind variable in forall (a :: TYPE r)
. However, GHC mistakenly didn't require the explicit use of TypeInType
here in earlier versions. This has been rectified in 8.4, so now myError
will not typecheck without TypeInType
being explicitly enabled.
In addition, prior GHCs would permit this sort of GADT, where the GADT return type constrains a kind parameter, without the use of TypeInType
:
data G (a :: k) where GInt :: G Int
Similarly, this now requires TypeInType
in GHC 8.4.
TemplateHaskell
reification changes for GADTs
Before GHC 8.4, whether or not Template Haskell would reify a data type as a GadtC
(or RecGadtC
) was somewhat unpredictable, as it used heuristics to determine whether a data type was declared using GADT syntax or not. While this worked for most use cases, there were nevertheless some corner cases where a GADT would not be reified as a GadtC
, and conversely, a non-GADT would be reified as a GadtC
. For example:
GHCi, version 8.2.1: http://www.haskell.org/ghc/ :? for help λ> :set -XTemplateHaskell -XExistentialQuantification -XGADTs λ> import Language.Haskell.TH λ> data Foo a where MkFoo :: Show a => Foo a λ> $(reify ''Foo >>= stringE . show) "TyConI (DataD [] Ghci4.Foo [KindedTV a_6989586621679027473 StarT] Nothing [ForallC [] [AppT (ConT GHC.Show.Show) (VarT a_6989586621679027473)] (NormalC Ghci4.MkFoo [])] [])" λ> data Bar a = (a ~ Int) => MkBar λ> $(reify ''Bar >>= stringE . show) "TyConI (DataD [] Ghci6.Bar [KindedTV a_6989586621679027637 StarT] Nothing [ForallC [KindedTV a_6989586621679027637 StarT] [AppT (AppT (ConT Data.Type.Equality.~) (VarT a_6989586621679027637)) (ConT GHC.Types.Int)] (GadtC [Ghci6.MkBar] [] (AppT (ConT Ghci6.Bar) (VarT a_6989586621679027637)))] [])"
Note that Foo
, a GADT, is not reified as a GadtC
, whereas Bar
, which is not a GADT, is reified as a GadtC
. In GHC 8.4, this bug has been fixed, so as a result, Foo
will be reified as a GadtC
, but Bar
will not be, as one would expect.
In accordance with the changes to GADT constructor type variable order (mentioned above), reified GADT constructors also now track the order in which users wrote type variables. Continuing the earlier example:
data T a where MkT :: forall b a. b -> T a
In earlier GHCs, reifying MkT
would have yielded a type headed by ForallC [PlainTV a, PlainTV b]
. Now, reifying MkT
will give a type headed by ForallC [PlainTV b, PlainTV a]
, as one would expect.
Deriving for empty data types
As part of this proposal was implemented, GHC now derives instances for empty data types (with no constructors) much differently than it did before. Here are the highlights:
- There is now an
EmptyDataDeriving
pragma which allows derivingEq
,Ord
,Read
,Show
instances for empty data types. (Previously, this could only be done viaStandaloneDeriving
, but withEmptyDataDeriving
, one can usederiving
clauses to accomplish the same thing now.)
- Previously, the generated code for derived instances for empty data types was quite awful, involving lots of uses of
error
. What follows a list of what code GHC used to derive for empty data types, contrasted with what GHC now derives after this proposal was implemented (using a running example ofdata Empty a
, with no constructors):
- Derived
Eq
andOrd
instances would previously emit code that usederror
:
instance Eq (Empty a) where (==) = error "Void ==" instance Ord (Empty a) where compare = error "Void compare"
Now, they emit code that uses maximally defined, lazier semantics:
instance Eq (Empty a) where _ == _ = True instance Ord (Empty a) where compare _ _ = EQ
- Derived
Read
instances would previous emit code that usedparens
:
instance Read (Empty a) where readPrec = parens pfail
But
parens
forces parts of the parsed string that it doesn't need to. Now, the derived instance will not useparens
(that it, parsingEmpty
will always fail, without reading *any* input):
instance Read (Empty a) where readPrec = pfail
- Derived
Show
instances would previously emit code that usederror
:
instance Show (Empty a) where showsPrec = "Void showsPrec"
Now, they emit code that inspects the argument. That is, if the argument diverges, then showing it will also diverge:
instance Show (Empty a) where showsPrec _ x = case x of {}
- Derived
Functor
,Foldable
,Traversable
,Generic
,Generic1
,Lift
, andData
instances previously emitted code that usederror
:
instance Functor Empty where fmap = error "Void fmap" instance Foldable Empty where foldMap = error "Void foldMap" instance Traversable Empty where traverse = error "Void traverse" instance Generic (Empty a) where from = M1 (error "No generic representation for empty datatype Empty") to (M1 _) = error "No values for empty datatype Empty" -- Similarly for Generic1 instance Lift (Empty a) where lift _ = error "Can't lift value of empty datatype Empty" instance Data a => Data (Empty a) where gfoldl _ _ _ = error "Void gfoldl" toConstr _ = error "Void toConstr" ...
Now, derived
Functor
,Traversable,
Generic,
Generic1`,Lift
, andData
instances emit code which inspects their arguments:
instance Functor Empty where fmap _ x = case x of {} instance Traversable Empty where traverse _ x = pure (case x of {}) instance Generic (Empty a) where from x = M1 (case x of {}) to (M1 x) = case x of {} -- Similarly for Generic1 instance Lift (Empty a) where lift x = pure (case x of {}) instance Data a => Data (Empty a) where gfoldl _ x = case x of {} toConstr x = case x of {} ...
Derived
Foldable
instances now are maximally lazy:
instance Foldable Empty where foldMap _ _ = mempty
Library changes
base-4.11.0.0
Recommendations for forward-compatibility
In order to future-proof your packages for upcoming changes, add the following snippet to your .cabal
file, and address the warnings emitted by GHC when compiling your package:
if impl(ghc >= 8.0) ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances else -- provide/emulate `Control.Monad.Fail` and `Data.Semigroups` API for pre-GHC8 build-depends: fail == 4.9.*, semigroups == 0.18.*
See wiki:Migration/8.0#base-4.9.0.0 for more details
Semigroup
/Monoid
superclasses
Semigroup
becomes a superclass of Monoid
with this release, please consult prime:wiki:Libraries/Proposals/SemigroupMonoid#Writingcompatiblecode for more information on recommendations for writing backward & forward compatible code.
Typeable
The kind-monomorphic Typeable[1-7]
classes, which were deprecated in GHC 7.8, have been removed from Data.Typeable
. They can be replaced with the usual (kind-polymorphic) Typeable
class.
template-haskell-2.13.0.0
Tool changes
GHC API changes
Index types for the hsSyn AST
As part of ImplementingTreesThatGrow the index type for the hsSyn AST has been changed.
We now have
data GhcPass (c :: Pass) data Pass = Parsed | Renamed | Typechecked deriving (Data)
and synonyms
type GhcPs = GhcPass 'Parsed -- Old 'RdrName' type param type GhcRn = GhcPass 'Renamed -- Old 'Name' type param type GhcTc = GhcPass 'Typechecked -- Old 'Id' type para, type GhcTcId = GhcTc -- Old 'TcId' type param
So in practical terms, code will have to change as
fooParsed :: HsDecl RdrName fooRenamed :: HsDecl Name fooTypechecked :: HsDecl Id
becomes
fooParsed :: HsDecl GhcPs fooRenamed :: HsDecl GhcRn fooTypechecked :: HsDecl GhcTc
The following code provides backward-compatible versions of the new synonyms
#if __GLASGOW_HASKELL__ <= 802 type GhcPs = RdrName type GhcRn = Name type GhcTc = Id #endif
There is also a type family to define the underlying identifier type for a given index.
type family IdP p type instance IdP GhcPs = RdrName type instance IdP GhcRn = Name type instance IdP GhcTc = Id