Nếu bạn xem xét các chỉ mục (ẩn) của từng phần tử trong danh sách dưới dạng khóa của chúng, thì zipWith
giống như một liên kết bên trong quan hệ. Nó chỉ xử lý các khóa mà cả hai yếu tố đầu vào đều có giá trị:Chức năng zip tham gia bên ngoài Canonical
zipWith (+) [1..5] [10..20] == zipWith (+) [1..11] [10..14] == [11,13,15,17,19]
Có chức năng tương ứng chuẩn nào tương ứng với tham gia bên ngoài không? Một cái gì đó như:
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
hoặc có thể
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
Vì vậy, tôi có thể làm
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]
tôi thấy mình cần nó bất cứ lúc nào, và tôi muốn sử dụng một thành ngữ phổ biến để làm cho mã của tôi dễ ghi hơn (và dễ bảo trì hơn) so với việc thực hiện outerZipWith
hoặc thực hiện if length as < length bs then zipWith f (as ++ repeat a) bs else zipWith f as (bs ++ repeat b)
.
Sẽ không 'outerZip :: a -> b -> [a] -> [b] -> [(a, b)] '? – pat
Giống như 'outerZip :: (a -> c) -> (b -> d) -> c -> d -> [a] -> [b] -> [(c, d)]' – Apocalisp
Đã bao gồm -hoặc loại (như 'Những 'của bạn) có thể là bước đầu tiên cần thiết. Ít nhất, đó là một nơi tốt để bắt đầu. – rampion