2013-10-18 42 views
5

我試圖編寫一個類似於zip的函數,但不會丟棄額外的元素。我覺得我在某個地方犯了一個非常愚蠢的錯誤。我的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 
+2

你打電話'zip'而不是遞歸調用你的'zipMaybe'。 – Tarmil

+4

你可能會喜歡['align'](http://hackage.haskell.org/package/these-0.3/docs/Data-Align.html)。 –

+0

@DanielWagner謝謝,'padAlign'完全符合我的要求。 – mcjohnalds45

回答

9

你應該叫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] 
+2

'map(\ x - >(Just x,Nothing))xs'而不是'map','zip'和'repeat'如何? –

+0

@DanielWagner:那我寧願理解。查看更新的答案。 –

+0

'map'可能看起來比這裏的理解更清晰 – alternative