File: README.markdown

package info (click to toggle)
haskell-base-compat 0.13.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 652 kB
  • sloc: haskell: 2,593; makefile: 6
file content (370 lines) | stat: -rw-r--r-- 17,241 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
# 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]

[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.

`base-compat` is intentionally designed to have zero dependencies. As a
consequence, there are some modules that can only be backported up to certain
versions of `base`. If an even wider support window is desired in these
scenarios, there also exists a `base-compat-batteries` package which augments
`base-compat` with certain compatibility package dependencies. For more info,
see the [Dependencies](#dependencies) 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`, `popCountDefault`, `(.^.)`, `(.>>.)`,
   `(.<<.)`, `(!>>.)`, and `(!<<.)` to `Data.Bits.Compat`
 * Added `toIntegralSized` and `oneBits` to `Data.Bits.Compat` (if using `base-4.7` or later)
 * 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`
 * `(&)` and `applyWhen` functions 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`, `traceShowM`, `traceWith`,
   `traceShowWith`, and `traceEventWith` 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`, `showGFloatAlt`, `readBin`, and `showBin` to `Numeric.Compat`
 * `lookupEnv`, `setEnv` and `unsetEnv` to `System.Environment.Compat`
 * `unsafeFixIO` and `unsafeDupablePerformIO` to `System.IO.Unsafe.IO`
 * `RuntimeRep`-polymorphic `($!)` to `Prelude.Compat`
 * `liftA2` is re-exported from `Prelude.Compat`
 * `RuntimeRep`-polymorphic `throw` to `Control.Exception.Compat`
 * `isResourceVanishedError`, `resourceVanishedErrorType`, and
   `isResourceVanishedErrorType` to `System.IO.Error.Compat`
 * `singleton` to `Data.List.Compat` and `Data.List.NonEmpty.Compat`
 * `inits1` and `tails1` to `Data.List.NonEmpty.Compat`
 * `hGetContents'`, `getContents'`, and `readFile'` to `System.IO.Compat`
 * `readBinP` to `Text.Read.Lex.Compat`
 * `withTypeable` and `pattern TypeRep` to `Type.Reflection.Compat`
 * `minusNaturalMaybe` to `Numeric.Natural.Compat`
 * `mapAccumM` and `forAccumM` to `Data.Traversable.Compat`
 * `heqT` to `Data.Typeable.Compat`
 * `unzip` to `Data.Functor.Compat`
 * `(!?)` and `unsnoc` to `Data.List.Compat`
 * `getSolo` to `Data.Tuple.Compat`
 * `decT` and `hdecT` to `Data.Typeable.Compat`
 * `decTypeRep` to `Type.Reflection.Compat`

## 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   -- ^ @since 4.8.0.0
    countTrailingZeros :: b -> Int  -- ^ @since 4.8.0.0
```

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
```

Another approach is to backport the API from `base-4.7.0.0` and to declare
additional methods outside of the class:

```haskell
#if MIN_VERSION_base(4,7,0) && !(MIN_VERSION_base(4,8,0))
countLeadingZeros :: FiniteBits b => b -> Int
countLeadingZeros = {- default implementation #-}
#endif
```

The situation is only slightly better for classes which exist across all versions of `base`,
but have grown their API. For example, it's tempting to define

```haskell
#if !(MIN_VERSION_base(4,8,0))
displayException :: Exception e => e -> String
displayException = show
#endif
```

As with the previous approach, you won't be able to define new members of the type
class without CPP guards. In other words, the non-CPP approach would limit
uses to the lowest common denominator.

As neither approach is a very satisfactory solution, and to embrace
consistency, we do not pursue either approach. For similar reasons, we do not
backport data types.

### Dependencies

`base-compat` is designed to have zero dependencies (besides libraries that
ship with GHC itself). A consequence of this choice is that there are certain
modules that have a "limited" support window. An important example of this is
`Prelude.Compat`, which backports the `Semigroup` class to versions of `base`
older than 4.11 (when it was added to the `Prelude`). Because `Semigroup` was
not added to `base` until `base-4.9`, `base-compat` cannot backport it to
any earlier version of `base` than this.

If you would instead desire to be able to use a version of `Prelude.Compat`
that _does_ backport `Semigroup` to even older versions of `base`, even if it
means pulling in other dependencies, then you are in luck. There also exists
a `base-compat-batteries` package, which exposes a strict superset of the API
in `base-compat`. `base-compat-batteries` has all the same modules as
`base-compat`, but exposes more functionality on more versions of `base` by
reexporting things from compatibility libraries whenever necessary. (For
instance, `base-compat-batteries` exports the `Semigroup` class from the
`semigroups` library when built against versions of `base` older than 4.9.)

Because `base-compat` and `base-compat-batteries` have the same module names,
they are quite easy to switch out for one another in library projects, at the
expense of having clashing names if one tries to import them in GHCi. To
work around this issue, `base-compat` and `base-compat-batteries` also provide
copies of each module with the suffix `.Repl` (for `base-compat`) and
`.Repl.Batteries` (for `base-compat-batteries`) to give them globally unique
namespaces in the event one wants to import them into GHCi.

Here is a list of compatibility libraries that `base-compat-batteries` depends
on, paired with the things that each library backports:

* [`bifunctor-classes-compat`](http://hackage.haskell.org/package/bifunctor-classes-compat)
  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`
* [`contravariant`](http://hackage.haskell.org/package/contravariant)
  for the [`Contravariant`](http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Contravariant.html#t:Contravariant)
  type class, introduced in `base-4.12.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`
* [`foldable1-classes-compat`](https://hackage.haskell.org/package/foldable1-classes-compat)
  for the [`Foldable1`](https://hackage.haskell.org/package/foldable1-classes-compat-0.1/docs/Data-Foldable1.html#t:Foldable1)
  and [`Bifoldable1`](https://hackage.haskell.org/package/foldable1-classes-compat-0.1/docs/Data-Bifoldable1.html#t:Bifoldable1)
  type classes, introduced in `base-4.18.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`
* [`OneTuple`](http://hackage.haskell.org/package/OneTuple)
  for the [`Solo`](https://hackage.haskell.org/package/base-4.16.0.0/docs/Data-Tuple.html#t:Solo)
  data type, introduced in `ghc-prim-0.7.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)
    type class; 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`

## Version policy

This package follows the [Haskell Package Versioning
Policy](https://pvp.haskell.org/). As such, if a new `base-compat` release only
adds new exports, then as a general rule, we will release it with a minor
version bump. Moreover, since `base-compat` does not backport data type or
class definitions (see the "What is not covered" section above), `base-compat`
usually has fewer major version bumps than `base` itself.

An exception to the general rule about adding new exports is the
`Prelude.Compat` module. If a new `base-compat` release adds any new exports,
then it will _always_ be accompanied by a major version bump, even if there are
no other API changes. This is because of the special nature of
`Prelude.Compat`, which is designed to be imported unqualified. Pre-emptively
bumping the major version number is meant to signal to downstream libraries
that they should check to see if the new `Prelude.Compat` additions will clash
with identifiers of the same names in their code.

## Supported versions of GHC/`base`

 * `ghc-9.8.*`  / `base-4.19.*`
 * `ghc-9.6.*`  / `base-4.18.*`
 * `ghc-9.4.*`  / `base-4.17.*`
 * `ghc-9.2.*`  / `base-4.16.*`
 * `ghc-9.0.*`  / `base-4.15.*`
 * `ghc-8.10.*` / `base-4.14.*`
 * `ghc-8.8.*`  / `base-4.13.*`
 * `ghc-8.6.*`  / `base-4.12.*`
 * `ghc-8.4.*`  / `base-4.11.*`
 * `ghc-8.2.*`  / `base-4.10.*`
 * `ghc-8.0.*`  / `base-4.9.*`
 * `ghc-7.10.*` / `base-4.8.*`
 * `ghc-7.8.*`  / `base-4.7.*`
 * `ghc-7.6.*`  / `base-4.6.*`
 * `ghc-7.4.*`  / `base-4.5.*`
 * `ghc-7.2.*`  / `base-4.4.*`
 * `ghc-7.0.*`  / `base-4.3.*`

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!