|
|
[[_TOC_]]
|
|
|
|
|
|
# GHC 8.8.x Migration Guide
|
|
|
|
|
|
|
... | ... | @@ -12,8 +14,11 @@ This guide summarises the changes you may need to make to your code to migrate f |
|
|
|
|
|
Consider the following function and data type:
|
|
|
|
|
|
```
|
|
|
dataFoo=MkFoo1Int|MkFoo2!Voidf::Foo->Intf(MkFoo1 i)= i
|
|
|
```hs
|
|
|
data Foo = MkFoo1 Int | MkFoo2 !Void
|
|
|
|
|
|
f :: Foo -> Int
|
|
|
f (MkFoo1 i) = i
|
|
|
```
|
|
|
|
|
|
`f` is actually an exhaustive function. Because `MkFoo2` has a strict field of type `Void` (which has no terminating values which inhabit it), it's impossible to construct anything with `MkFoo2` without triggering an infinite loop or throwing an exception. Therefore, one cannot reach the `MkFoo2` case of `f`.
|
... | ... | @@ -21,15 +26,15 @@ dataFoo=MkFoo1Int|MkFoo2!Voidf::Foo->Intf(MkFoo1 i)= i |
|
|
|
|
|
However, previous versions of GHC did not recognize this fact and flagged `f` as being non-exhaustive. As a workaround, one had to explicitly match on `MkFoo2` in `f`:
|
|
|
|
|
|
```hs
|
|
|
f :: Foo -> Int
|
|
|
f (MkFoo1 i) = i
|
|
|
f (MkFoo2 v) = absurd v
|
|
|
```
|
|
|
f::Foo->Intf(MkFoo1 i)= i
|
|
|
f(MkFoo2 v)= absurd v
|
|
|
```
|
|
|
|
|
|
|
|
|
However, now that GHC is smart enough to recognize that `MkFoo2` is unreachable, it will actually throw a warning (with `-Woverlapping-patterns` enabled) on the above code:
|
|
|
|
|
|
```wiki
|
|
|
```
|
|
|
Pattern match is redundant
|
|
|
In an equation for ‘f’: f (MkFoo2 v) = ...
|
|
|
```
|
... | ... | @@ -42,26 +47,27 @@ As a result, some code which compiled without warnings on previous versions of G |
|
|
|
|
|
Starting in GHC 8.8, we now generalize the kinds in the types of local definitions (e.g., `let`- or `where`-bound functions). As a result, there are a handful of programs which will no longer compile. Here is one such example:
|
|
|
|
|
|
```
|
|
|
typefamilyLetGo:: k
|
|
|
```hs
|
|
|
type family LetGo :: k
|
|
|
|
|
|
foo::Proxy(LetGo::Type)foo= undefined
|
|
|
foo :: Proxy (LetGo :: Type)
|
|
|
foo = undefined
|
|
|
|
|
|
sSconcat:: forall (x ::Type). x
|
|
|
sSconcat= undefined
|
|
|
where sGo :: x ->ProxyLetGo
|
|
|
sGo _= foo
|
|
|
sSconcat :: forall (x :: Type). x
|
|
|
sSconcat = undefined
|
|
|
where sGo :: x -> Proxy LetGo
|
|
|
sGo _ = foo
|
|
|
```
|
|
|
|
|
|
|
|
|
This kind-checks on previous versions of GHC, since the return kind of `LetGo` (in `sGo`) is not generalized, so we have `sGo :: x -> Proxy (LetGo :: Type)` (which is necessary for the body of `sGo` to typecheck). However, this will *not* kind-check on GHC 8.8, since the return kind of `LetGo`*is* generalized, giving us `sGo :: x -> Proxy (LetGo :: k)` (which is too polymorphic for `foo`). Therefore, this code fails on GHC 8.8 with a `Couldn't match type ‘k’ with ‘*’` error.
|
|
|
This kind-checks on previous versions of GHC, since the return kind of `LetGo` (in `sGo`) is not generalized, so we have `sGo :: x -> Proxy (LetGo :: Type)` (which is necessary for the body of `sGo` to typecheck). However, this will *not* kind-check on GHC 8.8, since the return kind of `LetGo` *is* generalized, giving us `sGo :: x -> Proxy (LetGo :: k)` (which is too polymorphic for `foo`). Therefore, this code fails on GHC 8.8 with a `Couldn't match type ‘k’ with ‘*’` error.
|
|
|
|
|
|
|
|
|
To avoid this, one can use an explicit kind signature on `LetGo`, like so:
|
|
|
|
|
|
```
|
|
|
sGo :: x ->Proxy(LetGo::Type)
|
|
|
sGo _= foo
|
|
|
```hs
|
|
|
sGo :: x -> Proxy (LetGo :: Type)
|
|
|
sGo _ = foo
|
|
|
```
|
|
|
|
|
|
### Template Haskell reification change for classes
|
... | ... | @@ -69,17 +75,17 @@ To avoid this, one can use an explicit kind signature on `LetGo`, like so: |
|
|
|
|
|
If you have a type class like this:
|
|
|
|
|
|
```
|
|
|
classC a where
|
|
|
```hs
|
|
|
class C a where
|
|
|
method :: a
|
|
|
```
|
|
|
|
|
|
|
|
|
Then in previous versions of GHC, reifying `C` would give you something like this:
|
|
|
Then in previous versions of GHC, reifying `C` with Template Haskell would give you something like this:
|
|
|
|
|
|
```
|
|
|
classC a where
|
|
|
method :: forall a.C a => a
|
|
|
```hs
|
|
|
class C a where
|
|
|
method :: forall a. C a => a
|
|
|
```
|
|
|
|
|
|
|
... | ... | @@ -93,14 +99,21 @@ There may be code in the wild that previously depended on the assumption that re |
|
|
|
|
|
GHC 8.8 tightened up the implementation of its unused import warning algorithm to more closely match the specification in [wiki:Commentary/Compiler/UnusedImports](commentary/compiler/unused-imports), as GHC 8.0 inadvertently introduced a [regression](https://gitlab.haskell.org/ghc/ghc/issues/13064) that caused it to stray from this specification. As a result, some programs which compile without warnings on GHC 8.0 through 8.6 will now produce warnings on GHC 8.8. A good example that illustrates this is this one:
|
|
|
|
|
|
```
|
|
|
{-# OPTIONS_GHC -Wunused-imports #-}moduleT13064whereimportControl.ApplicativeimportPrelude(IO,pure)-- Import of 'pure' is redundantfoo::IO()foo=()<$ pure ()
|
|
|
```hs
|
|
|
{-# OPTIONS_GHC -Wunused-imports #-}
|
|
|
module T13064 where
|
|
|
|
|
|
import Control.Applicative
|
|
|
import Prelude (IO, pure) -- Import of 'pure' is redundant
|
|
|
|
|
|
foo :: IO ()
|
|
|
foo = () <$ pure ()
|
|
|
```
|
|
|
|
|
|
|
|
|
This produces no warnings on 8.0–8.6, but does warn on GHC 8.8:
|
|
|
|
|
|
```wiki
|
|
|
```
|
|
|
T13064.hs:5:1: warning: [-Wunused-imports (in -Wextra)]
|
|
|
The import of ‘pure’ from module ‘Prelude’ is redundant
|
|
|
```
|
... | ... | @@ -111,15 +124,29 @@ To summarize the reasoning from [wiki:Commentary/Compiler/UnusedImports](comment |
|
|
|
|
|
If one wishes to keep this sort of compiling without any warnings on both GHC 8.8 and previous versions, there are two options. One is to make both imports catch-all:
|
|
|
|
|
|
```
|
|
|
{-# OPTIONS_GHC -Wunused-imports #-}moduleT13064whereimportControl.ApplicativeimportPreludefoo::IO()foo=()<$ pure ()
|
|
|
```hs
|
|
|
{-# OPTIONS_GHC -Wunused-imports #-}
|
|
|
module T13064 where
|
|
|
|
|
|
import Control.Applicative
|
|
|
import Prelude
|
|
|
|
|
|
foo :: IO ()
|
|
|
foo = () <$ pure ()
|
|
|
```
|
|
|
|
|
|
|
|
|
Alternatively, one can use `pure` qualified to avoid GHC warning about it:
|
|
|
|
|
|
```
|
|
|
{-# OPTIONS_GHC -Wunused-imports #-}moduleT13064whereimportControl.ApplicativeimportPrelude(IO,pure)foo::IO()foo=()<$Prelude.pure ()
|
|
|
```hs
|
|
|
{-# OPTIONS_GHC -Wunused-imports #-}
|
|
|
module T13064 where
|
|
|
|
|
|
import Control.Applicative
|
|
|
import Prelude (IO, pure)
|
|
|
|
|
|
foo :: IO ()
|
|
|
foo = () <$ Prelude.pure ()
|
|
|
```
|
|
|
|
|
|
### Additions to the `-Wcompat` warning group
|
... | ... | @@ -127,7 +154,7 @@ Alternatively, one can use `pure` qualified to avoid GHC warning about it: |
|
|
|
|
|
As part of [this GHC proposal](https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0030-remove-star-kind.rst), the uses of `*` that rely on the `StarIsType` extension now produce a warning:
|
|
|
|
|
|
```wiki
|
|
|
```
|
|
|
Prelude> type M = (Maybe :: * -> *)
|
|
|
|
|
|
<interactive>:1:20: warning: [-Wstar-is-type (in -Wcompat)]
|
... | ... | @@ -140,7 +167,7 @@ Prelude> type M = (Maybe :: * -> *) |
|
|
|
|
|
The recommended migration strategy is to follow the suggestion in the warning: import `Type` from the `Data.Kind` module and use it in place of `*`:
|
|
|
|
|
|
```wiki
|
|
|
```
|
|
|
Prelude Data.Kind> type M = (Maybe :: Type -> Type)
|
|
|
```
|
|
|
|
... | ... | @@ -161,56 +188,57 @@ Previous versions of GHC would permit code that should require certain language |
|
|
|
|
|
1. Previously, GHC would accept some uses of type synonyms which did not have all of their arguments supplied without requiring the `LiberalTypeSynonyms` extension. Starting with version 8.8, GHC is stricter about requiring the extension in these cases.
|
|
|
|
|
|
>
|
|
|
> For example, this code requires `LiberalTypeSynonyms` in GHC 8.8:
|
|
|
|
|
|
```
|
|
|
typeGeneric i o = forall x. i x -> o x
|
|
|
typeId x = x
|
|
|
|
|
|
foo::GenericIdIdfoo= undefined
|
|
|
```
|
|
|
For example, this code requires `LiberalTypeSynonyms` in GHC 8.8:
|
|
|
|
|
|
>
|
|
|
> If GHC is complaining about type synonyms not being passed enough arguments or an 'illegal polymorphic type', try enabling `LiberalTypeSynonyms` in that module.
|
|
|
```hs
|
|
|
type Generic i o = forall x. i x -> o x
|
|
|
type Id x = x
|
|
|
|
|
|
foo :: Generic Id Id
|
|
|
foo = undefined
|
|
|
```
|
|
|
|
|
|
1. Previously, it was possible to sneak in impredicative types through clever use of type synonyms. For instance, this code used to compile even without the `ImpredicativeTypes` extension enabled!
|
|
|
If GHC is complaining about type synonyms not being passed enough arguments or an 'illegal polymorphic type', try enabling `LiberalTypeSynonyms` in that module.
|
|
|
|
|
|
```
|
|
|
{-# LANGUAGE RankNTypes #-}typeFoo x = forall a. a -> a
|
|
|
typeBar x =Int->Foo x
|
|
|
2. Previously, it was possible to sneak in impredicative types through clever use of type synonyms. For instance, this code used to compile even without the `ImpredicativeTypes` extension enabled!
|
|
|
|
|
|
f::[Bar()]-- Impredicative!f=[]
|
|
|
```
|
|
|
```hs
|
|
|
{-# LANGUAGE RankNTypes #-}
|
|
|
|
|
|
type Foo x = forall a. a -> a
|
|
|
type Bar x = Int -> Foo x
|
|
|
|
|
|
f :: [Bar ()] -- Impredicative!
|
|
|
f = []
|
|
|
```
|
|
|
|
|
|
>
|
|
|
> GHC will now properly reject this:
|
|
|
GHC will now properly reject this:
|
|
|
|
|
|
```wiki
|
|
|
• Illegal polymorphic type: forall a. a -> a
|
|
|
GHC doesn't yet support impredicative polymorphism
|
|
|
• In the expansion of type synonym ‘Foo’
|
|
|
In the expansion of type synonym ‘Bar’
|
|
|
In the type signature: f :: [Bar ()]
|
|
|
```
|
|
|
```
|
|
|
• Illegal polymorphic type: forall a. a -> a
|
|
|
GHC doesn't yet support impredicative polymorphism
|
|
|
• In the expansion of type synonym ‘Foo’
|
|
|
In the expansion of type synonym ‘Bar’
|
|
|
In the type signature: f :: [Bar ()]
|
|
|
```
|
|
|
|
|
|
### Kind variable visibility in poly-kinded class methods
|
|
|
|
|
|
|
|
|
Previous versions of GHC were somewhat ambiguous about whether poly-kinded type class methods would make their kind variables be available for visible type application or not. This is best explained by examples. Consider the following two classes:
|
|
|
|
|
|
```
|
|
|
classC1(a :: k) b where
|
|
|
p1 ::Proxy a ->Proxy b
|
|
|
```hs
|
|
|
class C1 (a :: k) b where
|
|
|
p1 :: Proxy a -> Proxy b
|
|
|
|
|
|
classC2(a :: k)(b ::Type)where
|
|
|
p2 ::Proxy a ->Proxy b
|
|
|
class C2 (a :: k) (b :: Type) where
|
|
|
p2 :: Proxy a -> Proxy b
|
|
|
```
|
|
|
|
|
|
|
|
|
On previous versions of GHC, the kind of `a` is *not* available for visible type application in `p1`, but it *is* available for visible type application in `p2`:
|
|
|
|
|
|
```wiki
|
|
|
```
|
|
|
λ> :type +v p1
|
|
|
p1
|
|
|
:: forall {k1} {k2} (a :: k1) (b :: k2).
|
... | ... | @@ -223,7 +251,7 @@ p2 :: forall k (a :: k) b. C2 a b => Proxy a -> Proxy b |
|
|
|
|
|
GHC 8.8 has cleaned up this infelicity, so now both `p1` and `p2` treat the kind of `a` as being available for visible type application:
|
|
|
|
|
|
```wiki
|
|
|
```
|
|
|
λ> :type +v p1
|
|
|
p1
|
|
|
:: forall {k1} k2 (a :: k2) (b :: k1). C1 a b => Proxy a -> Proxy b
|
... | ... | @@ -234,7 +262,7 @@ p2 :: forall k (a :: k) b. C2 a b => Proxy a -> Proxy b |
|
|
|
|
|
There is a possibility that existing code will break due to this change. For example, the following code typechecks on old GHCs due to the aforementioned quirk of how GHC infers the kind of `a`:
|
|
|
|
|
|
```wiki
|
|
|
```
|
|
|
class C (a :: k) b where
|
|
|
p :: Proxy a -> Proxy b
|
|
|
|
... | ... | @@ -246,7 +274,7 @@ p' = p @a |
|
|
This will no longer typecheck on GHC 8.8. Two possible ways of fixing this are:
|
|
|
|
|
|
1. Change `class C (a :: k) b` to `class C a b` (this is backwards-compatible with old GHCs).
|
|
|
1. Change `p' = p @a` to `p' = p @k @a` (this is not backwards-compatible with old GHCs).
|
|
|
2. Change `p' = p @a` to `p' = p @k @a` (this is not backwards-compatible with old GHCs).
|
|
|
|
|
|
---
|
|
|
|
... | ... | @@ -257,7 +285,7 @@ This will no longer typecheck on GHC 8.8. Two possible ways of fixing this are: |
|
|
|
|
|
The Template Haskell AST has changed to accommodate the [Visible kind application](https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0015-type-level-type-applications.rst) and [More explicit foralls](https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0007-instance-foralls.rst) proposals, both of which debut in GHC 8.8. At a glance, the breaking API changes are as follows:
|
|
|
|
|
|
```
|
|
|
```diff
|
|
|
data Dec
|
|
|
= ...
|
|
|
- | DataInstD Cxt Name [Type] (Maybe Kind) [Con] [DerivClause]
|
... | ... | @@ -291,44 +319,69 @@ Here are the reasons why each of these had to change, and how one can accommodat |
|
|
- `DataInstD`, `NewtypeInstD`, and `TySynEqn` each gained a field of type type `Maybe [TyVarBndr]` to support the [More explicit foralls](https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0007-instance-foralls.rst) proposal, which allows writing type family instances and `RULES` with explicit `forall`s (binding type variables) at the front. (If you don't care about this feature, it's perfectly fine to use `Nothing` here, since that omits the `forall` entirely.)
|
|
|
- Because of the [Visible kind application](https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0015-type-level-type-applications.rst) proposal, type family instances can feature richer arguments than before. For example, this is an example of a type family one can write using visible kind applications:
|
|
|
|
|
|
```
|
|
|
typefamilyFoo(a :: k):: k whereFoo@Bool a = a
|
|
|
Foo@Char a = a
|
|
|
```
|
|
|
|
|
|
>
|
|
|
> As a result, the AST forms for type family instances needed to be updated to support these new forms of arguments. It was decided to migrate away from the old style using `[Type]` to store each individual type argument, since this doesn't encode enough information to tell whether an argument is applied using visible kind application or not. Instead, a single `Type` is used. For instance, this is how the `Foo @Bool a = a` equation is encoded:
|
|
|
|
|
|
```
|
|
|
TySynEqnNothing(ConT''Foo`AppKindT`ConT''Bool`AppT`VarT a)(VarT a)
|
|
|
```
|
|
|
|
|
|
>
|
|
|
> Note that the name of the type family, `Foo`, is now present on the left-hand side! This was not the case before, as previously only the *arguments* were included in a `TySynEqn`. This means that the `Name` field in `TySynInstD` is now wholly redundant (as that same `Name` is present in the `TynSynEqn`), so the `Name` field was removed from `TySynInstD`.
|
|
|
|
|
|
>
|
|
|
> Similar changes were made to `DataInstD` and `NewtypeInstD`. Their `Name` and `[Type]` fields (representing the data family name and left-hand-side arguments, respectively) were removed in favor of a single `Type` representing the data family name applied to its arguments.
|
|
|
|
|
|
>
|
|
|
> One consequence of this change is that retrieving the `Name` from a type or data family instance is no longer as straightforward as it used to be, as the `Name` is now inside of the left-hand side `Type` field. Similarly, the type arguments of the instance are also sprinkled throughout the LHS `Type` field. One may find the following utility function useful to retrieve the `Name` and arguments:
|
|
|
|
|
|
```
|
|
|
{-# LANGUAGE CPP #-}-- | An argument to a type, either a normal type ('TANormal') or a visible-- kind application ('TyArg').---- 'TypeArg' is useful when decomposing an application of a 'Type' to its-- arguments (e.g., in 'unfoldType').dataTypeArg=TANormalType-- Normal arguments|TyArgKind-- Visible kind applications-- | Decompose an applied type into its individual components. For example, this:---- @-- Proxy \@Type Char-- @---- would be unfolded to this:---- @-- ('ConT' ''Proxy, ['TyArg' ('ConT' ''Type), 'TANormal' ('ConT' ''Char)])-- @unfoldType::Type->(Type,[TypeArg])unfoldType= go []where
|
|
|
go ::[TypeArg]->Type->(Type,[TypeArg])
|
|
|
go acc (ForallT__ ty)= go acc ty
|
|
|
go acc (AppT ty1 ty2)= go (TANormal ty2:acc) ty1
|
|
|
go acc (SigT ty _)= go acc ty
|
|
|
#ifMIN_VERSION_template_haskell(2,11,0)
|
|
|
go acc (ParensT ty)= go acc ty
|
|
|
#endif
|
|
|
#ifMIN_VERSION_template_haskell(2,15,0)
|
|
|
go acc (AppKindT ty ki)= go (TyArg ki:acc) ty
|
|
|
#endif
|
|
|
go acc ty =(ty, acc)famInstLHSName::Type->MaybeNamefamInstLHSName t =case unfoldType t of(ConT n,_)->Just n
|
|
|
(_,_)->Nothing
|
|
|
```
|
|
|
```hs
|
|
|
type family Foo (a :: k) :: k where
|
|
|
Foo @Bool a = a
|
|
|
Foo @Char a = a
|
|
|
```
|
|
|
|
|
|
As a result, the AST forms for type family instances needed to be updated to support these new forms of arguments. It was decided to migrate away from the old style using `[Type]` to store each individual type argument, since this doesn't encode enough information to tell whether an argument is applied using visible kind application or not. Instead, a single `Type` is used. For instance, this is how the `Foo @Bool a = a` equation is encoded:
|
|
|
|
|
|
```hs
|
|
|
TySynEqn Nothing (ConT ''Foo `AppKindT` ConT ''Bool `AppT` VarT a) (VarT a)
|
|
|
```
|
|
|
|
|
|
Note that the name of the type family, `Foo`, is now present on the left-hand side! This was not the case before, as previously only the *arguments* were included in a `TySynEqn`. This means that the `Name` field in `TySynInstD` is now wholly redundant (as that same `Name` is present in the `TynSynEqn`), so the `Name` field was removed from `TySynInstD`.
|
|
|
|
|
|
Similar changes were made to `DataInstD` and `NewtypeInstD`. Their `Name` and `[Type]` fields (representing the data family name and left-hand-side arguments, respectively) were removed in favor of a single `Type` representing the data family name applied to its arguments.
|
|
|
|
|
|
One consequence of this change is that retrieving the `Name` from a type or data family instance is no longer as straightforward as it used to be, as the `Name` is now inside of the left-hand side `Type` field. Similarly, the type arguments of the instance are also sprinkled throughout the LHS `Type` field. One may find the following utility function useful to retrieve the `Name` and arguments:
|
|
|
|
|
|
```hs
|
|
|
{-# LANGUAGE CPP #-}
|
|
|
|
|
|
-- | An argument to a type, either a normal type ('TANormal') or a visible
|
|
|
-- kind application ('TyArg').
|
|
|
--
|
|
|
-- 'TypeArg' is useful when decomposing an application of a 'Type' to its
|
|
|
-- arguments (e.g., in 'unfoldType').
|
|
|
data TypeArg
|
|
|
= TANormal Type -- Normal arguments
|
|
|
| TyArg Kind -- Visible kind applications
|
|
|
|
|
|
-- | Decompose an applied type into its individual components. For example, this:
|
|
|
--
|
|
|
-- @
|
|
|
-- Proxy \@Type Char
|
|
|
-- @
|
|
|
--
|
|
|
-- would be unfolded to this:
|
|
|
--
|
|
|
-- @
|
|
|
-- ('ConT' ''Proxy, ['TyArg' ('ConT' ''Type), 'TANormal' ('ConT' ''Char)])
|
|
|
-- @
|
|
|
unfoldType :: Type -> (Type, [TypeArg])
|
|
|
unfoldType = go []
|
|
|
where
|
|
|
go :: [TypeArg] -> Type -> (Type, [TypeArg])
|
|
|
go acc (ForallT _ _ ty) = go acc ty
|
|
|
go acc (AppT ty1 ty2) = go (TANormal ty2:acc) ty1
|
|
|
go acc (SigT ty _) = go acc ty
|
|
|
#if MIN_VERSION_template_haskell(2,11,0)
|
|
|
go acc (ParensT ty) = go acc ty
|
|
|
#endif
|
|
|
#if MIN_VERSION_template_haskell(2,15,0)
|
|
|
go acc (AppKindT ty ki) = go (TyArg ki:acc) ty
|
|
|
#endif
|
|
|
go acc ty = (ty, acc)
|
|
|
|
|
|
famInstLHSName :: Type -> Maybe Name
|
|
|
famInstLHSName t =
|
|
|
case unfoldType t of
|
|
|
(ConT n, _) -> Just n
|
|
|
(_, _) -> Nothing
|
|
|
```
|
|
|
|
|
|
- Because of the bullet point above, it was no longer possible to keep the old type signature of `tySynEqn` since it lacks a `Type` containing the `Name` of the type family. For this reason, it was decided to just make a breaking change to the type of `tySynEqn` (and similarly for `tySynInstD`, which is almost always used in conjunction with `tySynEqn`).
|
|
|
|
|
|
>
|
|
|
> Note that neither of the type signatures for `dataInstD` nor `newtypeInstD` had to change since the data family `Name` was already an argument, so these functions happen to have enough information to stay backwards compatible even in the face of these AST changes. |
|
|
Note that neither of the type signatures for `dataInstD` nor `newtypeInstD` had to change since the data family `Name` was already an argument, so these functions happen to have enough information to stay backwards compatible even in the face of these AST changes. |