packages feed

operational 0.2.1.1 → 0.2.1.2

raw patch · 4 files changed

+111/−16 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

+ doc/examples/BreadthFirstParsing.hs view
@@ -0,0 +1,78 @@+{------------------------------------------------------------------------------+    Control.Monad.Operational+    +    Example:+    A reformulation of Koen Claessen's Parallel Parsing Processes+    http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.19.9217++    For a detailed explanation, see also+    http://apfelmus.nfshost.com/articles/operational-monad.html#monadic-parser-combinators+------------------------------------------------------------------------------}+{-# LANGUAGE GADTs, Rank2Types, TypeSynonymInstances #-}+module BreadthFirstParsing where++import Control.Monad+import Control.Monad.Operational++{------------------------------------------------------------------------------+    At their core, a parser monad consists of just three+    primitive instructions+    +        symbol -- fetch the next character+        mzero  -- indicate parse failure+        mplus  -- non-deterministic choice between two parsers+    +    and an interpreter function+        +        parse :: Parser a -> (String -> [a])+    +    that applies a parser to a string and returns+    all the possible parse results.+------------------------------------------------------------------------------}+data ParserInstruction a where+    Symbol :: ParserInstruction Char+    MZero  :: ParserInstruction a+    MPlus  :: Parser a -> Parser a -> ParserInstruction a++type Parser = Program ParserInstruction++symbol = singleton Symbol++instance MonadPlus Parser where+    mzero     = singleton $ MZero+    mplus x y = singleton $ MPlus x y++-- apply a parser to a string+-- breadth first fashion: each input character is touched only once+parse :: Parser a -> String -> [a]+parse p = go (expand p)+    where+    go :: [Parser a] -> String -> [a]+    go ps []     = [a | Return a <- map view ps]+    go ps (c:cs) = go [p | (Symbol :>>= is) <- map view ps, p <- expand (is c)] cs++-- keep track of parsers that are run in parallel+expand :: Parser a -> [Parser a]+expand p = case view p of+    MPlus p q :>>= k  -> expand (p >>= k) ++ expand (q >>= k)+    MZero     :>>= k  -> []+    _                 -> [p]+++-- example+-- > parse parens "()(()())"+-- [()]     -- one parse+-- > parse parens "()((())"+-- []       -- no parse+parens :: Parser ()+parens = return () `mplus` (enclose parens >> parens)+    where+    enclose q = char '(' >> q >> char ')'++many :: Parser a -> Parser [a]+many p = mzero `mplus` liftM2 (:) p (many p) ++satisfy :: (Char -> Bool) -> Parser Char+satisfy p = do c <- symbol; if p c then return c else mzero++char c = satisfy (==c)
doc/examples/PoorMansConcurrency.hs view
@@ -3,7 +3,7 @@          Example:     Koen Claessen's Poor Man's Concurrency Monad-    http://www.cs.chalmers.se/~koen/pubs/entry-jfp99-monad.html+    http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.39.8039  ------------------------------------------------------------------------------} {-# LANGUAGE GADTs, Rank2Types #-}@@ -15,7 +15,7 @@  {------------------------------------------------------------------------------     A concurrency monad runs several processes in parallel-    and supports two operations+    and supports two primitive operations          fork  -- fork a new process         stop  -- halt the current one@@ -37,7 +37,7 @@ fork = singleton . Fork lift = singleton . Lift -    -- interpreter+-- interpreter runProcess :: Monad m => Process m a -> m () runProcess m = schedule [m]     where@@ -51,8 +51,8 @@     run (Fork p :>>= k) xs = schedule (xs ++ [x2,x1])  -- fork new process         where x1 = k (); x2 = p >>= k -    -- example-    --      > runProcess example   -- warning: runs indefinitely+-- example+--      > runProcess example   -- warning: runs indefinitely example :: Process IO () example = do         write "Start!"
operational.cabal view
@@ -1,5 +1,5 @@ Name:               operational-Version:            0.2.1.1+Version:            0.2.1.2 Synopsis:           Implementation of difficult monads made easy                     with operational semantics. Description:
src/Control/Monad/Operational.hs view
@@ -13,8 +13,9 @@     -- $example          -- * Monad transformer-    ProgramT, ProgramViewT(..), viewT, liftProgram+    ProgramT, ProgramViewT(..), viewT,     -- $exampleT+    liftProgram,          ) where @@ -82,20 +83,26 @@ @ runCustomMonad :: CustomMonad a -> IO a runCustomMonad m = case view m of-    Return a            -> ...  -- done, return a result-    AskUserInput :>>= k -> ...  -- askUserInput instruction, continue with k+    Return a            -> return a -- done, return the result+    AskUserInput :>>= k -> do+        b <- waitForUserInput       -- wait for external user input+        runCustomMonad (k b)        -- proceed with next instruction @  The point is that you can now proceed in any way you like:-you can wait for the user to return input,+you can wait for the user to return input as shown, or you store the continuation @k@ and retrieve it when your web application receives another HTTP request, or you can keep a log of all user inputs on the client side an replay them,-and so on.+and so on. Moreover, you can implement different @run@ functions+for one and the same custom monad, which is useful for testing.+Also not that the result of the @run@ function does not need to be a monad at all.+ In essence, your custom monad allows you to express your web application as a simple imperative program,-while the underlying implementation maps this to-an event-drived model or some other control flow architecture.+while the underlying implementation can freely map this to+an event-drived model or some other control flow architecture+of your choice.  The possibilities are endless. More usage examples can be found here:@@ -141,6 +148,7 @@  @     type StackProgram a = Program StackInstruction a+    type Stack b        = [b] @  @@@ -199,9 +207,18 @@ singleton = Instr  -- | View type for inspecting the first instruction.+-- This is very similar to pattern matching on lists.+--+-- * The case @(Return a)@ means that the program contains no instructions+-- and just returns the result @a@.+--+-- *The case @(someInstruction :>>= k)@ means that the first instruction+-- is @someInstruction@ and the remaining program is given by the function @k@. data ProgramViewT instr m a where     Return :: a -> ProgramViewT instr m a-    (:>>=) :: instr b -> (b -> ProgramT instr m a ) -> ProgramViewT instr m a+    (:>>=) :: instr b+           -> (b -> ProgramT instr m a)+           -> ProgramViewT instr m a  -- | View function for inspecting the first instruction. viewT :: Monad m => ProgramT instr m a -> m (ProgramViewT instr m a)@@ -243,11 +260,11 @@         Plus :: ListT m a -> ListT m a -> PlusI m a @ -@   +@     type ListT m a = ProgramT (PlusI m) m a @ -@   +@     runList :: Monad m => ListT m a -> m [a]     runList = eval <=< viewT         where