Jeśli weźmiesz pod uwagę (niejawne) indeksy każdego elementu listy jako klucze, to zipWith
jest czymś w rodzaju relacyjnego sprzężenia wewnętrznego. Przetwarza tylko klucze, w których oba wejścia mają wartości:Kanoniczna zewnętrzna funkcja zipowania
zipWith (+) [1..5] [10..20] == zipWith (+) [1..11] [10..14] == [11,13,15,17,19]
Czy istnieje kanoniczny odpowiednia funkcja odpowiadająca sprzężenie zewnętrzne? Coś jak:
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
czy może
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
Więc mogę zrobić
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]
znajdę się potrzebuje od czasu do czasu, a wolałbym używać wspólnego idiomu do spraw, aby mój kod był bardziej zapisywalny (i łatwiejszy w utrzymaniu) niż implementacja outerZipWith
, lub wykonanie if length as < length bs then zipWith f (as ++ repeat a) bs else zipWith f as (bs ++ repeat b)
.
Nie "zewnętrznyZip :: a -> b -> [a] -> [b] -> [(a, b)]"? – pat
Więcej jak 'outerZip :: (a -> c) -> (b -> d) -> c -> d -> [a] -> [b] -> [(c, d)]' – Apocalisp
-lub typ (jak twoje 'Te') może być koniecznym pierwszym krokiem. Przynajmniej jest to dobre miejsce na rozpoczęcie. – rampion