2016-04-28 13 views
8

Jak filtrować IO [Maybe String], aby zachować tylko wartości Just na liście używając >>= i zachować kontekst IO.Filtr IO [Maybe String] na IO [String]

-- returns Just, if the passed binary-name is not present on the system 
binDoesntExist :: String -> IO (Maybe String) 
binDoesntExist ... 

Moje obecne rozwiązanie bez bind-operatora:

missingBin :: [String] -> IO [String] 
missingBin xs = do 
    ys <- mapM (\x -> binDoesntExist x) xs 
    return $ catMaybes ys 

Jestem obecnie nauka Haskell i spróbować zrozumieć, jak korzystać z różnych funkcji z biblioteki standardowej. Moje rozwiązanie działa, ale myślę, że jest to czystszy sposób.

+5

I dla zabawy możemy nazwać go 'binDoesn'tExist' apostrofem i będzie on działał. –

Odpowiedz

9

Krótki rozwiązaniem byłoby

missingBin :: [String] -> IO [String] 
missingBin = fmap catMaybes . mapM binDoesntExist 

nie trzeba operatora >>= do tego.

Uwaga: (\x -> binDoesntExist x) = binDoesntExist

3

Od komentarzu masz napisane na binDoesntExist, podejrzewam, że może raczej mieć inny podpis typu, a mianowicie:

-- returns True if the passed binary is not present on the system 
binDoesntExist :: String -> IO Bool 
binDoesntExist = ... 

wykonania niniejszej podpisu będzie prawdopodobnie prostsze niż twoja obecna implementacja; i dodatkowo swój missingBin będzie trochę prościej, a także:

missingBin :: [String] -> IO [String] 
missingBin = filterM binDoesntExist 

Ta dyskusja zakłada, że ​​istniejąca funkcja zawsze zwraca dokładnie String to przeszedł (jeśli zwraca żadnej String w ogóle); ale to założenie nie wydaje mi się tak odległe.

+0

Masz rację, zamieniając 'missingBin' na' IO Bool'. Najtrudniejszą częścią po zrozumieniu Haskella jest dowiedzieć się, jak myśleć Haskell. Dzięki za wskazówkę. – Paradiesstaub