The base-compat package

[Tags:library, mit, test]

Provides functions available in later versions of base to a wider range of compilers, without requiring you to use CPP pragmas in your code. See the README for what is covered. Also see the changelog for recent changes.

Note that base-compat does not add any orphan instances. There is a separate package, base-orphans, for that.

In addition, base-compat does not backport any data types or type classes. See this section of the README for more info.

[Skip to Readme]


Versions 0.0.0, 0.1.0,, 0.2.0,,, 0.2.1, 0.3.0, 0.4.0, 0.4.1, 0.4.2, 0.5.0, 0.6.0, 0.7.0, 0.7.1, 0.8.0,, 0.8.1,, 0.8.2, 0.9.0, 0.9.1, 0.9.2 (info)
Change log CHANGES.markdown
Dependencies base (>=4.3 && <5), unix [details]
License MIT
Copyright (c) 2012-2017 Simon Hengel, (c) 2014-2017 João Cristóvão, (c) 2015-2017 Ryan Scott
Author Simon Hengel <>, João Cristóvão <>, Ryan Scott <>
Maintainer Simon Hengel <>, João Cristóvão <>, Ryan Scott <>
Stability Unknown
Category Compatibility
Source repository head: git clone
Uploaded Sat Mar 11 21:33:38 UTC 2017 by ryanglscott
Distributions Arch:0.9.2, Debian:0.8.2, Fedora:0.9.1, LTSHaskell:0.9.2, NixOS:0.9.1, Stackage:0.9.2, Tumbleweed:0.9.1
Downloads 11593 total (2372 in the last 30 days)
1 []
Status Docs available [build log]
Last success reported on 2017-03-11 [all 1 reports]




Maintainer's Corner

For package maintainers and hackage trustees

Readme for base-compat

Readme for base-compat-0.9.2

A compatibility layer for base

Hackage Hackage Dependencies Haskell Programming Language BSD3 License Build


The scope of base-compat 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 base-compat does not add any orphan instances. There is a separate package base-orphans for that.

In addition, base-compat 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.

Basic usage

In your cabal file, you should have something like this:

  build-depends:      base              >= 4.3
                    , base-compat       >= 0.9.0

Then, lets say you want to use the isRight function introduced with base- Replace:

import Data.Either


import Data.Either.Compat

Note (1): There is no need to import both unqualified. The .Compat modules re-exports 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 base-compat: patches are welcomed!

Using Prelude.Compat

If you want to use Prelude.Compat (which provides all the AMP/Traversable/Foldable changes from base-, 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 base-

Using this approach allows you to write code that works seamlessly with all versions of GHC that are supported by base-compat.

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 as Prelude from base-
  • System.IO.Error.catch is not re-exported from Prelude.Compat for older versions of base
  • Text.Read.Compat.readMaybe
  • Text.Read.Compat.readEither
  • Data.Monoid.Compat.<>
  • Added bitDefault, testBitDefault, and popCountDefault to Data.Bits.Compat
  • Added toIntegralSized to Data.Bits.Compat (if using base-4.7)
  • Added bool function to Data.Bool.Compat
  • Added isLeft and isRight to Data.Either.Compat
  • Added forkFinally to Control.Concurrent.Compat
  • Added withMVarMasked function to Control.Concurrent.MVar.Compat
  • Added (<$!>) function to Control.Monad.Compat
  • Weakened RealFloat constraints on realPart, imagPart, conjugate, mkPolar, and cis in Data.Complex.Compat
  • Added ($>) and void functions to Data.Functor.Compat
  • (&) function to Data.Function.Compat
  • ($>) and void functions to Data.Functor.Compat
  • modifyIORef', atomicModifyIORef' and atomicWriteIORef to Data.IORef.Compat
  • dropWhileEnd, isSubsequenceOf, sortOn, and uncons functions to Data.List.Compat
  • Correct versions of nub, nubBy, union, and unionBy to Data.List.Compat
  • modifySTRef' to Data.STRef.Compat
  • String, lines, words, unlines, and unwords to Data.String.Compat
  • makeVersion function to Data.Version.Compat
  • traceId, traceShowId, traceM, and traceShowM functions to Debug.Trace.Compat
  • byteSwap16, byteSwap32, and byteSwap64 to Data.Word.Compat
  • calloc and callocBytes functions to Foreign.Marshal.Alloc.Compat
  • callocArray and callocArray0 functions to Foreign.Marshal.Array.Compat
  • fillBytes to Foreign.Marshal.Utils.Compat
  • Added Data.List.Compat.scanl'
  • showFFloatAlt and showGFloatAlt to Numeric.Compat
  • lookupEnv, setEnv and unsetEnv to System.Environment.Compat
  • unsafeFixIO and unsafeDupablePerformIO to System.IO.Unsafe.IO

What is not covered

Data types and type classes

base-compat 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 base- with the following API:

class Bits b => FiniteBits b where
    finiteBitSize :: b -> Int

However, in base-, FiniteBits gained additional functions:

class Bits b => FiniteBits b where
    finiteBitSize :: b -> Int
    countLeadingZeros :: b -> Int
    countTrailingZeros :: b -> Int

This raises the question: how can FiniteBits be backported consistently across all versions of base? One approach is to backport the API exposed in base- on versions prior to The problem with this is that countLeadingZeros and countTrailingZeros are not exposed in base-, 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 = ...

This is a very unsatisfactory solution, and for this reason, we do not pursue it. For similar reasons, we do not backport data types.

Other compatibility packages

If you really need your favorite data type or type class in base to be backported, you might be in luck, since several data types have their own compatibility packages on Hackage. Here is a list of such packages:

Supported versions of GHC/base

  • ghc-8.0.2 / base-
  • ghc-8.0.1 / base-
  • ghc-7.10.3 / base-
  • ghc-7.10.2 / base-
  • ghc-7.10.1 / base-
  • ghc-7.8.4 / base-
  • ghc-7.8.3 / base-
  • ghc-7.8.2 / base-
  • ghc-7.8.1 / base-
  • ghc-7.6.3 / base-
  • ghc-7.6.2 / base-
  • ghc-7.6.1 / base-
  • ghc-7.4.2 / base-
  • ghc-7.4.1 / base-
  • ghc-7.2.2 / base-
  • ghc-7.2.1 / base-
  • ghc-7.0.4 / base-
  • ghc-7.0.3 / base-
  • ghc-7.0.2 / base-
  • ghc-7.0.1 / base-

We also make an attempt to keep base-compat 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!