basecompat
A compatibility layer for base
Version on this page:  0.9.1 
LTS Haskell 12.18:  0.10.5 
Stackage Nightly 20181113:  0.10.5 
Latest on Hackage:  0.10.5 
Module documentation for 0.9.1
 Control
 Control.Concurrent
 Control.Concurrent.Compat
 Control.Concurrent.MVar
 Control.Monad
 Control.Monad.Compat
 Control.Monad.ST
 Control.Monad.ST.Lazy
 Control.Monad.ST.Lazy.Unsafe
 Control.Monad.ST.Unsafe
 Control.Monad.ST.Lazy
 Control.Concurrent
 Data
 Data.Bits
 Data.Bool
 Data.Complex
 Data.Either
 Data.Foldable
 Data.Function
 Data.Functor
 Data.Functor.Compat
 Data.Functor.Const
 Data.IORef
 Data.List
 Data.Monoid
 Data.Ratio
 Data.STRef
 Data.String
 Data.Version
 Data.Word
 Debug
 Debug.Trace
 Foreign
 Foreign.Compat
 Foreign.ForeignPtr
 Foreign.ForeignPtr.Safe
 Foreign.ForeignPtr.Unsafe
 Foreign.Marshal
 Foreign.Marshal.Alloc
 Foreign.Marshal.Array
 Foreign.Marshal.Compat
 Foreign.Marshal.Safe
 Foreign.Marshal.Unsafe
 Foreign.Marshal.Utils
 Numeric
 Prelude
 System
 System.Environment
 System.Exit
 System.IO
 System.IO.Unsafe
 Text
 Text.Read
A compatibility layer for base
Scope
The scope of basecompat
is to provide functions available in later versions
of base to a wider (older) range of compilers.
In addition, successful library proposals that have been accepted to be part of
upcoming versions of base
are also included. This package is not intended to
replace base
, but to complement it.
Note that basecompat
does not add any orphan instances. There is a separate
package baseorphans
for
that.
In addition, basecompat
only backports functions. In particular, we
purposefully do not backport data types or type classes introduced in newer
versions of base
. For more info, see the
Data types and type classes
section.
basecompat
is intentionally designed to have zero dependencies. As a
consequence, there are some modules that can only be backported up to certain
versions of base
. If an even wider support window is desired in these
scenarios, there also exists a basecompatbatteries
package which augments
basecompat
with certain compatibility package dependencies. For more info,
see the Dependencies section.
Basic usage
In your cabal file, you should have something like this:
builddepends: base >= 4.3
, basecompat >= 0.9.0
Then, lets say you want to use the isRight
function introduced with
base4.7.0.0
. Replace:
import Data.Either
with
import Data.Either.Compat
Note (1): There is no need to import both unqualified. The .Compat
modules
reexports the original module.
Note (2): If a given module .Compat
version is not defined, that either
means that:
 The module has not changed in recent base versions, thus no
.Compat
is needed.  The module has changed, but the changes depend on newer versions of GHC, and thus are not portable.
 The module has changed, but those changes have not yet been merged in
basecompat
: patches are welcomed!
Using Prelude.Compat
If you want to use Prelude.Compat
(which provides all the
AMP/Traversable/Foldable changes from base4.8.0.0
), it’s best to hide
Prelude
, e.g.:
import Prelude ()
import Prelude.Compat
main :: IO ()
main = mapM_ print (Just 23)
Alternatively, you can use the NoImplicitPrelude
language extension:
{# LANGUAGE NoImplicitPrelude #}
import Prelude.Compat
main :: IO ()
main = mapM_ print (Just 23)
Note that we use
mapM_ :: (Foldable t, Monad m) => (a > m b) > t a > m ()
from Data.Foldable
here, which is only exposed from Prelude
since
base4.8.0.0
.
Using this approach allows you to write code that works seamlessly with all
versions of GHC that are supported by basecompat
.
What is covered
So far the following is covered.
For compatibility with the latest released version of base
Prelude.Compat
incorporates the AMP/Foldable/Traversable changes and exposes the same interface asPrelude
frombase4.9.0.0
System.IO.Error.catch
is not reexported fromPrelude.Compat
for older versions ofbase
Text.Read.Compat.readMaybe
Text.Read.Compat.readEither
Data.Monoid.Compat.<>
 Added
bitDefault
,testBitDefault
, andpopCountDefault
toData.Bits.Compat
 Added
toIntegralSized
toData.Bits.Compat
(if usingbase4.7
)  Added
bool
function toData.Bool.Compat
 Added
isLeft
,isRight
,fromLeft
, andfromRight
toData.Either.Compat
 Added
forkFinally
toControl.Concurrent.Compat
 Added
withMVarMasked
function toControl.Concurrent.MVar.Compat
 Added
(<$!>)
function toControl.Monad.Compat
 Weakened
RealFloat
constraints onrealPart
,imagPart
,conjugate
,mkPolar
, andcis
inData.Complex.Compat
 Added more efficient
maximumBy
/minimumBy
toData.Foldable.Compat
 Added
($>)
andvoid
functions toData.Functor.Compat
(&)
function toData.Function.Compat
($>)
andvoid
functions toData.Functor.Compat
modifyIORef'
,atomicModifyIORef'
andatomicWriteIORef
toData.IORef.Compat
dropWhileEnd
,isSubsequenceOf
,sortOn
, anduncons
functions toData.List.Compat
 Correct versions of
nub
,nubBy
,union
, andunionBy
toData.List.Compat
asProxyTypeOf
with a generalized type signature toData.Proxy.Compat
modifySTRef'
toData.STRef.Compat
String
,lines
,words
,unlines
, andunwords
toData.String.Compat
gcoerceWith
toData.Type.Coercion.Compat
makeVersion
function toData.Version.Compat
traceId
,traceShowId
,traceM
, andtraceShowM
functions toDebug.Trace.Compat
byteSwap16
,byteSwap32
, andbyteSwap64
toData.Word.Compat
plusForeignPtr
toForeign.ForeignPtr.Compat
calloc
andcallocBytes
functions toForeign.Marshal.Alloc.Compat
callocArray
andcallocArray0
functions toForeign.Marshal.Array.Compat
fillBytes
toForeign.Marshal.Utils.Compat
 Added
Data.List.Compat.scanl'
showFFloatAlt
andshowGFloatAlt
toNumeric.Compat
lookupEnv
,setEnv
andunsetEnv
toSystem.Environment.Compat
unsafeFixIO
andunsafeDupablePerformIO
toSystem.IO.Unsafe.IO
RuntimeRep
polymorphic($!)
toPrelude.Compat
RuntimeRep
polymorphicthrow
toControl.Exception.Compat
What is not covered
Data types and type classes
basecompat
purposefully does not export any data types or type classes that
were introduced in more recent versions of base
. The main reasoning for this
policy is that it is not some data types and type classes have had their APIs
change in different versions of base
, which makes having a consistent
compatibility API for them practically impossible.
As an example, consider the FiniteBits
type class. It was introduced in
base4.7.0.0
with the following API:
class Bits b => FiniteBits b where
finiteBitSize :: b > Int
However, in base4.8.0.0
,
FiniteBits
gained additional functions:
class Bits b => FiniteBits b where
finiteBitSize :: b > Int
countLeadingZeros :: b > Int  ^ @since 4.8.0.0
countTrailingZeros :: b > Int  ^ @since 4.8.0.0
This raises the question: how can FiniteBits
be backported consistently
across all versions of base
? One approach is to backport the API exposed in
base4.8.0.0
on versions prior to 4.7.0.0
. The problem with this is that
countLeadingZeros
and countTrailingZeros
are not exposed in base4.7.0.0
,
so instances of FiniteBits
would have to be declared like this:
instance FiniteBits Foo where
finiteBitSize = ...
#if MIN_VERSION_base(4,8,0)  !(MIN_VERSION_base(4,7,0))
countLeadingZeros = ...
countTrailingZeros = ...
#endif
Another approach is to backport the API from base4.7.0.0
and to declare
additional methods outside of the class:
#if MIN_VERSION_base(4,7,0) && !(MIN_VERSION_base(4,8,0))
countLeadingZeros :: FiniteBits b => b > Int
countLeadingZeros = { default implementation #}
#endif
The situation is only slightly better for classes which exist across all versions of base
,
but have grown their API. For example, it’s tempting to define
#if !(MIN_VERSION_base(4,8,0))
displayException :: Exception e => e > String
displayException = show
#endif
As with the previous approach, you won’t be able to define new members of the type class without CPP guards. In other words, the nonCPP approach would limit uses to the lowest common denominator.
As neither approach is a very satisfactory solution, and to embrace consistency, we do not pursue either approach. For similar reasons, we do not backport data types.
Dependencies
basecompat
is designed to have zero dependencies (besides libraries that
ship with GHC itself). A consequence of this choice is that there are certain
modules that have a “limited” support window. An important example of this is
Prelude.Compat
, which backports the Semigroup
class to versions of base
older than 4.11 (when it was added to the Prelude
). Because Semigroup
was
not added to base
until base4.9
, basecompat
cannot backport it to
any earlier version of base
than this.
If you would instead desire to be able to use a version of Prelude.Compat
that does backport Semigroup
to even older versions of base
, even if it
means pulling in other dependencies, then you are in luck. There also exists
a basecompatbatteries
package, which exposes a strict superset of the API
in basecompat
. basecompatbatteries
has all the same modules as
basecompat
, but exposes more functionality on more versions of base
by
reexporting things from compatibility libraries whenever necessary. (For
instance, basecompatbatteries
exports the Semigroup
class from the
semigroups
library when built against versions of base
older than 4.9.)
Because basecompat
and basecompatbatteries
have the same module names,
they are quite easy to switch out for one another in library projects, at the
expense of having clashing names if one tries to import them in GHCi. To
work around this issue, basecompat
and basecompatbatteries
also provide
copies of each module with the suffix .Repl
(for basecompat
) and
.Repl.Batteries
(for basecompatbatteries
) to give them globally unique
namespaces in the event one wants to import them into GHCi.
Here is a list of compatibility libraries that basecompatbatteries
depends
on, paired with the things that each library backports:
bifunctors
for: The
Bifunctor
type class, introduced inbase4.8.0.0
 The
Bifoldable
andBitraversable
type classes, introduced inbase4.10.0.0
 The
contravariant
for theContravariant
type class, introduced inbase4.12.0.0
.fail
for theMonadFail
type class, introduced inbase4.9.0.0
nats
for theNatural
data type, introduced inbase4.8.0.0
semigroups
for theSemigroup
typeclass and theNonEmpty
,Min
,Max
,First
,Last
,WrappedMonoid
,Option
, andArg
data types, introduced inbase4.9.0.0
tagged
for theProxy
data type, introduced inbase4.7.0.0
transformers
for:void
for theVoid
data type, introduced inbase4.8.0.0
Supported versions of GHC/base
ghc8.6.1
/base4.12.0.0
ghc8.4.4
/base4.11.1.0
ghc8.4.3
/base4.11.1.0
ghc8.4.2
/base4.11.1.0
ghc8.4.1
/base4.11.0.0
ghc8.2.2
/base4.10.1.0
ghc8.2.1
/base4.10.0.0
ghc8.0.2
/base4.9.1.0
ghc8.0.1
/base4.9.0.0
ghc7.10.3
/base4.8.2.0
ghc7.10.2
/base4.8.1.0
ghc7.10.1
/base4.8.0.0
ghc7.8.4
/base4.7.0.2
ghc7.8.3
/base4.7.0.1
ghc7.8.2
/base4.7.0.0
ghc7.8.1
/base4.7.0.0
ghc7.6.3
/base4.6.0.1
ghc7.6.2
/base4.6.0.1
ghc7.6.1
/base4.6.0.0
ghc7.4.2
/base4.5.1.0
ghc7.4.1
/base4.5.0.0
ghc7.2.2
/base4.4.1.0
ghc7.2.1
/base4.4.0.0
ghc7.0.4
/base4.3.1.0
ghc7.0.3
/base4.3.1.0
ghc7.0.2
/base4.3.1.0
ghc7.0.1
/base4.3.0.0
We also make an attempt to keep basecompat
building with GHC HEAD, but due
to its volatility, it may not work at any given point in time. If it doesn’t,
please report it!
Patches are welcome; add tests for new code!
Changes
Changes in 0.10.5 [2018.10.18]
 Enable
BangPatterns
inPrelude.Compat
.
Changes in 0.10.4 [2018.07.03]
 Make more modules
Trustworthy
. In particular, fix a regression in whichPrelude.Compat
was inferred asUnsafe
by explicitly marking it asTrustwothy
.
Changes in 0.10.3 [2018.07.02]
 Backport the proper fixity for
($!)
, which was accidentally omitted inbasecompat0.10.2
.
Changes in 0.10.2 [2018.07.02]

Sync with
base4.12
/GHC 8.6 
Backport
RuntimeRep
polymorphic versions of($!)
andthrow
toPrelude.Compat
andControl.Exception.Compat
, respectively (if usingbase4.10
/GHC 8.2 or later). 
Introduce the
Data.Functor.Contravariant.Compat
module, which reexportsData.Functor.Contravariant
if usingbase4.12
/GHC 8.6 or later.See
Data.Functor.Contravariant.Compat
in the correspondingbasecompatbatteries
release for a version with a wider support window.
Changes in 0.10.1 [2018.04.10]
 Add
Data.List.NonEmpty.Compat
.  Reexport
(Data.Semigroup.<>)
fromData.Monoid.Compat
back tobase4.9
.
Changes in 0.10.0 [2018.04.05]

Sync with
base4.11
/GHC 8.4 
Backport
Semigroup((<>))
toPrelude.Compat
.Note that the
Semigroup
class has only been inbase
sincebase4.9
/GHC 8.0, so accordingly, this can only be backported back to GHC 8.0. If you wish to have a version ofPrelude.Compat
that backportsSemigroup
to older GHCs (by conditionally depending on thesemigroups
library), use thePrelude.Compat
module from thebasecompatbatteries
package. 
Backport
(<&>)
toData.Functor.Compat

Backport
iterate'
toData.List.Compat

Backport
showHFloat
toNumeric.Compat

Backport a
RuntimeRep
polymorphicwithTypeable
function toType.Reflection.Compat
. (This is only exported onbase4.10
/GHC 8.2.) 
Introduce the following modules, back until the oldest version of
base
that can support backporting them. If you wish to use them in conjunction with older versions ofbase
, use thebasecompatbatteries
package.Control.Monad.Fail.Compat
(back untilbase4.9
/GHC 8.0)Control.Monad.IO.Class.Compat
(back untilbase4.9
/GHC 8.0)Data.Bifunctor
(back untilbase4.8
/GHC 7.10)Data.Bifoldable
andData.Bitraversable
(back untilbase4.10
/GHC 8.2)Data.Functor.Compose.Compat
,Data.Functor.Product.Compat
, andData.Functor.Sum.Compat
(back untilbase4.9
/GHC 8.0)Data.Functor.Identity.Compat
(back untilbase4.8
/GHC 7.10)Data.Semigroup.Compat
(back untilbase4.9
/GHC 8.0)Data.Void.Compat
(back untilbase4.8
/GHC 7.10)Numeric.Natural.Compat
(back untilbase4.8
/GHC 7.10)

Introduce versions of modules with the suffix
.Repl
. These simply reexport the contents of their counterparts without the.Repl
suffix to provide a globally unique namespace to import from in the event one wants to importbasecompat
modules into GHCi. (Inbasecompatbatteries
, the corresponding suffix is.Repl.Batteries
.)
Changes in 0.9.3 [2017.04.10]
 Sync with
base4.10
/GHC 8.2  Backport
fromLeft
/fromRight
toData.Either.Compat
 Backport implementations of
maximumBy
/minimumBy
which use constant stack space toData.Foldable.Compat
 Backport
asProxyTypeOf
with a generalized type signature toData.Proxy.Compat
 Backport
gcoerceWith
toData.Type.Coercion.Compat
 Backport
plusForeignPtr
toForeign.ForeignPtr.Compat
Changes in 0.9.2
 Allow building on the HaLVM
Changes in 0.9.1
 Use the more efficient version of
replicateM
andreplicateM_
introduced inbase4.9
Changes in 0.9.0
 Sync with
base4.9
/GHC 8.0  Weakened
RealFloat
constraints onrealPart
,imagPart
,conjugate
,mkPolar
, andcis
inData.Complex.Compat
 Backport
Foreign.ForeignPtr.Safe
andForeign.Marshal.Safe
 Generalize
filterM
,forever
,mapAndUnzipM
,zipWithM
,zipWithM_
,replicateM
, andreplicateM_
inControl.Monad
fromMonad
toApplicative
 Backport
.Unsafe.Compat
modules (forControl.Monad.ST
,Control.Monad.ST.Lazy
,Foreign.ForeignPtr
, andForeign.Marshal
)  Backport
forkFinally
andforkOSWithUnmask
toControl.Concurrent.Compat
 Backport
Data.Functor.Const
 Backport
modifyIORef'
,atomicModifyIORef'
andatomicWriteIORef
toData.IORef.Compat
Data.Ratio.{denominator,numerator}
have noIntegral
constraint anymore Backport
modifySTRef'
toData.STRef.Compat
 Export
String
,lines
,words
,unlines
, andunwords
toData.String.Compat
 Generalize
Debug.Trace.{traceM, traceShowM}
fromMonad
toApplicative
 Backport
errorWithoutStackTrace
toPrelude.Compat
 Backport
unsafeFixIO
andunsafeDupablePerformIO
toSystem.IO.Unsafe.Compat
Changes in 0.8.2
 Backport
bitDefault
,testBitDefault
, andpopCountDefault
inData.Bits.Compat
to all versions ofbase
 Backport
toIntegralSized
tobase4.7
 Backport
 Backport
nub
andnubBy
(as well asunion
andunionBy
, which are implemented in terms of them) to fix logic error inData.List.Compat
 Backport
byteSwap16
,byteSwap32
, andbyteSwap64
toData.Word.Compat
 Backport
fillBytes
inForeign.Marshal.Utils.Compat
 Backport
showFFloatAlt
andshowGFloatAlt
toNumeric.Compat
Changes in 0.8.1.1
 Fixed Windows build
Changes in 0.8.1
 Implement
setEnv
andunsetEnv
inSystem.Environment.Compat
(which were ported from thesetenv
package). As a result,basecompat
now depends onunix
on POSIXlike operating systems.  Drop GHC 6.12 (and
base4.2.0.0
) compatibility
Changes in 0.8.0.1
 Retrospective version bump updating the changelog to reflect the changes made in 0.8.0
Changes 0.8.0
 All orphan instances were split off into a separate package,
baseorphans
basecompat
no longer redefines the data typesDown
andAlt
. See here for the discussion that led to this change. Update
Control.Monad.Compat
forbase4.8.0.0
 Update
Data.List.Compat
forbase4.8.0.0
 Update
Data.Foldable.Compat
forbase4.8.0.0
Changes in 0.7.1
 Backported
Alt
toData.Monoid.Compat
 Backported
Down
toData.Ord.Compat
Changes in 0.7.0
 Add functions and orphan instances introduced by changes to
base4.7.0.0
andbase4.8.0.0
Changes in 0.6.0
 Update
Prelude.Compat
forbase4.8.0.0
and AMP
Changes in 0.5.0
 Remove Control.Exception.Base.Compat and GHC.Exception.Compat
 Add System.Exit.Compat.die
 Compatibility with base4.7.1
Changes in 0.4.1
 Add
setEnv
andunsetEnv
toSystem.Environment.Compat
Changes in 0.4.0
 Major refactoring: basecompat no longer aims to replace all base, only new code is included in module .Compat
 Removed stubbed modules
 Removed generation scripts
Changes in 0.3
 Added functions from Base 4.7 (bool, isLeft, isRight)
 Added instances from Base 4.7 (Either Foldable, Traversable,…)
Changes in 0.2.1
 Fix build on windows
Changes in 0.2.0
 Reexport everything from base
 provides access to
VERSION_base
andMIN_VERSION_base
CPP macros (with#include "basecompat.h"
)  Do not reexport
System.IO.Error.catch
fromPrelude
forbase
< 4.6.0  Add
Eq
/Ord
instance forErrorCall
 Remove
GHC.IOBase
,GHC.Handle
,Control.Concurrent.QSem
,Control.Concurrent.QSemN
,Control.Concurrent.SampleVar
,Data.HashTable
Changes in 0.1.0
 Remove getExecutablePath, it did not work with GHC < 7.2 (patches welcome!)
 Add
<>