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.
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.