If you consider the (implicit) indices of each list item as your keys, then zipWith
is a kind of relational inner join. It processes only keys for which both inputs have values:
zipWith (+) [1..5] [10..20] == zipWith (+) [1..11] [10..14] == [11,13,15,17,19]
Is there a canonical corresponding function corresponding to the outer join? Sort of:
outerZipWith :: (a -> b -> c) -> a -> b -> [a] -> [b] -> [c] outerZipWith _ _ _ [] [] = [] outerZipWith fa' b' [] (b:bs) = fa' b : outerZipWith fa' b' [] bs outerZipWith fa' b' (a:as) [] = fab' : outerZipWith fa' b' as [] outerZipWith fa' b' (a:as) (b:bs) = fab : outerZipWith fa' b' as bs
or maybe
outerZipWith' :: (a -> b -> c) -> Maybe a -> Maybe b -> [a] -> [b] -> [c] outerZipWith' _ _ _ [] [] = [] outerZipWith' _ Nothing _ [] _ = [] outerZipWith' _ _ Nothing _ [] = [] outerZipWith' fa' b' [] (b:bs) = f (fromJust a') b : outerZipWith fa' b' [] bs outerZipWith' fa' b' (a:as) [] = fa (fromJust b') : outerZipWith fa' b' as [] outerZipWith' fa' b' (a:as) (b:bs) = fab : outerZipWith fa' b' as bs
So what can i do
outerZipWith (+) 0 0 [1..5] [10..20] == [11,13,15,17,19,15,16,17,18,19,20] outerZipWith (+) 0 0 [1..11] [10..14] == [11,13,15,17,19,6,7,8,9,10,11]
I need to need this from time to time, and I would rather use a common idiom to make my code more writable (and easier to maintain), rather than implementing outerZipWith
or doing if length as < length bs then zipWith f (as ++ repeat a) bs else zipWith f as (bs ++ repeat b)
.