2013-08-02 42 views
5

Tôi muốn có một chức năng với các loại:Chức năng trong Haskell rằng thích catMaybes, nhưng có loại [Có lẽ a] -> Có lẽ [a]

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

ví dụ

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

Nó tương tự như catMaybes :: [Maybe a] -> [a] trong Data.Maybe, ngoại trừ việc catMaybes bỏ qua Nothing, trong khi f của tôi là rất nghiêm túc về Nothing. Tôi có thể thực hiện f một cách ngây thơ (như hình dưới đây), nhưng tự hỏi nếu có cách nhiều thành ngữ (như "functor applicative"):

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

hoặc

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

Là một người thừa kế - nếu bạn đang viết một chức năng danh sách điển hình, và bạn thấy mình sử dụng 'length' (đặc biệt là nếu bạn sử dụng nó nhiều hơn một lần), có lẽ bạn đang làm điều gì sai. Nó không phù hợp với hầu hết các mã danh sách trong Haskell. Điều đó không phải luôn luôn như vậy, nhưng khi bạn đang học, bạn nên sai về phía không sử dụng nó. :-) – shachaf

+4

Khi nghi ngờ, [hoogle] (http://www.haskell.org/hoogle/?hoogle=%5BMaybe+a%5D+-%3E+Maybe+%5Ba%5D). Tôi đã tìm kiếm '[Có thể a] -> Có thể [a]' trong Hoogle và nhận được câu trả lời đúng được liệt kê bên dưới ('chuỗi'). – aaronlevin

+1

Tôi 'hoogle'd và chú ý' catMaybes'. 'sequence' là lần đầu tiên trong danh sách. Tôi phớt lờ nó vì kiểu đó không phải là 'Có lẽ' nhưng 'Monad', và tôi không nhận ra được kết nối. – Causality

Trả lời

20

Chức năng bạn đang tìm kiếm được gọi là trình tự:

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

Bạn có thể tìm thấy chức năng này sử dụng hoogle: link.

Ví dụ:

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

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

Lưu ý: Ngoài ra còn có sequenceA trong Data.Traversable đó là một chút khái quát hóa, nhưng để sử dụng trường hợp chuỗi của bạn từ Control.Monad là đủ.