Haskell有一个贪婪的拉链(一个保留所有元素)?

Eli*_*off 25 haskell

我不确定我的命名法是否正确,但我想知道Haskell中是否有一个贪婪的zip函数.这意味着,如果我有

a = [1, 2, 3]
b = [4, 5]
zip' a b
#=> [(Just 1, Just 4),(Just 2, Just 5),(Just 3, Nothing)]
Run Code Online (Sandbox Code Playgroud)

... 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
Run Code Online (Sandbox Code Playgroud)

dup*_*ode 37

贪婪的拉链可以通过非排他性的分离类型(相反Either,这是一种独特的分离)整齐地表达出来.两个受欢迎的套餐提供.一个是极简主义,无依赖性的数据 - 或:

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]
Run Code Online (Sandbox Code Playgroud)

另一个是这些,它带有许多花里胡哨的东西:

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]
Run Code Online (Sandbox Code Playgroud)

我相信Or a bThese a b表达你的意图比(Maybe a, Maybe b)(后一种类型包括(Nothing, Nothing),贪婪的拉链永远不会产生).不过,你可以表达你的zip'使用无论是zipOrWithData.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)
Run Code Online (Sandbox Code Playgroud)

......或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)
Run Code Online (Sandbox Code Playgroud)

Data.Align实际上,它提供了你的名字下的功能padZip.

  • 似乎`align`已经准确地提供了所需的功能 - "padZip :: Align f => fa - > fb - > f(也许是a,也许是b)` - 但正如你所说,`或者ab`表达了更好的意图比起`(也许是,也许是b)`无论如何. (2认同)