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.
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-4.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
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
.Compatis 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!
If you want to use Prelude.Compat (which provides all the
AMP/Traversable/Foldable changes from base-4.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
base-4.8.0.0.
Using this approach allows you to write code that works seamlessly with all
versions of GHC that are supported by base-compat.
So far the following is covered.
Prelude.Compatincorporates the AMP/Foldable/Traversable changes and exposes the same interface asPreludefrombase-4.9.0.0System.IO.Error.catchis not re-exported fromPrelude.Compatfor older versions ofbaseText.Read.Compat.readMaybeText.Read.Compat.readEitherData.Monoid.Compat.<>- Added
bitDefault,testBitDefault, andpopCountDefaulttoData.Bits.Compat - Added
toIntegralSizedtoData.Bits.Compat(if usingbase-4.7) - Added
boolfunction toData.Bool.Compat - Added
isLeftandisRighttoData.Either.Compat - Added
forkFinallytoControl.Concurrent.Compat - Added
withMVarMaskedfunction toControl.Concurrent.MVar.Compat - Added
(<$!>)function toControl.Monad.Compat - Weakened
RealFloatconstraints onrealPart,imagPart,conjugate,mkPolar, andcisinData.Complex.Compat - Added
($>)andvoidfunctions toData.Functor.Compat (&)function toData.Function.Compat($>)andvoidfunctions toData.Functor.CompatmodifyIORef',atomicModifyIORef'andatomicWriteIOReftoData.IORef.CompatdropWhileEnd,isSubsequenceOf,sortOn, andunconsfunctions toData.List.Compat- Correct versions of
nub,nubBy,union, andunionBytoData.List.Compat modifySTRef'toData.STRef.CompatString,lines,words,unlines, andunwordstoData.String.CompatmakeVersionfunction toData.Version.CompattraceId,traceShowId,traceM, andtraceShowMfunctions toDebug.Trace.CompatbyteSwap16,byteSwap32, andbyteSwap64toData.Word.CompatcallocandcallocBytesfunctions toForeign.Marshal.Alloc.CompatcallocArrayandcallocArray0functions toForeign.Marshal.Array.CompatfillBytestoForeign.Marshal.Utils.Compat- Added
Data.List.Compat.scanl' showFFloatAltandshowGFloatAlttoNumeric.CompatlookupEnv,setEnvandunsetEnvtoSystem.Environment.CompatunsafeFixIOandunsafeDupablePerformIOtoSystem.IO.Unsafe.IO
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-4.7.0.0
with the following API:
class Bits b => FiniteBits b where
finiteBitSize :: b -> IntHowever, in base-4.8.0.0,
FiniteBits gained additional functions:
class Bits b => FiniteBits b where
finiteBitSize :: b -> Int
countLeadingZeros :: b -> Int
countTrailingZeros :: b -> IntThis raises the question: how can FiniteBits be backported consistently
across all versions of base? One approach is to backport the API exposed in
base-4.8.0.0 on versions prior to 4.7.0.0. The problem with this is that
countLeadingZeros and countTrailingZeros are not exposed in base-4.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 = ...
#endifThis is a very unsatisfactory solution, and for this reason, we do not pursue it. For similar reasons, we do not backport data types.
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:
bifunctorsfor theBifunctortype class, introduced inbase-4.8.0.0generic-derivingfor everything in theGHC.Genericsmodule, introduced toghc-primin GHC 7.2 (and later moved tobase-4.6.0.0)natsfor theNaturaldata type, introduced inbase-4.8.0.0semigroupsfor theSemigrouptypeclass and theNonEmpty,Min,Max,First,Last,WrappedMonoid,Option, andArgdata types, introduced inbase-4.9.0.0taggedfor theProxydata type, introduced inbase-4.7.0.0transformersfor:voidfor theVoiddata type, introduced inbase-4.8.0.0
ghc-8.0.1/base-4.9.0.0ghc-7.10.3/base-4.8.2.0ghc-7.10.2/base-4.8.1.0ghc-7.10.1/base-4.8.0.0ghc-7.8.4/base-4.7.0.2ghc-7.8.3/base-4.7.0.1ghc-7.8.2/base-4.7.0.0ghc-7.8.1/base-4.7.0.0ghc-7.6.3/base-4.6.0.1ghc-7.6.2/base-4.6.0.1ghc-7.6.1/base-4.6.0.0ghc-7.4.2/base-4.5.1.0ghc-7.4.1/base-4.5.0.0ghc-7.2.2/base-4.4.1.0ghc-7.2.1/base-4.4.0.0ghc-7.0.4/base-4.3.1.0ghc-7.0.3/base-4.3.1.0ghc-7.0.2/base-4.3.1.0ghc-7.0.1/base-4.3.0.0
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!