Honestly, I feel like this must have a dupe somewhere, but I couldn't find it even after searching .
Say I have the following code to simply get read a double from the user and echo it back:
import qualified Control.Monad.Except as E
import Text.Read(readMaybe) 
data Error = ParseError String
             | Default String deriving (Show)
type ThrowsError = Either Error 
main = do
  putStrLn "Enter your number: "
  val <- getDouble
  print val
parseString :: String -> ThrowsError Double
parseString val = maybe (E.throwError $ ParseError val) return 
                        (readMaybe val :: Maybe Double)
getDouble :: ThrowsError Double
getDouble = getLine >>= parseString
This breaks in two places:
In
main,putStrLnis typeIO DoublebutgetDoubleis typeThrowsError Double.In
getDouble,getLineis typeIO DoublebutparseStringreturnsIO Double.
Essentially, I'd want to be able to extract the value out of the IO monad, apply computations on it, and put it back inside the appropriate monad. However, the bind function seems to expect the same monad types for input and output, so what I want to do doesn't work.
What's the way around it?