2013-08-02 3 views
5

ja jak do funkcji z rodzaju:Funkcja Haskell, który jak catMaybes, ale uwzględniając typ [Może] -> Może [a]

f :: [Maybe a] -> Maybe [a] 

np

f [Just 3, Just 5] == Just [3, 5] 
f [Just 3, Nothing] == Nothing 
f [] == Just [] 

Jest ona podobna do catMaybes :: [Maybe a] -> [a] w Data.Maybe, chyba że catMaybes ignoruje Nothing, podczas gdy mój f jest bardzo poważny temat Nothing. mogłaby wdrożyć f w naiwny sposób (jak pokazano poniżej), ale zastanawiam się, czy istnieje bardziej idiomatycznych sposób (na przykład „aplikacyjnej funktora”):

f :: [Maybe a] -> Maybe [a] 
f xs = let ys = catMaybes xs 
     in if length ys == length xs 
      then Just ys 
      else Nothing 

lub

f :: [Maybe a] -> Maybe [a] 
f xs = if all isJust xs 
     then catMaybes xs 
     else Nothing 
+6

Odkładając na bok heurystykę - jeśli piszesz typową funkcję listy i używasz 'length' (szczególnie jeśli używasz jej więcej niż raz), prawdopodobnie robisz coś źle. Nie pasuje do większości kodów list w Haskell. Nie zawsze tak jest, ale kiedy się uczysz, powinieneś pomyśleć o tym, że go nie używasz. :-) – shachaf

+4

W przypadku wątpliwości [hoogle] (http://www.haskell.org/hoogle/?hoogle=%5BMaybe+a%5D+-%3E+Maybe+%5Ba%5D). Szukałem "[Maybe a] -> Maybe [a]" w Hoogle i otrzymałem poprawną odpowiedź wymienioną poniżej ('sequence'). – aaronlevin

+1

I 'hoogleed go i zauważyłem' catMaybes'. "sequence" było pierwszym na liście. Zignorowałem to, ponieważ typ nie był 'Maybe', ale' Monad', i nie udało mi się rozpoznać połączenia. – Causality

Odpowiedz

20

Funkcja szukasz nazywa się sekwencja:

sequence :: (Monad m) => [m a] -> m [a] 

Można znaleźć tej funkcji za pomocą hoogle: link.

Przykład:

>>> sequence [Just 3, Just 5] 
Just [3,5] 

>>> sequence [] :: Maybe [Int] 
Just [] 

Uwaga: Istnieje również sequenceA w Data.Traversable który jest nieco uogólnić, ale do wykorzystania sekwencji przypadku od Control.Monad wystarczy.

Powiązane problemy