Reputation: 31
Within a loop, integers are collected inside a list, and a tuple of these integers is return
ed. How does this change to a list of tuples?
input :: IO [(Int,Int)]
input = do
n <- readLn :: IO Int
forM [1..n] $ \_ -> do
[x,y] <- map read . words <$> getLine
return (x,y)
I expected type of value to be (Int,Int)
but it is [(Int,Int)]
. Why?
Upvotes: 0
Views: 684
Reputation: 71075
Let's re-write your code with explicit separators making the code structure more self-apparent:
input :: IO [(Int,Int)]
input = do {
n <- readLn ;
forM [1..n] (\ _ -> do {
[x,y] <- fmap (map read . words) getLine ;
return (x,y) })
}
so return (x,y)
belongs to the internal do
.
Since there's a getLine :: IO String
there, the internal do
's type is IO (t1,t2)
where x :: t1, y :: t2
. So this is also the return type of that lambda function participating in that forM
call.
Since forM :: Monad m => [a] -> (a -> m b) -> m [b]
, and we know m ~ IO
here, we get the type of the overall do
's last expression as
forM :: [a] -> (a -> IO b) -> IO [b]
and thus the overall type is IO [b] ~ IO [(t1,t2)]
since b ~ (t1,t2)
as per that return
expression.
The lambda function returns IO b
so forM
returns IO [b]
as per its type above. And the type of do
block is the same as the type of its last expression.
The function's signature says it's IO [(Int,Int)]
, so finally t1 ~ Int
and t2 ~ Int
and everything fits.
Upvotes: 3