arity-generic-liftA-0.1.0.0: Provides an arity-generic version of the liftA2, liftA3... liftAn functions.

Control.Applicative.Lift.Internal

Description

There's a family of functions in Control.Applicative which follow the pattern liftA2, liftA3, etc. Using some tricks from Richard Eisenberg's thesis we can write them all at once.

Synopsis

# Documentation

data N Source #

Simple implementation of Peano numbers.

Constructors

 Z S N

type family AppFunc f n a where ... Source #

AppFunc f n a returns the type of the function a "lifted" over n arguments.

Equations

 AppFunc f Z a = f a AppFunc f (S n) (a -> b) = f a -> AppFunc f n b

type family CountArgs f where ... Source #

Counts the arguments of a function

Equations

 CountArgs (_ -> b) = S (CountArgs b) CountArgs _ = Z

class CountArgs a ~ n => Applyable a n where Source #

The actual class which constructs the lifted function.

Methods

apply :: Applicative f => f a -> AppFunc f (CountArgs a) a Source #

Instances
 CountArgs a ~ Z => Applyable a Z Source # Instance detailsDefined in Control.Applicative.Lift.Internal Methodsapply :: Applicative f => f a -> AppFunc f (CountArgs a) a Source # Applyable b n => Applyable (a -> b) (S n) Source # Instance detailsDefined in Control.Applicative.Lift.Internal Methodsapply :: Applicative f => f (a -> b) -> AppFunc f (CountArgs (a -> b)) (a -> b) Source #

lift :: (Applyable b n, Applicative f) => (a -> b) -> f a -> AppFunc f n b Source #

Lift a function over applicative arguments. This function is an arity-generic version of the functions liftA2, liftA3, etc.

Type inference works best when the function being lifted is monomorphic:

>>> lift (\x y z -> x ++ y ++ z) (Just "a") (Just "b") (Just "c")
Just "abc"


In these cases, GHC can see the number of arguments the function must have, and so is able to pick the correct instance for Applyable.

If the function is not monomorphic (for instance +), you will need to give a type signature:

>>> lift ((+) :: Int -> Int -> Int) (Just 1) (Just 2)
Just 3


Alternatively, you can use type applications to monomorphise the function:

>>> :set -XTypeApplications
>>> lift ((+) @Int) (Just 1) (Just 2)
Just 3


Finally, everything is aggressively inlined, so there should be no cost to using this function over manually writing liftA3 etc.