2013-10-18 1 views
5

Ich versuche, eine Funktion zu schreiben, die zip ähnelt, aber keine zusätzlichen Elemente verwerfen wird. Ich habe das Gefühl, irgendwo einen wirklich dummen Fehler gemacht zu haben.Was ist los mit meiner veränderten Version von zip?

Beispiel Eingabe:

zipMaybe [1,2,3] [1,2] 

gewünschte Ausgabe:

[(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 _ _ = [] 

Dies wird jedoch nicht kompilieren.

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

Du nennst 'zip' statt Ihrer' zipMaybe' rekursiv aufrufen. – Tarmil

+4

Vielleicht gefällt Ihnen ['align'] (http://hackage.haskell.org/package/these-0.3/docs/Data-Align.html). –

+0

@DanielWagner danke, 'padAlign' macht genau das, wonach ich suche. – mcjohnalds45

Antwort

9

sollten Sie zipMaybe rufen rekursiv statt backing off zu Vanille zip, die den falschen Typ hat. .

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 _ _ = [] 

Btw, gibt es eine kürzere Definition dieser Funktion:

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

Wie wäre es mit 'map (\ x -> (Nur x, Nothing)) xs' anstelle von' map', 'zip' und' repeat'? –

+0

@DanielWagner: Dann würde ich ein Verständnis bevorzugen. Siehe aktualisierte Antwort. –

+0

'map' sieht hier wahrscheinlich klarer aus als ein Verständnis – alternative