concatenative 0.0.0 → 1.0.0
raw patch · 2 files changed
+215/−26 lines, 2 filesdep +template-haskellPVP ok
version bump matches the API change (PVP)
Dependencies added: template-haskell
API changes (from Hackage documentation)
+ Control.Concatenative: (&.) :: (a -> b) -> (a -> e) -> Concatenative a b (e -> c) c
+ Control.Concatenative: (*.) :: (t -> b) -> (a -> b1) -> Concatenative a b (b1 -> c) (t -> c)
+ Control.Concatenative: (.&.) :: Concatenative a b c d -> (a -> e) -> Concatenative a b (e -> c) d
+ Control.Concatenative: (.*.) :: Concatenative a b c d -> (e -> f) -> Concatenative e b (f -> c) (a -> d)
+ Control.Concatenative: Concatenative :: ((b -> c) -> (a -> d)) -> Concatenative a b c d
+ Control.Concatenative: apM :: Int -> Q Exp
+ Control.Concatenative: apM_ :: (Monad m) => Int -> m a -> m ()
+ Control.Concatenative: apN :: Int -> Q Exp
+ Control.Concatenative: biApM :: (Monad m) => (t -> m t1) -> (t1 -> t1 -> m t2) -> t -> t -> m t2
+ Control.Concatenative: biApM_ :: (Monad m) => (t -> m t1) -> t -> t -> m ()
+ Control.Concatenative: biM :: (Monad m) => (a -> m b) -> (a -> m c) -> (b -> c -> m d) -> a -> m d
+ Control.Concatenative: biM_ :: (Monad m) => (a -> m b) -> (a -> m c) -> a -> m ()
+ Control.Concatenative: biSpM :: (Monad m) => (a -> m c) -> (b -> m d) -> (c -> d -> m e) -> a -> b -> m e
+ Control.Concatenative: cat :: (a -> b) -> Concatenative a b c c
+ Control.Concatenative: catM :: (Monad m) => (a -> m b) -> Concatenative a b (m c) (m c)
+ Control.Concatenative: cl :: (Monad m) => (a -> m b) -> (a -> m e) -> Concatenative a b (e -> m d) (m d)
+ Control.Concatenative: clM :: (Monad m) => Concatenative a b c (m d) -> (a -> m e) -> Concatenative a b (e -> c) (m d)
+ Control.Concatenative: newtype Concatenative a b c d
+ Control.Concatenative: sp :: (Monad m) => (a -> m b) -> (e -> m f) -> Concatenative e b (f -> m d) (a -> m d)
+ Control.Concatenative: spM :: (Monad m) => Concatenative a b c (m d) -> (e -> m f) -> Concatenative e b (f -> c) (a -> m d)
+ Control.Concatenative: triApM :: (Monad m) => (a -> m b) -> (b -> b -> b -> m c) -> a -> a -> a -> m c
+ Control.Concatenative: triApM_ :: (Monad m) => (a -> m b) -> a -> a -> a -> m ()
+ Control.Concatenative: triM :: (Monad m) => (a -> m b) -> (a -> m c) -> (a -> m d) -> (b -> c -> d -> m e) -> a -> m e
+ Control.Concatenative: triM_ :: (Monad m) => (a -> m b) -> (a -> m c) -> (a -> m d) -> a -> m ()
+ Control.Concatenative: triSpM :: (Monad m) => (a -> m d) -> (b -> m e) -> (c -> m f) -> (d -> e -> f -> m g) -> a -> b -> c -> m g
+ Control.Concatenative: with :: Concatenative a b c d -> (b -> c) -> (a -> d)
Files
- Control/Concatenative.hs +211/−20
- concatenative.cabal +4/−6
Control/Concatenative.hs view
@@ -1,56 +1,172 @@-{-| Control.Concatenative brings postfix notation in the style of factor- (see http://factorcode.org) to haskell. Interfaces using both- combinators and arrows are available. +{-# LANGUAGE TemplateHaskell #-}+{-| Control.Concatenative brings concatenative combinators in the style of factor+ (see <http://docs.factorcode.org/content/article-dataflow-combinators.html>)+ to haskell in a variety of interfaces, allowing a terse, pointfree style. -} module Control.Concatenative ( -- * Postfix combinators+ + -- | These concatenative combinators essentially apply multiple functions to+ -- one or more values before combining all the results using another+ -- function.+ -- Without concatenative combinators:+ --+ -- > \x-> (x+1) + (subtract 1 x)+ --+ -- With concatenative combinators:+ --+ -- > bi (+1) (subtract 1) (+)+ bi, tri, biSp, triSp, biAp, triAp, ifte,- -- * Postfix arrows + biM, triM, biSpM, triSpM, biApM, triApM,+ biM_, triM_, biApM_, triApM_,+ + -- * Postfix arrows+ + -- | The arrow functions '&&&' and '***' are equivalent to 'bi' and 'biSp'.+ -- Combining here must be done seperately, through the '>>@' function.+ (>>@), dup, swap, both,- (>>>), (&&&), (***), first, second+ (>>>), (&&&), (***), first, second,+ + -- * Generalized Datatypes+ + -- | The Concatenative datatype can be used to cleave, spread, or+ -- apply any number of functions and values. + -- Using the 'bi' combinator:+ --+ -- > bi (+1) (subtract 1) (+)+ --+ -- is equivalent to using the '&.' function:+ --+ -- > with ((+1) &. (subtract 1)) (+)+ --+ -- and may be generalized to any number of functions:+ --+ -- > with ((subtract 10) &. (+1) .&. (*50)) enumFromThenTo+ --+ -- '*.' similarly generalizes 'biSp', and 'cl' and 'sp' generalize+ -- their monadic variants. Generic application presents a problem for the+ -- type system, however, and the library resorts to template haskell:+ --+ -- > biAp (+1)+ --+ -- translates to+ --+ -- > $(apN 2) (+1)+ + Concatenative(..),+ cat, (&.), (.&.), (*.), (.*.),+ catM, clM, cl, spM, sp,+ apN, apM, apM_ ) where import Control.Arrow+import Control.Monad+import Language.Haskell.TH -- Function Interface --- |Apply both arguments to a and combine the results+-- | Apply both arguments to a and combine the results bi :: (a -> b) -> (a -> c) -> (b -> c -> d) -> a -> d-bi f g c = \x-> c (f x) (g x)+bi f g c x = c (f x) (g x) --- |Apply each of three arguments to a and combine the results+-- | Apply each of three arguments to a and combine the results tri :: (a -> b) -> (a -> c) -> (a -> d) -> (b -> c -> d -> e) -> a -> e-tri f g h c = \x-> c (f x) (g x) (h x)+tri f g h c x = c (f x) (g x) (h x) --- |Apply the first argument to a, the second to b, and combine the results+-- | Apply the first argument to a, the second to b, and combine the results biSp :: (a -> c) -> (b -> d) -> (c -> d -> e) -> a -> b -> e-biSp f g c = \x y-> c (f x) (g y)+biSp f g c x y = c (f x) (g y) --- |Apply the first argument to a, the second to b, and the third to c, combining the results+-- | Apply the first argument to a, the second to b, and the third to c, combining the results triSp :: (a -> d) -> (b -> e) -> (c -> f) -> (d -> e -> f -> g) -> a -> b -> c -> g-triSp f g h c = \x y z-> c (f x) (g y) (h z)+triSp f g h c x y z = c (f x) (g y) (h z) --- |Apply a function to two values and combine the results+-- | Apply a function to two values and combine the results biAp :: (t -> t1) -> (t1 -> t1 -> t2) -> t -> t -> t2-biAp f c = \x y-> c (f x) (f y)+biAp f c x y = c (f x) (f y) --- |Apply a function to three values and combine the results+-- | Apply a function to three values and combine the results triAp :: (a -> b) -> (b -> b -> b -> c) -> a -> a -> a -> c-triAp f c = \x y z-> c (f x) (f y) (f z)+triAp f c x y z = c (f x) (f y) (f z) ifte :: (a -> Bool) -- ^ A predicate -> (a -> b) -- ^ Applied if the predicate yields True -> (a -> b) -- ^ Applied if the predicate yields False -> a -> b-ifte test ca cb = \x ->+ifte test ca cb x = if test x then ca x else cb x +-- Monad Utilities++-- | Like 'bi', but functions can return monadic values+biM :: Monad m => (a -> m b) -> (a -> m c) -> (b -> c -> m d) -> a -> m d+biM f g c a = do+ x <- f a+ y <- g a+ c x y++-- | Like 'biM', but throws away the end result+biM_ :: Monad m => (a -> m b) -> (a -> m c) -> a -> m ()+biM_ f g a = f a >> g a >> return ()++-- | Like 'tri', but functions can return monadic values+triM :: Monad m => (a -> m b) -> (a -> m c) -> (a -> m d) -> (b -> c -> d -> m e) -> a -> m e+triM f g l c a = do+ x <- f a+ y <- g a+ z <- l a+ c x y z++-- | Like 'triM', but throws away the end result+triM_ :: Monad m => (a -> m b) -> (a -> m c) -> (a -> m d) -> a -> m ()+triM_ f g l a = f a >> g a >> l a >> return ()++-- | Like 'biSp', but functions can return monadic values+biSpM :: Monad m => (a -> m c) -> (b -> m d) -> (c -> d -> m e) -> a -> b -> m e+biSpM f g c x y = do+ a <- f x+ b <- g y+ c a b++-- | Like 'triSp', but functions can return monadic values+triSpM :: Monad m => (a -> m d) -> (b -> m e) -> (c -> m f) -> (d -> e -> f -> m g) -> a -> b -> c -> m g+triSpM f g h c x y z = do+ a <- f x+ b <- g y+ n <- h z+ c a b n++-- | Like 'biAp', but functions can return monadic values+biApM :: Monad m => (t -> m t1) -> (t1 -> t1 -> m t2) -> t -> t -> m t2+biApM f c x y = do+ a <- f x+ b <- f y+ c a b++-- | Like 'biApM', but throws away the end result+biApM_ :: Monad m => (t -> m t1) -> t -> t -> m ()+biApM_ f x y = f x >> f y >> return ()++-- | Like 'triAp', but functions can return monadic values+triApM :: Monad m => (a -> m b) -> (b -> b -> b -> m c) -> a -> a -> a -> m c+triApM f c x y z = do+ a <- f x+ b <- f y+ n <- f z+ c a b n++-- | Like 'triApM', but throws away the end result+triApM_ :: Monad m => (a -> m b) -> a -> a -> a-> m ()+triApM_ f x y z = f x >> f y >> f z >> return ()+ -- Arrow Interface --- |Combine with a binary function+-- | Combine with a binary function (>>@) :: Arrow a => a b (x,y) -> (x -> y -> z) -> a b z a >>@ f = a >>> arr (\(x,y) -> f x y) --- |Arrow version of biAp+-- | Arrow version of 'biAp' both :: Arrow a => a b c -> a (b,b) (c,c) both a = first a >>> second a @@ -59,3 +175,78 @@ swap :: Arrow a => a (x,y) (y,x) swap = arr (\(x,y) -> (y,x))++-- Datatypes++-- | Concatenative continuation+newtype Concatenative a b c d = Concatenative { with :: (b -> c) -> (a -> d) }++-- | Lifts a function into 'Concatenative'+cat :: (a -> b) -> Concatenative a b c c+cat f = Concatenative (.f)++-- | Construct a 'Concatenative' for cleaving+(.&.) :: Concatenative a b c d -> (a -> e) -> Concatenative a b (e -> c) d+(Concatenative l) .&. f = Concatenative $ \c a-> l (flip c (f a)) a++-- | Lift a function and add it to a 'Concatenative' for cleaving+(&.) :: (a -> b) -> (a -> e) -> Concatenative a b (e -> c) c+f &. g = (cat f) .&. g++-- | Construct a 'Concatenative' for spreading+(.*.) :: Concatenative a b c d -> (e -> f) -> Concatenative e b (f -> c) (a -> d)+(Concatenative l) .*. f = Concatenative $ \c e-> l (flip c (f e))++-- | Lift a function and add it to a 'Concatenative' for spreading+(*.) :: (t -> b) -> (a -> b1) -> Concatenative a b (b1 -> c) (t -> c)+f *. g = (cat f) .*. g++-- | Lift a monadic function to a 'Concatenative'+catM :: Monad m => (a -> m b) -> Concatenative a b (m c) (m c)+catM f = Concatenative $ \c a-> f a >>= c++-- | Construct a 'Concatenative' for spreading monadic functions+clM :: Monad m => Concatenative a b c (m d) -> (a -> m e) -> Concatenative a b (e -> c) (m d)+(Concatenative l) `clM ` f = Concatenative $ \c a-> f a >>= (\x-> l (flip c x) a)++-- | Lift a monadic function and add it to a 'Concatenative' for cleaving+cl :: (Monad m) => (a -> m b) -> (a -> m e) -> Concatenative a b (e -> m d) (m d)+f `cl` g = (catM f) `clM` g++-- | Construct a 'Concatenative' for spreading monadic functions+spM :: Monad m => Concatenative a b c (m d) -> (e -> m f) -> Concatenative e b (f -> c) (a -> m d)+(Concatenative l) `spM` f = Concatenative $ \c e a-> f e >>= \x-> l (flip c x) a ++-- | Lift a monadic function and add it to a 'Concatenative' for spreading+sp :: (Monad m) => (a -> m b) -> (e -> m f) -> Concatenative e b (f -> m d) (a -> m d)+f `sp` g = (catM f) `spM` g++-- | Create a 'Concatenative' for applying a function n times+--+-- > biAp (+1)+--+-- translates to+--+-- > $(apN 2) (+1)+apN :: Int -> Q Exp+apN n = [| \f-> $(apN' n) f |] where+ apN' :: Int -> Q Exp+ apN' n | n > 1 = [| \f-> $(apN' (n-1)) f .*. f |]+ | otherwise = [| cat |]++-- | Create a 'Concatenative' for applying a monadic function n times+--+-- > biApM (+1)+--+-- translates to+--+-- > $(apM 2) (+1)+apM :: Int -> Q Exp+apM n = [| \f-> $(apM' n) f |] where+ apM' :: Int -> Q Exp+ apM' n | n > 1 = [| \f-> $(apM' (n-1)) f `spM` f |]+ | otherwise = [| catM |]++-- | Convenience synonym for 'replicateM_'+apM_ :: Monad m => Int -> m a -> m ()+apM_ = replicateM_
concatenative.cabal view
@@ -1,5 +1,5 @@ name: concatenative-version: 0.0.0+version: 1.0.0 synopsis: A library for postfix control flow. description: Concatenative gives haskell factor style combinators and arrows for postfix notation.@@ -10,10 +10,8 @@ license-file: LICENSE author: Sam Anklesaria maintainer: amsay@amsay.net-build-depends: base >= 3 && < 5+build-depends: base >= 3 && < 5, template-haskell > 2 && < 3 build-type: Simple Cabal-Version: >= 1.2--Library- exposed-modules: Control.Concatenative- Build-Depends: base >= 3 && < 5+exposed-modules: Control.Concatenative+homepage: https://patch-tag.com/r/salazar/concatenative/snapshot/current/content/pretty