Подтвердить что ты не робот

Есть ли у Haskell жадный почтовый индекс (один сохраняет все элементы)?

Я не совсем уверен, что моя номенклатура здесь правильная, но мне было интересно, была ли в Haskell функция zip, которая была жадной. Это означает, что если бы я имел

a = [1, 2, 3]
b = [4, 5]
zip' a b
#=> [(Just 1, Just 4),(Just 2, Just 5),(Just 3, Nothing)]

... где zip' - это жадная функция zip, она вернет список кортежей длины более длинного списка и где более длинный список имеет элемент, но более короткий список не помещается Nothing в соответствующей позиции кортежа. Я не спрашиваю, как писать это, но вместо этого задавался вопросом, существует ли это как встроенный.

Вот моя реализация (которая, вероятно, невелика)

zip' :: [a] -> [b] -> [(Maybe a, Maybe b)]
zip' (a:xs) [] = (Just a, Nothing) : zip' xs []
zip' [] (b:ys) = (Nothing, Just b) : zip' [] ys
zip' [] _ = []
zip' (a:xs) (b:ys) = (Just a, Just b) : zip' xs ys
4b9b3361

Ответ 1

Жадный zip может быть аккуратно выражен через неэксклюзивный тип дизъюнкции (в отличие от Either, который является исключительной дизъюнкцией). Это предлагают два популярных пакета. Один из них - минималистский, без зависимости data-or:

GHCi> import Data.Or
GHCi> :t zipOr
zipOr :: [a] -> [b] -> [Or a b]
GHCi> zipOr [1, 2, 3] [4, 5]
[Both 1 4,Both 2 5,Fst 3]

Другой these, который поставляется с множеством колоколов и свистков:

GHCi> import Data.These 
GHCi> import Data.Align
GHCi> :t align
align :: Align f => f a -> f b -> f (These a b)
GHCi> align [1, 2, 3] [4, 5]
[These 1 4,These 2 5,This 3]

Я считаю, что Or a b и These a b выражают ваше намерение лучше, чем (Maybe a, Maybe b) (последний тип включает (Nothing, Nothing), который жадный zip никогда не произведет). Тем не менее, вы можете выразить zip' с помощью zipOrWith из Data.Or...

import Data.Or

zip' :: [a] -> [b] -> [(Maybe a, Maybe b)]
zip' = zipOrWith $ \xy -> case xy of
    Both x y -> (Just x, Just y)
    Fst x -> (Just x, Nothing)
    Snd y -> (Nothing, Just y)

... или alignWith из Data.Align:

import Data.These
import Data.Align

zip' :: Align f => f a -> f b -> f (Maybe a, Maybe b)
zip' = alignWith $ \xy -> case xy of
    These x y -> (Just x, Just y)
    This x -> (Just x, Nothing)
    That y -> (Nothing, Just y)

Data.Align, на самом деле, предоставляет вашу функцию под именем padZip.