-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | mapWith: like fmap, but with additional parameters (isFirst, isLast, etc). -- -- fmap over Traversables (including lists), but pass additional -- parameters to the map function, such as isFirst, isLast, prevElt, -- nextElt, index from start or end, custom params. For examples see -- https://github.com/davjam/MapWith/blob/master/doc/examples.hs @package MapWith @version 0.2.0.0 -- | A generalisation of curry and uncurry , allowing -- currying of any number of arguments of different types. -- -- For the class instances provided here, the arguments are packaged into -- a "stacked tuple". For example ('x', (3 :: Int, (True, ()))) -- represents a set of three arguments of different types: -- -- -- -- The TF stands for Type Family. I've given this the (possibly weird) -- name to avoid any conflict with similar implementations. module CurryTF -- | Given: -- -- -- -- CurryTF args r represents the ability to convert either way -- between functions: -- -- -- -- so that: -- -- class CurryTF args r where { -- | The type of the (curried) function that can have arguments of the -- types embedded in args applied and that returns a result of -- type r. For example: -- --
    --   >>> :kind! FnType (Char, (Int, (Bool, ()))) String
    --   FnType (Char, (Int, (Bool, ()))) String :: *
    --   = Char -> Int -> Bool -> [Char]
    --   
type family FnType args r :: *; } -- | Embeds a number of separate arguments into a single args -- parameter, applies args to a function, and returns the -- result. -- -- For example: -- --
--   >>> fn1 (c, (n, (b, ()))) = c : replicate n '1' ++ if b then "hello" else "goodbye"
--   
--   >>> curryN fn1 'x' 3 True
--   "x111hello"
--   
-- -- This also support partial application: -- --
--   >>> :t curryN fn1 'x'
--   curryN fn1 'x' :: Int -> Bool -> [Char]
--   
curryN :: CurryTF args r => (args -> r) -> FnType args r -- | Applies each argument embedded in args as a separate -- parameter to a function, and returns the result. -- -- For example: -- --
--   >>> fn2 c n b = c : replicate n '2' ++ if b then "hello" else "goodbye"
--   
--   >>> uncurryN fn2 ('x', (3, (True, ())))
--   "x222hello"
--   
uncurryN :: CurryTF args r => FnType args r -> args -> r -- | A binary operator for uncurryN, so if values a, b and c are -- embedded in args then f $# args = f a b c ($#) :: CurryTF args r => FnType args r -> args -> r -- | A "stacked tuple" of one value type App1 a = (a, ()) -- | A "stacked tuple" of two values type App2 a b = (a, (b, ())) -- | A "stacked tuple" of three values type App3 a b c = (a, (b, (c, ()))) -- | A "stacked tuple" of four values type App4 a b c d = (a, (b, (c, (d, ())))) -- | stacks one value app1 :: a -> App1 a -- | stacks two values app2 :: a -> b -> App2 a b -- | stacks three values app3 :: a -> b -> c -> App3 a b c -- | stacks four values app4 :: a -> b -> c -> d -> App4 a b c d instance CurryTF.CurryTF () r instance CurryTF.CurryTF moreArgs r => CurryTF.CurryTF (arg, moreArgs) r -- | Provides fmap-like functionality, but can also "inject" -- additional parameters to the mapping function, such as: -- -- -- -- It offers excellent performance. module MapWith -- | Maps over a Traversable, with an additional parameter -- indicating whether an item is the first. -- --
--   >>> let g x f = [if f then '*' else ' ', x] in withFirst g "fred"
--   ["*f", " r", " e", " d"]
--   
withFirst :: Traversable t => (a -> Bool -> b) -> t a -> t b -- | Maps over a Traversable, with an additional parameter -- indicating whether an item is the last. -- --
--   >>> let g x l = [x, if l then '*' else ' '] in withLast g "fred"
--   ["f ","r ","e ","d*"]
--   
withLast :: Traversable t => (a -> Bool -> b) -> t a -> t b -- | Maps over a Traversable, with additional parameters indicating -- whether an item is the first or last (or both). -- --
--   >>> let g x f l = [star f, x, star l]; star b = if b then '*' else ' ' in withFirstLast g "fred"
--   ["*f ", " r ", " e ", " d*"]
--   
withFirstLast :: Traversable t => (a -> Bool -> Bool -> b) -> t a -> t b -- |
--   andFirstLast = withFirstLast (,,)
--   
andFirstLast :: Traversable t => t a -> t (a, Bool, Bool) -- | Maps over a Traversable, with additional parameters indicating -- the previous and next elements. -- -- The second (or third) parameter to the map function is Nothing -- when called for the first (or last) item, otherwise it's Just -- the previous (or next) item. -- --
--   >>> let f x prvMay nxtMay = maybe "*" (cmp x) prvMay ++ x ++ maybe "*" (cmp x) nxtMay; cmp x y = show $ compare x y in withPrevNext f ["foo", "bar", "baz"]
--   ["*fooGT","LTbarLT","GTbaz*"]
--   
withPrevNext :: Traversable t => (a -> Maybe a -> Maybe a -> b) -> t a -> t b -- |
--   andPrevNext = withPrevNext (,,)
--   
andPrevNext :: Traversable t => t a -> t (a, Maybe a, Maybe a) -- | maps an InjectedFn over a Traversable type t, -- turning a t a into a t b and preserving the -- structure of t. -- -- Parameters (as defined in the InjectedFn) are passed to a map -- function (embedded in the InjectedFn), in addition to the -- elements of the Traversable. mapWith :: Traversable t => InjectedFn a b -> t a -> t b -- | like mapM, but with an InjectedFn. mapWithM :: (Traversable t, Monad m) => InjectedFn a (m b) -> t a -> m (t b) -- | like mapM_ (which is like mapM but ignores the results), -- but with an InjectedFn. mapWithM_ :: (Traversable t, Monad m) => InjectedFn a (m b) -> t a -> m () -- | like foldMap, but with an InjectedFn foldMapWith :: (Traversable t, Monoid b) => InjectedFn a b -> t a -> b -- | Represents a function from a, plus a number of injected -- values, to b. -- -- Used by mapWith (& related), which maps over a -- Traversable, injecting the additional values as it goes. -- -- Constructed by combining a map function with Injectors using -- the ^-> and <-^ operators. -- -- The sequence: -- --
--   (a -> i1 -> i2 -> ... -> in -> b) op1 inj1 op2 inj2 ... opn injn
--   
-- -- where: -- -- -- -- produces an InjectedFn a b, with n injected values (or -- more if any of the injectors inject multiple values). data InjectedFn a b -- | An Injectable is (recursively) either: -- -- -- -- When n is the number of parameters injected by an injector -- (most commonly 1). class Injectable m -- | Inject "from the left" (^->) :: (Injectable m, CurryTF i b) => m a (FnType i b) -> Injector a i -> InjectedFn a b -- | Inject "from the right" (<-^) :: (Injectable m, CurryTF i b) => m a (FnType i b) -> Injector a i -> InjectedFn a b infixl 1 ^-> infixl 1 <-^ -- | inject True if the item is at the limit: -- -- -- -- else inject False. -- --
--   >>> let f a l = [a, if l then '*' else ' '] in mapWith (f ^-> isLim) "12345"
--   ["1*","2 ","3 ","4 ","5 "]
--   
--   >>> let f a l = [a, if l then '*' else ' '] in mapWith (f <-^ isLim) "12345"
--   ["1 ","2 ","3 ","4 ","5*"]
--   
isLim :: Injector a (App1 Bool) -- | inject Just the adjacent item: -- -- -- -- inject Nothing if there is no adjacent item (i.e. for the first -- / last). -- --
--   >>> let f a b = [a,maybe '-' id b] in mapWith (f ^-> adjElt) "12345"
--   ["1-","21","32","43","54"]
--   
--   >>> let f a b = [a,maybe '-' id b] in mapWith (f <-^ adjElt) "12345"
--   ["12","23","34","45","5-"]
--   
adjElt :: Injector a (App1 (Maybe a)) -- | like adjElt, but injects the two adjacent items into separate -- parameters. -- --
--   >>> let f a b c = [a,ch b,ch c]; ch = maybe '-' id in mapWith (f ^-> adj2Elts) "12345"
--   ["1--","21-","321","432","543"]
--   
--   >>> let f a b c = [a,ch b,ch c]; ch = maybe '-' id in mapWith (f <-^ adj2Elts) "12345"
--   ["123","234","345","45-","5--"]
--   
adj2Elts :: Injector a (App2 (Maybe a) (Maybe a)) -- | inject the item index: -- -- -- --
--   >>> let f a b = a : show b in mapWith (f ^-> eltIx) "freddy"
--   ["f0","r1","e2","d3","d4","y5"]
--   
--   >>> let f a b = a : show b in mapWith (f <-^ eltIx) "freddy"
--   ["f5","r4","e3","d2","d1","y0"]
--   
eltIx :: Integral i => Injector a (App1 i) -- | True if an even-numbered (0th, 2nd, 4th, etc) item, counting from the -- left or from the right. -- --
--   >>> let f a e = [a, if e then '*' else ' '] in mapWith (f ^-> evenElt) "012345"
--   ["0*","1 ","2*","3 ","4*","5 "]
--   
--   >>> let f a e = [a, if e then '*' else ' '] in mapWith (f <-^ evenElt) "543210"
--   ["5 ","4*","3 ","2*","1 ","0*"]
--   
evenElt :: Injector a (App1 Bool) -- | Inject a (left-associative) fold of the items: -- -- TODO: table -- --
--   >>> let f a b = a ++ show b in mapWith (f ^-> foldlElts (\l s -> l + length s) 0) ["every", "good", "boy"]
--   ["every5","good9","boy12"]
--   
--   >>> let f a b = a ++ show b in mapWith (f <-^ foldlElts (\l s -> l + length s) 0) ["every", "good", "boy"]
--   ["every12","good7","boy3"]
--   
foldlElts :: (i -> a -> i) -> i -> Injector a (App1 i) -- | A variant of foldlElts that has no starting value: -- -- TODO: table -- --
--   >>> mapWith ((,) ^-> foldl1Elts (-)) [10,1,3]
--   [(10,10),(1,9),(3,6)]
--   
--   >>> mapWith ((,) <-^ foldl1Elts (-)) [10,1,3]
--   [(10,-8),(1,2),(3,3)]
--   
foldl1Elts :: (a -> a -> a) -> Injector a (App1 a) -- | Inject each given element in turn: -- -- -- --
--   >>> let f a b = [a,b] in mapWith (f ^-> eltFrom "bill") "sue"
--   ["sb","ui","el"]
--   
--   >>> let f a b = [a,b] in mapWith (f <-^ eltFrom "bill") "sue"
--   ["sl","ui","eb"]
--   
-- -- As a result of laziness, it is not always an error if there are not -- enough elements, for example: -- --
--   >>> drop 1 $ mapWith ((\_ i -> i) <-^ eltFrom [8,2]) "abc"
--   [2,8]
--   
eltFrom :: [i] -> Injector a (App1 i) -- | a safe version of eltFrom. Injects Just each given -- element in turn, or Nothing after they've been exhausted. -- --
--   >>> let f a b = [a,ch b]; ch = maybe '-' id in mapWith (f ^-> eltFromMay "ben") "sally"
--   ["sb","ae","ln","l-","y-"]
--   
--   >>> let f a b = [a,ch b]; ch = maybe '-' id in mapWith (f <-^ eltFromMay "ben") "sally"
--   ["s-","a-","ln","le","yb"]
--   
eltFromMay :: [i] -> Injector a (App1 (Maybe i)) -- | a safe version of eltFrom. Injects each given element in turn, -- or the default after they've been exhausted. -- --
--   >>> let f a b = [a,b] in mapWith (f ^-> eltFromDef 'X' "ben") "sally"
--   ["sb","ae","ln","lX","yX"]
--   
--   >>> let f a b = [a,b] in mapWith (f <-^ eltFromDef 'X' "ben") "sally"
--   ["sX","aX","ln","le","yb"]
--   
eltFromDef :: i -> [i] -> Injector a (App1 i) -- | isLim, from the left. isFirst :: Injectable f => f a (Bool -> b) -> InjectedFn a b -- | isLim, from the right. isLast :: Injectable f => f a (Bool -> b) -> InjectedFn a b -- | adjElt, from the left. prevElt :: Injectable f => f a (Maybe a -> b) -> InjectedFn a b -- | adjElt, from the right. nextElt :: Injectable f => f a (Maybe a -> b) -> InjectedFn a b -- | An Injector a i can be used with mapWith to map over a -- Traversable containing elements of type a, injecting -- values according to the type i as it goes. -- -- Injectors have an initial state and a generate function. -- -- For each item in the Traversable, the generate function can use -- both: -- -- -- -- to determine both: -- -- -- -- The injection value(s) must be an args (per CurryTF), -- in order for the injector to work with the ^-> and -- <-^ operators. These can be created by: -- -- -- -- The first value(s) to inject is/are determined by a first call to the -- generate function. The first call to the generate function is with the -- first (if combined with ^->) or last (if combined with -- <-^) item from the Traversable and the initial state. -- -- For example: -- --
--   >>> funnyNext a s = (a + 1, app1 $ a + s)
--   
--   >>> funnyInjector = Injector funnyNext 17
--   
--   >>> mapWith ((\_ i -> i) ^-> funnyInjector) [4,8,3]
--   [21,13,12]
--   
-- -- TODO: table -- --
--   >>> mapWith ((\_ i -> i) <-^ funnyInjector) [4,8,3]
--   [13,12,20]
--   
-- -- TODO: table -- -- More usefully, this might allow for e.g. injection of random values, -- etc. data Injector a i -- | the first parameter is a generate function, the second parameter is -- the initial/prior state. Injector :: (a -> s -> (s, i)) -> s -> Injector a i -- | A "stacked tuple" of four values type App4 a b c d = (a, (b, (c, (d, ())))) -- | A "stacked tuple" of three values type App3 a b c = (a, (b, (c, ()))) -- | A "stacked tuple" of two values type App2 a b = (a, (b, ())) -- | A "stacked tuple" of one value type App1 a = (a, ()) -- | stacks one value app1 :: a -> App1 a -- | stacks two values app2 :: a -> b -> App2 a b -- | stacks three values app3 :: a -> b -> c -> App3 a b c -- | stacks four values app4 :: a -> b -> c -> d -> App4 a b c d instance MapWith.Injectable (->) instance MapWith.Injectable MapWith.InjectedFn