Search code examples
functionhaskelliomonadsdo-notation

How to rewrite `do` block using bind with an IO read Int?


So, I want to rewrite the given prog function with using >>/>>= bindings instead of do and <- :

prog :: IO Int
     prog =
       do putStrLn "Hello there! How old are you?"
       age <- (readLn :: IO Int)
       let agedays = show $ age * 365
       putStrLn $ "So you are at least than " ++ agedays ++ " days old."
       return (read agedays)

Rewriting more simple functions is not a problem for me, but the readLn :: IO Int is giving me a headache...

My suggestion was:

prog :: IO Int
prog =
     putStrLn "Hello there!How old are you?" >>
     readLn::IO >>=
     let agedays = \age -> show $ age * 365 >>
     putStrLn $ "So you are at least than " ++ agedays ++ " days old."

However this just does not work, as there is a problem with binding the readLn :: IO to the next anonymous function \age. Any help?


Solution

  • You can let the type inference do the work for you,

    prog :: IO Int
    prog =
         putStrLn "Hello there! How old are you?" >>
         readLn >>= (\ age ->
         let agedays = age * 365 in
           putStrLn ("So you are at least " ++ show agedays ++ " days old.") >>
           return agedays )
    

    Since you already specify prog :: IO Int, it means return agedays :: IO Int, and agedays :: Int.

    Then, both operands to * in age * 365 must be of the same type, specifically, that of agedays, since we have agedays = age * 365 there. Thus it follows that age :: Int already.