Copyright | (c) Donnacha Oisín Kidney 2018 |
---|---|

License | MIT |

Maintainer | mail@doisinkidney.com |

Portability | GHC |

Safe Haskell | Safe |

Language | Haskell2010 |

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.

- Eisenberg, Richard A. "Dependent Types in Haskell: Theory and Practice." University of Pennsylvania, 2016. https://github.com/goldfirere/thesis/raw/master/built/thesis.pdf

# Documentation

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

returns the type of the function `AppFunc`

f n a`a`

"lifted" over `n`

arguments.

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

The actual class which constructs the lifted function.

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:

`>>>`

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

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:

`>>>`

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

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

`>>>`

`:set -XTypeApplications`

`>>>`

Just 3`lift ((+) @Int) (Just 1) (Just 2)`

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

etc.