Functor outer product

outer :: (Functor l, Functor r)
      => (a->b->c) -> l a -> r b -> l (r c)

We replace the list constructors [] with functors. The result nests two functors—note that we now keep track of which is which.

λ> let outer f x y = fmap (\a -> fmap (f a) y) x
λ> outer (*) [1,2,3] (Just 3)
[Just 3,Just 6,Just 9]
λ> outer (*) [1,2,3] Nothing
[Nothing,Nothing,Nothing]
λ> (outer (\a b -> [a,b]) (1+) (2*)) 3 4
[4,8]