Search code examples
haskellmonadsdo-notation

Haskell: Function using do notation and returning i.e. Integer value


I want to write a function that read some data using getLine and return i.e. a tuple (Integer, Integer) but using do-notation. Something like this (of course it doesn't work):

fun :: (Integer, Integer)
fun = do
    a <- read (getLine::Integer)
    b <- read (getLine::Integer)
    return (a, b)

Do I have to write my own monad for this? Is there any solution to not writing a new monad?


EDIT

So I can write main function that use fun, I think it's the only solution:

main :: IO ()
main = do
    tuple <- fun
    putStrLn (show tuple)

fun :: IO (Integer, Integer)
fun = do
    a1 <- getLine
    b1 <- getLine
    let a = read (a1)
        b = read (b1)
    return (a, b)

And above code works.


Solution

  • You type of function should be

    fun :: IO (Integer, Integer)
    

    as mentioned by @kaan you should not try to get a mondic value (with side effects) out of the monad as that will break referential transparency. Running fun should always return same value no matter how many times it is run and if we use your type this will not happen. However if the type is IO (Integer, Integer) then it returns the same action every time you use that function and running this action actually perform the side effect of reading the values from the console.

    Coming back to using you function. You can do that inside another IO monad like

    main = do
      (a,b) <- fun
      print a
      print b
    

    Although there are ways of getting things out of IO using unsafe functions but that is not recommended until you know exactly what you are doing.