Se si considerano gli indici (impliciti) di ciascun elemento di un elenco come chiavi, allora zipWith
è un po 'come un join interno relazionale. Elabora solo le chiavi per cui entrambi gli input hanno valori:Funzione zip dell'unione canonica esterna
zipWith (+) [1..5] [10..20] == zipWith (+) [1..11] [10..14] == [11,13,15,17,19]
Esiste una funzione corrispondente canonica corrispondente all'unione esterna? Qualcosa di simile:
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
o forse
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
Così posso fare
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]
mi trovo a dover di volta in volta, e io preferisco usare un idioma comune a rendere il mio codice più scrivibile (e più facile da mantenere) piuttosto che implementare outerZipWith
o fare if length as < length bs then zipWith f (as ++ repeat a) bs else zipWith f as (bs ++ repeat b)
.
Non 'outerZip :: a -> b -> [a] -> [b] -> [(a, b)]'? – pat
Più come 'outerZip :: (a -> c) -> (b -> d) -> c -> d -> [a] -> [b] -> [(c, d)]' – Apocalisp
Un inclusivo -o tipo (come il tuo 'Questi') potrebbe essere il primo passo necessario. Per lo meno, è un buon punto di partenza. – rampion