Если вы рассматриваете (неявные) индексы каждого элемента списка как их ключи, то zipWith
является своего рода реляционным внутренним соединением. Он обрабатывает только те ключи, для которых оба входа имеют значения:
zipWith (+) [1..5] [10..20] == zipWith (+) [1..11] [10..14] == [11,13,15,17,19]
Существует ли каноническая соответствующая функция, соответствующая внешнему объединению? Что-то вроде:
outerZipWith :: (a -> b -> c) -> a -> b -> [a] -> [b] -> [c]
outerZipWith _ _ _ [] [] = []
outerZipWith f a' b' [] (b:bs) = f a' b : outerZipWith f a' b' [] bs
outerZipWith f a' b' (a:as) [] = f a b' : outerZipWith f a' b' as []
outerZipWith f a' b' (a:as) (b:bs) = f a b : outerZipWith f a' b' as bs
или, может быть
outerZipWith' :: (a -> b -> c) -> Maybe a -> Maybe b -> [a] -> [b] -> [c]
outerZipWith' _ _ _ [] [] = []
outerZipWith' _ Nothing _ [] _ = []
outerZipWith' _ _ Nothing _ [] = []
outerZipWith' f a' b' [] (b:bs) = f (fromJust a') b : outerZipWith f a' b' [] bs
outerZipWith' f a' b' (a:as) [] = f a (fromJust b') : outerZipWith f a' b' as []
outerZipWith' f a' b' (a:as) (b:bs) = f a b : outerZipWith f a' b' as bs
Так что я могу сделать
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]
Время от времени я нуждаюсь в этом, и я предпочел бы использовать общую идиому, чтобы сделать мой код более доступным для записи (и легче поддерживать), чем реализовывать outerZipWith
или выполнять if length as < length bs then zipWith f (as ++ repeat a) bs else zipWith f as (bs ++ repeat b)
.