module Data.Function.Variadic.Utils
  ( composeN,
    constN,
    mappendN,
  )
where

import Data.Function.Variadic

-- | Function composition for an arbitrary number of arguments.
--
-- >>> (show `composeN` \a b c -> (a + b + c :: Int)) 1 2 3
-- "6"
composeN :: (Function f args b EmptyConstraint, Function g args a EmptyConstraint) => (a -> b) -> g -> f
composeN :: (a -> b) -> g -> f
composeN a -> b
f = Any EmptyConstraint
-> (forall a. EmptyConstraint a => () -> a -> ())
-> (() -> a -> b)
-> ()
-> ConstructFunction args a
-> f
forall f (args :: [*]) r (argC :: * -> Constraint)
       (proxy :: (* -> Constraint) -> *) acc r0.
Function f args r argC =>
proxy argC
-> (forall a. argC a => acc -> a -> acc)
-> (acc -> r0 -> r)
-> acc
-> ConstructFunction args r0
-> f
transformFunction (forall k (p :: (k -> Constraint) -> *). p EmptyConstraint
forall a. HasCallStack => a
undefined :: p EmptyConstraint) forall a. EmptyConstraint a => () -> a -> ()
forall a b. a -> b -> a
const (\()
_ a
r -> a -> b
f a
r) ()

-- | Constant function for an arbitrary number of arguments.
--
-- @
-- let const2 = constN :: x -> a -> b -> x
-- @
--
-- >>> zipWith3 (constN 1) [1..10] [1..5] ["a", "b", "c"] :: [Int]
-- [1,1,1]
constN :: Function f args a EmptyConstraint => a -> f
constN :: a -> f
constN a
a = Any EmptyConstraint
-> (forall a. EmptyConstraint a => () -> a -> ())
-> (() -> a)
-> ()
-> f
forall f (args :: [*]) r (argC :: * -> Constraint)
       (proxy :: (* -> Constraint) -> *) acc.
Function f args r argC =>
proxy argC
-> (forall a. argC a => acc -> a -> acc) -> (acc -> r) -> acc -> f
createFunction (forall k (p :: (k -> Constraint) -> *). p EmptyConstraint
forall a. HasCallStack => a
undefined :: p EmptyConstraint) forall a. EmptyConstraint a => () -> a -> ()
forall a b. a -> b -> a
const (a -> () -> a
forall a b. a -> b -> a
const a
a) ()

-- | Append multiple monoid values. It is similar to `mconcat` but takes the values as arguments rather than list elements.
--
-- >>> mappendN [1, 2] [3] [4, 5] :: [Int]
-- [1,2,3,4,5]
mappendN :: forall r f args. (Function f args r ((~) r), Monoid r) => f
mappendN :: f
mappendN = Any ((~) r)
-> (forall a. (r ~ a) => r -> a -> r) -> (r -> r) -> r -> f
forall f (args :: [*]) r (argC :: * -> Constraint)
       (proxy :: (* -> Constraint) -> *) acc.
Function f args r argC =>
proxy argC
-> (forall a. argC a => acc -> a -> acc) -> (acc -> r) -> acc -> f
createFunction (forall k (proxy :: (k -> Constraint) -> *) (r :: k). proxy ((~) r)
forall a. HasCallStack => a
undefined :: proxy ((~) r)) forall a. Monoid a => a -> a -> a
forall a. (r ~ a) => r -> a -> r
mappend r -> r
forall a. a -> a
id r
forall a. Monoid a => a
mempty