Skip to content

Commit

Permalink
Functions/modules added in base-4.9
Browse files Browse the repository at this point in the history
See the `CHANGES` file (or the `base-4.9.0.0` section of #24) for all of the changes made.
  • Loading branch information
RyanGlScott committed Jan 14, 2016
1 parent d450a33 commit 08c93f3
Show file tree
Hide file tree
Showing 22 changed files with 241 additions and 51 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ matrix:
- env: CABALVER=1.22 GHCVER=7.10.3
compiler: ": #GHC 7.10.3"
addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3], sources: [hvr-ghc]}}
- env: CABALVER=1.24 GHCVER=8.0.1
compiler: ": #GHC 8.0.1"
addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1], sources: [hvr-ghc]}}
- env: CABALVER=head GHCVER=head
compiler: ": #GHC head"
addons: {apt: {packages: [cabal-install-head,ghc-head], sources: [hvr-ghc]}}
Expand Down
13 changes: 11 additions & 2 deletions CHANGES.markdown
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
## Changes in next
- Sync with `base-4.9`/GHC 8.0
- Weakened `RealFloat` constraints on `realPart`, `imagPart`, `conjugate`,
`mkPolar`, and `cis` in `Data.Complex.Compat`
- Backport `Foreign.ForeignPtr.Safe` and `Foreign.Marshal.Safe`
- Generalize `filterM`, `forever`, `mapAndUnzipM`, `zipWithM`, `zipWithM_`,
`replicateM`, and `replicateM_` in `Control.Monad` from `Monad` to
`Applicative`
- Backport `.Unsafe.Compat` modules (for `Control.Monad.ST`,
`Control.Monad.ST.Lazy`, `Foreign.ForeignPtr`, and `Foreign.Marshal`)
- Backport `forkFinally` to `Control.Concurrent.Compat`
- Backport `forkFinally` and `forkOSWithUnmask` to `Control.Concurrent.Compat`
- Backport `Data.Functor.Const`
- Backport `modifyIORef'`, `atomicModifyIORef'` and `atomicWriteIORef` to
`Data.IORef.Compat`
- `Data.Ratio.{denominator,numerator}` have no `Integral` constraint anymore
- Backport `modifySTRef'` to `Data.STRef.Compat`
- Export `String`, `lines`, `words`, `unlines`, and `unwords` to
`Data.String.Compat`
- Backport `unsafeFixIO` and `unsafeDupablePerformIO` to `System.IO.Unsafe.IO`
- Generalize `Debug.Trace.{traceM, traceShowM}` from `Monad` to `Applicative`
- Backport `errorWithoutStackTrace` to `Prelude.Compat`
- Backport `unsafeFixIO` and `unsafeDupablePerformIO` to
`System.IO.Unsafe.Compat`

## Changes in 0.8.2
- Backport `bitDefault`, `testBitDefault`, and `popCountDefault` in
Expand Down
39 changes: 35 additions & 4 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
[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
Expand Down Expand Up @@ -105,7 +105,7 @@ 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.8.0.0`
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`
Expand Down Expand Up @@ -200,18 +200,49 @@ compatibility packages on Hackage. Here is a list of such packages:
* [`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`
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.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`
Expand Down
2 changes: 2 additions & 0 deletions base-compat.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,11 @@ library
Data.Foldable.Compat
Data.Function.Compat
Data.Functor.Compat
Data.Functor.Const.Compat
Data.IORef.Compat
Data.List.Compat
Data.Monoid.Compat
Data.Ratio.Compat
Data.STRef.Compat
Data.String.Compat
Data.Version.Compat
Expand Down
8 changes: 0 additions & 8 deletions check/Data.Complex.Compat.index

This file was deleted.

8 changes: 0 additions & 8 deletions check/Data.Complex.Compat.types

This file was deleted.

1 change: 1 addition & 0 deletions check/TypeCheck.hs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ modules = do
excluded = [
#if !(MIN_VERSION_base(4,4,0))
"Data.Complex.Compat"
, "Data.Ratio.Compat"
#endif
]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{-# LANGUAGE NoImplicitPrelude #-}
module Test where
import Data.Complex.Compat
import Data.Ratio.Compat
1 change: 1 addition & 0 deletions check/index/Control.Monad.Compat.index
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ foldM_
forever
forM
forM_
(GHC.Base.<$)
guard
join
liftM
Expand Down
4 changes: 4 additions & 0 deletions check/index/Data.Ratio.Compat.index
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(%)
approxRational
denominator
numerator
1 change: 1 addition & 0 deletions check/index/Prelude.Compat.index
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ enumFromThenTo
enumFromTo
EQ
error
errorWithoutStackTrace
even
exp
exponent
Expand Down
1 change: 1 addition & 0 deletions check/mk-index.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ runhaskell dumpindex.hs Control.Monad.Compat | sort > index/Control.Monad.Compat
runhaskell dumpindex.hs Data.Complex.Compat | sort > index/Data.Complex.Compat.index
runhaskell dumpindex.hs Data.Foldable.Compat | sort > index/Data.Foldable.Compat.index
runhaskell dumpindex.hs Data.List.Compat | sort > index/Data.List.Compat.index
runhaskell dumpindex.hs Data.Ratio.Compat | sort > index/Data.Ratio.Compat.index
2 changes: 1 addition & 1 deletion check/type-check.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ test-suite type-check-test
, hspec >= 1.8
, HUnit >= 1.2.5
, process >= 1.0.1.1
, temporary-rc
, temporary
23 changes: 12 additions & 11 deletions check/types/Control.Monad.Compat.types
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,35 @@
(>>) :: Monad m => m a -> m b -> m b
ap :: Monad m => m (a -> b) -> m a -> m b
fail :: Monad m => GHC.Base.String -> m a
filterM :: Monad m => (a -> m GHC.Types.Bool) -> [a] -> m [a]
filterM :: GHC.Base.Applicative m => (a -> m GHC.Types.Bool) -> [a] -> m [a]
fmap :: Functor f => (a -> b) -> f a -> f b
foldM :: (Monad m, Data.Foldable.Foldable t) => (b -> a -> m b) -> b -> t a -> m b
foldM_ :: (Monad m, Data.Foldable.Foldable t) => (b -> a -> m b) -> b -> t a -> m ()
forever :: Monad m => m a -> m b
forever :: GHC.Base.Applicative f => f a -> f b
forM :: (Monad m, Data.Traversable.Traversable t) => t a -> (a -> m b) -> m (t b)
forM_ :: (Monad m, Data.Foldable.Foldable t) => t a -> (a -> m b) -> m ()
guard :: Control.Applicative.Alternative f => GHC.Types.Bool -> f ()
(GHC.Base.<$) :: Functor f => a -> f b -> f a
guard :: GHC.Base.Alternative f => GHC.Types.Bool -> f ()
join :: Monad m => m (m a) -> m a
liftM :: Monad m => (a1 -> r) -> m a1 -> m r
liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM3 :: Monad m => (a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
liftM4 :: Monad m => (a1 -> a2 -> a3 -> a4 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m r
liftM5 :: Monad m => (a1 -> a2 -> a3 -> a4 -> a5 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m a5 -> m r
mapAndUnzipM :: Monad m => (a -> m (b, c)) -> [a] -> m ([b], [c])
mapAndUnzipM :: GHC.Base.Applicative m => (a -> m (b, c)) -> [a] -> m ([b], [c])
mapM :: (Monad m, Data.Traversable.Traversable t) => (a -> m b) -> t a -> m (t b)
mapM_ :: (Monad m, Data.Foldable.Foldable t) => (a -> m b) -> t a -> m ()
mfilter :: MonadPlus m => (a -> GHC.Types.Bool) -> m a -> m a
mplus :: MonadPlus m => m a -> m a -> m a
msum :: (MonadPlus m, Data.Foldable.Foldable t) => t (m a) -> m a
msum :: (Data.Foldable.Foldable t, MonadPlus m) => t (m a) -> m a
mzero :: MonadPlus m => m a
replicateM :: Monad m => GHC.Types.Int -> m a -> m [a]
replicateM_ :: Monad m => GHC.Types.Int -> m a -> m ()
replicateM :: GHC.Base.Applicative m => GHC.Types.Int -> m a -> m [a]
replicateM_ :: GHC.Base.Applicative m => GHC.Types.Int -> m a -> m ()
return :: Monad m => a -> m a
sequence :: (Monad m, Data.Traversable.Traversable t) => t (m a) -> m (t a)
sequence_ :: (Monad m, Data.Foldable.Foldable t) => t (m a) -> m ()
unless :: Control.Applicative.Applicative f => GHC.Types.Bool -> f () -> f ()
unless :: GHC.Base.Applicative f => GHC.Types.Bool -> f () -> f ()
void :: Functor f => f a -> f ()
when :: Control.Applicative.Applicative f => GHC.Types.Bool -> f () -> f ()
zipWithM :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM_ :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m ()
when :: GHC.Base.Applicative f => GHC.Types.Bool -> f () -> f ()
zipWithM :: GHC.Base.Applicative m => (a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM_ :: GHC.Base.Applicative m => (a -> b -> m c) -> [a] -> [b] -> m ()
4 changes: 4 additions & 0 deletions check/types/Data.Ratio.Compat.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(%) :: GHC.Real.Integral a => a -> a -> Ratio a
approxRational :: GHC.Real.RealFrac a => a -> a -> Rational
denominator :: Ratio a -> a
numerator :: Ratio a -> a
1 change: 1 addition & 0 deletions check/types/Prelude.Compat.types
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ enumFromThenTo :: Enum a => a -> a -> a -> [a]
enumFromTo :: Enum a => a -> a -> [a]
EQ :: Ordering
error :: [Char] -> a
errorWithoutStackTrace :: [Char] -> a
even :: Integral a => a -> Bool
exp :: Floating a => a -> a
exponent :: RealFloat a => a -> Int
Expand Down
15 changes: 15 additions & 0 deletions src/Control/Concurrent/Compat.hs
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
{-# LANGUAGE CPP, NoImplicitPrelude #-}
{-# LANGUAGE RankNTypes #-}
module Control.Concurrent.Compat (
module Base
, forkFinally
, forkOSWithUnmask
) where

import Control.Concurrent as Base

#if !(MIN_VERSION_base(4,6,0))
import Control.Exception
#endif

#if !(MIN_VERSION_base(4,9,0))
import GHC.IO (unsafeUnmask)
import Prelude
#endif

#if !(MIN_VERSION_base(4,6,0))
-- | fork a thread and call the supplied function when the thread is about
-- to terminate, with an exception or a returned value. The function is
-- called with asynchronous exceptions masked.
Expand All @@ -27,3 +35,10 @@ forkFinally action and_then =
mask $ \restore ->
forkIO $ try (restore action) >>= and_then
#endif

#if !(MIN_VERSION_base(4,9,0))
-- | Like 'forkIOWithUnmask', but the child thread is a bound thread,
-- as with 'forkOS'.
forkOSWithUnmask :: ((forall a . IO a -> IO a) -> IO ()) -> IO ThreadId
forkOSWithUnmask io = forkOS (io unsafeUnmask)
#endif
72 changes: 69 additions & 3 deletions src/Control/Monad/Compat.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,30 @@ module Control.Monad.Compat (

, (<$!>)
#endif
#if !(MIN_VERSION_base(4,9,0))
, forever
, filterM
, mapAndUnzipM
, zipWithM
, zipWithM_
, replicateM
, replicateM_
#endif
) where

#if MIN_VERSION_base(4,8,0)
#if MIN_VERSION_base(4,9,0)
import Control.Monad as Base
#else
import Control.Monad as Base hiding (
foldM
forever
, filterM
, mapAndUnzipM
, zipWithM
, zipWithM_
, replicateM
, replicateM_
# if !(MIN_VERSION_base(4,8,0))
, foldM
, foldM_
, forM
, forM_
Expand All @@ -37,8 +54,9 @@ import Control.Monad as Base hiding (
, sequence_
, unless
, when
# endif
)
import Control.Applicative (Alternative(..))
import Control.Applicative
import Data.Foldable.Compat
import Data.Traversable
import Prelude.Compat
Expand Down Expand Up @@ -116,3 +134,51 @@ f <$!> m = do
let z = f x
z `seq` return z
#endif

#if !(MIN_VERSION_base(4,9,0))
-- | @'forever' act@ repeats the action infinitely.
forever :: (Applicative f) => f a -> f b
{-# INLINE forever #-}
forever a = let a' = a *> a' in a'
-- Use explicit sharing here, as it is prevents a space leak regardless of
-- optimizations.

-- | This generalizes the list-based 'filter' function.
{-# INLINE filterM #-}
filterM :: (Applicative m) => (a -> m Bool) -> [a] -> m [a]
filterM p = foldr (\ x -> liftA2 (\ flg -> if flg then (x:) else id) (p x)) (pure [])

-- | The 'mapAndUnzipM' function maps its first argument over a list, returning
-- the result as a pair of lists. This function is mainly used with complicated
-- data structures or a state-transforming monad.
mapAndUnzipM :: (Applicative m) => (a -> m (b,c)) -> [a] -> m ([b], [c])
{-# INLINE mapAndUnzipM #-}
mapAndUnzipM f xs = unzip <$> traverse f xs

-- | The 'zipWithM' function generalizes 'zipWith' to arbitrary applicative functors.
zipWithM :: (Applicative m) => (a -> b -> m c) -> [a] -> [b] -> m [c]
{-# INLINE zipWithM #-}
zipWithM f xs ys = sequenceA (zipWith f xs ys)

-- | 'zipWithM_' is the extension of 'zipWithM' which ignores the final result.
zipWithM_ :: (Applicative m) => (a -> b -> m c) -> [a] -> [b] -> m ()
{-# INLINE zipWithM_ #-}
zipWithM_ f xs ys = sequenceA_ (zipWith f xs ys)

-- | @'replicateM' n act@ performs the action @n@ times,
-- gathering the results.
replicateM :: (Applicative m) => Int -> m a -> m [a]
{-# INLINEABLE replicateM #-}
{-# SPECIALISE replicateM :: Int -> IO a -> IO [a] #-}
{-# SPECIALISE replicateM :: Int -> Maybe a -> Maybe [a] #-}
replicateM 0 _ = pure []
replicateM n x = liftA2 (:) x (replicateM (pred n) x)

-- | Like 'replicateM', but discards the result.
replicateM_ :: (Applicative m) => Int -> m a -> m ()
{-# INLINEABLE replicateM_ #-}
{-# SPECIALISE replicateM_ :: Int -> IO a -> IO () #-}
{-# SPECIALISE replicateM_ :: Int -> Maybe a -> Maybe () #-}
replicateM_ 0 _ = pure ()
replicateM_ n x = x *> replicateM_ (pred n) x
#endif
4 changes: 4 additions & 0 deletions src/Data/Functor/Const/Compat.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{-# LANGUAGE CPP, NoImplicitPrelude #-}
module Data.Functor.Const.Compat (Const(..)) where

import Control.Applicative (Const(..))
Loading

0 comments on commit 08c93f3

Please sign in to comment.