packages feed

free-operational (empty) → 0.2.0.0

raw patch · 12 files changed

+723/−0 lines, 12 filesdep +QuickCheckdep +basedep +checkerssetup-changed

Dependencies added: QuickCheck, base, checkers, comonad-transformers, free, free-operational, kan-extensions, mtl, test-framework, test-framework-quickcheck2, transformers

Files

+ Control/Alternative/Operational.hs view
@@ -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)
+ Control/Applicative/Operational.hs view
@@ -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)
+ Control/Monad/Operational.hs view
@@ -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+
+ Control/Monad/Operational/Simple.hs view
@@ -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)
+ Control/Monad/Trans/Operational.hs view
@@ -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+
+ Control/MonadPlus/Operational.hs view
@@ -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)
+ Control/Operational/Class.hs view
@@ -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
+ Control/Operational/Instruction.hs view
@@ -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+
+ LICENSE view
@@ -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.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ free-operational.cabal view
@@ -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+  
+ tests/Properties.hs view
@@ -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 ]