`return` 语句的类型与函数定义的类型有何不同?
How does `return` statement have different type than that of a function's definition?
在一个循环中,整数被收集在一个列表中,并且这些整数的元组被return
ed。这如何更改为元组列表?
input :: IO [(Int,Int)]
input = do
n <- readLn :: IO Int
forM [1..n] $ \_ -> do
[x,y] <- map read . words <$> getLine
return (x,y)
我希望值的类型是 (Int,Int)
,但它是 [(Int,Int)]
。为什么?
让我们 re-write 您的代码带有明确的分隔符,使代码结构更 self-apparent:
input :: IO [(Int,Int)]
input = do {
n <- readLn ;
forM [1..n] (\ _ -> do {
[x,y] <- fmap (map read . words) getLine ;
return (x,y) })
}
所以return (x,y)
属于内部do
。
因为那里有一个 getLine :: IO String
,内部 do
的类型是 IO (t1,t2)
,其中 x :: t1, y :: t2
。所以这也是参与那个 forM
调用的 那个 lambda 函数 的 return 类型。
因为 forM :: Monad m => [a] -> (a -> m b) -> m [b]
,我们在这里知道 m ~ IO
,我们得到总体 do
的最后一个表达式的类型为
forM :: [a] -> (a -> IO b) -> IO [b]
因此整体类型是 IO [b] ~ IO [(t1,t2)]
因为 b ~ (t1,t2)
根据那个 return
表达式。
lambda 函数 returns IO b
所以 forM
returns IO [b]
按照上面的类型。 do
块的类型与其最后一个表达式的类型相同。
函数的签名说它是 IO [(Int,Int)]
,所以最后 t1 ~ Int
和 t2 ~ Int
一切都适合。
在一个循环中,整数被收集在一个列表中,并且这些整数的元组被return
ed。这如何更改为元组列表?
input :: IO [(Int,Int)]
input = do
n <- readLn :: IO Int
forM [1..n] $ \_ -> do
[x,y] <- map read . words <$> getLine
return (x,y)
我希望值的类型是 (Int,Int)
,但它是 [(Int,Int)]
。为什么?
让我们 re-write 您的代码带有明确的分隔符,使代码结构更 self-apparent:
input :: IO [(Int,Int)]
input = do {
n <- readLn ;
forM [1..n] (\ _ -> do {
[x,y] <- fmap (map read . words) getLine ;
return (x,y) })
}
所以return (x,y)
属于内部do
。
因为那里有一个 getLine :: IO String
,内部 do
的类型是 IO (t1,t2)
,其中 x :: t1, y :: t2
。所以这也是参与那个 forM
调用的 那个 lambda 函数 的 return 类型。
因为 forM :: Monad m => [a] -> (a -> m b) -> m [b]
,我们在这里知道 m ~ IO
,我们得到总体 do
的最后一个表达式的类型为
forM :: [a] -> (a -> IO b) -> IO [b]
因此整体类型是 IO [b] ~ IO [(t1,t2)]
因为 b ~ (t1,t2)
根据那个 return
表达式。
lambda 函数 returns IO b
所以 forM
returns IO [b]
按照上面的类型。 do
块的类型与其最后一个表达式的类型相同。
函数的签名说它是 IO [(Int,Int)]
,所以最后 t1 ~ Int
和 t2 ~ Int
一切都适合。