diff --git a/Control/Parallel.hs b/Control/Parallel.hs
new file mode 100644
--- /dev/null
+++ b/Control/Parallel.hs
@@ -0,0 +1,104 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Parallel
+-- Copyright   :  (c) The University of Glasgow 2001
+-- License     :  BSD-style (see the file libraries/base/LICENSE)
+-- 
+-- Maintainer  :  libraries@haskell.org
+-- Stability   :  experimental
+-- Portability :  non-portable
+--
+-- Parallel Constructs
+--
+-----------------------------------------------------------------------------
+
+module Control.Parallel (
+          par, pseq,
+	  seq, -- for backwards compatibility, 6.6 exported this
+#if defined(__GRANSIM__)
+	, parGlobal, parLocal, parAt, parAtAbs, parAtRel, parAtForNow     
+#endif
+    ) where
+
+import Prelude
+
+#ifdef __GLASGOW_HASKELL__
+import qualified GHC.Conc	( par, pseq )
+#endif
+
+#if defined(__GRANSIM__)
+import PrelBase
+import PrelErr   ( parError )
+import PrelGHC   ( parGlobal#, parLocal#, parAt#, parAtAbs#, parAtRel#, parAtForNow# )
+
+infixr 0 `par`
+
+{-# INLINE parGlobal #-}
+{-# INLINE parLocal #-}
+{-# INLINE parAt #-}
+{-# INLINE parAtAbs #-}
+{-# INLINE parAtRel #-}
+{-# INLINE parAtForNow #-}
+parGlobal   :: Int -> Int -> Int -> Int -> a -> b -> b
+parLocal    :: Int -> Int -> Int -> Int -> a -> b -> b
+parAt	    :: Int -> Int -> Int -> Int -> a -> b -> c -> c
+parAtAbs    :: Int -> Int -> Int -> Int -> Int -> a -> b -> b
+parAtRel    :: Int -> Int -> Int -> Int -> Int -> a -> b -> b
+parAtForNow :: Int -> Int -> Int -> Int -> a -> b -> c -> c
+
+parGlobal (I# w) (I# g) (I# s) (I# p) x y = case (parGlobal# x w g s p y) of { 0# -> parError; _ -> y }
+parLocal  (I# w) (I# g) (I# s) (I# p) x y = case (parLocal#  x w g s p y) of { 0# -> parError; _ -> y }
+
+parAt       (I# w) (I# g) (I# s) (I# p) v x y = case (parAt#       x v w g s p y) of { 0# -> parError; _ -> y }
+parAtAbs    (I# w) (I# g) (I# s) (I# p) (I# q) x y = case (parAtAbs#  x q w g s p y) of { 0# -> parError; _ -> y }
+parAtRel    (I# w) (I# g) (I# s) (I# p) (I# q) x y = case (parAtRel#  x q w g s p y) of { 0# -> parError; _ -> y }
+parAtForNow (I# w) (I# g) (I# s) (I# p) v x y = case (parAtForNow# x v w g s p y) of { 0# -> parError; _ -> y }
+
+#endif
+
+-- Maybe parIO and the like could be added here later.
+
+-- | Indicates that it may be beneficial to evaluate the first
+-- argument in parallel with the second.  Returns the value of the
+-- second argument.
+-- 
+-- @a `par` b@ is exactly equivalent semantically to @b@.
+--
+-- @par@ is generally used when the value of @a@ is likely to be
+-- required later, but not immediately.  Also it is a good idea to
+-- ensure that @a@ is not a trivial computation, otherwise the cost of
+-- spawning it in parallel overshadows the benefits obtained by
+-- running it in parallel.
+--
+-- Note that actual parallelism is only supported by certain
+-- implementations (GHC with the @-threaded@ option, and GPH, for
+-- now).  On other implementations, @par a b = b@.
+--
+par :: a -> b -> b
+#ifdef __GLASGOW_HASKELL__
+par = GHC.Conc.par
+#else
+-- For now, Hugs does not support par properly.
+par a b = b
+#endif
+
+-- | Semantically identical to 'seq', but with a subtle operational
+-- difference: 'seq' is strict in both its arguments, so the compiler
+-- may, for example, rearrange @a `seq` b@ into @b `seq` a `seq` b@.
+-- This is normally no problem when using 'seq' to express strictness,
+-- but it can be a problem when annotating code for parallelism,
+-- because we need more control over the order of evaluation; we may
+-- want to evaluate @a@ before @b@, because we know that @b@ has
+-- already been sparked in parallel with 'par'.
+--
+-- This is why we have 'pseq'.  In contrast to 'seq', 'pseq' is only
+-- strict in its first argument (as far as the compiler is concerned),
+-- which restricts the transformations that the compiler can do, and
+-- ensures that the user can retain control of the evaluation order.
+--
+pseq :: a -> b -> b
+#ifdef __GLASGOW_HASKELL__
+pseq = GHC.Conc.pseq
+#else
+pseq = seq
+#endif
diff --git a/Control/Parallel/Strategies.hs b/Control/Parallel/Strategies.hs
new file mode 100644
--- /dev/null
+++ b/Control/Parallel/Strategies.hs
@@ -0,0 +1,593 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Parallel.Strategies
+-- Copyright   :  (c) The University of Glasgow 2001
+-- License     :  BSD-style (see the file libraries/base/LICENSE)
+-- 
+-- Maintainer  :  libraries@haskell.org
+-- Stability   :  experimental
+-- Portability :  non-portable
+--
+-- Parallel strategy combinators. See
+-- <http://www.macs.hw.ac.uk/~dsg/gph/papers/html/Strategies/strategies.html>
+-- for more information.
+--
+-- Original authors:
+--	Phil Trinder, Hans-Wolfgang Loidl, Kevin Hammond et al. 
+--
+-----------------------------------------------------------------------------
+module Control.Parallel.Strategies (
+   -- *	Strategy Type, Application and Semantics
+   Done, Strategy,
+   (>|), (>||),
+   using, demanding, sparking,
+   -- *	Basic Strategies				     
+   r0, rwhnf, NFData(..),
+   -- * Strategic Function Application
+   ($|), ($||),
+   (.|), (.||),
+   (-|), (-||),
+   -- * Tuples
+   seqPair, parPair,
+   seqTriple, parTriple,
+   -- * Lists: Parallel Strategies
+   parList, parListN, parListNth, parListChunk, 
+   parMap, parFlatMap, parZipWith,
+   -- * Lists: Sequential Strategies
+   seqList, seqListN, seqListNth, parBuffer,
+   -- *	Arrays
+   seqArr, parArr,
+   -- * Deprecated types and functions
+   sPar, sSeq,
+   Assoc(..),
+   fstPairFstList, force, sforce
+  ) where
+
+-- based on hslibs/concurrent/Strategies.lhs; see it for more detailed
+-- code comments. 
+
+import Control.Parallel as Parallel (par, pseq)
+import Data.Array
+import Data.Complex
+import Data.Int
+import qualified Data.IntMap (IntMap, toList)
+import qualified Data.IntSet (IntSet, toList)
+import qualified Data.Map (Map, toList)
+import qualified Data.Set (Set, toList)
+import qualified Data.Tree (Tree(..))
+import Data.Word
+
+import Prelude hiding (seq)
+import qualified Prelude (seq)
+
+-- not a terribly portable way of getting at Ratio rep.
+#ifdef __GLASGOW_HASKELL__
+import GHC.Real	(Ratio(..))	-- The basic defns for Ratio
+#endif
+
+#ifdef __HUGS__
+import Hugs.Prelude(Ratio(..) )
+#endif
+
+#ifdef __NHC__
+import Ratio (Ratio(..) )
+#endif
+
+infixl 0 `using`,`demanding`,`sparking`              -- weakest precedence!
+
+infixr 2 >||                -- another name for par
+infixr 3 >|                 -- another name for seq
+infixl 6 $||, $|            -- strategic function application (seq and par)
+infixl 9 .|, .||, -|, -||   -- strategic (inverse) function composition
+
+-- We need 'pseq', not the Prelude 'seq' here.  See the documentation
+-- with 'pseq' in Control.Parallel.
+seq = Parallel.pseq
+
+------------------------------------------------------------------------------
+-- *			Strategy Type, Application and Semantics	      
+------------------------------------------------------------------------------
+
+{-
+The basic combinators for strategies are 'par' and 'seq' but with types that 
+indicate that they only combine the results of a strategy application. 
+
+NB: This version can be used with Haskell 1.4 (GHC 2.05 and beyond), *but*
+    you won't get strategy checking on seq (only on par)!
+
+The operators >| and >|| are alternative names for `seq` and `par`.
+With the introduction of a Prelude function `seq` separating the Prelude 
+function from the Strategy function becomes a pain. The notation also matches
+the notation for strategic function application.
+-}
+
+type Done = ()
+
+-- | A strategy takes a value and returns a 'Done' value to indicate that
+--   the specifed evaluation has been performed.
+type Strategy a = a -> Done
+
+
+-- | Evaluates the first argument before the second.
+(>|) :: Done -> Done -> Done 
+{-# INLINE (>|) #-}
+(>|) = Prelude.seq
+
+-- | Evaluates the first argument in parallel with the second.
+(>||) :: Done -> Done -> Done 
+{-# INLINE (>||) #-}
+(>||) = Parallel.par
+
+
+-- | Takes a value and a strategy, and applies the strategy to the
+-- value before returning the value. Used to express data-oriented 
+-- parallelism. @x \`using\` s@ is a projection on @x@, i.e. both:
+--
+-- [a retraction] @x \`using\` s@ &#x2291; @x@
+--
+-- [idempotent] @(x \`using\` s) \`using\` s@ = @x \`using\` s@
+--
+using :: a -> Strategy a -> a
+using x s = s x `seq` x
+
+
+-- | Evaluates the second argument before the first.
+-- Used to express control-oriented parallelism. The second
+-- argument is usually a strategy application.
+demanding :: a -> Done -> a
+demanding = flip seq
+
+
+-- | Evaluates the second argument in parallel with the first.
+-- Used to express control-oriented
+-- parallelism. The second argument is usually a strategy application.
+sparking :: a -> Done -> a
+sparking  = flip Parallel.par
+-- Sparking should only be used
+-- with a singleton sequence as it is not necessarily executed.
+
+-- | A strategy corresponding to 'par': 
+-- @x \`par\` e@ = @e \`using\` sPar x@.
+--
+-- 'sPar' has been superceded by 'sparking'.
+-- Replace @e \`using\` sPar x@ with @e \`sparking\` rwhnf x@.
+{-# DEPRECATED sPar "Use sparking instead." #-}
+sPar :: a -> Strategy b
+sPar x y = x `par` ()
+
+-- | A strategy corresponding to 'seq': 
+-- @x \`seq\` e@ = @e \`using\` sSeq x@.
+--
+-- 'sSeq' has been superceded by 'demanding'. 
+-- Replace @e \`using\` sSeq x@ with @e \`demanding\` rwhnf x@.
+{-# DEPRECATED sSeq "Use demanding instead." #-}
+sSeq :: a -> Strategy b
+sSeq x y = x `seq` ()
+
+-----------------------------------------------------------------------------
+-- *			Basic Strategies				     
+-----------------------------------------------------------------------------
+
+-- | Performs /no/ evaluation of its argument.
+r0 :: Strategy a 
+r0 x = ()
+
+-- | Reduces its argument to weak head normal form.
+rwhnf :: Strategy a 
+rwhnf x = x `seq` ()  
+
+class NFData a where
+  -- | Reduces its argument to (head) normal form.
+  rnf :: Strategy a
+  -- Default method. Useful for base types. A specific method is necessay for
+  -- constructed types
+  rnf = rwhnf
+
+class (NFData a, Integral a) => NFDataIntegral a
+class (NFData a, Ord a) => NFDataOrd a
+
+------------------------------------------------------------------------------
+-- *                     Strategic Function Application
+------------------------------------------------------------------------------
+
+{-
+These are very
+handy when writing pipeline parallelism asa sequence of @$@, @$|@ and
+@$||@'s. There is no need of naming intermediate values in this case. The
+separation of algorithm from strategy is achieved by allowing strategies
+only as second arguments to @$|@ and @$||@.
+-}
+
+-- | Sequential function application. The argument is evaluated using
+--   the given strategy before it is given to the function.
+($|) :: (a -> b) -> Strategy a -> a -> b
+f $| s  = \ x -> f x `demanding` s x
+
+-- | Parallel function application. The argument is evaluated using
+-- the given strategy, in parallel with the function application.
+($||) :: (a -> b) -> Strategy a -> a -> b
+f $|| s = \ x -> f x `sparking` s x
+
+-- | Sequential function composition. The result of
+-- the second function is evaluated using the given strategy, 
+-- and then given to the first function.
+(.|) :: (b -> c) -> Strategy b -> (a -> b) -> (a -> c)
+(.|) f s g = \ x -> let  gx = g x 
+                    in   f gx `demanding` s gx
+
+-- | Parallel function composition. The result of the second
+-- function is evaluated using the given strategy,
+-- in parallel with the application of the first function.
+(.||) :: (b -> c) -> Strategy b -> (a -> b) -> (a -> c)
+(.||) f s g = \ x -> let  gx = g x 
+                     in   f gx `sparking` s gx
+
+-- | Sequential inverse function composition, 
+-- for those who read their programs from left to right.
+-- The result of the first function is evaluated using the 
+-- given strategy, and then given to the second function.
+(-|) :: (a -> b) -> Strategy b -> (b -> c) -> (a -> c)
+(-|) f s g = \ x -> let  fx = f x 
+                    in   g fx `demanding` s fx
+
+-- | Parallel inverse function composition,
+-- for those who read their programs from left to right.
+-- The result of the first function is evaluated using the 
+-- given strategy, in parallel with the application of the 
+-- second function.
+(-||) :: (a -> b) -> Strategy b -> (b -> c) -> (a -> c)
+(-||) f s g = \ x -> let  fx = f x 
+                     in   g fx `sparking` s fx 
+
+------------------------------------------------------------------------------
+--			Marking a Strategy
+------------------------------------------------------------------------------
+
+{-
+Marking a strategy.
+
+Actually, @markStrat@  sticks a label @n@  into the sparkname  field of the
+thread executing strategy @s@. Together with a runtime-system that supports
+propagation of sparknames to the children this means that this strategy and
+all its children have  the sparkname @n@ (if the  static sparkname field in
+the @parGlobal@ annotation contains the value 1). Note, that the @SN@ field
+of starting the marked strategy itself contains the sparkname of the parent
+thread. The END event contains @n@ as sparkname.
+-}
+
+#if 0
+markStrat :: Int -> Strategy a -> Strategy a 
+markStrat n s x = unsafePerformPrimIO (
+     _casm_ ``%r = set_sparkname(CurrentTSO, %0);'' n `thenPrimIO` \ z ->
+     returnPrimIO (s x))
+#endif
+
+-----------------------------------------------------------------------------
+--			Strategy Instances and Functions		     
+-----------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------
+-- *	                Tuples
+-----------------------------------------------------------------------------
+
+{-
+We currently support up to 9-tuples. If you need longer tuples you have to 
+add the instance explicitly to your program.
+-}
+
+instance (NFData a, NFData b) => NFData (a,b) where
+  rnf (x,y) = rnf x `seq` rnf y
+
+instance (NFData a, NFData b, NFData c) => NFData (a,b,c) where
+  rnf (x,y,z) = rnf x `seq` rnf y `seq` rnf z 
+
+instance (NFData a, NFData b, NFData c, NFData d) => NFData (a,b,c,d) where
+  rnf (x1,x2,x3,x4) = rnf x1 `seq` 
+		        rnf x2 `seq` 
+		        rnf x3 `seq` 
+		        rnf x4 
+
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5) => 
+         NFData (a1, a2, a3, a4, a5) where
+  rnf (x1, x2, x3, x4, x5) =
+                  rnf x1 `seq`
+                  rnf x2 `seq`
+                  rnf x3 `seq`
+                  rnf x4 `seq`
+                  rnf x5
+
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6) => 
+         NFData (a1, a2, a3, a4, a5, a6) where
+  rnf (x1, x2, x3, x4, x5, x6) =
+                  rnf x1 `seq`
+                  rnf x2 `seq`
+                  rnf x3 `seq`
+                  rnf x4 `seq`
+                  rnf x5 `seq`
+                  rnf x6
+
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7) => 
+         NFData (a1, a2, a3, a4, a5, a6, a7) where
+  rnf (x1, x2, x3, x4, x5, x6, x7) =
+                  rnf x1 `seq`
+                  rnf x2 `seq`
+                  rnf x3 `seq`
+                  rnf x4 `seq`
+                  rnf x5 `seq`
+                  rnf x6 `seq`
+                  rnf x7
+
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8) => 
+         NFData (a1, a2, a3, a4, a5, a6, a7, a8) where
+  rnf (x1, x2, x3, x4, x5, x6, x7, x8) =
+                  rnf x1 `seq`
+                  rnf x2 `seq`
+                  rnf x3 `seq`
+                  rnf x4 `seq`
+                  rnf x5 `seq`
+                  rnf x6 `seq`
+                  rnf x7 `seq`
+                  rnf x8
+
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8, NFData a9) => 
+         NFData (a1, a2, a3, a4, a5, a6, a7, a8, a9) where
+  rnf (x1, x2, x3, x4, x5, x6, x7, x8, x9) =
+                  rnf x1 `seq`
+                  rnf x2 `seq`
+                  rnf x3 `seq`
+                  rnf x4 `seq`
+                  rnf x5 `seq`
+                  rnf x6 `seq`
+                  rnf x7 `seq`
+                  rnf x8 `seq`
+                  rnf x9
+
+-- | Apply two strategies to the elements of a pair sequentially
+--   from left to right.
+seqPair :: Strategy a -> Strategy b -> Strategy (a,b)
+seqPair strata stratb (x,y) = strata x `seq` stratb y 
+
+-- | Apply two strategies to the elements of a pair in parallel.
+parPair :: Strategy a -> Strategy b -> Strategy (a,b)
+parPair strata stratb (x,y) = strata x `par` stratb y `par` ()
+-- The reason for the last 'par' is so that the strategy terminates 
+-- quickly. This is important if the strategy is used as the 1st 
+-- argument of a seq
+
+-- | Apply three strategies to the elements of a triple in sequentially
+--   from left to right.
+seqTriple :: Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)
+seqTriple strata stratb stratc p@(x,y,z) = 
+  strata x `seq` 
+  stratb y `seq`
+  stratc z 
+
+-- | Apply three strategies to the elements of a triple in parallel.
+parTriple :: Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)
+parTriple strata stratb stratc (x,y,z) = 
+  strata x `par` 
+  stratb y `par` 
+  stratc z `par`
+  ()
+
+-----------------------------------------------------------------------------
+-- 			Atomic types
+-----------------------------------------------------------------------------
+
+{-
+Weak head normal form and normal form are identical for integers, so the 
+default rnf is sufficient. 
+-}
+instance NFData Int 
+instance NFData Integer
+instance NFData Float
+instance NFData Double
+
+instance NFData Int8
+instance NFData Int16
+instance NFData Int32
+instance NFData Int64
+
+instance NFData Word8
+instance NFData Word16
+instance NFData Word32
+instance NFData Word64
+
+instance NFDataIntegral Int
+instance NFDataOrd Int
+
+--Rational and complex numbers.
+
+instance (Integral a, NFData a) => NFData (Ratio a) where
+  rnf (x:%y) = rnf x `seq` 
+               rnf y `seq`
+               ()
+
+instance (RealFloat a, NFData a) => NFData (Complex a) where
+  rnf (x:+y) = rnf x `seq` 
+	         rnf y `seq`
+               ()
+
+instance NFData Char
+instance NFData Bool
+instance NFData ()
+
+-----------------------------------------------------------------------------
+-- 			Various library types						    
+-----------------------------------------------------------------------------
+
+instance NFData a => NFData (Maybe a) where
+    rnf Nothing  = ()
+    rnf (Just x) = rnf x
+
+instance (NFData a, NFData b) => NFData (Either a b) where
+    rnf (Left x)  = rnf x
+    rnf (Right y) = rnf y
+
+instance (NFData k, NFData a) => NFData (Data.Map.Map k a) where
+    rnf = rnf . Data.Map.toList
+
+instance NFData a => NFData (Data.Set.Set a) where
+    rnf = rnf . Data.Set.toList
+
+instance NFData a => NFData (Data.Tree.Tree a) where
+    rnf (Data.Tree.Node r f) = rnf r `seq` rnf f
+
+instance NFData a => NFData (Data.IntMap.IntMap a) where
+    rnf = rnf . Data.IntMap.toList
+
+instance NFData Data.IntSet.IntSet where
+    rnf = rnf . Data.IntSet.toList
+
+-----------------------------------------------------------------------------
+-- 			Lists						    
+-----------------------------------------------------------------------------
+
+instance NFData a => NFData [a] where
+  rnf [] = ()
+  rnf (x:xs) = rnf x `seq` rnf xs
+
+----------------------------------------------------------------------------
+-- *                   Lists: Parallel Strategies
+----------------------------------------------------------------------------
+
+-- | Applies a strategy to every element of a list in parallel.
+parList :: Strategy a -> Strategy [a]
+parList strat []     = ()
+parList strat (x:xs) = strat x `par` (parList strat xs)
+
+-- | Applies a strategy to the first @n@ elements of a list in parallel.
+parListN :: (Integral b) => b -> Strategy a -> Strategy [a]
+parListN n strat []     = ()
+parListN 0 strat xs     = ()
+parListN n strat (x:xs) = strat x `par` (parListN (n-1) strat xs)
+
+-- | Evaluates @n@ elements of the spine of the argument list and applies
+-- the given strategy to the @n@th element (if there is one) in parallel with
+-- the result. E.g. @parListNth 2 [e1, e2, e3]@ evaluates @e3@.
+parListNth :: Int -> Strategy a -> Strategy [a]
+parListNth n strat xs 
+  | null rest = ()
+  | otherwise = strat (head rest) `par` ()
+  where
+    rest = drop n xs
+
+-- | Splits a list into chunks (sub-sequences) of length @n@,
+-- and applies a strategy sequentially to the elements in each
+-- chunk. The chunks are evaluated in parallel.
+-- This is useful for increasing the grain size.
+parListChunk :: Int -> Strategy a -> Strategy [a]
+parListChunk n strat [] = ()
+parListChunk n strat xs = seqListN n strat xs `par` 
+			    parListChunk n strat (drop n xs)
+
+-- | Applies a function to each element of a list and 
+-- and evaluates the result list in parallel,
+-- using the given strategy for each element.
+parMap :: Strategy b -> (a -> b) -> [a] -> [b]
+parMap strat f xs = map f xs `using` parList strat
+
+-- | Uses 'parMap' to apply a list-valued function to each
+-- element of a list in parallel, and concatenates the results.
+parFlatMap :: Strategy [b] -> (a -> [b]) -> [a] -> [b]
+parFlatMap strat f xs = concat (parMap strat f xs)
+
+-- | Zips together two lists using a function,
+-- and evaluates the result list in parallel.
+parZipWith :: Strategy c -> (a -> b -> c) -> [a] -> [b] -> [c]
+parZipWith strat z as bs = 
+  zipWith z as bs `using` parList strat
+
+----------------------------------------------------------------------------
+-- *                     Lists: Sequential Strategies
+----------------------------------------------------------------------------
+
+-- | Sequentially applies a strategy to each element of a list.
+seqList :: Strategy a -> Strategy [a]
+seqList strat []     = ()
+seqList strat (x:xs) = strat x `seq` (seqList strat xs)
+
+-- | Sequentially applies a strategy to the first n elements of a list.
+seqListN :: (Integral a) => a -> Strategy b -> Strategy [b]
+seqListN n strat []     = ()
+seqListN 0 strat xs     = ()
+seqListN n strat (x:xs) = strat x `seq` (seqListN (n-1) strat xs)
+
+-- | Applies a strategy to the @n@th element of a list
+--  (if there is one) before returning the result. 
+--  E.g. @seqListNth 2 [e1, e2, e3]@ evaluates @e3@.
+seqListNth :: Int -> Strategy b -> Strategy [b]
+seqListNth n strat xs 
+  | null rest = ()
+  | otherwise = strat (head rest) 
+  where
+    rest = drop n xs
+
+-- | Parallel n-buffer function added for the revised version of the strategies
+-- paper. 'parBuffer' supersedes the older @fringeList@. It has the same
+-- semantics.
+parBuffer :: Int -> Strategy a -> [a] -> [a]
+parBuffer n s xs = 
+  return xs (start n xs)
+  where
+    return (x:xs) (y:ys) = (x:return xs ys) `sparking` s y
+    return xs     []     = xs
+
+    start n []     = []
+    start 0 ys     = ys
+    start n (y:ys) = start (n-1) ys `sparking` s y
+
+{-
+ 'fringeList' implements a `rolling buffer' of length n, i.e.applies a
+ strategy to the nth element of list when the head is demanded. More
+ precisely:
+
+   semantics:         fringeList n s = id :: [b] -> [b]
+   dynamic behaviour: evalutates the nth element of the list when the
+		      head is demanded.
+   
+ The idea is to provide a `rolling buffer' of length n.
+fringeList :: (Integral a) => a -> Strategy b -> [b] -> [b]
+fringeList n strat [] = []
+fringeList n strat (r:rs) = 
+  seqListNth n strat rs `par`
+  r:fringeList n strat rs
+-}
+
+------------------------------------------------------------------------------
+-- *			Arrays
+------------------------------------------------------------------------------
+instance (Ix a, NFData a, NFData b) => NFData (Array a b) where
+  rnf x = rnf (bounds x) `seq` seqList rnf (elems x) `seq` ()
+
+-- | Apply a strategy to all elements of an array sequentially.
+seqArr :: (Ix b) => Strategy a -> Strategy (Array b a)
+seqArr s arr = seqList s (elems arr)
+
+-- | Apply a strategy to all elements of an array in parallel.
+parArr :: (Ix b) => Strategy a -> Strategy (Array b a)
+parArr s arr = parList s (elems arr)
+
+{-# DEPRECATED Assoc "Does not belong in Control.Parallel.Strategies" #-}
+data  Assoc a b =  a := b  deriving ()
+
+instance (NFData a, NFData b) => NFData (Assoc a b) where
+  rnf (x := y) = rnf x `seq` rnf y `seq` ()
+
+------------------------------------------------------------------------------
+-- *	                Some strategies specific for Lolita	
+------------------------------------------------------------------------------
+
+{-# DEPRECATED fstPairFstList "This was just an example. Write your own." #-}
+fstPairFstList :: (NFData a) => Strategy [(a,b)]
+fstPairFstList = seqListN 1 (seqPair rwhnf r0)
+
+-- Some HACKs for Lolita. AFAIK force is just another name for our rnf and
+-- sforce is a shortcut (definition here is identical to the one in Force.lhs)
+
+{-# DEPRECATED force, sforce "Lolita-specific hacks." #-}
+force :: (NFData a) => a -> a 
+sforce :: (NFData a) => a -> b -> b
+
+force = id $| rnf
+sforce x y = force x `seq` y
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,39 @@
+This library (libraries/parallel) is derived from code from
+the GHC project which is largely (c) The University of
+Glasgow, and distributable under a BSD-style license (see below).
+
+-----------------------------------------------------------------------------
+
+The Glasgow Haskell Compiler License
+
+Copyright 2004, The University Court of the University of Glasgow. 
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+ 
+- Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+ 
+- Neither name of the University nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF
+GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+-----------------------------------------------------------------------------
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,6 @@
+module Main (main) where
+
+import Distribution.Simple
+
+main :: IO ()
+main = defaultMain
diff --git a/parallel.cabal b/parallel.cabal
new file mode 100644
--- /dev/null
+++ b/parallel.cabal
@@ -0,0 +1,15 @@
+name:		parallel
+version:	1.0.0.0
+license:	BSD3
+license-file:	LICENSE
+maintainer:	libraries@haskell.org
+synopsis:	parallel programming library
+description:
+    This package provides a library for parallel programming.
+build-type:     Simple
+exposed-modules:
+	Control.Parallel
+	Control.Parallel.Strategies
+extensions:	CPP
+build-depends: base >= 3, containers, array
+
