{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies, CPP #-}
module Control.Monad.Par.Scheds.Sparks
 (
   Par(..), Future(..),
   runPar,
   get, spawn, spawn_, spawnP, fixPar
 )
where
import Control.Applicative
import Control.Monad
import Control.DeepSeq
import Control.Parallel
import qualified Control.Monad.Par.Class as PC
import Control.Monad.Fix (MonadFix (mfix))
#ifdef NEW_GENERIC
import qualified       Control.Par.Class as PN
import qualified       Control.Par.Class.Unsafe as PU
import System.IO.Unsafe (unsafePerformIO)
#endif
{-# INLINE runPar #-}
{-# INLINE spawn #-}
{-# INLINE spawn_ #-}
{-# INLINE spawnP #-}
{-# INLINE get #-}
data Par    a = Done   a
data Future a = Future a
runPar :: Par a -> a
runPar (Done x) = x
spawn_ :: Par a -> Par (Future a)
spawn_ a = let a' = runPar a in a' `par` return (Future a')
spawn :: NFData a => Par a -> Par (Future a)
spawn a = let a' = runPar a in a' `par` return (Future (rnf a' `pseq` a'))
spawnP :: NFData a => a -> Par (Future a)
spawnP a = a `par` return (Future (rnf a `pseq` a))
get :: Future a -> Par a
get (Future a) = a `pseq` return a
instance Monad Par where
  return = pure
  Done x >>= k = k x
instance PC.ParFuture Future Par  where
  get    = get
  spawn  = spawn
  spawn_ = spawn_
  spawnP = spawnP
instance Functor Par where
   fmap f xs = xs >>= return . f
instance Applicative Par where
   (<*>) = ap
   pure  = Done
instance MonadFix Par where
   mfix = fixPar
fixPar :: (a -> Par a) -> Par a
fixPar f =
  let fr = f (case fr of Done x -> x)
  in fr
#ifdef NEW_GENERIC
doio :: IO a -> Par a
doio io = let x = unsafePerformIO io in
          return $! x
instance PU.ParMonad Par where
  
  
  
  
  
  
  
  fork m = m
  internalLiftIO = doio
instance PU.ParThreadSafe Par where
  unsafeParIO = doio
instance PN.ParFuture Par where
  type Future Par = Future
  type FutContents Par a = ()
  get    = get
  spawn  = spawn
  spawn_ = spawn_
  spawnP = spawnP
#endif