Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter IO [Maybe String] to IO [String]

Tags:

haskell

monads

How to filter IO [Maybe String] to only keep the Just values of the list using >>= and keep the IO context.

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

My current solution without the bind-operator:

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

I'm currently learning Haskell and try to understand how to use the different functions of the standard library. My solution works, but I guess there is a cleaner way.

like image 206
Paradiesstaub Avatar asked Apr 28 '16 16:04

Paradiesstaub


2 Answers

A short solution would be

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

you don't need the >>= operator for that.

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

like image 130
epsilonhalbe Avatar answered Oct 29 '22 14:10

epsilonhalbe


From the comment you've written on binDoesntExist, I suspect that you might rather have a different type signature, namely:

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

The implementation of this signature will probably be simpler than your existing implementation; and additionally your missingBin will be quite a bit simpler as well:

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

This discussion assumes that your existing function always returns exactly the String it's passed (if it returns any String at all); but this assumption doesn't seem so far out to me.

like image 31
Daniel Wagner Avatar answered Oct 29 '22 14:10

Daniel Wagner