arrow-list 0.6.1.5 → 0.7
raw patch · 10 files changed
+394/−382 lines, 10 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Control.Arrow.ArrowF: arrMF :: (ArrowF f arr, ArrowKleisli m arr) => (a -> m (f c)) -> a arr c
- Control.Arrow.ArrowF: class Arrow arr => ArrowF f arr | arr -> f
- Control.Arrow.ArrowF: concatA :: ArrowPlus arr => [a arr b] -> a arr b
- Control.Arrow.ArrowF: const :: Arrow arr => b -> a arr b
- Control.Arrow.ArrowF: constF :: ArrowF f arr => f c -> a arr c
- Control.Arrow.ArrowF: embed :: ArrowF f arr => f a arr a
- Control.Arrow.ArrowF: filterA :: (Alternative f, Foldable f, ArrowF f arr, ArrowChoice arr) => (a arr c) -> a arr a
- Control.Arrow.ArrowF: guards :: (Alternative f, Foldable f, ArrowF f arr, ArrowChoice arr) => (a arr c) -> (a arr b) -> (a arr b)
- Control.Arrow.ArrowF: ifA :: (Foldable f, ArrowF f arr, ArrowChoice arr) => (a arr b) -> (a arr t) -> (a arr t) -> a arr t
- Control.Arrow.ArrowF: isA :: (Alternative f, ArrowF f arr) => (a -> Bool) -> a arr a
- Control.Arrow.ArrowF: mapF :: ArrowF f arr => (f b -> f c) -> a arr b -> a arr c
- Control.Arrow.ArrowF: maybeA :: (Alternative f, ArrowF f arr) => Maybe a arr a
- Control.Arrow.ArrowF: none :: (Alternative f, ArrowF f arr) => a arr b
- Control.Arrow.ArrowF: notA :: (Alternative f, Foldable f, ArrowF f arr, ArrowChoice arr) => (a arr c) -> a arr a
- Control.Arrow.ArrowF: observe :: ArrowF f arr => (a arr b) -> a arr f b
- Control.Arrow.ArrowF: optional :: (Foldable f, ArrowF f arr, ArrowChoice arr) => (a arr b) -> a arr Maybe b
- Control.Arrow.ArrowF: orElse :: (Foldable f, ArrowF f arr, ArrowChoice arr) => (a arr b) -> (a arr b) -> a arr b
- Control.Arrow.ArrowF: plus :: (Alternative f, ArrowF f arr) => (a arr b) -> (a arr b) -> a arr b
- Control.Arrow.ArrowF: results :: (Foldable f, ArrowF f arr) => (a arr b) -> (a arr Bool)
- Control.Arrow.ArrowF: unite :: ArrowPlus arr => (b, b) arr b
- Control.Arrow.ArrowF: when :: (Foldable f, ArrowF f arr, ArrowChoice arr) => (a arr a) -> (a arr c) -> a arr a
- Control.Arrow.ArrowKleisli: arrIO :: (MonadIO m, ArrowKleisli m arr) => (a -> IO b) -> a arr b
- Control.Arrow.ArrowKleisli: arrM :: ArrowKleisli m arr => (a -> m b) -> a arr b
- Control.Arrow.ArrowKleisli: class (Monad m, Arrow arr) => ArrowKleisli m arr | arr -> m
- Control.Arrow.ArrowKleisli: constM :: ArrowKleisli m arr => m b -> a arr b
- Control.Arrow.ArrowKleisli: effect :: ArrowKleisli m arr => m () -> a arr a
- Control.Arrow.ArrowKleisli: instance Monad m => ArrowKleisli m (Kleisli m)
- Control.Arrow.ArrowList: arrL :: ArrowList arr => (a -> [b]) -> a arr b
- Control.Arrow.ArrowList: class Arrow arr => ArrowList arr
- Control.Arrow.ArrowList: concatA :: ArrowPlus arr => [a arr b] -> a arr b
- Control.Arrow.ArrowList: empty :: ArrowList arr => (a arr b) -> a arr Bool
- Control.Arrow.ArrowList: filterA :: (ArrowChoice arr, ArrowList arr) => (a arr c) -> a arr a
- Control.Arrow.ArrowList: guards :: (ArrowList arr, ArrowChoice arr) => (a arr c) -> (a arr b) -> a arr b
- Control.Arrow.ArrowList: ifA :: (ArrowList arr, ArrowChoice arr) => (a arr c) -> (a arr b) -> (a arr b) -> a arr b
- Control.Arrow.ArrowList: isA :: ArrowList arr => (a -> Bool) -> a arr a
- Control.Arrow.ArrowList: list :: ArrowList arr => (a arr b) -> a arr [b]
- Control.Arrow.ArrowList: mapL :: ArrowList arr => ([b] -> [c]) -> (a arr b) -> (a arr c)
- Control.Arrow.ArrowList: maybeL :: ArrowList arr => Maybe a arr a
- Control.Arrow.ArrowList: none :: ArrowList arr => a arr b
- Control.Arrow.ArrowList: notA :: (ArrowList arr, ArrowChoice arr) => (a arr c) -> a arr a
- Control.Arrow.ArrowList: optional :: (ArrowChoice arr, ArrowList arr) => (a arr b) -> a arr Maybe b
- Control.Arrow.ArrowList: orElse :: (ArrowList arr, ArrowChoice arr) => (a arr b) -> (a arr b) -> a arr b
- Control.Arrow.ArrowList: unite :: ArrowList arr => (a arr (b, b)) -> a arr b
- Control.Arrow.ArrowList: unlist :: ArrowList arr => [b] arr b
- Control.Arrow.ArrowList: when :: (ArrowList arr, ArrowChoice arr) => (a arr a) -> (a arr b) -> a arr a
- Control.Arrow.List: instance Monad m => ArrowF [] (ListTArrow m)
- Control.Arrow.Sequence: instance Monad m => ArrowF Seq (SeqTArrow m)
- Control.Monad.Sequence: instance Alternative Seq
- Control.Monad.Sequence: instance Applicative Seq
+ Control.Arrow.Kleisli.Class: arrIO :: (MonadIO m, ArrowKleisli m arr) => (a -> IO b) -> a `arr` b
+ Control.Arrow.Kleisli.Class: arrM :: ArrowKleisli m arr => (a -> m b) -> a `arr` b
+ Control.Arrow.Kleisli.Class: class (Monad m, Arrow arr) => ArrowKleisli m arr | arr -> m
+ Control.Arrow.Kleisli.Class: constM :: ArrowKleisli m arr => m b -> a `arr` b
+ Control.Arrow.Kleisli.Class: effect :: ArrowKleisli m arr => m () -> a `arr` a
+ Control.Arrow.Kleisli.Class: instance Monad m => ArrowKleisli m (Kleisli m)
+ Control.Arrow.List: instance Monad m => ArrowListLike [] (ListTArrow m)
+ Control.Arrow.List.Class: arrL :: ArrowList arr => (a -> [b]) -> a `arr` b
+ Control.Arrow.List.Class: class Arrow arr => ArrowList arr
+ Control.Arrow.List.Class: concatA :: ArrowPlus arr => [a `arr` b] -> a `arr` b
+ Control.Arrow.List.Class: empty :: ArrowList arr => (a `arr` b) -> a `arr` Bool
+ Control.Arrow.List.Class: filterA :: (ArrowChoice arr, ArrowList arr) => (a `arr` c) -> a `arr` a
+ Control.Arrow.List.Class: guards :: (ArrowList arr, ArrowChoice arr) => (a `arr` c) -> (a `arr` b) -> a `arr` b
+ Control.Arrow.List.Class: ifA :: (ArrowList arr, ArrowChoice arr) => (a `arr` c) -> (a `arr` b) -> (a `arr` b) -> a `arr` b
+ Control.Arrow.List.Class: isA :: ArrowList arr => (a -> Bool) -> a `arr` a
+ Control.Arrow.List.Class: list :: ArrowList arr => (a `arr` b) -> a `arr` [b]
+ Control.Arrow.List.Class: mapL :: ArrowList arr => ([b] -> [c]) -> (a `arr` b) -> (a `arr` c)
+ Control.Arrow.List.Class: maybeL :: ArrowList arr => Maybe a `arr` a
+ Control.Arrow.List.Class: none :: ArrowList arr => a `arr` b
+ Control.Arrow.List.Class: notA :: (ArrowList arr, ArrowChoice arr) => (a `arr` c) -> a `arr` a
+ Control.Arrow.List.Class: optional :: (ArrowChoice arr, ArrowList arr) => (a `arr` b) -> a `arr` Maybe b
+ Control.Arrow.List.Class: orElse :: (ArrowList arr, ArrowChoice arr) => (a `arr` b) -> (a `arr` b) -> a `arr` b
+ Control.Arrow.List.Class: unite :: ArrowList arr => (a `arr` (b, b)) -> a `arr` b
+ Control.Arrow.List.Class: unlist :: ArrowList arr => [b] `arr` b
+ Control.Arrow.List.Class: when :: (ArrowList arr, ArrowChoice arr) => (a `arr` a) -> (a `arr` b) -> a `arr` a
+ Control.Arrow.ListLike.Class: arrMF :: (ArrowListLike f arr, ArrowKleisli m arr) => (a -> m (f c)) -> a `arr` c
+ Control.Arrow.ListLike.Class: class Arrow arr => ArrowListLike f arr | arr -> f
+ Control.Arrow.ListLike.Class: concatA :: ArrowPlus arr => [a `arr` b] -> a `arr` b
+ Control.Arrow.ListLike.Class: const :: Arrow arr => b -> a `arr` b
+ Control.Arrow.ListLike.Class: constF :: ArrowListLike f arr => f c -> a `arr` c
+ Control.Arrow.ListLike.Class: embed :: ArrowListLike f arr => f a `arr` a
+ Control.Arrow.ListLike.Class: filterA :: (Alternative f, Foldable f, ArrowListLike f arr, ArrowChoice arr) => (a `arr` c) -> a `arr` a
+ Control.Arrow.ListLike.Class: guards :: (Alternative f, Foldable f, ArrowListLike f arr, ArrowChoice arr) => (a `arr` c) -> (a `arr` b) -> (a `arr` b)
+ Control.Arrow.ListLike.Class: ifA :: (Foldable f, ArrowListLike f arr, ArrowChoice arr) => (a `arr` b) -> (a `arr` t) -> (a `arr` t) -> a `arr` t
+ Control.Arrow.ListLike.Class: isA :: (Alternative f, ArrowListLike f arr) => (a -> Bool) -> a `arr` a
+ Control.Arrow.ListLike.Class: mapF :: ArrowListLike f arr => (f b -> f c) -> a `arr` b -> a `arr` c
+ Control.Arrow.ListLike.Class: maybeA :: (Alternative f, ArrowListLike f arr) => Maybe a `arr` a
+ Control.Arrow.ListLike.Class: none :: (Alternative f, ArrowListLike f arr) => a `arr` b
+ Control.Arrow.ListLike.Class: notA :: (Alternative f, Foldable f, ArrowListLike f arr, ArrowChoice arr) => (a `arr` c) -> a `arr` a
+ Control.Arrow.ListLike.Class: observe :: ArrowListLike f arr => (a `arr` b) -> a `arr` f b
+ Control.Arrow.ListLike.Class: optional :: (Foldable f, ArrowListLike f arr, ArrowChoice arr) => (a `arr` b) -> a `arr` Maybe b
+ Control.Arrow.ListLike.Class: orElse :: (Foldable f, ArrowListLike f arr, ArrowChoice arr) => (a `arr` b) -> (a `arr` b) -> a `arr` b
+ Control.Arrow.ListLike.Class: plus :: (Alternative f, ArrowListLike f arr) => (a `arr` b) -> (a `arr` b) -> a `arr` b
+ Control.Arrow.ListLike.Class: results :: (Foldable f, ArrowListLike f arr) => (a `arr` b) -> (a `arr` Bool)
+ Control.Arrow.ListLike.Class: unite :: ArrowPlus arr => (b, b) `arr` b
+ Control.Arrow.ListLike.Class: when :: (Foldable f, ArrowListLike f arr, ArrowChoice arr) => (a `arr` a) -> (a `arr` c) -> a `arr` a
+ Control.Arrow.Sequence: instance Monad m => ArrowListLike Seq (SeqTArrow m)
- Control.Arrow.List: arrML :: (ArrowList arr, ArrowKleisli m arr) => (a -> m [b]) -> a arr b
+ Control.Arrow.List: arrML :: (ArrowList arr, ArrowKleisli m arr) => (a -> m [b]) -> a `arr` b
Files
- CHANGELOG.md +9/−0
- arrow-list.cabal +4/−4
- src/Control/Arrow/ArrowF.hs +0/−172
- src/Control/Arrow/ArrowKleisli.hs +0/−31
- src/Control/Arrow/ArrowList.hs +0/−160
- src/Control/Arrow/Kleisli/Class.hs +31/−0
- src/Control/Arrow/List.hs +8/−8
- src/Control/Arrow/List/Class.hs +163/−0
- src/Control/Arrow/ListLike/Class.hs +172/−0
- src/Control/Arrow/Sequence.hs +7/−7
CHANGELOG.md view
@@ -1,5 +1,14 @@ # Changelog +## 0.7++* Renamed modules to not clash with hxt+ * `Control.Arrow.ArrowF` => `Control.Arrow.ArrowListLike.Class`+ * `Control.Arrow.ArrowKleisli` => `Control.Arrow.ArrowKleisli.Class`+ * `Control.Arrow.ArrowList` => `Control.Arrow.ArrowList.Class`++* Renamed the `ArrowF` class to `ArrowListLike`.+ #### 0.6.1.5 * Allow mtl 2.2.
arrow-list.cabal view
@@ -1,5 +1,5 @@ name: arrow-list-version: 0.6.1.5+version: 0.7 synopsis: List arrows for Haskell. description: This small Haskell library provides some type class, types and functions to@@ -30,9 +30,9 @@ ghc-options: -Wall hs-source-dirs: src exposed-modules:- Control.Arrow.ArrowF- Control.Arrow.ArrowKleisli- Control.Arrow.ArrowList+ Control.Arrow.Kleisli.Class+ Control.Arrow.List.Class+ Control.Arrow.ListLike.Class Control.Arrow.List Control.Arrow.Sequence Control.Monad.Sequence
− src/Control/Arrow/ArrowF.hs
@@ -1,172 +0,0 @@-{-# LANGUAGE- TypeOperators- , Arrows- , MultiParamTypeClasses- , FunctionalDependencies- #-}-module Control.Arrow.ArrowF-(- -- * Container arrow type class.- ArrowF (..)-, mapF-, arrMF-- -- * Generic arrow utilities.-, unite-, const-, concatA-, plus-- -- * Container arrow utilities.-, constF-, none-, results-- -- * Conditional and filter arrows.-, isA-, ifA-, when-, guards-, filterA-, notA-, orElse-- -- * Optionality.-, maybeA-, optional-)-where--import Control.Applicative hiding (optional)-import Control.Arrow-import Control.Arrow.ArrowKleisli-import Control.Category-import Data.Foldable (Foldable, toList)-import Prelude hiding ((.), id, const)-import qualified Prelude---- | A type class for arrows that produce containers of results. The container--- arrow can be seen as a generalization for list arrows. Most operations--- assume the container type has an 'Applicative', an 'Alternative' and a--- 'Foldable' instance.--class Arrow arr => ArrowF f arr | arr -> f where- embed :: f a `arr` a -- ^ Use a container as the input for an arrow.- observe :: (a `arr` b) -> a `arr` f b -- ^ Get the result as container.---- | Embed a monadic function returning an ordered list into a container arrow.--arrMF :: (ArrowF f arr, ArrowKleisli m arr) => (a -> m (f c)) -> a `arr` c-arrMF x = embed . arrM x---- | Map a function over the result collection of a container arrow.--mapF :: ArrowF f arr => (f b -> f c) -> a `arr` b -> a `arr` c-mapF f a = embed . arr f . observe a---- | Take the output of an arrow producing two results and concatenate them--- into the result of the container arrow.--unite :: ArrowPlus arr => (b, b) `arr` b-unite = arr fst <+> arr snd---- | Skip the input and produce a constant output.--const :: Arrow arr => b -> a `arr` b-const = arr . Prelude.const---- | Collect the results of applying multiple arrows to the same input.--concatA :: ArrowPlus arr => [a `arr` b] -> a `arr` b-concatA = foldr (<+>) zeroArrow---- | Join the results of two arrows, like (<+>) from ArrowPlus.--plus :: (Alternative f, ArrowF f arr) => (a `arr` b) -> (a `arr` b) -> a `arr` b-plus a b = embed . arr (\(x, y) -> x <|> y) . (observe a &&& observe b)---- | Skip the input and produce a constant output specified as a container.--constF :: ArrowF f arr => f c -> a `arr` c-constF f = embed . const f---- | Ignore the input and produce no results. Like `zeroArrow'.--none :: (Alternative f, ArrowF f arr) => a `arr` b-none = constF empty---- | Returns a `Bool' indicating whether the input arrow produces a container--- with any results.--results :: (Foldable f, ArrowF f arr) => (a `arr` b) -> (a `arr` Bool)-results a = arr (not . null . toList) . observe a---- | Create a filtering container arrow by mapping a predicate function over the--- input. When the predicate returns `True' the input will be returned in the--- output container, when `False' the empty container is returned.--isA :: (Alternative f, ArrowF f arr) => (a -> Bool) -> a `arr` a-isA f = embed . arr (\a -> if f a then pure a else empty)---- | Use the result of a container arrow as a conditional, like an if-then-else--- arrow. When the first arrow produces any results the /then/ arrow will be--- used, when the first arrow produces no results the /else/ arrow will be--- used.--ifA :: (Foldable f, ArrowF f arr, ArrowChoice arr) => (a `arr` b) -> (a `arr` t) -> (a `arr` t) -> a `arr` t-ifA c t e = proc i -> do x <- results c -< i; if x then t -< i else e -< i---- | Apply a container arrow only when a conditional arrow produces any--- results. When the conditional produces no results the output arrow /behaves--- like the identity/. The /second/ input arrow is used as the conditional,--- this allow you to write: @ a \`when\` condition @--infix 7 `when`--when :: (Foldable f, ArrowF f arr, ArrowChoice arr) => (a `arr` a) -> (a `arr` c) -> a `arr` a-when a c = ifA c a id---- | Apply a container arrow only when a conditional arrow produces any--- results. When the conditional produces no results the output arrow--- /produces no results/. The /first/ input arrow is used as the conditional,--- this allow you to write: @ condition \`guards\` a @--infix 8 `guards`--guards :: (Alternative f, Foldable f, ArrowF f arr, ArrowChoice arr) => (a `arr` c) -> (a `arr` b) -> (a `arr` b)-guards c a = ifA c a none---- | Filter the results of an arrow with a predicate arrow, when the filter--- condition produces results the input is accepted otherwise it is excluded.--filterA :: (Alternative f, Foldable f, ArrowF f arr, ArrowChoice arr) => (a `arr` c) -> a `arr` a-filterA c = ifA c id none---- | Negation container arrow. Only accept the input when the condition--- produces no output.--notA :: (Alternative f, Foldable f, ArrowF f arr, ArrowChoice arr) => (a `arr` c) -> a `arr` a-notA c = ifA c none id---- | Apply the input arrow, when the arrow does not produces any results the--- second fallback arrow is applied.--- Likely written infix like this @ a \`orElse\` b @--infix 6 `orElse`--orElse :: (Foldable f, ArrowF f arr, ArrowChoice arr) => (a `arr` b) -> (a `arr` b) -> a `arr` b-orElse a = ifA a a---- | Map a `Maybe' input to a container output. When the Maybe is a `Nothing'--- an empty container will be returned, `Just' will result in a singleton--- container.--maybeA :: (Alternative f, ArrowF f arr) => Maybe a `arr` a-maybeA = embed . arr (maybe empty pure)---- | Apply a container arrow, when there are no results a `Nothing' will be--- returned, otherwise the results will be wrapped in a `Just'. This function--- always produces result.--optional :: (Foldable f, ArrowF f arr, ArrowChoice arr) => (a `arr` b) -> a `arr` Maybe b-optional a = ifA a (arr Just . a) (arr (const Nothing))
− src/Control/Arrow/ArrowKleisli.hs
@@ -1,31 +0,0 @@-{- |-The `ArrowKleisli' type class allows for embedding monadic operations in-Kleisli arrows.--}-{-# LANGUAGE- TypeOperators- , MultiParamTypeClasses- , FlexibleInstances- , FunctionalDependencies- #-}-module Control.Arrow.ArrowKleisli where--import Control.Arrow-import Control.Category-import Control.Monad.Trans-import Prelude hiding ((.), id)--class (Monad m, Arrow arr) => ArrowKleisli m arr | arr -> m where- arrM :: (a -> m b) -> a `arr` b--instance Monad m => ArrowKleisli m (Kleisli m) where- arrM f = Kleisli f--constM :: ArrowKleisli m arr => m b -> a `arr` b-constM a = arrM (const a)--effect :: ArrowKleisli m arr => m () -> a `arr` a-effect a = arrM (\b -> a >> return b)--arrIO :: (MonadIO m, ArrowKleisli m arr) => (a -> IO b) -> a `arr` b-arrIO f = arrM (liftIO . f)
− src/Control/Arrow/ArrowList.hs
@@ -1,160 +0,0 @@-{-# LANGUAGE TypeOperators, Arrows #-}-{- |-The `ArrowList' type class, and a collection of list arrow related functions.-This typeclass can be used to embed functions producing multiple outputs into a-an arrow.--}-module Control.Arrow.ArrowList-(- -- * ArrowList type class.- ArrowList (..)-- -- * Creating list arrows.-, unlist-, unite-, none-, concatA-- -- * Collecting the results.-, list-, empty-- -- * Conditional and filter arrows.-, isA-, ifA-, when-, guards-, filterA-, notA-, orElse-- -- * Optionality.-, maybeL-, optional-)-where--import Control.Monad hiding (when)-import Control.Category-import Control.Arrow-import Prelude hiding ((.), id)---- | The `ArrowList' class represents two possible actions:------ 1. Lifting functions from one value to a list of values into a list arrow.------ 2. Mapping a function over the result list of a list arrow.--class Arrow arr => ArrowList arr where- arrL :: (a -> [b]) -> a `arr` b- mapL :: ([b] -> [c]) -> (a `arr` b) -> (a `arr` c)---- | Create a list arrow of an input list.--unlist :: ArrowList arr => [b] `arr` b-unlist = arrL id---- | Take the output of an arrow producing two results and concatenate them--- into the result of the list arrow.--unite :: ArrowList arr => (a `arr` (b, b)) -> a `arr` b-unite = mapL (concatMap (\(a, b) -> [a, b]))---- | Ignore the input and produce no results. Like `zeroArrow'.--none :: ArrowList arr => a `arr` b-none = arrL (const [])---- | Collect the results of applying multiple arrows to the same input.--concatA :: ArrowPlus arr => [a `arr` b] -> a `arr` b-concatA = foldr (<+>) zeroArrow---- | Collect the entire results of an list arrow as a singleton value in the--- result list.--list :: ArrowList arr => (a `arr` b) -> a `arr` [b]-list = mapL return---- | Returns a `Bool' indicating whether the input arrow produce any results.--empty :: ArrowList arr => (a `arr` b) -> a `arr` Bool-empty = mapL (\xs -> [if null xs then True else False])---- | Create a filtering list arrow by mapping a predicate function over the--- input. When the predicate returns `True' the input will be returned in the--- output list, when `False' the empty list is returned.--isA :: ArrowList arr => (a -> Bool) -> a `arr` a-isA f = arrL (\a -> if f a then [a] else [])---- | Use the result a list arrow as a conditional, like an if-then-else arrow.--- When the first arrow produces any results the /then/ arrow will be used,--- when the first arrow produces no results the /else/ arrow will be used.--ifA :: (ArrowList arr, ArrowChoice arr)- => (a `arr` c) -- ^ Arrow used as condition.- -> (a `arr` b) -- ^ Arrow to use when condition has results.- -> (a `arr` b) -- ^ Arrow to use when condition has no results.- -> a `arr` b-ifA c t e = proc i -> do x <- empty c -< i; if x then e -< i else t -< i---- | Apply a list arrow only when a conditional arrow produces any results.--- When the conditional produces no results the output arrow /behaves like the identity/.--- The /second/ input arrow is used as the conditional, this allow--- you to write: @ a \`when\` c @--infix 8 `when`--when :: (ArrowList arr, ArrowChoice arr)- => (a `arr` a) -- ^ The arrow to apply,- -> (a `arr` b) -- ^ when this conditional holds.- -> a `arr` a-when a c = ifA c a id---- | Apply a list arrow only when a conditional arrow produces any results.--- When the conditional produces no results the output arrow /produces no results/.--- The /first/ input arrow is used as the conditional, this allow you--- to write: @ c \`guards\` a @--infix 8 `guards`--guards :: (ArrowList arr, ArrowChoice arr)- => (a `arr` c) -- ^ When this condition holds,- -> (a `arr` b) -- ^ then apply this arrow.- -> a `arr` b-guards c a = ifA c a none---- | Filter the results of an arrow with a predicate arrow, when the filter--- condition produces results the input is accepted otherwise it is excluded.--filterA :: (ArrowChoice arr, ArrowList arr) => (a `arr` c) -> a `arr` a-filterA c = ifA c id none---- | Negation list arrow. Only accept the input when the condition produces no--- output.--notA :: (ArrowList arr, ArrowChoice arr) => (a `arr` c) -> a `arr` a-notA c = ifA c none id---- | Apply the input arrow, when the arrow does not produces any results the--- second fallback arrow is applied.--- Likely written infix like this @ a \`orElse\` b @--infix 8 `orElse`--orElse :: (ArrowList arr, ArrowChoice arr) => (a `arr` b) -> (a `arr` b) -> a `arr` b-orElse a = ifA a a---- | Map a `Maybe' input to a list output. When the Maybe is a `Nothing' an--- empty list will be returned, `Just' will result in a singleton list.--maybeL :: ArrowList arr => Maybe a `arr` a-maybeL = arrL (maybe [] return)---- | Apply a list arrow, when there are no results a `Nothing' will be--- returned, otherwise the results will be wrapped in a `Just'. This function--- always produces result.--optional :: (ArrowChoice arr, ArrowList arr) => (a `arr` b) -> a `arr` Maybe b-optional a = ifA a (arr Just . a) (arr (const Nothing))
+ src/Control/Arrow/Kleisli/Class.hs view
@@ -0,0 +1,31 @@+{- |+The `ArrowKleisli' type class allows for embedding monadic operations in+Kleisli arrows.+-}+{-# LANGUAGE+ FlexibleInstances+ , FunctionalDependencies+ , MultiParamTypeClasses+ , TypeOperators+ #-}+module Control.Arrow.Kleisli.Class where++import Control.Arrow+import Control.Category+import Control.Monad.Trans+import Prelude hiding (id, (.))++class (Monad m, Arrow arr) => ArrowKleisli m arr | arr -> m where+ arrM :: (a -> m b) -> a `arr` b++instance Monad m => ArrowKleisli m (Kleisli m) where+ arrM f = Kleisli f++constM :: ArrowKleisli m arr => m b -> a `arr` b+constM a = arrM (const a)++effect :: ArrowKleisli m arr => m () -> a `arr` a+effect a = arrM (\b -> a >> return b)++arrIO :: (MonadIO m, ArrowKleisli m arr) => (a -> IO b) -> a `arr` b+arrIO f = arrM (liftIO . f)
src/Control/Arrow/List.hs view
@@ -1,20 +1,20 @@ {-# LANGUAGE- GeneralizedNewtypeDeriving- , TypeOperators- , FlexibleInstances+ FlexibleInstances+ , GeneralizedNewtypeDeriving , MultiParamTypeClasses , StandaloneDeriving+ , TypeOperators #-} module Control.Arrow.List where -import Prelude hiding ((.), id) import Control.Arrow-import Control.Arrow.ArrowKleisli-import Control.Arrow.ArrowList-import Control.Arrow.ArrowF+import Control.Arrow.Kleisli.Class+import Control.Arrow.List.Class+import Control.Arrow.ListLike.Class import Control.Category import Control.Monad.Identity import Control.Monad.List+import Prelude hiding (id, (.)) -- * ListT arrow. @@ -45,7 +45,7 @@ arrL a = ListTArrow (Kleisli (ListT . return . a)) mapL f g = arrML (liftM f . runListTArrow g) -instance Monad m => ArrowF [] (ListTArrow m) where+instance Monad m => ArrowListLike [] (ListTArrow m) where embed = ListTArrow (Kleisli (ListT . return)) observe f = ListTArrow . Kleisli $ \a -> ListT $ return `liftM` runListT (runKleisli (runListTArrow' f) a)
+ src/Control/Arrow/List/Class.hs view
@@ -0,0 +1,163 @@+{-# LANGUAGE+ Arrows+ , TypeOperators+ #-}+{- |+The `ArrowList' type class, and a collection of list arrow related functions.+This typeclass can be used to embed functions producing multiple outputs into a+an arrow.+-}+module Control.Arrow.List.Class+(+ -- * ArrowList type class.+ ArrowList (..)++ -- * Creating list arrows.+, unlist+, unite+, none+, concatA++ -- * Collecting the results.+, list+, empty++ -- * Conditional and filter arrows.+, isA+, ifA+, when+, guards+, filterA+, notA+, orElse++ -- * Optionality.+, maybeL+, optional+)+where++import Control.Arrow+import Control.Category+import Control.Monad hiding (when)+import Prelude hiding (id, (.))++-- | The `ArrowList' class represents two possible actions:+--+-- 1. Lifting functions from one value to a list of values into a list arrow.+--+-- 2. Mapping a function over the result list of a list arrow.++class Arrow arr => ArrowList arr where+ arrL :: (a -> [b]) -> a `arr` b+ mapL :: ([b] -> [c]) -> (a `arr` b) -> (a `arr` c)++-- | Create a list arrow of an input list.++unlist :: ArrowList arr => [b] `arr` b+unlist = arrL id++-- | Take the output of an arrow producing two results and concatenate them+-- into the result of the list arrow.++unite :: ArrowList arr => (a `arr` (b, b)) -> a `arr` b+unite = mapL (concatMap (\(a, b) -> [a, b]))++-- | Ignore the input and produce no results. Like `zeroArrow'.++none :: ArrowList arr => a `arr` b+none = arrL (const [])++-- | Collect the results of applying multiple arrows to the same input.++concatA :: ArrowPlus arr => [a `arr` b] -> a `arr` b+concatA = foldr (<+>) zeroArrow++-- | Collect the entire results of an list arrow as a singleton value in the+-- result list.++list :: ArrowList arr => (a `arr` b) -> a `arr` [b]+list = mapL return++-- | Returns a `Bool' indicating whether the input arrow produce any results.++empty :: ArrowList arr => (a `arr` b) -> a `arr` Bool+empty = mapL (\xs -> [if null xs then True else False])++-- | Create a filtering list arrow by mapping a predicate function over the+-- input. When the predicate returns `True' the input will be returned in the+-- output list, when `False' the empty list is returned.++isA :: ArrowList arr => (a -> Bool) -> a `arr` a+isA f = arrL (\a -> if f a then [a] else [])++-- | Use the result a list arrow as a conditional, like an if-then-else arrow.+-- When the first arrow produces any results the /then/ arrow will be used,+-- when the first arrow produces no results the /else/ arrow will be used.++ifA :: (ArrowList arr, ArrowChoice arr)+ => (a `arr` c) -- ^ Arrow used as condition.+ -> (a `arr` b) -- ^ Arrow to use when condition has results.+ -> (a `arr` b) -- ^ Arrow to use when condition has no results.+ -> a `arr` b+ifA c t e = proc i -> do x <- empty c -< i; if x then e -< i else t -< i++-- | Apply a list arrow only when a conditional arrow produces any results.+-- When the conditional produces no results the output arrow /behaves like the identity/.+-- The /second/ input arrow is used as the conditional, this allow+-- you to write: @ a \`when\` c @++infix 8 `when`++when :: (ArrowList arr, ArrowChoice arr)+ => (a `arr` a) -- ^ The arrow to apply,+ -> (a `arr` b) -- ^ when this conditional holds.+ -> a `arr` a+when a c = ifA c a id++-- | Apply a list arrow only when a conditional arrow produces any results.+-- When the conditional produces no results the output arrow /produces no results/.+-- The /first/ input arrow is used as the conditional, this allow you+-- to write: @ c \`guards\` a @++infix 8 `guards`++guards :: (ArrowList arr, ArrowChoice arr)+ => (a `arr` c) -- ^ When this condition holds,+ -> (a `arr` b) -- ^ then apply this arrow.+ -> a `arr` b+guards c a = ifA c a none++-- | Filter the results of an arrow with a predicate arrow, when the filter+-- condition produces results the input is accepted otherwise it is excluded.++filterA :: (ArrowChoice arr, ArrowList arr) => (a `arr` c) -> a `arr` a+filterA c = ifA c id none++-- | Negation list arrow. Only accept the input when the condition produces no+-- output.++notA :: (ArrowList arr, ArrowChoice arr) => (a `arr` c) -> a `arr` a+notA c = ifA c none id++-- | Apply the input arrow, when the arrow does not produces any results the+-- second fallback arrow is applied.+-- Likely written infix like this @ a \`orElse\` b @++infix 8 `orElse`++orElse :: (ArrowList arr, ArrowChoice arr) => (a `arr` b) -> (a `arr` b) -> a `arr` b+orElse a = ifA a a++-- | Map a `Maybe' input to a list output. When the Maybe is a `Nothing' an+-- empty list will be returned, `Just' will result in a singleton list.++maybeL :: ArrowList arr => Maybe a `arr` a+maybeL = arrL (maybe [] return)++-- | Apply a list arrow, when there are no results a `Nothing' will be+-- returned, otherwise the results will be wrapped in a `Just'. This function+-- always produces result.++optional :: (ArrowChoice arr, ArrowList arr) => (a `arr` b) -> a `arr` Maybe b+optional a = ifA a (arr Just . a) (arr (const Nothing))
+ src/Control/Arrow/ListLike/Class.hs view
@@ -0,0 +1,172 @@+{-# LANGUAGE+ Arrows+ , FunctionalDependencies+ , MultiParamTypeClasses+ , TypeOperators+ #-}+module Control.Arrow.ListLike.Class+(+ -- * Container arrow type class.+ ArrowListLike (..)+, mapF+, arrMF++ -- * Generic arrow utilities.+, unite+, const+, concatA+, plus++ -- * Container arrow utilities.+, constF+, none+, results++ -- * Conditional and filter arrows.+, isA+, ifA+, when+, guards+, filterA+, notA+, orElse++ -- * Optionality.+, maybeA+, optional+)+where++import Control.Applicative hiding (optional)+import Control.Arrow+import Control.Arrow.Kleisli.Class+import Control.Category+import Data.Foldable (Foldable, toList)+import Prelude hiding (const, id, (.))+import qualified Prelude++-- | A type class for arrows that produce containers of results. The container+-- arrow can be seen as a generalization for list arrows. Most operations+-- assume the container type has an 'Applicative', an 'Alternative' and a+-- 'Foldable' instance.++class Arrow arr => ArrowListLike f arr | arr -> f where+ embed :: f a `arr` a -- ^ Use a container as the input for an arrow.+ observe :: (a `arr` b) -> a `arr` f b -- ^ Get the result as container.++-- | Embed a monadic function returning an ordered list into a container arrow.++arrMF :: (ArrowListLike f arr, ArrowKleisli m arr) => (a -> m (f c)) -> a `arr` c+arrMF x = embed . arrM x++-- | Map a function over the result collection of a container arrow.++mapF :: ArrowListLike f arr => (f b -> f c) -> a `arr` b -> a `arr` c+mapF f a = embed . arr f . observe a++-- | Take the output of an arrow producing two results and concatenate them+-- into the result of the container arrow.++unite :: ArrowPlus arr => (b, b) `arr` b+unite = arr fst <+> arr snd++-- | Skip the input and produce a constant output.++const :: Arrow arr => b -> a `arr` b+const = arr . Prelude.const++-- | Collect the results of applying multiple arrows to the same input.++concatA :: ArrowPlus arr => [a `arr` b] -> a `arr` b+concatA = foldr (<+>) zeroArrow++-- | Join the results of two arrows, like (<+>) from ArrowPlus.++plus :: (Alternative f, ArrowListLike f arr) => (a `arr` b) -> (a `arr` b) -> a `arr` b+plus a b = embed . arr (\(x, y) -> x <|> y) . (observe a &&& observe b)++-- | Skip the input and produce a constant output specified as a container.++constF :: ArrowListLike f arr => f c -> a `arr` c+constF f = embed . const f++-- | Ignore the input and produce no results. Like `zeroArrow'.++none :: (Alternative f, ArrowListLike f arr) => a `arr` b+none = constF empty++-- | Returns a `Bool' indicating whether the input arrow produces a container+-- with any results.++results :: (Foldable f, ArrowListLike f arr) => (a `arr` b) -> (a `arr` Bool)+results a = arr (not . null . toList) . observe a++-- | Create a filtering container arrow by mapping a predicate function over the+-- input. When the predicate returns `True' the input will be returned in the+-- output container, when `False' the empty container is returned.++isA :: (Alternative f, ArrowListLike f arr) => (a -> Bool) -> a `arr` a+isA f = embed . arr (\a -> if f a then pure a else empty)++-- | Use the result of a container arrow as a conditional, like an if-then-else+-- arrow. When the first arrow produces any results the /then/ arrow will be+-- used, when the first arrow produces no results the /else/ arrow will be+-- used.++ifA :: (Foldable f, ArrowListLike f arr, ArrowChoice arr) => (a `arr` b) -> (a `arr` t) -> (a `arr` t) -> a `arr` t+ifA c t e = proc i -> do x <- results c -< i; if x then t -< i else e -< i++-- | Apply a container arrow only when a conditional arrow produces any+-- results. When the conditional produces no results the output arrow /behaves+-- like the identity/. The /second/ input arrow is used as the conditional,+-- this allow you to write: @ a \`when\` condition @++infix 7 `when`++when :: (Foldable f, ArrowListLike f arr, ArrowChoice arr) => (a `arr` a) -> (a `arr` c) -> a `arr` a+when a c = ifA c a id++-- | Apply a container arrow only when a conditional arrow produces any+-- results. When the conditional produces no results the output arrow+-- /produces no results/. The /first/ input arrow is used as the conditional,+-- this allow you to write: @ condition \`guards\` a @++infix 8 `guards`++guards :: (Alternative f, Foldable f, ArrowListLike f arr, ArrowChoice arr) => (a `arr` c) -> (a `arr` b) -> (a `arr` b)+guards c a = ifA c a none++-- | Filter the results of an arrow with a predicate arrow, when the filter+-- condition produces results the input is accepted otherwise it is excluded.++filterA :: (Alternative f, Foldable f, ArrowListLike f arr, ArrowChoice arr) => (a `arr` c) -> a `arr` a+filterA c = ifA c id none++-- | Negation container arrow. Only accept the input when the condition+-- produces no output.++notA :: (Alternative f, Foldable f, ArrowListLike f arr, ArrowChoice arr) => (a `arr` c) -> a `arr` a+notA c = ifA c none id++-- | Apply the input arrow, when the arrow does not produces any results the+-- second fallback arrow is applied.+-- Likely written infix like this @ a \`orElse\` b @++infix 6 `orElse`++orElse :: (Foldable f, ArrowListLike f arr, ArrowChoice arr) => (a `arr` b) -> (a `arr` b) -> a `arr` b+orElse a = ifA a a++-- | Map a `Maybe' input to a container output. When the Maybe is a `Nothing'+-- an empty container will be returned, `Just' will result in a singleton+-- container.++maybeA :: (Alternative f, ArrowListLike f arr) => Maybe a `arr` a+maybeA = embed . arr (maybe empty pure)++-- | Apply a container arrow, when there are no results a `Nothing' will be+-- returned, otherwise the results will be wrapped in a `Just'. This function+-- always produces result.++optional :: (Foldable f, ArrowListLike f arr, ArrowChoice arr) => (a `arr` b) -> a `arr` Maybe b+optional a = ifA a (arr Just . a) (arr (const Nothing))
src/Control/Arrow/Sequence.hs view
@@ -1,20 +1,20 @@ {-# LANGUAGE- GeneralizedNewtypeDeriving- , TypeOperators- , FlexibleInstances+ FlexibleInstances+ , GeneralizedNewtypeDeriving , MultiParamTypeClasses , StandaloneDeriving+ , TypeOperators #-} module Control.Arrow.Sequence where import Control.Arrow-import Control.Arrow.ArrowF-import Control.Arrow.ArrowKleisli+import Control.Arrow.Kleisli.Class+import Control.Arrow.ListLike.Class import Control.Category import Control.Monad.Identity import Control.Monad.Sequence import Data.Sequence-import Prelude hiding ((.), id, const)+import Prelude hiding (const, id, (.)) -- * SeqT arrow. @@ -41,7 +41,7 @@ runSeqArrow :: SeqArrow a b -> a -> Seq b runSeqArrow a = runIdentity . runSeqTArrow a -instance Monad m => ArrowF Seq (SeqTArrow m) where+instance Monad m => ArrowListLike Seq (SeqTArrow m) where embed = SeqTArrow (Kleisli (SeqT . return)) observe f = SeqTArrow . Kleisli $ \a -> SeqT $ singleton `liftM` runSeqT (runKleisli (runSeqTArrow' f) a)