Search code examples
haskelliomonadsio-monad

Is there a way to unwrap a type from an IO monad?


I have this very simple function

import qualified Data.ByteString.Lazy as B

getJson :: IO B.ByteString
getJson = B.readFile jsonFile

readJFile :: IO (Maybe Response)
readJFile =  parsing >>= (\d ->
             case d of
                 Left err -> return Nothing
                 Right ps -> return (Just ps))
    where parsing = fmap eitherDecode getJson :: IO (Either String Response)

where jsonFile is a path to a file on my harddrive (pardon the lack of do-notation, but I found this more clear to work with)

my question is; is there a way for me to ditch the IO part so I can work with the bytestring alone?

I know that you can pattern match on certain monads like Either and Maybe to get their values out, but can you do something similar with IO?

Or voiced differently: is there a way for me to make readJFile return Maybe Response without the IO?


Solution

  • To expand on my comments, here's how you can do it:

    getJson :: IO B.ByteString
    getJson = B.readFile jsonFile -- as before
    
    readJFile :: B.ByteString -> Maybe Response -- look, no IO
    readJFile b = case eitherDecode b of
                    Left err -> Nothing
                    Right ps -> Just ps
    

    In the end, you combine everything in one IO action again:

    getAndProcess :: IO (Maybe Response)
    getAndProcess = do
      b <- getJson
      return (readJFile b)