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
,putStrLn
is typeIO Double
butgetDouble
is typeThrowsError Double
.In
getDouble
,getLine
is typeIO Double
butparseString
returnsIO 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?