diff --git a/Control/Monad/Par/Class.hs b/Control/Monad/Par/Class.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Par/Class.hs
@@ -0,0 +1,173 @@
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, CPP,
+     FlexibleInstances, UndecidableInstances
+  #-}
+-- UndecidableInstances
+
+{-|
+
+    This module establishes a class hierarchy that captures the
+    interface(s) for valid Par monads.  In particular, the functionality
+    is split into layers: e.g. Futures vs. full IVars vs. Chans (Streams).  
+    
+    Not all Par monad schedulers must provide all functionality.
+
+    For more documentation of the programming model, see  
+
+      * The "Control.Monad.Par" module in the @monad-par@ package.
+      * The wiki/tutorial (<http://www.haskell.org/haskellwiki/Par_Monad:_A_Parallelism_Tutorial>)
+      * The original paper (<http://www.cs.indiana.edu/~rrnewton/papers/haskell2011_monad-par.pdf>)
+      * Tutorial slides (<http://community.haskell.org/~simonmar/slides/CUFP.pdf>)
+      * Other slides: <http://www.cs.ox.ac.uk/ralf.hinze/WG2.8/28/slides/simon.pdf>, 
+                      <http://www.cs.indiana.edu/~rrnewton/talks/2011_HaskellSymposium_ParMonad.pdf>
+
+ -}
+--  
+
+module Control.Monad.Par.Class 
+  (  
+  -- * Futures
+    ParFuture(..)
+  -- * IVars
+  , ParIVar(..)
+  
+    -- RRN: Not releasing this interface until there is a nice implementation of it:
+    --  Channels (Streams)
+    --  , ParChan(..)
+
+  , NFData()
+  )
+where
+
+import Control.DeepSeq
+
+--------------------------------------------------------------------------------
+
+-- | @ParFuture@ captures the class of Par monads which support
+--   futures.  This level of functionality subsumes @par@/@pseq@ and is
+--   similar to the "Control.Parallel.Strategies.Eval" monad.
+-- 
+--   A minimal implementation consists of `spawn_` and `get`.
+--   However, for monads that are also a member of `ParIVar` it is
+--   typical to simply define `spawn` in terms of `fork`, `new`, and `put`.
+class Monad m => ParFuture future m | m -> future where
+  -- | Create a potentially-parallel computation, and return a /future/
+  -- (or /promise/) that can be used to query the result of the forked
+  -- computataion.  
+  --
+  -- >  spawn p = do
+  -- >    r <- new
+  -- >    fork (p >>= put r)
+  -- >    return r
+  --
+  spawn  :: NFData a => m a -> m (future a)
+  
+  -- | Like 'spawn', but the result is only head-strict, not fully-strict.
+  spawn_ :: m a -> m (future a)
+  get    :: future a -> m a
+
+  -- | Spawn a pure (rather than monadic) computation.  Fully-strict.
+  -- 
+  -- >  spawnP = spawn . return
+  spawnP :: NFData a =>   a -> m (future a)
+  
+  -- Default implementations:
+  spawn  p = spawn_ (do x <- p; deepseq x (return x))
+  spawnP a = spawn (return a)
+
+
+--------------------------------------------------------------------------------
+
+-- | @ParIVar@ builds on futures by adding full /anyone-writes, anyone-reads/ IVars.
+--   These are more expressive but may not be supported by all distributed schedulers.
+-- 
+-- A minimal implementation consists of `fork`, `put_`, and `new`.
+class ParFuture ivar m  => ParIVar ivar m | m -> ivar where
+  -- | Forks a computation to happen in parallel.  The forked
+  -- computation may exchange values with other computations using
+  -- @IVar@s.
+  fork :: m () -> m ()
+  
+  -- | creates a new @IVar@
+  new  :: m (ivar a)
+  
+  -- | put a value into a @IVar@.  Multiple 'put's to the same @IVar@
+  -- are not allowed, and result in a runtime error.
+  --
+  -- 'put' fully evaluates its argument, which therefore must be an
+  -- instance of 'NFData'.  The idea is that this forces the work to
+  -- happen when we expect it, rather than being passed to the consumer
+  -- of the @IVar@ and performed later, which often results in less
+  -- parallelism than expected.
+  --
+  -- Sometimes partial strictness is more appropriate: see 'put_'.
+  --
+  put  :: NFData a => ivar a -> a -> m ()
+  put v a = deepseq a (put_ v a)
+  
+  -- | like 'put', but only head-strict rather than fully-strict.  
+  put_ :: ivar a -> a -> m ()
+
+  -- Extra API routines that have default implementations:
+  
+  -- | creates a new @IVar@ that contains a value
+  newFull :: NFData a => a -> m (ivar a)
+  newFull a = deepseq a (newFull_ a)
+  
+  -- | creates a new @IVar@ that contains a value (head-strict only)
+  newFull_ ::  a -> m (ivar a)
+  newFull_ a = do v <- new
+                  -- This is usually inefficient! 
+		  put_ v a
+		  return v
+
+--------------------------------------------------------------------------------  
+
+-- class ParYieldable ?? 
+  -- TODO: I think we should add yield officially:
+
+  -- Allows other parallel computations to progress.  (should not be
+  -- necessary in most cases).
+  --  yield  :: m ()
+
+
+--------------------------------------------------------------------------------
+
+-- | @ParChan@ provides communication via streams of values between
+--   computations in a Par monad.  Channels in this case are split
+--   into separate send and receive ports.
+--
+--   The critical thing to know about @Chan@s in @Par@ monads is that
+--   while the @recv@ method destructively advances the position of
+--   the consumer's \"cursor\" in the stream, this is only observable
+--   in the /local/ @Par@ thread.  That is, at @fork@ points it is
+--   necessary to give the child computation a separate set of stream
+--   cursors so that it observes the same sequences as the parent.
+class Monad m => ParChan snd rcv m | m -> snd, m -> rcv where
+   -- | Create a new communication channel, with separate send and receive ports.
+   newChan :: m (snd a, rcv a)
+   -- | Receive a message on a channel in a synchronous, blocking manner.
+   recv    :: rcv a -> m a
+   -- | Send a message on a channel.  This may or may not block.
+   send    :: snd a -> a -> m ()
+
+
+----------------------------------------------------------------------------------------------------
+
+-- t1 :: P.Par Int
+-- If the ParIVar => ParFuture instance exists the following is sufficient:
+t1 :: (ParFuture v m) => m Int
+t1 = do 
+  x <- spawn (return 3)
+  get x
+
+t2 :: (ParIVar v m) => m Int
+t2 = do 
+  x <- new
+  put x "hi"
+  return 3
+
+
+-- TODO: SPECIALIZE generic routines for the default par monad (and possibly ParRNG)?
+
+--  SPECIALISE parMap  :: (NFData b) => (a -> b)     -> [a] -> Par [b] 
+-- SPECIALISE parMapM :: (NFData b) => (a -> Par b) -> [a] -> Par [b] 
diff --git a/Control/Monad/Par/Unsafe.hs b/Control/Monad/Par/Unsafe.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Par/Unsafe.hs
@@ -0,0 +1,36 @@
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
+-- TODO: ADD Unsafe
+
+-- | Unsafe operations.  NOT part of "Safe Haskell".
+-- 
+-- These are "unsafe" (in the normal, Haskell sense) when used with a
+-- "runPar" of type `Par a -> a`.  If used with a `runParIO` that
+-- stays in the IO monad, then they are simply dangerous.
+-- 
+-- For the purposes of Safe Haskell, any module that imports this
+-- module becomes untrustworthy.
+
+module Control.Monad.Par.Unsafe 
+  (
+   ParUnsafe(..)
+  ) 
+where
+
+-- import Control.Monad.Par.Class
+
+-- | The class of Par monads that provide unsafe functionality.
+class ParUnsafe iv p | p -> iv where 
+  -- | Peek at the current contents of an 'IVar' in a nonblocking way.
+  unsafePeek   :: iv a -> p (Maybe a)
+
+  -- | Attempt to put a value into an 'IVar'.  If successful, return the
+  --   value put.  If something is already there, return it instead.
+  unsafeTryPut :: iv a -> a -> p a
+
+  -- | Lift an 'IO' operation into the Par monad.
+  unsafeParIO  :: IO a -> p a
+
+-- Aside:
+-- If the need ever arises we could also consider unsafeMultiplePut that
+-- would be able to change the current value of an IVar.  It could
+-- cause big problems in the distributed case, however.
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/abstract-par.cabal b/abstract-par.cabal
new file mode 100644
--- /dev/null
+++ b/abstract-par.cabal
@@ -0,0 +1,54 @@
+Name:                abstract-par
+Version:             0.3
+Synopsis:            Type classes generalizing the functionality of the 'monad-par' library.
+
+
+-- Version history:
+
+--  0.3      : Factored out of monad-par package.
+
+
+Description:         The 'Par' monad(s) offer an alternative 
+                     parallel programming API to that provided by the 
+                     @parallel@ package.
+
+                     A 'Par' monad allows the simple description of
+                     parallel computations, and can be used to add
+                     parallelism to pure Haskell code.  The basic API
+                     is straightforward: a @Par@ monad supports forking
+                     and simple communication in terms of 'IVar's.
+
+                     This module is an interface module only. It
+                     provides a number of type clasess, but not an
+                     implementation.  The type classes separate different 
+                     levels of @Par@ functionality.  See the 
+                     "Control.Monad.Par.Class" module for more details.
+
+                     The 'monad-par' library is one example of a
+                     concrete library providing this interface.
+
+
+Homepage:            https://github.com/simonmar/monad-par
+License:             BSD3
+License-file:        LICENSE
+Author:              Ryan Newton
+Maintainer:          Ryan Newton <rrnewton@gmail.com>
+Copyright:           (c) Ryan Newton 2011-2012
+Stability:           Experimental
+Category:            Control,Parallelism,Monads
+Build-type:          Simple
+Cabal-version:       >=1.8
+
+extra-source-files:
+
+
+Library
+  Exposed-modules: 
+                 -- A class generalizing different levels of monad-par functionality:
+                   Control.Monad.Par.Class
+
+                 -- A class providing unsafe functionality:
+                 , Control.Monad.Par.Unsafe
+
+  Build-depends: base >= 4 && < 5
+               , deepseq >= 1.2
