• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

src/H03-May-2022-3,2391,949

CHANGES.markdownH A D09-Sep-20019.8 KiB238198

LICENSEH A D09-Sep-20011.1 KiB2016

README.markdownH A D09-Sep-200114.4 KiB328272

Setup.lhsH A D09-Sep-200176 42

base-compat.cabalH A D09-Sep-20017.1 KiB202196

README.markdown

1# A compatibility layer for `base`
2[![Hackage](https://img.shields.io/hackage/v/base-compat.svg)][Hackage: base-compat]
3[![Hackage Dependencies](https://img.shields.io/hackage-deps/v/base-compat.svg)](http://packdeps.haskellers.com/reverse/base-compat)
4[![Haskell Programming Language](https://img.shields.io/badge/language-Haskell-blue.svg)][Haskell.org]
5[![BSD3 License](http://img.shields.io/badge/license-MIT-brightgreen.svg)][tl;dr Legal: MIT]
6
7[Hackage: base-compat]:
8  http://hackage.haskell.org/package/base-compat
9  "base-compat package on Hackage"
10[Haskell.org]:
11  http://www.haskell.org
12  "The Haskell Programming Language"
13[tl;dr Legal: MIT]:
14  https://tldrlegal.com/license/mit-license
15  "MIT License"
16
17## Scope
18
19The scope of `base-compat` is to provide functions available in later versions
20of base to a wider (older) range of compilers.
21
22In addition, successful library proposals that have been accepted to be part of
23upcoming versions of `base` are also included.  This package is not intended to
24replace `base`, but to complement it.
25
26Note that `base-compat` does not add any orphan instances.  There is a separate
27package [`base-orphans`](https://github.com/haskell-compat/base-orphans) for
28that.
29
30In addition, `base-compat` only backports functions. In particular, we
31purposefully do not backport data types or type classes introduced in newer
32versions of `base`. For more info, see the
33[Data types and type classes](#data-types-and-type-classes)
34section.
35
36`base-compat` is intentionally designed to have zero dependencies. As a
37consequence, there are some modules that can only be backported up to certain
38versions of `base`. If an even wider support window is desired in these
39scenarios, there also exists a `base-compat-batteries` package which augments
40`base-compat` with certain compatibility package dependencies. For more info,
41see the [Dependencies](#dependencies) section.
42
43## Basic usage
44
45In your cabal file, you should have something like this:
46
47```
48  build-depends:      base              >= 4.3
49                    , base-compat       >= 0.9.0
50```
51
52Then, lets say you want to use the `isRight` function introduced with
53`base-4.7.0.0`.  Replace:
54
55```
56import Data.Either
57```
58
59with
60
61```
62import Data.Either.Compat
63```
64
65_Note (1)_: There is no need to import both unqualified.  The `.Compat` modules
66re-exports the original module.
67
68_Note (2)_: If a given module `.Compat` version is not defined, that either
69means that:
70
71* The module has not changed in recent base versions, thus no `.Compat` is
72  needed.
73* The module has changed, but the changes depend on newer versions of GHC, and
74  thus are not portable.
75* The module has changed, but those changes have not yet been merged in
76  `base-compat`: patches are welcomed!
77
78## Using `Prelude.Compat`
79
80If you want to use `Prelude.Compat` (which provides all the
81AMP/Traversable/Foldable changes from `base-4.8.0.0`), it's best to hide
82`Prelude`, e.g.:
83
84    import Prelude ()
85    import Prelude.Compat
86
87    main :: IO ()
88    main = mapM_ print (Just 23)
89
90Alternatively, you can use the `NoImplicitPrelude` language extension:
91
92    {-# LANGUAGE NoImplicitPrelude #-}
93    import Prelude.Compat
94
95    main :: IO ()
96    main = mapM_ print (Just 23)
97
98Note that we use
99
100    mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
101
102from `Data.Foldable` here, which is only exposed from `Prelude` since
103`base-4.8.0.0`.
104
105Using this approach allows you to write code that works seamlessly with all
106versions of GHC that are supported by `base-compat`.
107
108## What is covered
109So far the following is covered.
110
111### For compatibility with the latest released version of `base`
112
113 * `Prelude.Compat` incorporates the AMP/Foldable/Traversable changes and
114   exposes the same interface as `Prelude` from `base-4.9.0.0`
115 * `System.IO.Error.catch` is not re-exported from `Prelude.Compat` for older
116   versions of `base`
117 * `Text.Read.Compat.readMaybe`
118 * `Text.Read.Compat.readEither`
119 * `Data.Monoid.Compat.<>`
120 * Added `bitDefault`, `testBitDefault`, and `popCountDefault` to `Data.Bits.Compat`
121 * Added `toIntegralSized` to `Data.Bits.Compat` (if using `base-4.7`)
122 * Added `bool` function to `Data.Bool.Compat`
123 * Added `isLeft`, `isRight`, `fromLeft`, and `fromRight` to `Data.Either.Compat`
124 * Added `forkFinally` to `Control.Concurrent.Compat`
125 * Added `withMVarMasked` function to `Control.Concurrent.MVar.Compat`
126 * Added `(<$!>)` function to `Control.Monad.Compat`
127 * Weakened `RealFloat` constraints on `realPart`, `imagPart`, `conjugate`, `mkPolar`,
128   and `cis` in `Data.Complex.Compat`
129 * Added more efficient `maximumBy`/`minimumBy` to `Data.Foldable.Compat`
130 * Added `($>)` and `void` functions to `Data.Functor.Compat`
131 * `(&)` function to `Data.Function.Compat`
132 * `($>)` and `void` functions to `Data.Functor.Compat`
133 * `modifyIORef'`, `atomicModifyIORef'` and `atomicWriteIORef` to `Data.IORef.Compat`
134 * `dropWhileEnd`, `isSubsequenceOf`, `sortOn`, and `uncons` functions to `Data.List.Compat`
135 * Correct versions of `nub`, `nubBy`, `union`, and `unionBy` to `Data.List.Compat`
136 * `asProxyTypeOf` with a generalized type signature to `Data.Proxy.Compat`
137 * `modifySTRef'` to `Data.STRef.Compat`
138 * `String`, `lines`, `words`, `unlines`, and `unwords` to `Data.String.Compat`
139 * `gcoerceWith` to `Data.Type.Coercion.Compat`
140 * `makeVersion` function to `Data.Version.Compat`
141 * `traceId`, `traceShowId`, `traceM`, and `traceShowM` functions to `Debug.Trace.Compat`
142 * `byteSwap16`, `byteSwap32`, and `byteSwap64` to `Data.Word.Compat`
143 * `plusForeignPtr` to `Foreign.ForeignPtr.Compat`
144 * `calloc` and `callocBytes` functions to `Foreign.Marshal.Alloc.Compat`
145 * `callocArray` and `callocArray0` functions to `Foreign.Marshal.Array.Compat`
146 * `fillBytes` to `Foreign.Marshal.Utils.Compat`
147 * Added `Data.List.Compat.scanl'`
148 * `showFFloatAlt` and `showGFloatAlt` to `Numeric.Compat`
149 * `lookupEnv`, `setEnv` and `unsetEnv` to `System.Environment.Compat`
150 * `unsafeFixIO` and `unsafeDupablePerformIO` to `System.IO.Unsafe.IO`
151 * `RuntimeRep`-polymorphic `($!)` to `Prelude.Compat`
152 * `RuntimeRep`-polymorphic `throw` to `Control.Exception.Compat`
153 * `isResourceVanishedError`, `resourceVanishedErrorType`, and
154   `isResourceVanishedErrorType` to `System.IO.Error.Compat`
155 * `singleton` to `Data.List.Compat` and `Data.List.NonEmpty.Compat`
156 * `hGetContents'`, `getContents'`, and `readFile'` to `System.IO`
157
158## What is not covered
159
160### Data types and type classes
161`base-compat` purposefully does not export any data types or type classes that
162were introduced in more recent versions of `base`. The main reasoning for this
163policy is that it is not some data types and type classes have had their APIs
164change in different versions of `base`, which makes having a consistent
165compatibility API for them practically impossible.
166
167As an example, consider the `FiniteBits` type class. It was introduced in
168[`base-4.7.0.0`](http://hackage.haskell.org/package/base-4.7.0.0/docs/Data-Bits.html#t:FiniteBits)
169with the following API:
170
171```haskell
172class Bits b => FiniteBits b where
173    finiteBitSize :: b -> Int
174```
175
176However, in [`base-4.8.0.0`](http://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Bits.html#t:FiniteBits),
177`FiniteBits` gained additional functions:
178
179```haskell
180class Bits b => FiniteBits b where
181    finiteBitSize :: b -> Int
182    countLeadingZeros :: b -> Int   -- ^ @since 4.8.0.0
183    countTrailingZeros :: b -> Int  -- ^ @since 4.8.0.0
184```
185
186This raises the question: how can `FiniteBits` be backported consistently
187across all versions of `base`? One approach is to backport the API exposed in
188`base-4.8.0.0` on versions prior to `4.7.0.0`.  The problem with this is that
189`countLeadingZeros` and `countTrailingZeros` are not exposed in `base-4.7.0.0`,
190so instances of `FiniteBits` would have to be declared like this:
191
192```haskell
193instance FiniteBits Foo where
194    finiteBitSize = ...
195#if MIN_VERSION_base(4,8,0) || !(MIN_VERSION_base(4,7,0))
196    countLeadingZeros = ...
197    countTrailingZeros = ...
198#endif
199```
200
201Another approach is to backport the API from `base-4.7.0.0` and to declare
202additional methods outside of the class:
203
204```haskell
205#if MIN_VERSION_base(4,7,0) && !(MIN_VERSION_base(4,8,0))
206countLeadingZeros :: FiniteBits b => b -> Int
207countLeadingZeros = {- default implementation #-}
208#endif
209```
210
211The situation is only slightly better for classes which exist across all versions of `base`,
212but have grown their API. For example, it's tempting to define
213
214```haskell
215#if !(MIN_VERSION_base(4,8,0))
216displayException :: Exception e => e -> String
217displayException = show
218#endif
219```
220
221As with the previous approach, you won't be able to define new members of the type
222class without CPP guards. In other words, the non-CPP approach would limit
223uses to the lowest common denominator.
224
225As neither approach is a very satisfactory solution, and to embrace
226consistency, we do not pursue either approach. For similar reasons, we do not
227backport data types.
228
229### Dependencies
230
231`base-compat` is designed to have zero dependencies (besides libraries that
232ship with GHC itself). A consequence of this choice is that there are certain
233modules that have a "limited" support window. An important example of this is
234`Prelude.Compat`, which backports the `Semigroup` class to versions of `base`
235older than 4.11 (when it was added to the `Prelude`). Because `Semigroup` was
236not added to `base` until `base-4.9`, `base-compat` cannot backport it to
237any earlier version of `base` than this.
238
239If you would instead desire to be able to use a version of `Prelude.Compat`
240that _does_ backport `Semigroup` to even older versions of `base`, even if it
241means pulling in other dependencies, then you are in luck. There also exists
242a `base-compat-batteries` package, which exposes a strict superset of the API
243in `base-compat`. `base-compat-batteries` has all the same modules as
244`base-compat`, but exposes more functionality on more versions of `base` by
245reexporting things from compatibility libraries whenever necessary. (For
246instance, `base-compat-batteries` exports the `Semigroup` class from the
247`semigroups` library when built against versions of `base` older than 4.9.)
248
249Because `base-compat` and `base-compat-batteries` have the same module names,
250they are quite easy to switch out for one another in library projects, at the
251expense of having clashing names if one tries to import them in GHCi. To
252work around this issue, `base-compat` and `base-compat-batteries` also provide
253copies of each module with the suffix `.Repl` (for `base-compat`) and
254`.Repl.Batteries` (for `base-compat-batteries`) to give them globally unique
255namespaces in the event one wants to import them into GHCi.
256
257Here is a list of compatibility libraries that `base-compat-batteries` depends
258on, paired with the things that each library backports:
259
260* [`bifunctors`](http://hackage.haskell.org/package/bifunctors)
261  for:
262  * The [`Bifunctor`](http://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Bifunctor.html#t:Bifunctor)
263    type class, introduced in `base-4.8.0.0`
264  * The [`Bifoldable`](http://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Bifoldable.html#t:Bifoldable)
265    and [`Bitraversable`](http://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Bitraversable.html#t:Bitraversable)
266    type classes, introduced in `base-4.10.0.0`
267* [`contravariant`](http://hackage.haskell.org/package/contravariant)
268  for the [`Contravariant`](http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Contravariant.html#t:Contravariant)
269  type class, introduced in `base-4.12.0.0`.
270* [`fail`](http://hackage.haskell.org/package/fail)
271  for the [`MonadFail`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Control-Monad-Fail.html#t:MonadFail)
272  type class, introduced in `base-4.9.0.0`
273* [`nats`](http://hackage.haskell.org/package/nats)
274  for the [`Natural`](http://hackage.haskell.org/package/base-4.8.0.0/docs/Numeric-Natural.html)
275  data type, introduced in `base-4.8.0.0`
276* [`semigroups`](http://hackage.haskell.org/package/semigroups)
277  for the [`Semigroup`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Semigroup)
278  typeclass and the
279  [`NonEmpty`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-List-NonEmpty.html#t:NonEmpty),
280  [`Min`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Min),
281  [`Max`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Max),
282  [`First`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:First),
283  [`Last`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Last),
284  [`WrappedMonoid`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:WrappedMonoid),
285  [`Option`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Option),
286  and
287  [`Arg`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Semigroup.html#t:Arg)
288  data types, introduced in `base-4.9.0.0`
289* [`tagged`](http://hackage.haskell.org/package/tagged)
290  for the [`Proxy`](http://hackage.haskell.org/package/base-4.7.0.0/docs/Data-Proxy.html#t:Proxy)
291  data type, introduced in `base-4.7.0.0`
292* [`transformers`](http://hackage.haskell.org/package/transformers)
293  for:
294  * The [`Identity`](http://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Functor-Identity.html#t:Identity)
295    data type, introduced in `base-4.8.0.0`
296  * The [`MonadIO`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Control-Monad-IO-Class.html#t:MonadIO)
297    type class; and the
298    [`Compose`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Compose.html#t:Compose),
299    [`Product`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Product.html#t:Product),
300    and
301    [`Sum`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Sum.html#t:Sum)
302    data types, introduced in `base-4.9.0.0`
303* [`void`](http://hackage.haskell.org/package/void)
304  for the [`Void`](http://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Void.html#t:Void)
305  data type, introduced in `base-4.8.0.0`
306
307## Supported versions of GHC/`base`
308
309 * `ghc-9.0.*`  / `base-4.15.*`
310 * `ghc-8.10.*` / `base-4.14.*`
311 * `ghc-8.8.*`  / `base-4.13.*`
312 * `ghc-8.6.*`  / `base-4.12.*`
313 * `ghc-8.4.*`  / `base-4.11.*`
314 * `ghc-8.2.*`  / `base-4.10.*`
315 * `ghc-8.0.*`  / `base-4.9.*`
316 * `ghc-7.10.*` / `base-4.8.*`
317 * `ghc-7.8.*`  / `base-4.7.*`
318 * `ghc-7.6.*`  / `base-4.6.*`
319 * `ghc-7.4.*`  / `base-4.5.*`
320 * `ghc-7.2.*`  / `base-4.4.*`
321 * `ghc-7.0.*`  / `base-4.3.*`
322
323We also make an attempt to keep `base-compat` building with GHC HEAD, but due
324to its volatility, it may not work at any given point in time. If it doesn't,
325please report it!
326
327Patches are welcome; add tests for new code!
328