base-compat-0.9.3: README.markdown
# A compatibility layer for `base`
[][Hackage: base-compat]
[](http://packdeps.haskellers.com/reverse/base-compat)
[][Haskell.org]
[][tl;dr Legal: MIT]
[](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!