-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Create poly variadic functions for monoidal results -- -- Please see README.md @package function-builder @version 0.1.0.3 -- | A builder for functions of variable parameters -- -- FunctionBuilder values can be composed, and eventually -- rendered into a function by toFunction. -- -- For example the composition of: -- --
-- fb1 :: FunctionBuilder MyMonoid composeMe (Int -> composeMe) -- fb1 = addParameter ... -- -- fb2 :: FunctionBuilder MyMonoid composeMe (String -> composeMe) -- fb2 = addParameter ... -- -- fb3 :: FunctionBuilder MyMonoid composeMe (Bool -> composeMe) -- fb3 = addParameter ... -- -- fb :: FunctionBuilder MyMonoid composeMe (Int -> String -> Bool -> composeMe) -- fb = fb1 . fb2 . fb3 -- -- f :: Int -> String -> Bool -> MyMonoid -- f = toFunction fb123 ---- -- FunctionBuilders are composed via . from Category -- and <> from Semigroup. -- -- This module provides Functor, Applicative, Monad, -- Semigroup, Monoid and Category instances; -- -- The smart-constructors immediate and addParameter create -- FunctionBuilders that either write a hard coded constant to the -- output Monoid or add a function that will be applied to an -- additional runtime parameter. -- -- Further glue-code is provided to allow changing the underlying -- Monoid, see bind. module Data.FunctionBuilder -- | A tricky newtype wrapper around a function that carries out a -- computation resulting in a monoidal output value that is passed to a -- continuation. -- -- Type parameters: -- --
-- fb1 :: FunctionBuilder MyMonoid next (Int -> next) -- fb1 = addParameter undefined -- -- fb2 :: FunctionBuilder MyMonoid next (String -> next) -- fb2 = addParameter undefined -- -- newtype MyMonoid = MyMonoid () deriving (Semigroup, Monoid) ---- -- When we desugar with ghci: -- --
-- >>> :t (runFunctionBuilder fb1) -- (runFunctionBuilder fb1) :: (MyMonoid -> next) -> Int -> next ---- --
-- >>> :t (runFunctionBuilder fb2) -- (runFunctionBuilder fb2) :: (MyMonoid -> next) -> String -> next ---- -- Composition comes in two flavours: -- --
-- >>> :t (fb1 . fb2) -- (fb1 . fb2) :: FunctionBuilder MyMonoid a (Int -> String -> a) ---- -- And desugared: -- --
-- >>> :t runFunctionBuilder (fb1 . fb2) -- runFunctionBuilder (fb1 . fb2) :: (MyMonoid -> next) -> Int -> String -> next ---- -- What happened during composition was that the next in -- fb1 was used to insert into Int -> next the -- String -> other_next from fb2; such that this -- results in Int -> (String -> other_next). (Note: For -- clarity I renamed the type local type parameter next to -- other_next from fb2) newtype FunctionBuilder acc next f_make_next FB :: ((acc -> next) -> f_make_next) -> FunctionBuilder acc next f_make_next [$sel:runFunctionBuilder:FB] :: FunctionBuilder acc next f_make_next -> (acc -> next) -> f_make_next -- | Get the composed output function of a FunctionBuilder. -- -- The FunctionBuilder passed to this function must match this -- signature: -- --
-- FunctionBuilder m m (arg0 -> .. -> m) ---- -- This means that the result of the generated function arg0 -> .. -- -> m MUST be m, the underlying Monoid. -- -- The FunctionBuilders generated by addParameter and -- immediate are parametric in the second type parameter and match -- the type signature required by this function. -- -- Example 1: -- --
-- fb :: FunctionBuilder String String (Int -> Double -> Int -> String) -- fb = undefined -- -- example :: Int -> Double -> Int -> String -- example = toFunction fb ---- -- Example 2: -- --
-- example :: Int -> Double -> Int -> String -- example = toFunction (i . d . i) -- -- s :: String -> FunctionBuilder String a a -- s x = FB (\k -> k x) -- -- i :: FunctionBuilder String next (Int -> next) -- i = FB (\k x -> k $ show x) -- -- d :: FunctionBuilder String next (Double -> next) -- d = FB (\k x -> k $ show x) --toFunction :: FunctionBuilder output output make_output -> make_output -- | Create a FunctionBuilder that appends something to the -- (monoidal-) output value. -- -- This is a smart constructor for a FunctionBuilder. This -- functions is probably equal to: -- --
-- immediate x = FB (\k -> k x) ---- -- The generated builder can be passed to toFunction since it is -- parametric in its second type parameter. -- -- Example: -- -- When building a String formatting FunctionBuilder the -- function to append a literal string could be: -- --
-- s :: String -> FunctionBuilder String a a -- s = immediate ---- --
-- c :: Char -> FunctionBuilder String a a -- c = immediate . (:[]) ---- --
-- example :: String -- example = toFunction (s "hello" . c ' ' . s "world") ---- --
-- >>> example -- "hello world" ---- -- See the example in toFunction. immediate :: m -> FunctionBuilder m r r -- | Create a FunctionBuilder that adds an argument to the output -- function, and converts that argument to a value that can be -- accumulated in the resulting monoidal value. -- -- This is a smart constructor for a FunctionBuilder. This -- functions is probably equal to: -- --
-- addParameter f = FB (\k x -> k (f x)) ---- -- The generated builder can be passed to toFunction since it is -- parametric in its second type parameter. -- -- Example: -- -- When building a String formatting FunctionBuilder the -- function to append a parameter that has a show instance could be: -- --
-- showing :: Show a => FunctionBuilder String r (a -> r) -- showing = addParameter show ---- --
-- example :: (Show a, Show b) => a -> b -> String -- example = toFunction (showing . showing) ---- --
-- >>> example True 0.33214 -- "True0.33214" ---- -- See the example in toFunction. addParameter :: (a -> m) -> FunctionBuilder m r (a -> r) -- | Take away a function parameter added with addParameter by -- pre - applying it to some value. -- -- For example: -- --
-- intArg :: FunctionBuilder MyMonoid a (Int -> a) -- intArg = addParameter undefined -- -- stringArg :: FunctionBuilder MyMonoid a (String -> a) -- stringArg = addParameter undefined -- -- twoInt :: FunctionBuilder MyMonoid a (Int -> String -> a) -- twoInt = intArg . stringArg -- -- example :: FunctionBuilder MyMonoid a (String -> a) -- example = fillParameter twoInt 42 ---- -- This is equivalent to: -- --
-- fillParameter f x = f * pure x --fillParameter :: FunctionBuilder m r (a -> b) -> a -> FunctionBuilder m r b -- | Convert a FunctionBuilder for a function (a -> b) -- to (Tagged tag a -> b). tagParameter :: forall tag m r a b. FunctionBuilder m r (a -> b) -> FunctionBuilder m r (Tagged tag a -> b) -- | Compose to FunctionBuilders such that the second -- FunctionBuilder may depend on the intermediate result of the -- first. Similar to a monadic bind >>= but more flexible -- sind the underlying Monoid may change too, for example: -- --
-- intText :: FunctionBuilder Text next (Int -> next) -- intText = addParameter undefined -- -- unpackB :: Text -> FunctionBuilder String next next -- unpackB = immediate . unpack -- -- intStr :: FunctionBuilder String next (Int -> next) -- intStr = intText `bind` unpackB --bind :: FunctionBuilder m g_next f_g_next -> (m -> FunctionBuilder n next g_next) -> FunctionBuilder n next f_g_next -- | Convert the accumulated (usually monoidal-) value, this allows to -- change the underlying accumlator type. mapAccumulator :: (m -> n) -> FunctionBuilder m a b -> FunctionBuilder n a b -- | Convert the output of a FunctionBuilder value; since most -- FunctionBuilders are parameteric in r they also have -- r in a in a, such that a always either is -- r or is a function returning r eventually. -- -- In order to get from a FunctionBuilder that can accept a -- continuation returning it an r to a FunctionBuilder -- that accepts continuations returning an s instead, we need to -- apply a function s -> r to the return value of the -- continuation. -- -- Note that a mapNext will not only change the r to an -- s but probably also the the a, when it is -- parametric, as in this contrived example: -- --
-- example :: Int -> x -> Sum Int -- example = toFunction (ign add) -- -- add :: FunctionBuilder (Sum Int) next (Int -> next) -- add = FB (\k x -> k $ Sum x) -- -- ign :: FunctionBuilder m (x -> r) a -> FunctionBuilder m r a -- ign = mapNext const ---- -- Here the extra parameter x is pushed down into the -- a of the add FunctionBuilder. mapNext :: (s -> r) -> FunctionBuilder m r a -> FunctionBuilder m s a instance GHC.Base.Monoid m => Control.Category.Category (Data.FunctionBuilder.FunctionBuilder m) instance GHC.Base.Semigroup m => GHC.Base.Semigroup (Data.FunctionBuilder.FunctionBuilder m r r) instance GHC.Base.Monoid m => GHC.Base.Monoid (Data.FunctionBuilder.FunctionBuilder m r r) instance GHC.Base.Functor (Data.FunctionBuilder.FunctionBuilder m r) instance GHC.Base.Applicative (Data.FunctionBuilder.FunctionBuilder m r) instance GHC.Base.Monad (Data.FunctionBuilder.FunctionBuilder m r)