# A compatibility layer for `base` [![Hackage](https://img.shields.io/hackage/v/base-compat.svg)][Hackage: base-compat] [![Hackage Dependencies](https://img.shields.io/hackage-deps/v/base-compat.svg)](http://packdeps.haskellers.com/reverse/base-compat) [![Haskell Programming Language](https://img.shields.io/badge/language-Haskell-blue.svg)][Haskell.org] [![BSD3 License](http://img.shields.io/badge/license-MIT-brightgreen.svg)][tl;dr Legal: MIT] [![Build](https://img.shields.io/travis/haskell-compat/base-compat.svg)](https://travis-ci.org/haskell-compat/base-compat) [Hackage: base-compat]: http://hackage.haskell.org/package/base-compat "base-compat package on Hackage" [Haskell.org]: http://www.haskell.org "The Haskell Programming Language" [tl;dr Legal: MIT]: https://tldrlegal.com/license/mit-license "MIT License" ## Scope 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`](https://github.com/haskell-compat/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](#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-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 `.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-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`. ## 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-4.9.0.0` * `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`, `isRight`, `fromLeft`, and `fromRight` 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 more efficient `maximumBy`/`minimumBy` to `Data.Foldable.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` * `asProxyTypeOf` with a generalized type signature to `Data.Proxy.Compat` * `modifySTRef'` to `Data.STRef.Compat` * `String`, `lines`, `words`, `unlines`, and `unwords` to `Data.String.Compat` * `gcoerceWith` to `Data.Type.Coercion.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` * `plusForeignPtr` to `Foreign.ForeignPtr.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-4.7.0.0`](http://hackage.haskell.org/package/base-4.7.0.0/docs/Data-Bits.html#t:FiniteBits) with the following API: ```haskell class Bits b => FiniteBits b where finiteBitSize :: b -> Int ``` However, in [`base-4.8.0.0`](http://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Bits.html#t:FiniteBits), `FiniteBits` gained additional functions: ```haskell 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-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: ```haskell instance FiniteBits Foo where finiteBitSize = ... #if MIN_VERSION_base(4,8,0) || !(MIN_VERSION_base(4,7,0)) countLeadingZeros = ... countTrailingZeros = ... #endif ``` 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: * [`bifunctors`](http://hackage.haskell.org/package/bifunctors) for: * The [`Bifunctor`](http://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Bifunctor.html#t:Bifunctor) type class, introduced in `base-4.8.0.0` * The [`Bifoldable`](http://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Bifoldable.html#t:Bifoldable) and [`Bitraversable`](http://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Bitraversable.html#t:Bitraversable) type classes, introduced in `base-4.10.0.0` * [`fail`](http://hackage.haskell.org/package/fail) for the [`MonadFail`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Control-Monad-Fail.html#t:MonadFail) type class, introduced in `base-4.9.0.0` * [`generic-deriving`](http://hackage.haskell.org/package/generic-deriving) for everything in the [`GHC.Generics`](http://hackage.haskell.org/package/base-4.8.0.0/docs/GHC-Generics.html) module, introduced to `ghc-prim` in GHC 7.2 (and later moved to `base-4.6.0.0`) * [`nats`](http://hackage.haskell.org/package/nats) for the [`Natural`](http://hackage.haskell.org/package/base-4.8.0.0/docs/Numeric-Natural.html) data type, introduced in `base-4.8.0.0` * [`semigroups`](http://hackage.haskell.org/package/semigroups) for the [`Semigroup`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Semigroup) typeclass and the [`NonEmpty`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-List-NonEmpty.html#t:NonEmpty), [`Min`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Min), [`Max`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Max), [`First`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:First), [`Last`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Last), [`WrappedMonoid`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:WrappedMonoid), [`Option`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Option), and [`Arg`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Arg) data types, introduced in `base-4.9.0.0` * [`tagged`](http://hackage.haskell.org/package/tagged) for the [`Proxy`](http://hackage.haskell.org/package/base-4.7.0.0/docs/Data-Proxy.html#t:Proxy) data type, introduced in `base-4.7.0.0` * [`transformers`](http://hackage.haskell.org/package/transformers) for: * The [`Identity`](http://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Functor-Identity.html#t:Identity) data type, introduced in `base-4.8.0.0` * The [`MonadIO`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Control-Monad-IO-Class.html#t:MonadIO), [`Eq1`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Eq1), [`Eq2`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Eq2), [`Ord1`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Ord1), [`Ord2`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Ord2), [`Read1`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Read1), [`Read2`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Read2), [`Show1`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Show1), and [`Show2`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html#t:Show2) typeclasses; and the [`Compose`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Compose.html#t:Compose), [`Product`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Product.html#t:Product), and [`Sum`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Sum.html#t:Sum) data types, introduced in `base-4.9.0.0` * [`void`](http://hackage.haskell.org/package/void) for the [`Void`](http://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Void.html#t:Void) data type, introduced in `base-4.8.0.0` ## Supported versions of GHC/`base` * `ghc-8.2.1` / `base-4.10.0.0` * `ghc-8.0.2` / `base-4.9.1.0` * `ghc-8.0.1` / `base-4.9.0.0` * `ghc-7.10.3` / `base-4.8.2.0` * `ghc-7.10.2` / `base-4.8.1.0` * `ghc-7.10.1` / `base-4.8.0.0` * `ghc-7.8.4` / `base-4.7.0.2` * `ghc-7.8.3` / `base-4.7.0.1` * `ghc-7.8.2` / `base-4.7.0.0` * `ghc-7.8.1` / `base-4.7.0.0` * `ghc-7.6.3` / `base-4.6.0.1` * `ghc-7.6.2` / `base-4.6.0.1` * `ghc-7.6.1` / `base-4.6.0.0` * `ghc-7.4.2` / `base-4.5.1.0` * `ghc-7.4.1` / `base-4.5.0.0` * `ghc-7.2.2` / `base-4.4.1.0` * `ghc-7.2.1` / `base-4.4.0.0` * `ghc-7.0.4` / `base-4.3.1.0` * `ghc-7.0.3` / `base-4.3.1.0` * `ghc-7.0.2` / `base-4.3.1.0` * `ghc-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!