diff --git a/Control/Monad/Par/AList.hs b/Control/Monad/Par/AList.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Par/AList.hs
@@ -0,0 +1,285 @@
+{-# LANGUAGE CPP, DeriveDataTypeable #-}
+{-# OPTIONS_GHC -Wall -fno-warn-name-shadowing -fwarn-unused-imports #-}
+
+-- | This module defines the 'AList' type, a list that supports
+-- constant-time append, and is therefore ideal for building the
+-- result of tree-shaped parallel computations.
+
+module Control.Monad.Par.AList 
+{-# DEPRECATED "This structure does not perform well, and will be removed in future versions" #-}
+ (
+  -- * The 'AList' type and operations
+  AList(..),
+  empty, singleton, cons, head, tail, length, null, append,
+  toList, fromList, fromListBalanced, 
+
+  -- * Regular (non-parallel) Combinators
+  filter, map, partition,
+
+  -- * Operations to build 'AList's in the 'Par' monad
+  parBuildThresh, parBuildThreshM,
+  parBuild, parBuildM,
+
+  -- * Inspect and modify the internal structure of an AList tree 
+  depth, balance
+ )
+where 
+
+import Control.DeepSeq
+import Prelude hiding (length,head,tail,null,map,filter)
+import qualified Prelude as P
+import qualified Data.List as L
+import qualified Control.Monad.Par.Combinator as C
+import Control.Monad.Par.Class
+import Data.Typeable
+import qualified Data.Serialize as S
+
+----------------------------------------------------------------------------------------------------
+
+-- | List that support constant-time append (sometimes called
+-- join-lists).
+data AList a = ANil | ASing a | Append (AList a) (AList a) | AList [a]
+ deriving (Typeable)
+
+-- TODO -- Add vectors.
+
+instance NFData a => NFData (AList a) where
+ rnf ANil         = ()
+ rnf (ASing a)    = rnf a 
+ rnf (Append l r) = rnf l `seq` rnf r
+ rnf (AList  l)   = rnf l
+
+instance Show a => Show (AList a) where 
+  show al = "fromList "++ show (toList al)
+
+-- TODO: Better Serialization
+instance S.Serialize a => S.Serialize (AList a) where
+  put al = S.put (toList al)
+  get = do x <- S.get 
+	   return (fromList x)
+
+
+
+----------------------------------------------------------------------------------------------------
+
+{-# INLINE append #-}
+-- | /O(1)/ Append two 'AList's
+append :: AList a -> AList a -> AList a
+append ANil r = r
+append l ANil = l
+append l r    = Append l r
+
+{-# INLINE empty #-}
+-- | /O(1)/ an empty 'AList'
+empty :: AList a
+empty = ANil
+
+{-# INLINE singleton #-}
+-- | /O(1)/ a singleton 'AList'
+singleton :: a -> AList a
+singleton = ASing
+
+{-# INLINE fromList #-}
+-- | /O(1)/ convert an ordinary list to an 'AList'
+fromList :: [a] -> AList a
+fromList  = AList
+
+-- | Convert an ordinary list, but do so using 'Append' and
+-- 'ASing' rather than 'AList'
+fromListBalanced :: [a] -> AList a
+fromListBalanced xs = go xs (P.length xs)
+  where 
+   go _  0 = ANil
+   go ls 1 = case ls of 
+	       (h:_) -> ASing h
+	       []    -> error "the impossible happened"
+   go ls n = 
+     let (q,r) = quotRem n 2 in
+     Append (go ls q)
+            (go (drop q ls) (q+r))
+
+
+-- | Balance the tree representation of an AList.  
+balance :: AList a -> AList a
+balance = fromListBalanced . toList
+-- This would be much better if ALists tracked their size.
+
+{-# INLINE cons #-}
+-- | /O(1)/ prepend an element
+cons :: a -> AList a -> AList a
+cons x ANil = ASing x
+cons x al   = Append (ASing x) al
+-- If we tracked length perhaps this could make an effort at balance.
+
+-- | /O(n)/ take the head element of an 'AList'
+--
+-- NB. linear-time, because the list might look like this:
+--
+-- > (((... `append` a) `append` b) `append` c)
+--
+head :: AList a -> a
+head al = 
+  case loop al of
+    Just x -> x 
+    Nothing -> error "cannot take head of an empty AList"
+ where 
+  -- Alas there are an infinite number of representations for null:
+  loop al =
+   case al of 
+     Append l r -> case loop l of 
+		     x@(Just _) -> x
+		     Nothing    -> loop r
+     ASing x     -> Just x
+     AList (h:_) -> Just h
+     AList []    -> Nothing
+     ANil        -> Nothing
+
+-- | /O(n)/ take the tail element of an 'AList'
+tail :: AList a -> AList a
+tail al = 
+  case loop al of
+    Just x -> x 
+    Nothing -> error "cannot take tail of an empty AList"
+ where 
+  loop al =
+   case al of 
+     Append l r -> case loop l of 
+		     (Just x) -> Just (Append x r)
+		     Nothing  -> loop r
+
+     ASing _     -> Just ANil
+     AList (_:t) -> Just (AList t)
+     AList []    -> Nothing
+     ANil        -> Nothing
+
+-- | /O(n)/ find the length of an 'AList'
+length :: AList a -> Int
+length ANil         = 0
+length (ASing _)    = 1
+length (Append l r) = length l + length r
+length (AList  l)   = P.length l 
+
+{-# INLINE null #-}
+-- | /O(n)/ returns 'True' if the 'AList' is empty
+null :: AList a -> Bool
+null = (==0) . length 
+
+-- | /O(n)/ converts an 'AList' to an ordinary list
+toList :: AList a -> [a]
+toList a = go a []
+ where go ANil         rest = rest
+       go (ASing a)    rest = a : rest
+       go (Append l r) rest = go l $! go r rest
+       go (AList xs)   rest = xs ++ rest
+
+partition :: (a -> Bool) -> AList a -> (AList a, AList a)
+partition p a = go a (ANil, ANil)
+  where go ANil      acc = acc
+        go (ASing a) (ys, ns) | p a = (a `cons` ys, ns)
+        go (ASing a) (ys, ns) | otherwise = (ys, a `cons` ns)
+        go (Append l r) acc = go l $! go r acc
+        go (AList xs) (ys, ns) = (AList ys' `append` ys, AList ns' `append` ns)
+          where
+            (ys', ns') = L.partition p xs
+
+depth :: AList a -> Int
+depth ANil      = 0
+depth (ASing _) = 1
+depth (AList _) = 1
+depth (Append l r) = 1 + max (depth l) (depth r)
+
+
+-- The filter operation compacts dead space in the tree that would be
+-- left by ANil nodes.
+filter :: (a -> Bool) -> AList a -> AList a
+filter p l = loop l 
+ where 
+  loop ANil         = ANil
+  loop o@(ASing x)  = if p x then o else ANil
+  loop   (AList ls) = AList$ P.filter p ls
+  loop (Append x y) = 
+     let l = loop x
+	 r = loop y in
+     case (l,r) of 
+       (ANil,ANil) -> ANil
+       (ANil,y)    -> y
+       (x,ANil)    -> x
+       (x,y)       -> Append x y
+
+-- | The usual `map` operation.
+map :: (a -> b) -> AList a -> AList b
+map _  ANil = ANil 
+map f (ASing x) = ASing (f x)
+map f (AList l) = AList (P.map f l)
+map f (Append x y) = Append (map f x) (map f y)
+
+
+--------------------------------------------------------------------------------
+-- * Combinators built on top of a Par monad.
+
+-- | A parMap over an AList can result in more balanced parallelism than
+--   the default parMap over Traversable data types.
+-- parMap :: NFData b => (a -> b) -> AList a -> Par (AList b)
+
+-- | Build a balanced 'AList' in parallel, constructing each element as a
+--   function of its index.  The threshold argument provides control
+--   over the degree of parallelism.  It indicates under what number
+--   of elements the build process should switch from parallel to
+--   serial.
+parBuildThresh :: (NFData a, ParFuture f p) => Int -> C.InclusiveRange -> (Int -> a) -> p (AList a)
+parBuildThresh threshold range fn =
+  C.parMapReduceRangeThresh threshold range
+			  (return . singleton . fn) appendM empty
+
+-- | Variant of 'parBuildThresh' in which the element-construction function is itself a 'Par' computation.
+parBuildThreshM :: (NFData a, ParFuture f p) => Int -> C.InclusiveRange -> (Int -> p a) -> p (AList a)
+parBuildThreshM threshold range fn =
+  C.parMapReduceRangeThresh threshold range 
+			  (\x -> fn x >>= return . singleton) appendM empty
+
+-- | \"Auto-partitioning\" version of 'parBuildThresh' that chooses the threshold based on
+--    the size of the range and the number of processors..
+parBuild :: (NFData a, ParFuture f p) => C.InclusiveRange -> (Int -> a) -> p (AList a)
+parBuild range fn =
+  C.parMapReduceRange range (return . singleton . fn) appendM empty
+
+-- | like 'parBuild', but the construction function is monadic
+parBuildM :: (NFData a, ParFuture f p) => C.InclusiveRange -> (Int -> p a) -> p (AList a)
+parBuildM range fn =
+  C.parMapReduceRange range (\x -> fn x >>= return . singleton) appendM empty
+
+--------------------------------------------------------------------------------
+
+-- TODO: Provide a strategy for @par@-based maps:
+
+-- TODO: tryHead -- returns Maybe
+
+-- TODO: headTail -- returns head and tail, 
+--    i.e. if we're doing O(N) work, don't do it twice.
+
+-- FIXME: Could be more efficient:
+instance Eq a => Eq (AList a) where
+ a == b = toList a == toList b 
+
+-- TODO: Finish me:
+-- instance F.Foldable AList where
+--  foldr fn init al = 
+--   case al of 
+--    ANil    -> 
+
+-- instance Functor AList where
+--  fmap = undefined
+
+-- -- Walk the data structure without introducing any additional data-parallelism.
+-- instance Traversable AList where 
+--   traverse f al = 
+--     case al of 
+--       ANil    -> pure ANil
+--       ASing x -> ASing <$> f x
+
+
+--------------------------------------------------------------------------------
+-- Internal helpers:
+
+appendM :: ParFuture f p => AList a -> AList a -> p (AList a)
+appendM x y = return (append x y)
diff --git a/Control/Monad/Par/Combinator.hs b/Control/Monad/Par/Combinator.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Par/Combinator.hs
@@ -0,0 +1,183 @@
+{-# LANGUAGE BangPatterns #-}
+{-| 
+    A collection of useful parallel combinators based on top of a 'Par' monad.
+
+    In particular, this module provides higher order functions for
+     traversing data structures in parallel.  
+
+-}
+
+module Control.Monad.Par.Combinator
+  (
+    parMap, parMapM,
+    parMapReduceRangeThresh, parMapReduceRange,
+    InclusiveRange(..),
+    parFor
+  )
+where 
+
+import Control.DeepSeq
+import Data.Traversable
+import Control.Monad as M hiding (mapM, sequence, join)
+import Prelude hiding (mapM, sequence, head,tail)
+import GHC.Conc (numCapabilities)
+
+import Control.Monad.Par.Class
+
+-- -----------------------------------------------------------------------------
+-- Parallel maps over Traversable data structures
+
+-- | Applies the given function to each element of a data structure
+-- in parallel (fully evaluating the results), and returns a new data
+-- structure containing the results.
+--
+-- > parMap f xs = mapM (spawnP . f) xs >>= mapM get
+--
+-- @parMap@ is commonly used for lists, where it has this specialised type:
+--
+-- > parMap :: NFData b => (a -> b) -> [a] -> Par [b]
+--
+parMap :: (Traversable t, NFData b, ParFuture iv p) => (a -> b) -> t a -> p (t b)
+parMap f xs = mapM (spawnP . f) xs >>= mapM get
+
+-- | Like 'parMap', but the function is a @Par@ monad operation.
+--
+-- > parMapM f xs = mapM (spawn . f) xs >>= mapM get
+--
+parMapM :: (Traversable t, NFData b, ParFuture iv p) => (a -> p b) -> t a -> p (t b)
+parMapM f xs = mapM (spawn . f) xs >>= mapM get
+
+-- TODO: parBuffer
+
+
+
+-- --------------------------------------------------------------------------------
+
+-- TODO: Perhaps should introduce a class for the "splittable range" concept.
+data InclusiveRange = InclusiveRange Int Int
+
+-- | Computes a binary map\/reduce over a finite range.  The range is
+-- recursively split into two, the result for each half is computed in
+-- parallel, and then the two results are combined.  When the range
+-- reaches the threshold size, the remaining elements of the range are
+-- computed sequentially.
+--
+-- For example, the following is a parallel implementation of
+--
+-- >  foldl (+) 0 (map (^2) [1..10^6])
+--
+-- > parMapReduceRangeThresh 100 (InclusiveRange 1 (10^6))
+-- >        (\x -> return (x^2))
+-- >        (\x y -> return (x+y))
+-- >        0
+--
+parMapReduceRangeThresh
+   :: (NFData a, ParFuture iv p)
+      => Int                            -- ^ threshold
+      -> InclusiveRange                 -- ^ range over which to calculate
+      -> (Int -> p a)                 -- ^ compute one result
+      -> (a -> a -> p a)              -- ^ combine two results (associative)
+      -> a                              -- ^ initial result
+      -> p a
+
+parMapReduceRangeThresh threshold (InclusiveRange min max) fn binop init
+ = loop min max
+ where
+  loop min max
+    | max - min <= threshold =
+	let mapred a b = do x <- fn b;
+			    result <- a `binop` x
+			    return result
+	in foldM mapred init [min..max]
+
+    | otherwise  = do
+	let mid = min + ((max - min) `quot` 2)
+	rght <- spawn $ loop (mid+1) max
+	l  <- loop  min    mid
+	r  <- get rght
+	l `binop` r
+
+-- How many tasks per process should we aim for?  Higher numbers
+-- improve load balance but put more pressure on the scheduler.
+auto_partition_factor :: Int
+auto_partition_factor = 4
+
+-- | \"Auto-partitioning\" version of 'parMapReduceRangeThresh' that chooses the threshold based on
+--    the size of the range and the number of processors..
+parMapReduceRange :: (NFData a, ParFuture iv p) => 
+		     InclusiveRange -> (Int -> p a) -> (a -> a -> p a) -> a -> p a
+parMapReduceRange (InclusiveRange start end) fn binop init =
+   loop (length segs) segs
+ where
+  segs = splitInclusiveRange (auto_partition_factor * numCapabilities) (start,end)
+  loop 1 [(st,en)] =
+     let mapred a b = do x <- fn b;
+			 result <- a `binop` x
+			 return result
+     in foldM mapred init [st..en]
+  loop n segs =
+     let half = n `quot` 2
+	 (left,right) = splitAt half segs in
+     do l  <- spawn$ loop half left
+        r  <- loop (n-half) right
+	l' <- get l
+	l' `binop` r
+
+
+-- TODO: A version that works for any splittable input domain.  In this case
+-- the "threshold" is a predicate on inputs.
+-- parMapReduceRangeGeneric :: (inp -> Bool) -> (inp -> Maybe (inp,inp)) -> inp ->
+
+
+-- Experimental:
+
+-- | Parallel for-loop over an inclusive range.  Semantically equivalent
+-- to
+-- 
+-- > parFor (InclusiveRange n m) f = forM_ [n..m] f
+--
+-- except that the implementation will split the work into an
+-- unspecified number of subtasks in an attempt to gain parallelism.
+-- The exact number of subtasks is chosen at runtime, and is probably
+-- a small multiple of the available number of processors.
+--
+-- Strictly speaking the semantics of 'parFor' depends on the
+-- number of processors, and its behaviour is therefore not
+-- deterministic.  However, a good rule of thumb is to not have any
+-- interdependencies between the elements; if this rule is followed
+-- then @parFor@ has deterministic semantics.  One easy way to follow
+-- this rule is to only use 'put' or 'put_' in @f@, never 'get'.
+
+parFor :: (ParFuture iv p) => InclusiveRange -> (Int -> p ()) -> p ()
+parFor (InclusiveRange start end) body =
+ do
+    let run (x,y) = for_ x (y+1) body
+        range_segments = splitInclusiveRange (4*numCapabilities) (start,end)
+
+    vars <- M.forM range_segments (\ pr -> spawn_ (run pr))
+    M.mapM_ get vars
+    return ()
+
+splitInclusiveRange :: Int -> (Int, Int) -> [(Int, Int)]
+splitInclusiveRange pieces (start,end) =
+  map largepiece [0..remain-1] ++
+  map smallpiece [remain..pieces-1]
+ where
+   len = end - start + 1 -- inclusive [start,end]
+   (portion, remain) = len `quotRem` pieces
+   largepiece i =
+       let offset = start + (i * (portion + 1))
+       in (offset, offset + portion)
+   smallpiece i =
+       let offset = start + (i * portion) + remain
+       in (offset, offset + portion - 1)
+
+-- My own forM for numeric ranges (not requiring deforestation optimizations).
+-- Inclusive start, exclusive end.
+{-# INLINE for_ #-}
+for_ :: Monad m => Int -> Int -> (Int -> m ()) -> m ()
+for_ start end _fn | start > end = error "for_: start is greater than end"
+for_ start end fn = loop start
+  where
+   loop !i | i == end  = return ()
+	   | otherwise = do fn i; loop (i+1)
diff --git a/Control/Monad/Par/Pedigree.hs b/Control/Monad/Par/Pedigree.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Par/Pedigree.hs
@@ -0,0 +1,49 @@
+{-# LANGUAGE TypeSynonymInstances, CPP, FlexibleInstances, BangPatterns #-}
+
+-- | This module extends a Par monad with /pedigree/.  That is, it
+--   allows a running computation to look up its position in the
+--   dynamic binary tree of `fork` calls ("ancestry").
+
+module Control.Monad.Par.Pedigree
+ (
+   pedigree, ParPedigreeT
+ , unpack, runParPedigree
+ ) 
+ where 
+
+import Control.Monad.Par.Class
+import Control.Monad.Par.State
+import Control.Monad.Trans.State.Strict as S 
+
+-- It's running slightly better with normal lists for parfib:
+#if 0 
+import Data.BitList
+type BList = BitList
+#else
+type BList = [Bool]
+unpack (Pedigree _ x) = x
+cons = (:)
+empty = []
+#endif
+
+type ParPedigreeT p a = S.StateT Pedigree p a
+
+-- type Pedigree = BList
+-- -- | Trivial instance.
+-- instance SplittableState Pedigree where
+--   splitState bl = (cons False bl, cons True bl)
+
+data Pedigree = 
+      Pedigree { ivarCounter :: {-# UNPACK #-} !Int, 
+	         treePath    :: !BList }
+
+instance SplittableState Pedigree where
+  splitState (Pedigree cnt bl) = 
+    (Pedigree cnt (cons False bl), 
+     Pedigree cnt (cons True bl))
+
+pedigree :: ParFuture iv p => S.StateT Pedigree p Pedigree
+pedigree = S.get
+
+runParPedigree :: Monad p => ParPedigreeT p a -> p a
+runParPedigree m = S.evalStateT m (Pedigree 0 empty)
diff --git a/Control/Monad/Par/RNG.hs b/Control/Monad/Par/RNG.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Par/RNG.hs
@@ -0,0 +1,64 @@
+{-# LANGUAGE FlexibleInstances, UndecidableInstances  #-}
+
+-- | This module defines another Par-related class to capture the
+--   random number generation capability.  
+-- 
+--   The `rand` operation provides deterministic parallel random
+--   number generation from within a Par monad.
+-- 
+--   Most likely one will simply use the `ParRand` the instance
+--   provided in this file, which is based on a state transformer
+--   carrying the random generator.
+
+
+module Control.Monad.Par.RNG 
+ (
+  ParRand(..), runParRand, ParRandStd
+ ) where 
+
+import System.Random
+import Control.Exception
+
+import Control.Monad.Par.Class
+import Control.Monad.Par.State
+import Control.Monad.Trans
+import Control.Monad.Trans.State.Strict as S 
+
+-- | A `ParRand` monad is a Par monad with support for random number generation..
+class ParRand p where 
+  rand :: Random a => p a
+  -- This can be more efficient:
+  randInt :: p Int
+  randInt = rand 
+
+-- | Trivial instance.
+instance RandomGen g => SplittableState g where
+  splitState = split
+
+-- | The most straightforward way to get a `ParRand` monad: carry a
+--   RNG in a state transformer.
+instance (ParFuture fut p, RandomGen g) => ParRand (StateT g p) where 
+  rand    = do 
+               g <- S.get
+	       let (x,g') = random g 
+	       S.put g'
+	       return x
+  randInt = do 
+               g <- S.get
+               let (x,g') = next g
+	       S.put g'
+	       return x
+
+-- An alternative is for these operators to be standalone without a class:
+-- rand    :: (ParFuture p fut, RandomGen g, Random a) => StateT g p a
+-- randInt :: (ParFuture p fut, RandomGen g)           => StateT g p Int
+
+-- runParRand :: ParRand p => (p a -> a) -> p a -> IO a
+runParRand :: ParFuture fut p => (p a -> a) -> StateT StdGen p a -> IO a
+runParRand runPar m = 
+  do g <- newStdGen
+     evaluate (runPar (evalStateT m g))
+
+
+-- | A convenience type for the most standard
+type ParRandStd par a = StateT StdGen par a 
diff --git a/Control/Monad/Par/State.hs b/Control/Monad/Par/State.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Par/State.hs
@@ -0,0 +1,116 @@
+{-# LANGUAGE ScopedTypeVariables, FlexibleInstances, 
+     MultiParamTypeClasses, UndecidableInstances, CPP
+  #-}
+
+-- | This module provides a notion of (Splittable) State that is
+--   compatible with any Par monad.
+
+
+module Control.Monad.Par.State 
+  (
+   SplittableState(..)
+  )
+  where
+
+import Control.Monad
+import qualified Control.Monad.Par.Class as PC
+import Control.Monad.Trans
+import qualified Control.Monad.Trans.State.Strict as S
+import qualified Control.Monad.Trans.State.Lazy as SL
+
+---------------------------------------------------------------------------------
+--- Make Par computations with state work.
+--- (TODO: move these instances to a different module.)
+
+-- | A type in `SplittableState` is meant to be added as to a Par monad
+--   using StateT.  It works like any other state except at `fork`
+--   points, where the runtime system splits the state using `splitState`.
+-- 
+--   Common examples for applications of `SplittableState` would
+--   include (1) routing a splittable random number generator through
+--   a parallel computation, and (2) keeping a tree-index that locates
+--   the current computation within the binary tree of `fork`s.
+class SplittableState a where
+  splitState :: a -> (a,a)
+
+----------------------------------------------------------------------------------------------------
+-- Strict State:
+
+-- | Adding State to a `ParFuture` monad yields another `ParFuture` monad.
+instance (SplittableState s, PC.ParFuture fut p) 
+      =>  PC.ParFuture fut (S.StateT s p) 
+ where
+  get = lift . PC.get
+  spawn_ (task :: S.StateT s p ans) = 
+    do s <- S.get 
+       let (s1,s2) = splitState s
+       S.put s2                               -- Parent comp. gets one branch.
+       lift$ PC.spawn_ $ S.evalStateT task s1   -- Child the other.
+
+-- | Likewise, adding State to a `ParIVar` monad yield s another `ParIVar` monad.
+instance (SplittableState s, PC.ParIVar iv p) 
+      =>  PC.ParIVar iv (S.StateT s p) 
+ where
+  fork (task :: S.StateT s p ()) = 
+              do s <- S.get 
+                 let (s1,s2) = splitState s
+                 S.put s2
+                 lift$ PC.fork $ do S.runStateT task s1; return ()
+
+  new      = lift PC.new
+  put_ v x = lift$ PC.put_ v x
+  newFull_ = lift . PC.newFull_
+
+-- ParChan not released yet:
+#if 0
+-- | Likewise, adding State to a `ParChan` monad yield s another `ParChan` monad.
+instance (SplittableState s, PC.ParChan snd rcv p) 
+      =>  PC.ParChan snd rcv (S.StateT s p) 
+ where
+   newChan  = lift   PC.newChan
+   recv   r = lift $ PC.recv r
+   send s x = lift $ PC.send s x
+#endif
+
+
+----------------------------------------------------------------------------------------------------
+-- Lazy State:
+
+-- <DUPLICATE_CODE>
+
+-- | Adding State to a `ParFuture` monad yield s another `ParFuture` monad.
+instance (SplittableState s, PC.ParFuture fut p) 
+      =>  PC.ParFuture fut (SL.StateT s p) 
+ where
+  get = lift . PC.get
+  spawn_ (task :: SL.StateT s p ans) = 
+    do s <- SL.get 
+       let (s1,s2) = splitState s
+       SL.put s2                               -- Parent comp. gets one branch.
+       lift$ PC.spawn_ $ SL.evalStateT task s1   -- Child the other.
+
+-- | Likewise, adding State to a `ParIVar` monad yield s another `ParIVar` monad.
+instance (SplittableState s, PC.ParIVar iv p) 
+      =>  PC.ParIVar iv (SL.StateT s p) 
+ where
+  fork (task :: SL.StateT s p ()) = 
+              do s <- SL.get 
+                 let (s1,s2) = splitState s
+                 SL.put s2
+                 lift$ PC.fork $ do SL.runStateT task s1; return ()
+
+  new      = lift PC.new
+  put_ v x = lift$ PC.put_ v x
+  newFull_ = lift . PC.newFull_
+
+#if 0
+-- | Likewise, adding State to a `ParChan` monad yield s another `ParChan` monad.
+instance (SplittableState s, PC.ParChan snd rcv p) 
+      =>  PC.ParChan snd rcv (SL.StateT s p)
+ where
+   newChan  = lift   PC.newChan
+   recv   r = lift $ PC.recv r
+   send s x = lift $ PC.send s x
+#endif
+
+-- </DUPLICATE_CODE>
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Simon Marlow 2011
+
+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 the name of Simon Marlow nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 COPYRIGHT
+OWNER OR 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,3 @@
+#!/usr/bin/env runhaskell
+import Distribution.Simple
+main = defaultMain
diff --git a/monad-par-extras.cabal b/monad-par-extras.cabal
new file mode 100644
--- /dev/null
+++ b/monad-par-extras.cabal
@@ -0,0 +1,61 @@
+Name:                monad-par-extras
+Version:             0.3
+Synopsis:            Combinators and extra features for Par monads
+
+
+-- Version history:
+--  0.3      : Factored/reorganized modules.  This module is a spinoff of 
+--             the original monad-par
+
+
+Description:         The modules below provide additional
+                     data structures, and other added capabilities
+                     layered on top of the 'Par' monad.
+
+                       * Finish These
+                       * Module Descriptions
+
+Homepage:            https://github.com/simonmar/monad-par
+License:             BSD3
+License-file:        LICENSE
+Author:              Simon Marlow
+Maintainer:          Simon Marlow <marlowsd@gmail.com>
+Copyright:           (c) Simon Marlow 2011
+Stability:           Experimental
+Category:            Control,Parallelism,Monads
+Build-type:          Simple
+Cabal-version:       >=1.8
+
+Library
+  Exposed-modules: 
+                 -- A collection of combinators for common parallel
+                 -- patterns and data structure traversals:
+                 Control.Monad.Par.Combinator,
+
+                 -- Deprecated AList interface
+                 Control.Monad.Par.AList,
+
+                 -- State on top of Par is generally useful, but experimental
+                 Control.Monad.Par.State,
+ 
+                 -- Deterministic RNG needs more testing.
+                 Control.Monad.Par.RNG
+
+  Other-modules:
+                 -- Pedigree is experimental, but potentially useful for
+                 -- many purposes such as assigning unique, reproducable
+                 -- identifiers to IVars
+                 Control.Monad.Par.Pedigree
+
+
+  Build-depends: base >= 4 && < 5
+               -- This provides the interface which monad-par implements:
+               , abstract-par == 0.3.*
+               , cereal == 0.3.*
+               , deepseq == 1.3.*     
+               , mtl == 2.0.*
+               , random == 1.0.*          
+               , transformers == 0.2.*
+
+  ghc-options: -O2
+  Other-modules:
