|
|
[[_TOC_]]
|
|
|
|
|
|
# GHC 9.0.x Migration Guide
|
|
|
|
|
|
|
|
|
This guide summarises the changes you may need to make to your code to migrate from GHC 8.10 to GHC 9.0. This guide complements the GHC 9.0.x release notes which should be consulted as well.
|
|
|
|
|
|
---
|
|
|
|
|
|
## Compiler changes
|
|
|
|
|
|
### Simplified subsumption
|
|
|
|
|
|
GHC now implements simplified subsumption, as described in [GHC Proposal #287](https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0287-simplify-subsumption.rst). This change simplifies the type system, and prevents the possiblity of GHC silently changing the semantics of user programs, but it does mean that some libraries may need eta-expansion to typecheck. Here are some examples of specific programs that will no longer work under simplified subsumption and how they can be repaired in a backwards-compatible manner:
|
|
|
|
|
|
#### Deep skolemisation
|
|
|
|
|
|
Given these definitions:
|
|
|
|
|
|
```hs
|
|
|
f :: forall a b. a -> b -> b
|
|
|
g :: (forall p. p -> forall q. q -> q) -> Int
|
|
|
```
|
|
|
|
|
|
Previous versions of GHC would typecheck the following:
|
|
|
|
|
|
```hs
|
|
|
h :: Int
|
|
|
h = g f
|
|
|
```
|
|
|
|
|
|
This relies on deep skolemisation, which no longer exists under simplified subsumption. As a result, GHC 9.0 will reject `h`:
|
|
|
|
|
|
```
|
|
|
error:
|
|
|
• Couldn't match type: b0 -> b0
|
|
|
with: forall q. q -> q
|
|
|
Expected: p -> forall q. q -> q
|
|
|
Actual: p -> b0 -> b0
|
|
|
• In the first argument of ‘g’, namely ‘f’
|
|
|
In the expression: g f
|
|
|
In an equation for ‘h’: h = g f
|
|
|
|
|
|
|
| h = g f
|
|
|
| ^
|
|
|
```
|
|
|
|
|
|
To make `h` work under simplified subsumption, eta expand the argument to `g`:
|
|
|
|
|
|
```hs
|
|
|
h :: Int
|
|
|
h = g (\x -> f x)
|
|
|
```
|
|
|
|
|
|
The above example uses higher-rank `forall`s, but a similar scenario exists with higher-rank contexts as well. Given these definitions:
|
|
|
|
|
|
```hs
|
|
|
f' :: (Eq a, Eq b) => a -> b -> b
|
|
|
g' :: (Eq p => p -> Eq q => q -> q) -> Int
|
|
|
```
|
|
|
|
|
|
Previous versions of GHC would typecheck the following:
|
|
|
|
|
|
```hs
|
|
|
h' :: Int
|
|
|
h' = g' f'
|
|
|
```
|
|
|
|
|
|
Again, this relies on deep skolemisation. As a result, GHC 9.0 will reject `h'`:
|
|
|
|
|
|
```
|
|
|
error:
|
|
|
• Couldn't match kind ‘Constraint’ with ‘*’
|
|
|
When matching types
|
|
|
q0 -> q0 :: *
|
|
|
Eq q0 :: Constraint
|
|
|
Expected: p0 -> Eq q0 => q0 -> q0
|
|
|
Actual: p0 -> (q0 -> q0) -> q0 -> q0
|
|
|
• In the first argument of ‘g'’, namely ‘f'’
|
|
|
In the expression: g' f'
|
|
|
In an equation for ‘h'’: h' = g' f'
|
|
|
|
|
|
|
| h' = g' f'
|
|
|
| ^^
|
|
|
```
|
|
|
|
|
|
`h'` can also be repaired with manual eta expansion:
|
|
|
|
|
|
```hs
|
|
|
h' :: Int
|
|
|
h' = g' (\x -> f' x)
|
|
|
```
|
|
|
|
|
|
Given that the situation with higher-rank contexts mirrors that of higher-rank `forall`s so closely, we will only provide examples involving higher-rank `forall`s from here on out.
|
|
|
|
|
|
#### Deep instantiation
|
|
|
|
|
|
Given this definition:
|
|
|
|
|
|
```hs
|
|
|
f :: Int -> forall a. a -> a
|
|
|
f _ x = x
|
|
|
```
|
|
|
|
|
|
Previous versions of GHC would typecheck the following:
|
|
|
|
|
|
```hs
|
|
|
g :: b -> Int -> a -> a
|
|
|
g x = f
|
|
|
```
|
|
|
|
|
|
This requires deeply instantiating the type of `f`. Simplified subsumption gets rid of deep instantiation, however, so `g` will not typecheck on GHC 9.0:
|
|
|
|
|
|
```
|
|
|
error:
|
|
|
• Couldn't match type: forall a1. a1 -> a1
|
|
|
with: a -> a
|
|
|
Expected: Int -> a -> a
|
|
|
Actual: Int -> forall a. a -> a
|
|
|
• In the expression: f
|
|
|
In an equation for ‘g’: g x = f
|
|
|
• Relevant bindings include
|
|
|
g :: b -> Int -> a -> a (bound at Bug.hs:8:1)
|
|
|
|
|
|
|
| g x = f
|
|
|
| ^
|
|
|
```
|
|
|
|
|
|
There are two possible ways to migrate this code:
|
|
|
|
|
|
1. Change the type of `g` to have a nested `forall`:
|
|
|
|
|
|
```hs
|
|
|
g :: b -> Int -> forall a. a -> a
|
|
|
g x = f
|
|
|
```
|
|
|
2. Eta expand `g`:
|
|
|
|
|
|
```hs
|
|
|
g :: b -> Int -> a -> a
|
|
|
g x y = f y
|
|
|
```
|
|
|
|
|
|
#### Contravariance/covariance of function arrows
|
|
|
|
|
|
Given these definitions:
|
|
|
|
|
|
```hs
|
|
|
f :: (Bool -> Bool) -> Char
|
|
|
g :: ((forall a. a -> a) -> Char) -> Int
|
|
|
```
|
|
|
|
|
|
Previous versions of GHC would typecheck the following:
|
|
|
|
|
|
```hs
|
|
|
h :: Int
|
|
|
h = g f
|
|
|
```
|
|
|
|
|
|
This is because GHC's subtyping rules supported contravariance in function arrows, which is something that simplified subsumption removes. As a result, `h` will not typecheck on GHC 9.0:
|
|
|
|
|
|
```
|
|
|
error:
|
|
|
• Couldn't match type: Bool -> Bool
|
|
|
with: forall a. a -> a
|
|
|
Expected: (forall a. a -> a) -> Char
|
|
|
Actual: (Bool -> Bool) -> Char
|
|
|
• In the first argument of ‘g’, namely ‘f’
|
|
|
In the expression: g f
|
|
|
In an equation for ‘h’: h = g f
|
|
|
|
|
|
|
| h = g f
|
|
|
| ^
|
|
|
```
|
|
|
|
|
|
`h` can be repaired with manual eta expansion:
|
|
|
|
|
|
```hs
|
|
|
h :: Int
|
|
|
h = g (\x -> f x)
|
|
|
```
|
|
|
|
|
|
Just as simplified subsumption removes contravariance in function arrows, it also removes covariance in function arrows. In concrete terms, `h'` below will no longer typecheck:
|
|
|
|
|
|
```hs
|
|
|
f' :: Char -> forall a. a -> a
|
|
|
g' :: (Char -> Bool -> Bool) -> Int
|
|
|
|
|
|
h' :: Int
|
|
|
h' = g' f'
|
|
|
```
|
|
|
```
|
|
|
error:
|
|
|
• Couldn't match type: forall a. a -> a
|
|
|
with: Bool -> Bool
|
|
|
Expected: Char -> Bool -> Bool
|
|
|
Actual: Char -> forall a. a -> a
|
|
|
• In the first argument of ‘g'’, namely ‘f'’
|
|
|
In the expression: g' f'
|
|
|
In an equation for ‘h'’: h' = g' f'
|
|
|
|
|
|
|
| h' = g' f'
|
|
|
| ^^
|
|
|
```
|
|
|
|
|
|
Once again, `h'` can be repaired with manual eta expansion:
|
|
|
|
|
|
```hs
|
|
|
h' :: Int
|
|
|
h' = g' (\x -> f' x)
|
|
|
```
|
|
|
|
|
|
### Whitespace-sensitive `!`, `~`, `@`, and `$`
|
|
|
|
|
|
GHC 9.0 implements [Proposal 229](https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0229-whitespace-bang-patterns.rst), which means that the `!`, `~`, and `@` characters are more sensitive to preceding and trailing whitespace than they were before. As a result, some things which used to parse one way will now parse differently (or throw a parse error). Here are some particular scenarios that you may encounter:
|
|
|
|
|
|
1. ```hs
|
|
|
f ~ x = x
|
|
|
```
|
|
|
|
|
|
* Before: function named `f` with a lazy (irrefutable) pattern on its argument `x`
|
|
|
* After: After: infix function named `(~)`
|
|
|
|
|
|
To restore the old behavior, remove the trailing whitespace after `~`, like so:
|
|
|
|
|
|
```hs
|
|
|
f ~x = x
|
|
|
```
|
|
|
|
|
|
2. ```hs
|
|
|
f @ x = y
|
|
|
```
|
|
|
|
|
|
* Before: value binding that binds both `f` and `x` to `y` using an as-pattern
|
|
|
* After: infix function named `(@)`
|
|
|
|
|
|
To restore the old behavior, remove the leading and trailing whitespace around `@`, like so:
|
|
|
|
|
|
```hs
|
|
|
f@x = x
|
|
|
```
|
|
|
|
|
|
3. ```hs
|
|
|
f ! x = x
|
|
|
```
|
|
|
|
|
|
* Before: function named `f` with a bang pattern on its argument `x`
|
|
|
* After: infix function named `(!)`
|
|
|
|
|
|
To restore the old behavior, remove the trailing whitespace after `!`, like so:
|
|
|
|
|
|
```hs
|
|
|
f !x = x
|
|
|
```
|
|
|
|
|
|
4. ```hs
|
|
|
f = g @ True
|
|
|
```
|
|
|
|
|
|
* Before: visible type application
|
|
|
* After: application of the infix function `(@)` to `g` and `True`
|
|
|
|
|
|
To restore the old behavior, remove the trailing whitespace after `@`, like so:
|
|
|
|
|
|
```hs
|
|
|
f = g @True
|
|
|
```
|
|
|
|
|
|
5. ```hs
|
|
|
f = ($x)
|
|
|
```
|
|
|
|
|
|
* Before: operator section that applies the infix function `($)` to the argument `x`
|
|
|
* After: Template Haskell splice that splices in `x :: Q Exp`
|
|
|
|
|
|
To restore the old behavior, add a space between `$` and `x`, like so:
|
|
|
|
|
|
```hs
|
|
|
f = ($ x)
|
|
|
```
|
|
|
|
|
|
6. ```hs
|
|
|
f = (!x)
|
|
|
```
|
|
|
|
|
|
* Before: operator section that applies the infix function `(!)` to the argument `x`
|
|
|
* After: parse error:
|
|
|
|
|
|
```
|
|
|
error:
|
|
|
Bang pattern in expression context: !x
|
|
|
Did you mean to add a space after the '!'?
|
|
|
```
|
|
|
|
|
|
As the parse error suggests, the old behavior can be restored by instead writing:
|
|
|
|
|
|
```hs
|
|
|
f = (! x)
|
|
|
```
|
|
|
|
|
|
7. ```hs
|
|
|
data T = MkT ! Int
|
|
|
```
|
|
|
|
|
|
* Before: data constructor `MkT` with a strict `Int` field
|
|
|
* After: parse error:
|
|
|
|
|
|
```
|
|
|
error: Not a data constructor: ‘!’
|
|
|
```
|
|
|
|
|
|
To restore the old behavior, remove the trailing whitespace after `!`, like so:
|
|
|
|
|
|
```hs
|
|
|
data T = MkT !Int
|
|
|
```
|
|
|
|
|
|
### The order of TH splices is more important
|
|
|
|
|
|
GHC's constraint solver now solves constraints in each top-level group sooner. This has practical consequences for Template Haskell, as TH splices necessarily separate top-level groups. For example, the following program would compile in previous versions of GHC, but not in GHC 9.0:
|
|
|
|
|
|
```hs
|
|
|
data T = MkT
|
|
|
|
|
|
tStr :: String
|
|
|
tStr = show MkT
|
|
|
|
|
|
$(return [])
|
|
|
|
|
|
instance Show T where
|
|
|
show MkT = "MkT"
|
|
|
```
|
|
|
|
|
|
This is because each top-level group's constraints are solved before moving on to the next, and since the top-level group for `tStr` appears before the top-level group that defines a `Show T` instance, GHC 9.0 will throw an error about a missing `Show T` instance in the expression `show MkT`. The issue can be fixed by rearranging the order of declarations. For instance, the following _will_ compile:
|
|
|
|
|
|
```hs
|
|
|
data T = MkT
|
|
|
|
|
|
instance Show T where
|
|
|
show MkT = "MkT"
|
|
|
|
|
|
$(return [])
|
|
|
|
|
|
tStr :: String
|
|
|
tStr = show MkT
|
|
|
```
|
|
|
|
|
|
### Overloaded Quotation Brackets
|
|
|
|
|
|
GHC 9.0 implements [Proposal 246](https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0246-overloaded-bracket.rst), which means that the type of expression quotation brackets is now generalised from `Q Exp` to `Quote m => m Exp`. All other forms of quotation are similarly generalised. There are two main breaking changes as a result:
|
|
|
|
|
|
1. Top-level unannotated quotations now fail to typecheck due to the monomorphism restriction:
|
|
|
```hs
|
|
|
x = [| 5 ||]
|
|
|
```
|
|
|
|
|
|
Fix: Provide a type signature for `x` or enable `NoMonomorphismRestriction`.
|
|
|
|
|
|
2. Methods of the `Lift` typeclass are restricted from `Q` to only using methods from `Quote`. The definition of `Lift` is now:
|
|
|
```hs
|
|
|
class Lift (t :: TYPE r) where
|
|
|
lift :: Quote m => t -> m Exp
|
|
|
liftTyped :: Quote m => t -> m (TExp t)
|
|
|
```
|
|
|
|
|
|
If you have manually defined instances for `Lift` then it might be necessary to rewrite some type signatures in terms of the more restricted `Quote` interface. In our testing so far we've not found any `Lift` instances relying on any special methods of `Q`.
|
|
|
|
|
|
Another solution is to use the `DeriveLift` extension rather than manually defining the instance.
|
|
|
|
|
|
### Type variable order in top-level field selectors
|
|
|
|
|
|
Previous versions of GHC did not specify the order or specificity of type variables in the types of top-level field selectors. GHC 9.0 does specify this, which can impact users of `TypeApplications`. For example, given the following definitions:
|
|
|
|
|
|
```hs
|
|
|
{-# LANGUAGE PolyKinds #-}
|
|
|
|
|
|
newtype P a = MkP { unP :: Proxy a }
|
|
|
|
|
|
newtype N :: Type -> Type -> Type where
|
|
|
MkN :: forall b a. { unN :: Either a b } -> N a b
|
|
|
```
|
|
|
|
|
|
Previous versions of GHC would give the following types to `unP` and `unN`:
|
|
|
|
|
|
```hs
|
|
|
unP :: forall k (a :: k). P a -> Proxy a
|
|
|
unN :: forall a b. N a b -> Either a b
|
|
|
```
|
|
|
|
|
|
GHC will now give them the following types instead: ::
|
|
|
|
|
|
```hs
|
|
|
unP :: forall {k} (a :: k). P a -> Proxy a
|
|
|
unN :: forall b a. N a b -> Either a b
|
|
|
```
|
|
|
|
|
|
### More validity checking in quantified constraints
|
|
|
|
|
|
GHC now performs more validity checks on quantified constraints, meaning that some code will require enabling language extensions that were not previously required. As one example, this code will compile on previous versions of GHC:
|
|
|
|
|
|
```hs
|
|
|
{-# LANGUAGE QuantifiedConstraints #-}
|
|
|
{-# LANGUAGE TypeFamilies #-}
|
|
|
|
|
|
data family F a
|
|
|
|
|
|
f :: (forall a. Show (F a)) => Int
|
|
|
f = 42
|
|
|
```
|
|
|
|
|
|
However, it will be rejected with GHC 9.0:
|
|
|
|
|
|
```
|
|
|
error:
|
|
|
• Non type-variable argument in the constraint: Show (F a)
|
|
|
(Use FlexibleContexts to permit this)
|
|
|
• In the quantified constraint ‘forall a. Show (F a)’
|
|
|
In the type signature: f :: (forall a. Show (F a)) => Int
|
|
|
|
|
|
|
7 | f :: (forall a. Show (F a)) => Int
|
|
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
```
|
|
|
|
|
|
### Eager instantiation
|
|
|
|
|
|
GHC now consistently does eager instantiation during type inference. As a consequence, visible type application (VTA) now only works when the head of the application is:
|
|
|
|
|
|
* A variable
|
|
|
* An expression with a type signature
|
|
|
|
|
|
For example `(let x = blah in id) @Bool True` no longer typechecks. You should write `let x = blah in id @Bool True` instead.
|
|
|
|
|
|
### GHC is pickier about nested `forall`s and contexts in GADT constructors
|
|
|
|
|
|
GHC has a rule that GADT constructors cannot contain nested `forall`s or contexts in GADT constructors. This was always true in previous released, but GHC 9.0 enforces this rule more strictly. In particular, nested `forall`s or contexts that occur underneath parentheses are now rejected. This means the following examples will no longer compile on GHC 9.0:
|
|
|
|
|
|
```hs
|
|
|
data S a where
|
|
|
MkS :: (forall a. S a)
|
|
|
|
|
|
data U a where
|
|
|
MkU :: (Show a => U a)
|
|
|
```
|
|
|
|
|
|
### GHC is pickier about nested `forall`s and contexts in instance and `deriving` declarations
|
|
|
|
|
|
Much like GHC does not permit nested `forall`s or contexts in GADT constructors, it also does not permit them in the types at the tops of instance declarations. GHC also enforces this more strictly in 9.0, so the following examples will no longer compile:
|
|
|
|
|
|
```hs
|
|
|
instance (forall a. C a) where ...
|
|
|
instance (Show a => C a) where ...
|
|
|
```
|
|
|
|
|
|
A similar no-nested-`forall`s rule applies to types involved in `deriving` clauses and `via` types (for instances derived with `DerivingVia`). The following examples will also be rejected with GHC 9.0:
|
|
|
|
|
|
```hs
|
|
|
data T = MkT deriving (C1, (forall x. C2 x))
|
|
|
deriving via (forall x. V x) instance C (S x)
|
|
|
```
|
|
|
|
|
|
### Improved Pattern-Match Coverage checker
|
|
|
|
|
|
The coverage checker will now detect more redundant cases, in particular wrt. long distance information.
|
|
|
If for some reason (like bitrot prevention of a debug-only case branch) a redundant or inaccessible right-hand side is not to be flagged, a guard like `| GHC.Magic.lazy False` should prevent the checker from flagging it as such.
|
|
|
|
|
|
---
|
|
|
|
|
|
## Library changes
|
|
|
|
|
|
### `base-4.15.*`
|
|
|
|
|
|
The `unsafeCoerce#` function has been moved from `GHC.Prim` to `Unsafe.Coerce`. As a result, attempting to import `unsafeCoerce#` from `GHC.Prim` (or `GHC.Base`, which previously re-exported `unsafeCoerce#`) will result in an error with GHC 9.0. A backwards-compatible way to fix the error is to import `unsafeCoerce#` from `GHC.Exts` instead.
|
|
|
|
|
|
### `ghc-9.0.*`
|
|
|
|
|
|
The meaning of the `hs_fixds` field of `HsGroup` has changed slightly. It now only contains fixity signatures defined for top-level declarations and class methods defined _outside_ of the class itself. Previously, `hs_fixds` would also contain fixity signatures for class methods defined _inside_ the class, such as the fixity signature for `m` in the following example: ::
|
|
|
|
|
|
```hs
|
|
|
class C a where
|
|
|
infixl 4 `m`
|
|
|
m :: a -> a -> a
|
|
|
```
|
|
|
|
|
|
If you wish to attain the previous behavior of `hs_fixds`, use the new `hsGroupTopLevelFixitySigs` function, which collects all top-level fixity signatures, including those for class methods defined inside classes.
|
|
|
|
|
|
### `ghc-prim-0.7.*`
|
|
|
|
|
|
The `Unit` data type from `GHC.Tuple` has been renamed to `Solo`, per #14673/#18099.
|
|
|
|
|
|
### `integer-gmp-1.1` / `integer-simple` / `ghc-bignum-1.0`
|
|
|
|
|
|
`integer-simple` package has been removed, use `ghc-bignum` built with `native` backend instead.
|
|
|
|
|
|
`integer-gmp-1.1` package is provided for backward compatibility but now it is based on `ghc-bignum`. As a consequence packages depending on `integer-gmp`:
|
|
|
- to use `Integer`'s constructors (`S#`, `Jn#`, `Jp#`): should continue to work as before, whatever backend is used by `ghc-bignum` (i.e. even if it's not `gmp`).
|
|
|
- to use functions from `GHC.Integer`: don't need to depend on it anymore as `GHC.Integer` is now in `base`.
|
|
|
- to use GMP specific functions (prime test, secure powmod, etc.): should use another package providing these functions (e.g. [hgmp](https://hackage.haskell.org/package/hgmp)). `ghc-bignum` only exposes functions provided by all of its backends.
|
|
|
|
|
|
|
|
|
### `template-haskell-2.17.*`
|
|
|
|
|
|
TODO: Explicit specificity-related changes |
|
|
\ No newline at end of file |