我正在尝试编写一个类似于 zip 的函数,但不会丢弃额外的元素。我觉得我在某个地方犯了一个非常愚蠢的错误。
输入示例:
zipMaybe [1,2,3] [1,2]
所需输出:
[(Just 1, Just 1), (Just 2, Just 2), (Just 3, Nothing)]
zipMaybe :: [a] -> [b] -> [(Maybe a, Maybe b)]
zipMaybe (a:as) (b:bs) = (Just a, Just b) : zip as bs -- line with error
zipMaybe (a:as) [] = (Just a, Nothing) : zip as []
zipMaybe [] (b:bs) = (Nothing, Just b) : zip [] bs
zipMaybe _ _ = []
但是这不会编译。
Test.hs:2:49:
Couldn't match type `a' with `Maybe a'
`a' is a rigid type variable bound by
the type signature for
zipMaybe :: [a] -> [b] -> [(Maybe a, Maybe b)]
at Test.hs:1:13
Expected type: [Maybe a]
Actual type: [a]
In the first argument of `zip', namely `as'
In the second argument of `(:)', namely `zip as bs'
In the expression: (Just a, Just b) : zip as bs
您应该递归调用
zipMaybe
,而不是退回到普通 zip
,因为它的类型错误。
zipMaybe :: [a] -> [b] -> [(Maybe a, Maybe b)]
zipMaybe (a:as) (b:bs) = (Just a, Just b) : zipMaybe as bs
zipMaybe (a:as) [] = (Just a, Nothing) : zipMaybe as []
zipMaybe [] (b:bs) = (Nothing, Just b) : zipMaybe [] bs
zipMaybe _ _ = []
顺便说一句,这个函数有一个更短的定义:
zipMaybe (x:xs) (y:ys) = (Just x, Just y) : zipMaybe xs ys
zipMaybe xs [] = [(Just x, Nothing) | x <- xs]
zipMaybe [] ys = [(Nothing, Just y) | y <- ys]
--This will work (already tested):
zipMaybe :: [a] -> [b] -> [(Maybe a, Maybe b)]
zipMaybe [] [] = []
zipMaybe (x:xs) [] = [(Just x, Nothing)] ++ zipMaybe xs []
zipMaybe [] (y:ys) = [(Nothing, Just y)] ++ zipMaybe [] ys
zipMaybe (x:xs) (y:ys) = [(Just x, Just y)] ++ zipMaybe xs ys