ap package:defun-core

Destructor of Lam2
Destructor of Lam3
Type level function application.
List append.
>>> :kind! Append [1, 2, 3] [4, 5, 6]
Append [1, 2, 3] [4, 5, 6] :: [Natural]
= [1, 2, 3, 4, 5, 6]
List concatMap
List map
>>> :kind! Map NotSym [True, False]
Map NotSym [True, False] :: [Bool]
= [False, True]
>>> :kind! Map (Con1 Just) [1, 2, 3]
Map (Con1 Just) [1, 2, 3] :: [Maybe Natural]
= [Just 1, Just 2, Just 3]
List binary map. I.e. liftA2 for lists. Note: this is not ZipWith.
>>> :kind! Map2 (Con2 '(,)) [1, 2, 3] ['x', 'y']
Map2 (Con2 '(,)) [1, 2, 3] ['x', 'y'] :: [(Natural, Char)]
= ['(1, 'x'), '(1, 'y'), '(2, 'x'), '(2, 'y'), '(3, 'x'), '(3, 'y')]
This function is a good example to highlight how to defunctionalize definitions with anonymous functions. The simple definition can be written using concatMap and map from Prelude:
>>> import Prelude as P (concatMap, map, (.), flip)

>>> let map2 f xs ys = P.concatMap (\x -> P.map (f x) ys) xs

>>> map2 (,) "abc" "xy"
[('a','x'),('a','y'),('b','x'),('b','y'),('c','x'),('c','y')]
However, to make it easier (arguably) to defunctionalize, the concatMap argument lambda can be written in point-free form using combinators:
>>> let map2 f xs ys = P.concatMap (P.flip P.map ys P.. f) xs

>>> map2 (,) "abc" "xy"
[('a','x'),('a','y'),('b','x'),('b','y'),('c','x'),('c','y')]
Alternatively, we could define a new "top-level" function
>>> let map2Aux f ys x = P.map (f x) ys
and use it to define @map2:
>>> let map2 f xs ys = P.concatMap (map2Aux f ys) xs

>>> map2 (,) "abc" "xy"
[('a','x'),('a','y'),('b','x'),('b','y'),('c','x'),('c','y')]