2016-12-26 35 views
22

Nie jestem do końca pewien, czy moja nomenklatura jest tutaj poprawna, ale zastanawiałem się, czy w Haskell była funkcja zipa, która była chciwa. Oznacza to, że jeśli miałemCzy Haskell ma chciwy zamek (jeden z zachowaniem wszystkich elementów)?

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

... gdzie zip' jest funkcja zip chciwy, to zwraca listę krotek długości dłuższej listy, a gdzie jest już lista zawiera element, ale krócej lista nie ma pozycji Nothing umieszczonej w odpowiedniej pozycji krotki. Nie pytam, jak to napisać, ale zamiast tego zastanawiałem się, czy to istnieje jako wbudowane.

Oto moja implementacja (co prawdopodobnie nie jest wielki)

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 
+1

wyszukiwanie przez podpis. –

+0

@KarolyHorvath Przepraszam. Nie rozumiem, co masz na myśli. –

+0

https://www.haskell.org/hoogle/ –

Odpowiedz

34

Chciwy zip może być wyrażony poprzez starannie niewyłącznej rodzaju alternatywy (w przeciwieństwie do Either, która jest wyłącznym alternatywa). Oferują to dwa popularne pakiety. Jednym z nich jest minimalistyczny, zależność wolne 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] 

Drugi to these, który pochodzi z dużą ilością wodotryski:

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] 

wierzę Or a b i These a b wyrazić swoją intencją lepiej niż (Maybe a, Maybe b) (ten ostatni typ obejmuje (Nothing, Nothing), którego chciwy zamek nigdy nie wyprodukuje). Mimo to, można wyrazić swoją zip' stosując albo zipOrWith z 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) 

... lub alignWith z 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 w rzeczywistości zapewnia swoją funkcję pod nazwą padZip .

+1

Wow! "Or" jest lepszym pomysłem. Dziękuję bardzo! –

+2

Wygląda na to, że 'align' zapewnia już dokładnie pożądaną funkcję -' padZip :: Align f => fa -> fb -> f (Maybe a, Maybe b) '- ale jak mówisz,' Or ab 'wyraża intencję lepiej niż '(Maybe a, Maybe b)' anyways. – user2407038

+0

@ user2407038 Dobrze zauważony. Dodałem to do odpowiedzi; Dziękuję Ci. – duplode

Powiązane problemy