-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Uncurry functions with multiple arguments. -- -- This library provides a version of "uncurry" which takes a function of -- multiple arguments and stores the arguments into an n-ary product from -- "sop-core". The first non-function type encountered in the signature -- is considered the "end of the function". -- -- This library also provides a way of reassociating a sequence of nested -- Eithers, so that the innermost Rigth value floats to the top-level -- Right branch. @package multicurryable @version 0.1.0.1 -- | While writing function decorators, we often need to store the -- arguments of the function in a n-ary product. multiuncurry -- @(<-) is useful for that. -- --
--   >>> :{
--   type Fun0 = Int
--   type UFun0 = NP I '[] -> Int
--   type Fun1 = Bool -> Int
--   type UFun1 = NP I '[Bool] -> Int
--   type Fun2 = Char -> Bool -> Int
--   type UFun2 = NP I '[Char, Bool] -> Int
--   ufun0 :: UFun0 = multiuncurry @(->) @_ @_ @Fun0 $ 5
--   ufun1 :: UFun1 = multiuncurry @(->) @_ @_ @Fun1 $ \_ -> 5
--   ufun2 :: UFun2 = multiuncurry @(->) @_ @_ @Fun2 $ \_ _ -> 5
--   fun0 :: Fun0 = multicurry @(->) @_ @_ ufun0 
--   fun1 :: Fun1 = multicurry @(->) @_ @_ ufun1 
--   fun2 :: Fun2 = multicurry @(->) @_ @_ ufun2
--   :}
--   
-- -- Less often, when processing the result of functions, we have a nested -- chain of Eithers like Either Err1 (Either Err2 (Either Err3 -- Success)), and want to put all the errors in a top-level -- Left branch, and the lone Success value in a top-level -- Right branch. multiuncurry @Either is useful -- for that. -- --
--   >>> :{
--   type Eith0 = Int
--   type Eith1 = Either Bool Int
--   type Eith2 = Either Char (Either Bool Int)
--   type UEith0 = Either (NS I '[]) Int
--   type UEith1 = Either (NS I '[Bool]) Int
--   type UEith2 = Either (NS I '[Char, Bool]) Int
--   ueith0 :: UEith0 = multiuncurry @Either @_ @_ @Eith0 5
--   ueith1 :: UEith1 = multiuncurry @Either @_ @_ @Eith1 $ Right 5
--   ueith2 :: UEith2 = multiuncurry @Either @_ @_ @Eith2 $ Right (Right 5)
--   eith0 :: Eith0 = multicurry @Either @_ @_ ueith0
--   eith1 :: Eith1 = multicurry @Either @_ @_ ueith1
--   eith2 :: Eith2 = multicurry @Either @_ @_ ueith2
--   :}
--   
-- -- The Multicurryable class will get terribly confused if it can't -- determine the rightmost type, because it can't be sure it's not -- another (->), or another Either. So use it only -- with concrete rightmost types, not polymorphic ones. module Multicurryable class Multicurryable (f :: Type -> Type -> Type) (items :: [Type]) a curried | f items a -> curried, f curried -> items a where { type UncurriedArgs f :: [Type] -> Type; } multiuncurry :: Multicurryable f items a curried => curried -> f (UncurriedArgs f items) a multicurry :: Multicurryable f items a curried => f (UncurriedArgs f items) a -> curried -- | An n-ary product. -- -- The product is parameterized by a type constructor f and -- indexed by a type-level list xs. The length of the list -- determines the number of elements in the product, and if the -- i-th element of the list is of type x, then the -- i-th element of the product is of type f x. -- -- The constructor names are chosen to resemble the names of the list -- constructors. -- -- Two common instantiations of f are the identity functor -- I and the constant functor K. For I, the product -- becomes a heterogeneous list, where the type-level list describes the -- types of its components. For K a, the product becomes -- a homogeneous list, where the contents of the type-level list are -- ignored, but its length still specifies the number of elements. -- -- In the context of the SOP approach to generic programming, an n-ary -- product describes the structure of the arguments of a single data -- constructor. -- -- Examples: -- --
--   I 'x'    :* I True  :* Nil  ::  NP I       '[ Char, Bool ]
--   K 0      :* K 1     :* Nil  ::  NP (K Int) '[ Char, Bool ]
--   Just 'x' :* Nothing :* Nil  ::  NP Maybe   '[ Char, Bool ]
--   
data NP (a :: k -> Type) (b :: [k]) [Nil] :: forall {k} (a :: k -> Type). NP a ('[] :: [k]) [:*] :: forall {k} (a :: k -> Type) (x :: k) (xs :: [k]). a x -> NP a xs -> NP a (x : xs) infixr 5 :* -- | An n-ary sum. -- -- The sum is parameterized by a type constructor f and indexed -- by a type-level list xs. The length of the list determines -- the number of choices in the sum and if the i-th element of -- the list is of type x, then the i-th choice of the -- sum is of type f x. -- -- The constructor names are chosen to resemble Peano-style natural -- numbers, i.e., Z is for "zero", and S is for -- "successor". Chaining S and Z chooses the corresponding -- component of the sum. -- -- Examples: -- --
--   Z         :: f x -> NS f (x ': xs)
--   S . Z     :: f y -> NS f (x ': y ': xs)
--   S . S . Z :: f z -> NS f (x ': y ': z ': xs)
--   ...
--   
-- -- Note that empty sums (indexed by an empty list) have no non-bottom -- elements. -- -- Two common instantiations of f are the identity functor -- I and the constant functor K. For I, the sum -- becomes a direct generalization of the Either type to -- arbitrarily many choices. For K a, the result is a -- homogeneous choice type, where the contents of the type-level list are -- ignored, but its length specifies the number of options. -- -- In the context of the SOP approach to generic programming, an n-ary -- sum describes the top-level structure of a datatype, which is a choice -- between all of its constructors. -- -- Examples: -- --
--   Z (I 'x')      :: NS I       '[ Char, Bool ]
--   S (Z (I True)) :: NS I       '[ Char, Bool ]
--   S (Z (K 1))    :: NS (K Int) '[ Char, Bool ]
--   
data NS (a :: k -> Type) (b :: [k]) [Z] :: forall {k} (a :: k -> Type) (x :: k) (xs :: [k]). a x -> NS a (x : xs) [S] :: forall {k} (a :: k -> Type) (xs :: [k]) (x :: k). NS a xs -> NS a (x : xs) -- | The identity type functor. -- -- Like Identity, but with a shorter name. newtype I a I :: a -> I a instance Multicurryable.MulticurryableE (Multicurryable.IsEither curried) items a curried => Multicurryable.Multicurryable Data.Either.Either items a curried instance Multicurryable.MulticurryableE 'GHC.Types.False '[] a a instance Multicurryable.MulticurryableE (Multicurryable.IsEither curried) rest tip curried => Multicurryable.MulticurryableE 'GHC.Types.True (i : rest) tip (Data.Either.Either i curried) instance Multicurryable.MulticurryableF (Multicurryable.IsFunction curried) items a curried => Multicurryable.Multicurryable (->) items a curried instance Multicurryable.MulticurryableF 'GHC.Types.False '[] a a instance Multicurryable.MulticurryableF (Multicurryable.IsFunction curried) rest tip curried => Multicurryable.MulticurryableF 'GHC.Types.True (i : rest) tip (i -> curried)