11{-# LANGUAGE BangPatterns, CPP, MagicHash, UnboxedTuples #-}
2+ {-# LANGUAGE GeneralizedNewtypeDeriving #-}
23-----------------------------------------------------------------------------
34-- |
45-- Module : Control.Parallel.Strategies
@@ -145,11 +146,19 @@ import Control.Applicative
145146#endif
146147import Control.Parallel
147148import Control.DeepSeq (NFData (rnf ))
149+
150+ #if MIN_VERSION_base(4,4,0)
151+ import System.IO.Unsafe (unsafeDupablePerformIO )
152+ import Control.Exception (evaluate )
153+ #else
154+ import System.IO.Unsafe (unsafePerformIO )
148155import Control.Monad
156+ #endif
149157
150158import qualified Control.Seq
151159
152160import GHC.Exts
161+ import GHC.IO (IO (.. ))
153162
154163infixr 9 `dot` -- same as (.)
155164infixl 0 `using` -- lowest precedence and associate to the left
@@ -192,27 +201,19 @@ infixl 0 `using` -- lowest precedence and associate to the left
192201
193202#if __GLASGOW_HASKELL__ >= 702
194203
195- newtype Eval a = Eval (State # RealWorld -> (# State # RealWorld , a # ))
204+ newtype Eval a = Eval { unEval_ :: IO a }
205+ deriving (Functor , Applicative , Monad )
196206 -- GHC 7.2.1 added the seq# and spark# primitives, that we use in
197207 -- the Eval monad implementation in order to get the correct
198208 -- strictness behaviour.
199209
200210-- | Pull the result out of the monad.
201211runEval :: Eval a -> a
202- runEval (Eval x) = case x realWorld# of (# _, a # ) -> a
203-
204- instance Functor Eval where
205- fmap = liftM
206-
207- instance Applicative Eval where
208- pure x = Eval $ \ s -> (# s, x # )
209- (<*>) = ap
210-
211- instance Monad Eval where
212- return = pure
213- Eval x >>= k = Eval $ \ s -> case x s of
214- (# s', a # ) -> case k a of
215- Eval f -> f s'
212+ # if MIN_VERSION_base(4,4,0)
213+ runEval = unsafeDupablePerformIO . unEval_
214+ # else
215+ runEval = unsafePerformIO . unEval_
216+ # endif
216217#else
217218
218219data Eval a = Done a
@@ -234,9 +235,6 @@ instance Monad Eval where
234235
235236{-# RULES "lazy Done" forall x . lazy (Done x) = Done x #-}
236237
237- #endif
238-
239-
240238-- The Eval monad satisfies the monad laws.
241239--
242240-- (1) Left identity:
@@ -259,6 +257,8 @@ instance Monad Eval where
259257-- ==> undefined <== undefined >>= (\x -> f x >>= g)
260258-- <*= m >>= (\x -> f x >>= g)
261259
260+ #endif
261+
262262
263263-- -----------------------------------------------------------------------------
264264-- Strategies
@@ -356,10 +356,13 @@ r0 x = return x
356356--
357357rseq :: Strategy a
358358#if __GLASGOW_HASKELL__ >= 702
359- rseq x = Eval $ \ s -> seq # x s
359+ rseq x = Eval (evaluate x)
360360#else
361361rseq x = x `seq` return x
362362#endif
363+ -- Staged NOINLINE so we can match on rseq in RULES
364+ {-# NOINLINE [1] rseq #-}
365+
363366
364367-- Proof of rseq == evalSeq Control.Seq.rseq
365368--
@@ -388,7 +391,7 @@ rdeepseq x = do rseq (rnf x); return x
388391-- | 'rpar' sparks its argument (for evaluation in parallel).
389392rpar :: Strategy a
390393#if __GLASGOW_HASKELL__ >= 702
391- rpar x = Eval $ \ s -> spark# x s
394+ rpar x = Eval $ IO $ \ s -> spark# x s
392395#else
393396rpar x = case (par# x) of { _ -> Done x }
394397#endif
@@ -406,12 +409,7 @@ rpar x = case (par# x) of { _ -> Done x }
406409--
407410rparWith :: Strategy a -> Strategy a
408411#if __GLASGOW_HASKELL__ >= 702
409- rparWith s a = do l <- rpar r; return (case l of Lift x -> x)
410- where r = case s a of
411- Eval f -> case f realWorld# of
412- (# _, a' # ) -> Lift a'
413-
414- data Lift a = Lift a
412+ rparWith s = rpar `dot` s
415413#else
416414rparWith s a = do l <- rpar (s a); return (case l of Done x -> x)
417415#endif
@@ -502,26 +500,6 @@ chunk :: Int -> [a] -> [[a]]
502500chunk _ [] = []
503501chunk n xs = as : chunk n bs where (as,bs) = splitAt n xs
504502
505- -- Non-compositional version of 'parList', evaluating list elements
506- -- to weak head normal form.
507- -- Not to be exported; used for optimisation.
508-
509- -- | DEPRECATED: use @'parList' 'rseq'@ instead
510- parListWHNF :: Strategy [a ]
511- parListWHNF xs = go xs `pseq` return xs
512- where -- go :: [a] -> [a]
513- go [] = []
514- go (y: ys) = y `par` go ys
515-
516- -- The non-compositional 'parListWHNF' might be more efficient than its
517- -- more compositional counterpart; use RULES to do the specialisation.
518-
519- {-# NOINLINE [1] parList #-}
520- {-# NOINLINE [1] rseq #-}
521- {-# RULES
522- "parList/rseq" parList rseq = parListWHNF
523- #-}
524-
525503-- --------------------------------------------------------------------------
526504-- Convenience
527505
@@ -752,8 +730,6 @@ seqTraverse = evalTraversable
752730parTraverse :: Traversable t => Strategy a -> Strategy (t a )
753731parTraverse = parTraversable
754732
755- {-# DEPRECATED parListWHNF "use (parList rseq) instead" #-}
756-
757733{-# DEPRECATED seqList "renamed to evalList" #-}
758734-- | DEPRECATED: renamed to 'evalList'
759735seqList :: Strategy a -> Strategy [a ]
0 commit comments