Consumer (empty) → 1.2
raw patch · 4 files changed
+131/−0 lines, 4 filesdep +basedep +mtlsetup-changed
Dependencies added: base, mtl
Files
- Consumer.cabal +14/−0
- Control/Monad/Consumer.hs +111/−0
- Setup.hs +5/−0
- debian/copyright +1/−0
+ Consumer.cabal view
@@ -0,0 +1,14 @@+Name: Consumer+Version: 1.2+License: BSD3+License-File: debian/copyright+Author: Jeremy Shaw+Maintainer: partners@seereason.com+Homepage: http://src.seereason.com/ghc6103/haskell-consumer+Category: Monads+Synopsis: A monad and monad transformer for consuming streams+Description: Useful for building parsing type operations on top of a list of elements+Build-type: Simple+Build-Depends: base < 5, mtl+Exposed-modules:+ Control.Monad.Consumer
+ Control/Monad/Consumer.hs view
@@ -0,0 +1,111 @@+{-# LANGUAGE FunctionalDependencies, FlexibleInstances, MultiParamTypeClasses #-}+-- |A monad for consuming streams - I believe this is basically just a specialized version of the State monad. +module Control.Monad.Consumer where++import Control.Applicative+import Control.Monad+import Control.Monad.Fix+import Control.Monad.Trans++-- * Consumer Monad++newtype Consumer c a = Consumer ([c] -> (a, [c]))++-- | Execute a stateful computation, as a result we get+-- the result of the computation, and the final state.+runConsumer :: [c] -> Consumer c a -> (a, [c])+runConsumer c (Consumer m) = m c++-- | Execute a stateful computation, ignoring the final state.+evalConsumer :: [c] -> Consumer c a -> a+evalConsumer c m = fst (runConsumer c m)++-- | Execute a stateful computation, just for the side effect.+execConsumer :: [c] -> Consumer c a -> [c]+execConsumer c m = snd (runConsumer c m)++instance Functor (Consumer c) where+ fmap f (Consumer m) = Consumer (\c -> let (a,c1) = m c+ in (f a, c1))++instance Monad (Consumer c) where+ return a = Consumer (\c -> (a,c))+ Consumer m >>= k = Consumer (\c -> let (a,c1) = m c+ Consumer n = k a+ in n c1)++instance MonadFix (Consumer c) where+ mfix f = Consumer (\c -> + let Consumer m = f (fst r)+ r = m c + in r)+++class (Monad m) => MonadConsumer m c | m -> c where+ next :: (Monad m') => m (m' c) -- ^ return next element from stream+ peek :: (Monad m') => m (m' c) -- ^ peek at next element, but leave it in the stream+ poke :: c -> m c -- ^ push and element onto the beginning on the stream++instance MonadConsumer (Consumer c) c where+ next = Consumer $ \cs ->+ case cs of+ [] -> (fail "end of stream", [])+ (c:rest) -> (return c,rest)+ peek = Consumer $ \cs ->+ case cs of+ [] -> (fail "end of stream", [])+ cs@(c:_) -> (return c,cs)+ poke c = Consumer $ \cs -> (c,c:cs)++instance Applicative (Consumer a) where+ pure = return+ (<*>) = ap++-- * Consumer Monad Transformer++newtype ConsumerT c m a = ConsumerT { runConsumerT :: [c] -> m (a, [c]) }+++instance (Monad m) => Functor (ConsumerT c m) where+ fmap f m = ConsumerT $ \c -> do+ (x, c') <- runConsumerT m c+ return (f x, c')++instance (Monad m) => Monad (ConsumerT c m) where+ return a = ConsumerT $ \c -> return (a, c)+ m >>= k = ConsumerT $ \c -> do+ (a, c') <- runConsumerT m c+ runConsumerT (k a) c'+ fail str = ConsumerT $ \_ -> fail str++instance (MonadPlus m) => MonadPlus (ConsumerT c m) where+ mzero = lift mzero+ mplus m1 m2 = + ConsumerT $ \c ->+ let m1' = (runConsumerT m1) c+ m2' = (runConsumerT m2) c + in+ mplus m1' m2'++instance (Monad m) => MonadConsumer (ConsumerT c m) c where+ next = ConsumerT $ \cs ->+ case cs of+ [] -> return (fail "End of Stream", [])+ (c:rest) -> return (return c,rest)+ peek = ConsumerT $ \cs ->+ case cs of+ [] -> return (fail "End of Stream", [])+ cs@(c:_) -> return (return c,cs)+ poke c = ConsumerT $ \cs -> return (c,c:cs)++instance MonadTrans (ConsumerT c) where+ lift m = ConsumerT $ \c -> do+ a <- m+ return (a, c)++instance (MonadIO m) => MonadIO (ConsumerT c m) where+ liftIO = lift . liftIO++instance (Monad m) => Applicative (ConsumerT c m) where+ pure = return+ (<*>) = ap
+ Setup.hs view
@@ -0,0 +1,5 @@+#!/usr/bin/runhaskell++import Distribution.Simple++main = defaultMainWithHooks simpleUserHooks
+ debian/copyright view
@@ -0,0 +1,1 @@+BSD