-- A simple implementation of polyvariadic `map` a.k.a. `zipWith` -- using typeclasses. class Map2 m where map2 :: (a -> b -> c) -> m a -> m b -> m c instance Map2 [] where map2 = zipWith class MapN a b where mapN :: a -> b instance (a ~ b) => MapN (m a) (m b) where mapN = id instance (a ~ c, Map2 m, MapN (m b) r) => MapN (m (a -> b)) (m c -> r) where mapN f a = mapN (map2 ($) f a) mapp :: (MapN (m b) c, Functor m) => (a -> b) -> m a -> c mapp f m = mapN (f <$> m) -- mapp (+) [1,2] [3,4] :: [Int] -- mapp (((+) .) . (+)) [1,2] [3,4] [5,6] :: [Int]