diff --git a/Control/Alternative/Operational.hs b/Control/Alternative/Operational.hs
new file mode 100644
--- /dev/null
+++ b/Control/Alternative/Operational.hs
@@ -0,0 +1,64 @@
+{-# LANGUAGE RankNTypes, ScopedTypeVariables, GADTs #-}
+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+
+-- | @operational@-style 'Alternative' programs.  See
+-- "Control.Applicative.Operational" for guidance on how to use this
+-- module.
+module Control.Alternative.Operational 
+    ( module Control.Operational.Class
+    , ProgramAlt(..)
+    , interpretAlt
+    , fromProgramAlt
+
+    , ProgramViewAlt(..)
+    , viewAlt
+    ) where
+
+import Control.Applicative
+import qualified Control.Alternative.Free as Free
+import Control.Alternative.Free hiding (Pure)
+import Control.Operational.Class
+import Control.Operational.Instruction
+import Data.Functor.Yoneda.Contravariant
+
+newtype ProgramAlt instr a =
+    ProgramAlt { -- | Interpret the program as a free 'Alternative' ('Alt').
+                 toAlt :: Alt (Yoneda instr) a 
+               } deriving (Functor, Applicative, Alternative)
+
+instance Operational instr (ProgramAlt instr) where
+    singleton = ProgramAlt . liftAlt . liftInstr
+
+interpretAlt :: forall instr f a.
+                Alternative f =>
+               (forall x. instr x -> f x)
+             -> ProgramAlt instr a 
+             -> f a
+interpretAlt evalI = runAlt (liftEvalI evalI) . toAlt
+
+fromProgramAlt 
+    :: (Operational instr f, Alternative f) => ProgramAlt instr a -> f a
+fromProgramAlt = interpretAlt singleton
+
+data ProgramViewAlt instr a where
+    Pure    :: a -> ProgramViewAlt instr a
+    (:<**>) :: instr a
+            -> ProgramViewAlt instr (a -> b) 
+            -> ProgramViewAlt instr b
+    Empty   :: ProgramViewAlt instr a
+    (:<|>)  :: ProgramViewAlt instr a 
+            -> ProgramViewAlt instr a
+            -> ProgramViewAlt instr a
+
+-- this is the same fixity as '<**>' and '<|>'; dunno why it's not infixr
+infixl 4 :<**>
+infixl 3 :<|>
+
+viewAlt :: ProgramAlt instr a -> ProgramViewAlt instr a
+viewAlt = viewAlt' . toAlt
+
+viewAlt' :: Alt (Yoneda instr) a -> ProgramViewAlt instr a
+viewAlt' (Free.Pure a) = Pure a
+viewAlt' (Free.Ap (Yoneda f i) next) = i :<**> viewAlt' (fmap (.f) next)
+viewAlt' (Free.Alt xs) = foldr (:<|>) Empty (map viewAlt' xs)
diff --git a/Control/Applicative/Operational.hs b/Control/Applicative/Operational.hs
new file mode 100644
--- /dev/null
+++ b/Control/Applicative/Operational.hs
@@ -0,0 +1,195 @@
+{-# LANGUAGE RankNTypes, ScopedTypeVariables, GADTs #-}
+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+
+-- | 'Applicative' programs over an @operational@-style instruction
+-- set, implemented on top of the 'Ap' free 'Applicative' type.
+module Control.Applicative.Operational 
+    ( module Control.Operational.Class
+    , ProgramAp(..)
+    , interpretAp
+    , fromProgramAp
+
+    , ProgramViewAp(..)
+    , viewAp
+    , compile
+
+    , foldProgramViewAp
+    , instructions
+    , AnyInstr(..)
+    ) where
+
+import Control.Applicative
+import Control.Applicative.Free (Ap, runAp, liftAp)
+import qualified Control.Applicative.Free as Free
+import Control.Operational.Class
+import Control.Operational.Instruction
+import Data.Functor.Yoneda.Contravariant
+
+
+-- | An 'Applicative' program over instruction set @instr@.  This is
+-- modeled after the 'Program' type from @operational@
+-- (<http://hackage.haskell.org/package/operational>), but this one is
+-- an 'Applicative', not a 'Monad'.  This makes it less powerful, but
+-- in exchange for the sacrificed power 'ProgramAp' is suceptible to
+-- much stronger static analysis.
+--
+-- For examples of this (though applied to free applicatives), see:
+--
+-- * <http://gergo.erdi.hu/blog/2012-12-01-static_analysis_with_applicatives/>
+-- 
+-- * <http://paolocapriotti.com/blog/2013/04/03/free-applicative-functors/>
+newtype ProgramAp instr a = 
+    ProgramAp { -- | Interpret a 'ProgramAp' as a free applicative ('Ap').
+               toAp :: Ap (Yoneda instr) a 
+              } deriving (Functor, Applicative)
+
+instance Operational instr (ProgramAp instr) where
+    singleton = ProgramAp . liftAp . liftInstr
+
+-- | Evaluate a 'ProgramAp' by interpreting each instruction as an
+-- 'Applicative' action. Example @Reader@ implementation:
+--
+-- > type Reader r a = ProgramAp (ReaderI r) a
+-- >
+-- > data ReaderI r a where
+-- >     Ask :: ReaderI r r
+-- > 
+-- > ask :: Reader r r
+-- > ask = singleton Ask
+-- > 
+-- > runReader :: forall r a. Reader r a -> r -> a
+-- > runReader = interpretAp evalI
+-- >     where evalI :: forall a. ReaderI r a -> r -> a
+-- >           evalI Ask = id
+interpretAp :: forall instr f a.
+               Applicative f =>
+               (forall x. instr x -> f x)
+            -> ProgramAp instr a 
+            -> f a
+interpretAp evalI = runAp (liftEvalI evalI) . toAp
+
+-- | Lift a 'ProgramAp' into any other 'Operational' program type that
+-- is at least as strong as 'Applicative'; e.g., lift an applicative
+-- program into a monadic one.  Note that not all applicatives are
+-- monads, so a lifted program may \"lose\" some of the
+-- interpretations that the original could be given.
+fromProgramAp
+    :: (Operational instr f, Applicative f) => ProgramAp instr a -> f a
+fromProgramAp = interpretAp singleton
+
+
+-- | A friendly concrete tree view type for 'ProgramAp'.  Unlike the
+-- ':>>=' constructor in the 'ProgramView' type of
+-- "Control.Monad.Operational", whose second data member is a function
+-- that consumes an instruction result to generate the rest of the
+-- program, our ':<**>' constructor exposes the rest of program
+-- immediately.
+--
+-- Note that the 'ProgramViewAp' type normalizes the program into a
+-- different ordering and bracketing than the applicative '<*>'
+-- operator does.  The ':<**>' constructor is an analogue of @'<**>'
+-- :: Applicative f => f a -> f (a -> b) -> f b@ from
+-- "Control.Applicative".  The normalization means that you get a
+-- list-like structure with instructions as the elements (in the same
+-- order as their effects) and 'Pure' as the terminator.
+--
+-- A static analysis example, based on Capriotti and Kaposi (2013,
+-- <http://paolocapriotti.com/blog/2013/04/03/free-applicative-functors/>):
+--
+-- > {-# LANGUAGE GADTs, RankNTypes, ScopedTypeVariables #-}
+-- >
+-- > import Control.Operational.Applicative
+-- > 
+-- > data FileSystemI a where
+-- >     Read  :: FilePath -> FileSystemI String 
+-- >     Write :: FilePath -> String -> FileSystemI ()
+-- > 
+-- > -- | Count how many file accesses a program does.
+-- > count :: ProgramAp FileSystemI a -> Int
+-- > count = count' . viewAp
+-- >     where count' :: forall x. ProgramViewAp FileSystemI x -> Int
+-- >           count' (Pure _)   = 0
+-- >           count' (_ :<**> k) = succ (count' k)
+-- 
+-- Or actually, just this:
+--
+-- > count :: ProgramAp FileSystemI a -> Int
+-- > count = length . instructions
+--
+-- You can also use the 'ProgramViewAp' to interpret the program, in
+-- the style of the @operational@ package.  Example implementation of
+-- a simple terminal language in this style:
+--
+-- > data TermI a where
+-- >     Say :: String -> TermI ()
+-- >     Get :: TermI String
+-- > 
+-- > say :: String -> ProgramAp TermI ()
+-- > say = singleton . Say
+-- > 
+-- > get :: ProgramAp TermI String
+-- > get = singleton Get
+-- > 
+-- > prompt :: String -> ProgramAp TermI String
+-- > prompt str = say str *> get
+-- > 
+-- > runTerm :: ProgramAp TermI a -> IO a
+-- > runTerm = eval . viewAp
+-- >     where eval :: forall x. ProgramViewAp TermI x -> IO x
+-- >           eval (Pure a) = pure a
+-- >           eval (Say str :<**> k) = putStr str <**> eval k
+-- >           eval (Get :<**> k)     = getLine    <**> eval k 
+-- >
+-- > example :: ProgramAp TermI (String, String)
+-- > example = (,) <$> prompt "First question: " <*> prompt "Second question: "
+-- > 
+-- > -- example = Say "First question: " :<**> (Get :<**> (Say "Second question: " :<**> (Get :<**> Pure (\_ a _ b -> (a, b)))))
+--
+-- But as a general rule, 'interpretAp' makes for shorter, less
+-- repetitive, fooler-proof interpreters:
+--
+-- > runTerm :: ProgramAp TermI a -> IO a
+-- > runTerm = interpretAp evalI
+-- >     where evalI :: forall x. TermI x -> IO x
+-- >           evalI (Say str)   = putStr str
+-- >           evalI Get         = getLine
+--
+data ProgramViewAp instr a where
+    Pure   :: a -> ProgramViewAp instr a
+    (:<**>) :: instr a
+            -> ProgramViewAp instr (a -> b) 
+            -> ProgramViewAp instr b
+
+-- this is the same fixity as '<**>'; dunno why it's not infixr
+infixl 4 :<**>  
+
+-- | Materialize a 'ProgramAp' as a concrete tree.  Note that
+-- 'ProgramAp''s 'Functor' and 'Applicative' instances normalize their
+-- programs, so the view term may not look like the code that created
+-- it.  Instructions however will appear in the order that their
+-- effects should happen, from left to right.
+viewAp :: ProgramAp instr a -> ProgramViewAp instr a
+viewAp = viewAp' . toAp
+
+viewAp' :: Ap (Yoneda instr) a -> ProgramViewAp instr a
+viewAp' (Free.Pure a) = Pure a
+viewAp' (Free.Ap (Yoneda f i) next) = i :<**> viewAp' (fmap (.f) next)
+
+-- | Compile a 'ProgramViewAp' back into a 'ProgramAp'.
+compile :: ProgramViewAp instr a -> ProgramAp instr a
+compile (Pure f) = pure f
+compile (instr :<**> k) = singleton instr <**> compile k
+
+
+foldProgramViewAp :: (forall x. instr x -> r -> r) 
+                 -> r
+                 -> ProgramViewAp instr a
+                 -> r
+foldProgramViewAp k z (Pure _) = z
+foldProgramViewAp k z (i :<**> is) = k i (foldProgramViewAp k z is)
+
+instructions :: ProgramAp instr a -> [AnyInstr instr]
+instructions = foldProgramViewAp (\i -> (AnyInstr i:)) [] . viewAp
+
+data AnyInstr instr = forall a. AnyInstr (instr a)
diff --git a/Control/Monad/Operational.hs b/Control/Monad/Operational.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Operational.hs
@@ -0,0 +1,104 @@
+{-# LANGUAGE RankNTypes, ScopedTypeVariables, GADTs #-}
+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+
+-- | A reconstruction of the @operational@ package in terms of the
+-- 'FreeT' monad transformer.
+--
+-- This module is meant to be a drop-in replacement for its
+-- counterpart in the @operational@ package.  Some of the
+-- implementation choices reflect that:
+--
+-- * @'Program' instr@ and @'ProgramView' instr@ are type synonyms for
+--   @'ProgramT' instr m@ and @'ProgramViewT' instr m@, just as in
+--   @operational@.  If you don't care for that,
+--   "Control.Monad.Operational.Simple" implements them directly in
+--   terms of 'Free'.
+--
+-- The 'ProgramT' and 'ProgramViewT' types and operations are
+-- reexported from "Control.Monad.Trans.Operational".
+module Control.Monad.Operational
+    ( module Control.Operational.Class
+    , module Control.Monad.Trans.Operational
+    , Program
+    , toFree
+    , fromProgram
+    , liftProgram
+    , interpret
+    , interpretWithMonad
+    , ProgramView
+    , view
+    ) where
+
+import Control.Applicative
+import Control.Monad
+import Control.Monad.Free (Free)
+import qualified Control.Monad.Free as Free
+import Control.Monad.Identity
+import Control.Monad.Trans
+import Control.Monad.Trans.Identity
+import Control.Monad.Trans.Free (FreeT)
+import qualified Control.Monad.Trans.Free as FreeT
+import Control.Monad.Trans.Operational
+import Control.Operational.Class
+import Control.Operational.Instruction
+import Data.Functor.Yoneda.Contravariant
+
+
+-- | Drop-in replacement for @operational@'s type synonym.
+type Program instr = ProgramT instr Identity
+
+-- | The 'Free' monad action for a 'Program'.
+toFree :: Program instr a -> Free (Yoneda instr) a
+toFree = freeT2Free . toFreeT
+    where
+      freeT2Free :: Functor f => FreeT f Identity a -> Free f a
+      freeT2Free = adjust . runIdentity . FreeT.runFreeT
+          where adjust (FreeT.Pure a) = Free.Pure a
+                adjust (FreeT.Free fb) = Free.Free $ fmap freeT2Free fb
+
+-- | Lift a 'Program' into any 'Operational' type at least as strong
+-- as 'Monad'.
+fromProgram
+    :: (Operational instr m, Functor m, Monad m) => Program instr a -> m a
+fromProgram = interpret singleton
+
+-- | Lift a 'Program' into a 'ProgramT'.  Really the same as
+-- 'fromProgram', but with a more restricted type; this function is a
+-- drop-in replacement for the eponymous function in @operational@.
+liftProgram :: Monad m => Program instr a -> ProgramT instr m a
+liftProgram = fromProgram
+
+
+-- | Interpret a 'Program' by interpreting each instruction as a
+-- monadic action.  Unlike 'interpretWithMonad', this soes not use
+-- 'view' nor 'ProgramView'.
+--
+-- This function is not a drop-in replacement for 'interpretWithMonad'
+-- because it has an extra @Functor m@ constraint.
+interpret :: forall m instr a. (Functor m, Monad m) =>
+             (forall x. instr x -> m x)
+          -> Program instr a
+          -> m a
+interpret evalI = runIdentityT . interpretTM (lift . evalI) . liftProgram
+
+-- | Drop-in replacement for the eponymous function in the
+-- @operational@ package.  This is like 'interpret' but with a
+-- slightly broader type, and the same implementation as in
+-- @operational@ (in terms of 'view').
+interpretWithMonad :: Monad m =>
+                      (forall x. instr x -> m x)
+                   -> Program instr a
+                   -> m a
+interpretWithMonad evalI = eval . view
+    where eval (Return a) = return a
+          eval (i :>>= k) = evalI i >>= interpretWithMonad evalI . k
+
+
+-- | Drop-in replacement for @operational@'s eponymous type synonym.
+type ProgramView instr = ProgramViewT instr Identity
+
+-- | Drop-in replacement for @operational@'s function.
+view :: Program instr a -> ProgramView instr a
+view = runIdentity . viewT
+
diff --git a/Control/Monad/Operational/Simple.hs b/Control/Monad/Operational/Simple.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Operational/Simple.hs
@@ -0,0 +1,53 @@
+{-# LANGUAGE RankNTypes, ScopedTypeVariables, GADTs #-}
+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+
+-- | A simpler, non-transformer version of this package's
+-- "Control.Monad.Operational"\'s 'Program' type, using 'Free'
+-- directly.
+module Control.Monad.Operational.Simple 
+    ( module Control.Operational.Class
+    , Program(..)
+    , interpret
+    , fromProgram
+    , ProgramView(..)
+    , view
+    ) where
+
+import Control.Applicative
+import Control.Monad.Free
+import Control.Operational.Class
+import Control.Operational.Instruction
+import Data.Functor.Yoneda.Contravariant
+
+
+newtype Program instr a = 
+    Program { -- | Intepret the program as a 'Free' monad.
+              toFree :: Free (Yoneda instr) a 
+            } deriving (Functor, Applicative, Monad)
+
+instance Operational instr (Program instr) where
+    singleton = Program . liftF . liftInstr
+
+-- | Interpret a 'Program' by translating each instruction to a
+-- 'Monad' action.  Does not use 'view'.
+interpret :: forall m instr a. (Functor m, Monad m) => 
+             (forall x. instr x -> m x)
+          -> Program instr a
+          -> m a
+interpret evalI = retract . hoistFree (liftEvalI evalI) . toFree
+
+-- | Lift a 'Program' to any 'Operational' instance at least as
+-- powerful as 'Monad'.
+fromProgram
+    :: (Operational instr m, Functor m, Monad m) => Program instr a -> m a
+fromProgram = interpret singleton
+
+data ProgramView instr a where
+    Return :: a -> ProgramView instr a
+    (:>>=) :: instr a -> (a -> Program instr b) -> ProgramView instr b
+
+view :: Program instr a -> ProgramView instr a
+view = eval . toFree 
+    where eval (Pure a) = Return a
+          eval (Free (Yoneda f i)) = i :>>= (Program . f)
diff --git a/Control/Monad/Trans/Operational.hs b/Control/Monad/Trans/Operational.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Trans/Operational.hs
@@ -0,0 +1,87 @@
+{-# LANGUAGE RankNTypes, ScopedTypeVariables, GADTs #-}
+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+
+module Control.Monad.Trans.Operational
+    ( ProgramT(..)
+    , interpretT
+    , interpretTM
+    , interpretM
+    , ProgramViewT(..)
+    , viewT
+    ) where
+
+import Control.Applicative
+import Control.Monad
+import Control.Monad.Trans
+import Control.Monad.Trans.Free
+import Control.Operational.Class
+import Control.Operational.Instruction
+import Data.Functor.Yoneda.Contravariant
+
+
+newtype ProgramT instr m a = 
+    ProgramT { toFreeT :: FreeT (Yoneda instr) m a 
+             } deriving (Functor, Applicative, Monad, MonadTrans)
+
+instance Monad m => Operational instr (ProgramT instr m) where
+    singleton = ProgramT . liftF . liftInstr
+
+-- | Given an intepretation of @instr x@ as actions over a given monad
+-- transformer @t@ (transforming over an arbitrary monad @m@),
+-- interpret @'ProgramT' instr@ as a monad transformer @t@.  Read that
+-- sentence and the type carefully: the instruction interpretation can
+-- pick its choice of @t@ but not @m@.
+interpretT
+    :: forall t m instr a. 
+       (MonadTrans t, Functor (t m), Monad (t m), Functor m, Monad m) => 
+       (forall n x. 
+        (Functor n, Monad n) =>
+        instr x -> t n x) -- ^ interpret @instr@ over a transformer
+                          -- @t@ and any wrapped monad @n@.
+    -> ProgramT instr m a 
+    -> t m a
+interpretT evalI = retractT . transFreeT evalF . toFreeT
+    where evalF :: forall m x.
+                   (Functor (t m), Monad (t m), Functor m, Monad m) => 
+                   Yoneda instr x -> t m x
+          evalF (Yoneda f i) = fmap f (evalI i)
+
+retractT :: (MonadTrans t, Functor (t m), Monad (t m), Monad m) => 
+            FreeT (t m) m a -> t m a
+retractT = retract . hoistFreeT lift
+
+retract :: Monad m => FreeT m m a -> m a
+retract prog = do fab <- runFreeT prog
+                  case fab of
+                    Pure a  -> return a
+                    Free fb -> join $ liftM retract fb
+
+-- | Given an intepretation of @instr x@ as actions over a given
+-- transformed monad @t m@, interpret @'ProgramT' instr@ as a
+-- transformed monad @t m@.  Read that sentence and the type
+-- carefully: the instruction interpretation can pick its choice of
+-- both @t@ and @m@.
+interpretTM
+    :: (MonadTrans t, Functor (t m), Monad (t m), Monad m) => 
+       (forall x. instr x -> t m x) -- ^ interpret @instr@ over @t m@
+    -> ProgramT instr m a
+    -> t m a
+interpretTM evalI = retractT . transFreeT (liftEvalI evalI) . toFreeT
+
+interpretM :: (Functor m, Monad m) => 
+              (forall x. instr x -> m x) -> ProgramT instr m a -> m a
+interpretM evalI = retract . transFreeT (liftEvalI evalI) . toFreeT
+
+
+data ProgramViewT instr m a where
+    Return :: a -> ProgramViewT instr m a
+    (:>>=) :: instr a -> (a -> ProgramT instr m b) -> ProgramViewT instr m b
+
+infixl 1 :>>=
+
+viewT :: Monad m => ProgramT instr m a -> m (ProgramViewT instr m a)
+viewT = liftM eval . runFreeT . toFreeT
+    where eval (Pure a) = Return a
+          eval (Free (Yoneda f i)) = i :>>= ProgramT . f
+
diff --git a/Control/MonadPlus/Operational.hs b/Control/MonadPlus/Operational.hs
new file mode 100644
--- /dev/null
+++ b/Control/MonadPlus/Operational.hs
@@ -0,0 +1,57 @@
+{-# LANGUAGE RankNTypes, ScopedTypeVariables, GADTs #-}
+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+
+-- | @operational@-style programs for 'MonadPlus'.  See the
+-- documentation for "Control.Applicative.Operational" and
+-- "Control.Monad.Operational" for guidance on how to use this module.
+module Control.MonadPlus.Operational
+    ( module Control.Operational.Class
+    , ProgramP(..)
+    , interpretP
+    , fromProgramP
+      
+    , ProgramViewP(..)
+    , view
+    ) where
+
+import Control.Applicative
+import Control.Monad
+import Control.MonadPlus.Free
+import Control.Operational.Class
+import Data.Functor.Yoneda.Contravariant
+
+newtype ProgramP instr a = 
+    ProgramP { -- | Interpret the program as a free 'MonadPlus'.
+               toFree :: Free (Yoneda instr) a 
+             } deriving (Functor, Applicative, Alternative, Monad, MonadPlus)
+
+instance Operational instr (ProgramP instr) where
+    singleton = ProgramP . liftF . liftYoneda
+
+interpretP :: forall m instr a. (Functor m, MonadPlus m) => 
+              (forall x. instr x -> m x)
+           -> ProgramP instr a
+           -> m a
+interpretP evalI = retract . hoistFree evalF . toFree
+    where evalF :: forall x. Yoneda instr x -> m x
+          evalF (Yoneda f i) = fmap f (evalI i)
+
+fromProgramP
+    :: (Operational instr m, Functor m, MonadPlus m) => ProgramP instr a -> m a
+fromProgramP = interpretP singleton
+
+
+data ProgramViewP instr a where
+    Return :: a -> ProgramViewP instr a
+    (:>>=) :: instr a -> (a -> ProgramP instr b) -> ProgramViewP instr b
+    MEmpty :: ProgramViewP instr a
+    MPlus  :: ProgramViewP instr a
+           -> ProgramViewP instr a
+           -> ProgramViewP instr a
+
+view :: ProgramP instr a -> ProgramViewP instr a
+view = eval . toFree 
+    where eval (Pure a) = Return a
+          eval (Free (Yoneda f i)) = i :>>= (ProgramP . f)
+          eval (Plus mas) = foldr MPlus MEmpty (map eval mas)
diff --git a/Control/Operational/Class.hs b/Control/Operational/Class.hs
new file mode 100644
--- /dev/null
+++ b/Control/Operational/Class.hs
@@ -0,0 +1,10 @@
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
+
+module Control.Operational.Class 
+    ( Operational(..)
+    ) where
+
+-- | The class of operational programs.  
+class Operational instr p | p -> instr where
+    -- | Make a program out of an instruction.
+    singleton :: instr a -> p a
diff --git a/Control/Operational/Instruction.hs b/Control/Operational/Instruction.hs
new file mode 100644
--- /dev/null
+++ b/Control/Operational/Instruction.hs
@@ -0,0 +1,34 @@
+{-# LANGUAGE Rank2Types #-}
+
+-- | Utility functions for working with instructions and instruction sets.
+--
+-- The "Data.Functor.Coproduct" module is very useful with instruction
+-- sets, so this module reexports it.  The 'Coproduct' type can be
+-- used to take the union of two instruction sets, and the 'coproduct'
+-- function can be used to construct an instruction evaluation for
+-- such an union.  So if we have these two instruction evaluations:
+--
+-- > evalI  :: forall x. instr  x -> f x
+-- > evalI' :: forall x. instr' x -> f x 
+--
+-- then their 'coproduct' is an evaluation for the union of the
+-- instruction sets:
+-- 
+-- > coproduct evalI evalI' :: forall x. (Coproduct instr instr' x) -> f x
+module Control.Operational.Instruction 
+    ( module Data.Functor.Coproduct
+    , liftEvalI
+    , liftInstr
+    ) where
+
+import Data.Functor.Coproduct
+import Data.Functor.Yoneda.Contravariant
+
+-- | Lift an operational instruction evaluator into a free 'Functor'
+-- evaluator.
+liftEvalI :: Functor f => (forall x. instr x -> f x)  -> Yoneda instr a -> f a
+liftEvalI evalI (Yoneda f i) = fmap f (evalI i) 
+
+liftInstr :: instr a -> Yoneda instr a
+liftInstr = liftYoneda
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2013, Luis Casillas
+
+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 Luis Casillas 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,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/free-operational.cabal b/free-operational.cabal
new file mode 100644
--- /dev/null
+++ b/free-operational.cabal
@@ -0,0 +1,74 @@
+name:                free-operational
+category:            Control
+version:             0.2.0.0
+build-type:          Simple
+cabal-version:       >=1.8
+synopsis:            Operational Applicative, Alternative, Monad and MonadPlus, built with free types.
+
+description:         
+    A reimplementation of the @operational@ package
+    (<http://hackage.haskell.org/package/operational>) using free monads 
+    (from <http://hackage.haskell.org/package/free>).  This implements
+    ideas discussed here:
+    .
+    * <http://stackoverflow.com/questions/14263363/is-operational-really-isomorphic-to-a-free-monad>
+    .
+    * <http://www.reddit.com/r/haskell/comments/17a33g/free_functors_the_reason_free_and_operational_are/>
+    .
+    To understand the basic concepts you can do no better than read
+    Heinrich Apfelmus' @operational@ tutorial:
+    .
+    * <http://apfelmus.nfshost.com/articles/operational-monad.html>
+    .
+    In addition to that, this package supplies @operational@-style
+    modules for 'Applicative', 'Alternative' and 'MonadPlus'.
+    'Applicative' and 'Alternative' programs easily admit of static
+    analysis.  See these references for discussion and examples:
+    .
+    * <http://gergo.erdi.hu/blog/2012-12-01-static_analysis_with_applicatives/> (discussion: <http://www.reddit.com/r/haskell/comments/143wpd/static_analysis_with_applicatives/>)
+    .
+    * <http://paolocapriotti.com/blog/2013/04/03/free-applicative-functors/> (discussion: <http://www.reddit.com/r/haskell/comments/1bnql3/free_applicative_functors_icfp_submission/>)
+    .
+    See "Control.Applicative.Operational" for the bulk of the documentation.
+
+license:             BSD3
+license-file:        LICENSE
+author:              Luis Casillas
+maintainer:          luis@casillas.org
+copyright:           2013 Luis Casillas
+bug-reports:         https://github.com/sacundim/free-operational/issues
+source-repository head
+  type:           git
+  location:       https://github.com/sacundim/free-operational
+
+
+test-suite tests
+  type:            exitcode-stdio-1.0
+  hs-source-dirs:  tests
+  Main-is:         Properties.hs
+  build-depends:   base ==4.*,
+                   mtl >=2.1,
+                   transformers >=0.3,
+                   free-operational >=0.2,
+                   test-framework >=0.8,
+                   test-framework-quickcheck2 >=0.3,  
+                   QuickCheck >=2.4,
+                   checkers >=0.3
+
+library
+  exposed-modules:  Control.Operational.Class,
+                    Control.Operational.Instruction,
+                    Control.Applicative.Operational,
+                    Control.Alternative.Operational,
+                    Control.Monad.Operational,
+                    Control.Monad.Operational.Simple,
+                    Control.Monad.Trans.Operational,
+                    Control.MonadPlus.Operational
+  
+  build-depends:       base == 4.*,
+                       transformers >=0.3,
+                       mtl >=2.1,
+                       free >=3.3,
+                       comonad-transformers >=3.0,
+                       kan-extensions >=3.1
+  
diff --git a/tests/Properties.hs b/tests/Properties.hs
new file mode 100644
--- /dev/null
+++ b/tests/Properties.hs
@@ -0,0 +1,13 @@
+module Main
+    ( main
+    ) where
+
+import qualified Properties.Applicative as Ap
+
+import Test.Framework (Test, defaultMain, testGroup)
+
+main :: IO ()
+main = defaultMain tests
+
+tests :: [Test]
+tests = [ testGroup "applicative" Ap.tests ]
