Search code examples
haskelliomonads

Pattern Maching IO variables in haskell


Currently I have a function getFP :: IO [String] -> Maybe (FilePath). What I want to do is something equivalent for getFP [] = Nothing if the argument was a non IO string. How could I do this? Thank you :p


Solution

  • IO [String] is an action that can produce [String]. There’s no way to convert it to a pure value Maybe FilePath, but you can easily combine it with a pure function to get another action. One way is to write it out in do notation. For example, suppose you want the first path:

    getFP :: IO [String] -> IO (Maybe FilePath)
    getFP action = do
      strings <- action
      case strings of
        path : _ -> pure (Just path)
        [] -> pure Nothing
    

    This might be used like getFP loadPaths where loadPaths is some action like lines <$> readFile "paths.txt" that returns a list of file paths. However, it’s more common to take a pure value as an argument instead of an action, if you’re just going to run that action immediately anyway.

    getFP :: [String] -> IO (Maybe FilePath)
    getFP strings =
      case strings of
        path : _ -> pure (Just path)
        [] -> pure Nothing
    

    That would be called as getFP =<< loadPaths.

    Now there’s no need for IO in getFP, since the only IO action it uses is pure.

    getFP :: [String] -> Maybe FilePath
    getFP strings =
      case strings of
        path : _ -> Just path
        [] -> Nothing
    

    This can be used like getFP <$> loadPaths. (Furthermore, in this example it’s now equivalent to the standard function listToMaybe from Data.List.)