diff --git a/Control/Applicative/Perm.hs b/Control/Applicative/Perm.hs
new file mode 100644
--- /dev/null
+++ b/Control/Applicative/Perm.hs
@@ -0,0 +1,20 @@
+{- |
+Copyright: Andy Sonnenburg (c) 2012
+License: BSD-style (see the file LICENSE)
+Maintainer: Andy Sonnenburg <andy22286@gmail.com>
+Stability: experimental
+Portability: non-portable
+-}
+module Control.Applicative.Perm
+       ( Perm
+       , runPerm
+       , PermT'
+       , liftPerm
+       , hoistPerm
+       ) where
+
+import Control.Monad.Perm.Internal (Perm,
+                                    PermT',
+                                    hoistPerm,
+                                    liftPerm,
+                                    runPerm)
diff --git a/Control/Monad/Perm.hs b/Control/Monad/Perm.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Perm.hs
@@ -0,0 +1,20 @@
+{- |
+Copyright: Andy Sonnenburg (c) 2012
+License: BSD-style (see the file LICENSE)
+Maintainer: Andy Sonnenburg <andy22286@gmail.com>
+Stability: experimental
+Portability: non-portable
+-}
+module Control.Monad.Perm
+       ( PermT
+       , runPermT
+       , PermT'
+       , liftPerm
+       , hoistPerm
+       ) where
+
+import Control.Monad.Perm.Internal (PermT,
+                                    PermT',
+                                    liftPerm,
+                                    hoistPerm,
+                                    runPermT)
diff --git a/Control/Monad/Perm/Internal.hs b/Control/Monad/Perm/Internal.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Perm/Internal.hs
@@ -0,0 +1,193 @@
+{-# LANGUAGE CPP #-}
+#ifdef LANGUAGE_DataKinds
+{-# LANGUAGE DataKinds #-}
+#else
+{-# LANGUAGE EmptyDataDecls #-}
+#endif
+{-# LANGUAGE
+    FlexibleInstances
+  , GADTs
+  , MultiParamTypeClasses
+  , Rank2Types
+  , TypeSynonymInstances
+  , UndecidableInstances #-}
+{- |
+Copyright: Andy Sonnenburg (c) 2012
+License: BSD-style (see the file LICENSE)
+Maintainer: Andy Sonnenburg <andy22286@gmail.com>
+Stability: experimental
+Portability: non-portable
+-}
+module Control.Monad.Perm.Internal
+       ( Perm
+       , runPerm
+       , PermT
+       , runPermT
+       , PermT'
+       , liftPerm
+       , hoistPerm
+       ) where
+
+import Control.Applicative hiding (Applicative)
+import qualified Control.Applicative as Applicative (Applicative)
+import Control.Monad hiding (Monad)
+import qualified Control.Monad as Monad (Monad)
+import Control.Monad.Catch.Class
+import Control.Monad.IO.Class
+import Control.Monad.Reader.Class
+import Control.Monad.State.Class
+import Control.Monad.Trans.Class (MonadTrans (lift))
+
+import Data.Foldable (foldr)
+import Data.Monoid ((<>), mempty)
+
+import Prelude (Maybe (..), ($), (.), const, flip, fst, id, map, maybe)
+
+-- | The permutation applicative
+type Perm = PermT' Applicative
+
+-- | The permutation monad
+type PermT = PermT' Monad
+
+{- |
+The permutation action, available as either an 'Applicative.Applicative'
+or a 'Monad.Monad', determined by the combinators used.
+-}
+data PermT' c m a = Choice (Maybe a) [Branch c m a]
+
+data Branch c m b where
+  Ap :: PermT' c m (a -> b) -> m a -> Branch c m b
+  Bind :: (a -> PermT m b) -> m a -> Branch Monad m b
+
+#ifdef LANGUAGE_DataKinds
+data Constraint = Applicative | Monad
+#else
+data Applicative
+data Monad
+#endif
+
+instance Functor (PermT' c m) where
+  fmap f (Choice a xs) = Choice (f <$> a) (fmap f <$> xs)
+
+instance Functor (Branch c m) where
+  fmap f (Ap perm m) = Ap (fmap (f .) perm) m
+  fmap f (Bind k m) = Bind (fmap f . k) m
+
+instance Applicative.Applicative (PermT' c m) where
+  pure a = Choice (pure a) mempty
+  f@(Choice f' fs) <*> a@(Choice a' as) =
+    Choice (f' <*> a') (fmap (`apB` a) fs <> fmap (f `apP`) as)
+  (*>) = liftThen (*>)
+
+apP :: PermT' c m (a -> b) -> Branch c m a -> Branch c m b
+f `apP` Ap perm m = (f .@ perm) `Ap` m
+f `apP` Bind k m = Bind ((f `ap`) . k) m
+
+(.@) :: Applicative.Applicative f => f (b -> c) -> f (a -> b) -> f (a -> c)
+(.@) = liftA2 (.)
+
+apB :: Branch c m (a -> b) -> PermT' c m a -> Branch c m b
+Ap perm m `apB` a = flipA2 perm a `Ap` m
+Bind k m `apB` a = Bind ((`ap` a) . k) m
+
+flipA2 :: Applicative.Applicative f => f (a -> b -> c) -> f b -> f (a -> c)
+flipA2 = liftA2 flip
+
+instance Alternative (PermT' c m) where
+  empty = liftZero empty
+  (<|>) = plus
+
+instance Monad.Monad (PermT m) where
+  return a = Choice (return a) mempty
+  Choice Nothing xs >>= k = Choice Nothing (map (bindP k) xs)
+  Choice (Just a) xs >>= k = case k a of
+    Choice a' xs' -> Choice a' (map (bindP k) xs <> xs')
+  (>>) = liftThen (>>)
+  fail _ = Choice mzero mempty
+
+bindP :: (a -> PermT m b) -> Branch Monad m a -> Branch Monad m b
+bindP k (Ap perm m) = Bind (\ a -> k . ($ a) =<< perm) m
+bindP k (Bind k' m) = Bind (k <=< k') m
+
+instance MonadPlus (PermT m) where
+  mzero = liftZero mzero
+  mplus = plus
+
+instance MonadTrans (PermT' c) where
+  lift = liftPerm
+
+instance MonadIO m => MonadIO (PermT m) where
+  liftIO = lift . liftIO
+
+instance MonadReader r m => MonadReader r (PermT m) where
+  ask = lift ask
+  local f (Choice a xs) = Choice a (map (localBranch f) xs)
+
+localBranch :: MonadReader r m =>
+               (r -> r) -> Branch Monad m a -> Branch Monad m a
+localBranch f (Ap perm m) = Ap (local f perm) (local f m)
+localBranch f (Bind k m) = Bind (local f . k) (local f m)
+
+instance MonadState s m => MonadState s (PermT m) where
+  get = lift get
+  put = lift . put
+
+#ifdef LANGUAGE_DefaultSignatures
+instance MonadThrow e m => MonadThrow e (PermT m)
+#else
+instance MonadThrow e m => MonadThrow e (PermT m) where
+  throw = lift . throw
+#endif
+
+liftThen :: (Maybe a -> Maybe b -> Maybe b) ->
+            PermT' c m a -> PermT' c m b -> PermT' c m b
+liftThen thenMaybe m@(Choice m' ms) n@(Choice n' ns) =
+  Choice (m' `thenMaybe` n') (map (`thenB` n) ms <> map (m `thenP`) ns)
+
+thenP :: PermT' c m a -> Branch c m b -> Branch c m b
+m `thenP` Ap perm m' = (m *> perm) `Ap` m'
+m `thenP` Bind k m' = Bind ((m >>) . k) m'
+
+thenB :: Branch c m a -> PermT' c m b -> Branch c m b
+Ap perm m `thenB` n = (perm *> fmap const n) `Ap` m
+Bind k m `thenB` n = Bind ((>> n) . k) m
+
+liftZero :: Maybe a -> PermT' c m a
+liftZero zeroMaybe = Choice zeroMaybe mempty
+
+plus :: PermT' c m a -> PermT' c m a -> PermT' c m a
+m@(Choice (Just _) _) `plus` _ = m
+Choice Nothing xs `plus` Choice b ys = Choice b (xs <> ys)
+
+-- | Unwrap a 'Perm', combining actions using the 'Alternative' for @f@.
+runPerm :: Alternative m => Perm m a -> m a
+runPerm = lower
+  where
+    lower (Choice a xs) = foldr ((<|>) . f) (maybe empty pure a) xs
+    f (perm `Ap` m) = m <**> runPerm perm
+
+-- | Unwrap a 'PermT', combining actions using the 'MonadPlus' for @f@.
+runPermT :: MonadPlus m => PermT m a -> m a
+runPermT = lower
+  where
+    lower (Choice a xs) = foldr (mplus . f) (maybe mzero return a) xs
+    f (perm `Ap` m) = flip ($) `liftM` m `ap` runPermT perm
+    f (Bind k m) = m >>= runPermT . k
+
+-- | A version of 'lift' without the @'Monad.Monad' m@ constraint
+liftPerm :: m a -> PermT' c m a
+liftPerm = Choice empty . pure . liftBranch
+
+liftBranch :: m a -> Branch c m a
+liftBranch = Ap (Choice (pure id) mempty)
+
+{- |
+Lift a natural transformation from @m@ to @n@ into a natural transformation
+from @'PermT'' c m@ to @'PermT'' c n@.
+-}
+hoistPerm :: (forall a . m a -> n a) -> PermT' c m b -> PermT' c n b
+hoistPerm f (Choice a xs) = Choice a (hoistBranch f <$> xs)
+
+hoistBranch :: (forall a . m a -> n a) -> Branch c m b -> Branch c n b
+hoistBranch f (perm `Ap` m) = hoistPerm f perm `Ap` f m
+hoistBranch f (Bind k m) = Bind (hoistPerm f . k) (f m)
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2012, Andy Sonnenburg
+
+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 Andy Sonnenburg 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.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,7 @@
+#!/usr/bin/env runhaskell
+> module Main (main) where
+
+> import Distribution.Simple (defaultMain)
+
+> main :: IO ()
+> main = defaultMain
diff --git a/perm.cabal b/perm.cabal
new file mode 100644
--- /dev/null
+++ b/perm.cabal
@@ -0,0 +1,50 @@
+name:          perm
+version:       0.1.0.0
+cabal-version: >= 1.10
+synopsis:      permutation Applicative and Monad with many mtl instances
+description:
+  Based on \"Parsing Permutation Phrases\", by Arthur Baars, Andres Loeh and S.
+  Doaitse Swierstra, /Haskell Workshop 2001/.  The implementation given here
+  does not include explicit optional actions, and instead implements
+  'Control.Applicative.Alternative' and 'Control.Monad.MonadPlus'.
+  @m 'Control.Applicative.<|>' 'Control.Applicative.pure' a@ should be used where
+  @'addOpt' a m@ would be used.
+license:       BSD3
+license-file:  LICENSE
+author:        Andy Sonnenburg
+maintainer:    Andy Sonnenburg <andy22286@gmail.com>
+category:      Control
+homepage:      https://github.com/sonyandy/perm
+bug-reports:   https://github.com/sonyandy/perm/issues
+build-type:    Simple
+
+source-repository head
+  type: git
+  location: git://github.com/sonyandy/perm.git
+
+library
+  default-language: Haskell98
+  exposed-modules:
+    Control.Applicative.Perm
+    Control.Monad.Perm
+  other-modules:
+    Control.Monad.Perm.Internal
+  build-depends:
+    base >= 4 && < 5,
+    transformers >= 0.2 && < 0.4,
+    mtl >= 2.0 && < 2.2,
+    catch-fd >= 0.2 && < 0.4
+  ghc-options: -Wall
+  if impl(ghc >= 7.6)
+    cpp-options: -DLANGUAGE_DataKinds
+  else
+    other-extensions: EmptyDataDecls
+  if impl(ghc >= 7.2)
+    cpp-options: -DLANGUAGE_DefaultSignatures
+  other-extensions:
+    FlexibleInstances
+    GADTs
+    MultiParamTypeClasses
+    Rank2Types
+    TypeSynonymInstances
+    UndecidableInstances
