{-# OPTIONS -cpp #-}
-- Parallelität in fkt. Sprachen
-- Auswertungsstrategien, Version (auch) fuer gransim:
--   #> gransim -gransim -c Strategies.hs -cpp
-- Jost Berthold

module Strategies where

import Complex
import Parallel

-------------------------------------------
-- grundlegende Definitionen: -------------

type Strategy a = a -> ()       -- Strategietyp

-- infixl 0 `using`,`demanding`,`sparking`              -- weakest precedence!

using :: a -> Strategy a -> a   -- zur Benutzung der Strategien
x `using` s = (s x) `seq` x

demanding, sparking :: a -> () -> a
demanding = flip seq
sparking  = flip par

r0 ::Strategy a                 -- keine Auswertung
r0 x = ()


#if defined(__HASKELL98__)
rwhnf :: Strategy a 
rwhnf x = x `seq` ()  
#else 
rwhnf :: Eval a => Strategy a 
rwhnf x = x `seq` ()  
#endif


#if defined(__HASKELL98__)
class NFData a where
#else
class Eval a => NFData a where
#endif
        rnf :: Strategy a       -- Ausw. in Normalform
        rnf = rwhnf             -- nur für Basistypen, dort wie Kopfnormalform

instance NFData Double
instance NFData Char
instance NFData Int

instance (RealFloat a, NFData a) => NFData (Complex a) 
    where rnf ( x :+ y) = rnf x `seq` rnf y

instance NFData a => NFData [a]
    where rnf [] = ()
          rnf (x:xs) = rnf x `seq` rnf xs

instance (NFData a, NFData b) => NFData (a,b) 
    where rnf (a,b) = rnf a `seq` rnf b

---------------------------------------------
-- grundlegende Strategien für Listen

seqList :: Strategy a -> Strategy [a] 
seqList s []     = ()
seqList s (x:xs) = (s x) `seq` seqList s xs

parList :: Strategy a -> Strategy [a] 
parList s []     = ()
parList s (x:xs) = (s x) `par` parList s xs

