wiki:Migration/8.4

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 deriving Eq, Ord, Read, Show instances for empty data types. (Previously, this could only be done via StandaloneDeriving, but with EmptyDataDeriving, one can use deriving 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 of data Empty a, with no constructors):
  • Derived Eq and Ord instances would previously emit code that used error:
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 used parens:
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 use parens (that it, parsing Empty will always fail, without reading *any* input):

instance Read (Empty a) where
  readPrec = pfail
  • Derived Show instances would previously emit code that used error:
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, and Data instances previously emitted code that used error:
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, and Data 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

  • 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

Last modified 3 weeks ago Last modified on Nov 2, 2017 11:45:35 PM