pipes 2.1.0 → 2.2.0
raw patch · 4 files changed
+19/−129 lines, 4 filesdep +transformers-free
Dependencies added: transformers-free
Files
- Control/IMonad/Trans/Free.hs +1/−1
- Control/Monad/Trans/Free.hs +0/−114
- Control/Pipe.hs +9/−9
- pipes.cabal +9/−5
Control/IMonad/Trans/Free.hs view
@@ -29,7 +29,7 @@ data IFreeF f r (x :: * -> *) i = Return (r i) | Wrap (f x i) -- | Indexed equivalent to @FreeT@-data IFreeT f m r i = IFreeT { runIFreeT :: m (IFreeF f r (IFreeT f m r)) i }+newtype IFreeT f m r i = IFreeT { runIFreeT :: m (IFreeF f r (IFreeT f m r)) i } instance (IFunctor f, IMonad m) => IFunctor (IFreeT f m) where fmapI f x = x ?>= returnI . f
− Control/Monad/Trans/Free.hs
@@ -1,114 +0,0 @@-{-|- People commonly misconstrue 'Free' as defining a monad transformer with- 'liftF' behaving like 'lift', however that approach violates the monad- transformer laws. Another common mistake is to include the base monad as a- term in the functor, which also gives rise to an incorrect monad- transformer.-- To solve this, this module provides 'FreeT', which properly generalizes the- free monad to a free monad transformer which is correct by construction.-- The 'FreeT' type commonly arises in coroutine and iteratee libraries that- wish to provide a monad transformer that correctly obeys the monad- transformer laws.--}--module Control.Monad.Trans.Free (- -- * Free monad transformer- -- $freet- FreeF(..),- FreeT(..),- wrap,- liftF,- -- * Free monad- -- $free- Free,- runFree- ) where--import Control.Applicative-import Control.Monad-import Control.Monad.Trans.Class-import Data.Functor.Identity--{- $freet- This differs substantially from the non-monad-transformer version because- of the requirement to nest the constructors within the base monad.-- To deconstruct a free monad transformer, use 'runFreeT' to unwrap it and- bind the result in the base monad. You can then pattern match against the- bound value to obtain the next constructor:--> do x <- runFreeT f-> case x of-> Return r -> ...-> Wrap w -> ...-- Because of this, you cannot create free monad transformers using the raw- constructors from 'FreeF'. Instead you use the smart constructors 'return'- (from @Control.Monad@) and 'wrap'.--}---- | The signature for 'Free'-data FreeF f r x = Return r | Wrap (f x)--{-|- A free monad transformer alternates nesting the base monad @m@ and the base- functor @f@.-- * @f@ - The functor that generates the free monad transformer-- * @m@ - The base monad-- * @r@ - The type of the return value--}-data FreeT f m r = FreeT { runFreeT :: m (FreeF f r (FreeT f m r)) }--instance (Functor f, Monad m) => Functor (FreeT f m) where- fmap = liftM--instance (Functor f, Monad m) => Applicative (FreeT f m) where- pure = return- (<*>) = ap--instance (Functor f, Monad m) => Monad (FreeT f m) where- return = FreeT . return . Return- m >>= f = FreeT $ do- x <- runFreeT m- runFreeT $ case x of- Return r -> f r- Wrap w -> wrap $ fmap (>>= f) w--instance MonadTrans (FreeT f) where- lift = FreeT . liftM Return---- | Smart constructor for 'Wrap'-wrap :: (Monad m) => f (FreeT f m r) -> FreeT f m r-wrap = FreeT . return . Wrap---- | Equivalent to @liftF@ from "Control.Monad.Free"-liftF :: (Functor f, Monad m) => f r -> FreeT f m r-liftF x = wrap $ fmap return x--{- $free- The 'Free' type is isomorphic to the following simple implementation:--> data Free f r = Return r | Wrap (f (Free f r))-- ... except that if you want to pattern match against those constructors, you- must first use 'runFree' to unwrap the value first.--> case (runFreeT f) of-> Return r -> ...-> Wrap w -> ...-- Similarly, you use the smart constructors 'return' and 'wrap' to build a- value of type 'Free'.--}---- | 'FreeT' reduces to 'Free' when specialized to the 'Identity' monad.-type Free f = FreeT f Identity---- | Observation function that exposes the next 'FreeF' constructor-runFree :: Free f r -> FreeF f r (Free f r)-runFree = runIdentity . runFreeT
Control/Pipe.hs view
@@ -201,14 +201,14 @@ x1 <- runFreeT p1 let p1' = FreeT $ return x1 runFreeT $ case x1 of- Return r -> return r- Wrap (Yield y ) -> wrap $ Yield $ fmap (<+< p2) y- Wrap (Await f1) -> FreeT $ do+ Pure r -> return r+ Free (Yield y ) -> wrap $ Yield $ fmap (<+< p2) y+ Free (Await f1) -> FreeT $ do x2 <- runFreeT p2 runFreeT $ case x2 of- Return r -> return r- Wrap (Yield (x, p)) -> f1 x <+< p- Wrap (Await f2 ) -> wrap $ Await $ fmap (p1' <+<) f2+ Pure r -> return r+ Free (Yield (x, p)) -> f1 x <+< p+ Free (Await f2 ) -> wrap $ Await $ fmap (p1' <+<) f2 -- | Corresponds to ('>>>') from @Control.Category@ (>+>) :: (Monad m) => Pipe a b m r -> Pipe b c m r -> Pipe a c m r@@ -268,6 +268,6 @@ runPipe p = do e <- runFreeT p case e of- Return r -> return r- Wrap (Await f) -> runPipe $ f ()- Wrap (Yield y) -> runPipe $ snd y+ Pure r -> return r+ Free (Await f) -> runPipe $ f ()+ Free (Yield y) -> runPipe $ snd y
pipes.cabal view
@@ -1,6 +1,6 @@ Name: pipes-Version: 2.1.0-Cabal-Version: >=1.10.1+Version: 2.2.0+Cabal-Version: >=1.14.0 Build-Type: Simple License: BSD3 License-File: LICENSE@@ -8,7 +8,7 @@ Author: Gabriel Gonzalez Maintainer: Gabriel439@gmail.com Stability: Experimental-Bug-Reports: mailto:Gabriel439@gmail.com+Bug-Reports: https://github.com/Gabriel439/Haskell-Pipes-Library/issues Synopsis: Compositional pipelines Description: \"Iteratees done right\". This library implements@@ -48,12 +48,16 @@ Location: https://github.com/Gabriel439/Haskell-Pipes-Library Library- Build-Depends: base >= 4 && < 5, transformers, void, index-core+ Build-Depends:+ base >= 4 && < 5,+ index-core,+ transformers,+ transformers-free,+ void Exposed-Modules: Control.Frame, Control.Frame.Tutorial, Control.IMonad.Trans.Free,- Control.Monad.Trans.Free, Control.Pipe, Control.Pipe.Tutorial GHC-Options: -O2