Table of Contents
The Hackage Matrix Builder is a great way to track how compatible a library is with historical versions of GHC (and therefore base
).
As a library author, if you've ever attempted to support more than the most recent versions of GHC, then you've been tossed around the ocean of Applicative
, Semigroup
, and MonadFail
, with CPP as your only olive branch.
This post is a reference for library authors to easily track how base
evolves, and how to deal with its changes. This is so that we don't all have to repeat the same labour of digging through GHC release notes or the base
CHANGELOG to find out what works. I will update this post as time goes on, so please feel free to bookmark it or even help update it.
GHC | base version | Stackage LTS | Cabal | Notable Changes |
---|---|---|---|---|
9.8 | 4.19 | ExtendedLiterals | ||
9.6 | 4.18 | WASM and JS backends (initial preview) | ||
Delimited continuation primops | ||||
9.4 | 4.17 | 21 | \cases syntax | |
9.2 | 4.16 | 20 | Record Dot Syntax available | |
GHC2021 extension set | ||||
9.0 | 4.15 | 19 | 3.4 | LinearTypes available |
8.10 | 4.14 | 18 | 3.2 | +RTS -xn for non-moving, concurrent GC |
8.8 | 4.13 | 16 | 3.0 | MonadFail exported by Prelude |
fail removed from Monad | ||||
8.6 | 4.12 | 14 | 2.4 | -funclutter-valid-hole-fits available |
deriving via available | ||||
8.4 | 4.11 | 12 | 2.2 | Semigroup is superclass of Monoid |
Semigroup exported by Prelude | ||||
8.2 | 4.10 | 11 | 2.0 | DerivingStrategies available |
8.0 | 4.9 | 9 | 1.24 | MonadFail enters base |
Semigroup enters base | ||||
7.10 | 4.8 | 6 | 1.22 | Applicative is superclass of Monad |
Applicative exported by Prelude | ||||
7.8 | 4.7 | 2 | 1.18 |
base
earlier than 4.n
, do XA construction like #if __GLASGOW_HASKELL__ < 841
is also possible, but I find this less clear than comparing against base
.
Monoid
InstancesThis will allow your library to support GHC >= 8.0. Excluding this CPP will limit your compatibility to GHC >= 8.4.
{-# LANGUAGE CPP #-}
#if !MIN_VERSION_base(4,11,0)
import Data.Semigroup
#endif
instance Semigroup Foo where
a <> b = ...
instance Monoid Foo where
mempty = ...
#if !MIN_VERSION_base(4,11,0)
mappend = (<>)
#endif
For instance, until GHC 8.0, the Semigroup
typeclass was not in base
. The following will include the semigroups
dependency, but only when it detects that you need it:
library build-depends: base >= 4.8 && < 5 ... if !impl(ghc >= 8.0) build-depends: semigroups >= 0.8.4 && < 1
Multiple build-depends
sections like this combine, they don't override one another.
*-compat
packagesThere are a number of packages that smooth the transition between compiler versions by backporting newer functionality. The major ones are:
base-compat
but with more dependenciesTo see all such libraries, search for "compat" on Hackage.
these
As of these-1
the project underwent a structural change. Its extended dependency graph is now "opt out", and the following can be added to a stack.yaml
to accomplish this:
If using these-1
or these-1.0.1
, set this instead:
witherable
wither :: Applicative f => (a -> f (Maybe b)) -> t a -> f (t b)
is a convenient function from the witherable
package. As of 2019 December, the core typeclass and functions are available with minimal dependencies via the witherable-class
library.
This trick lets your library/program have programmatic access to the version:
value you specified in your .cabal
file.
{-# LANGUAGE CPP #-}
#ifndef CURRENT_PACKAGE_VERSION
#define CURRENT_PACKAGE_VERSION "UNKNOWN"
#endif
ver :: Text
ver = CURRENT_PACKAGE_VERSION
Blog Archive