main :: do中[IO t0]的必要性

时间:2016-04-09 15:26:52

标签: haskell

让我们'考虑一下:

main :: IO ()
main = 
    do
        args <- getArgs
        p <- args !! 0

ghc说:

Couldn't match type `[Char]' with `IO t0'
    Expected type: [IO t0]
      Actual type: [String]

我无法理解为什么[IO t0]在这里是必要的以及如何修复ir。

2 个答案:

答案 0 :(得分:7)

请记住,在do-syntax中,箭头右侧的表达式必须具有“提升”或“monadic”类型。在getArgs :: IO [String]的情况下也是如此,这就是行类型检查的原因。

但是在下一行args !! 0被约束为类型IO t0,其中t0是类型检查器在类型检查过程中引入的类型。

main :: IO ()
main = do
  args <- getArgs
          -- :: IO [String]
  p <- args !! 0
       -- :: IO t0, for some t0
  ...

由于类型检查器受args !! 0 :: IO t0约束,因此它推断args必须具有类型[IO t0](这来自(!!) :: [a] -> Int -> a)。但这与args :: [String]冲突,导致你得到的这个非常无用的错误信息。

在这种情况下,您真正​​想要的是使用!!执行计算,这是纯粹的,并且根本不会在IO中返回值。您可以使用IOpure将计算“提升”到return

main :: IO ()
main = do
  args <- getArgs
          -- :: IO [String]
  p <- pure (args !! 0)
       -- :: IO [String]
  ...

或者您可以使用专门为此情况保留的符号,let - 绑定:

main :: IO ()
main = do
  args <- getArgs
          -- :: IO [String]
  let p = args !! 0
          -- :: String
  ...

答案 1 :(得分:4)

args[String],因此args !! 0String。由于main中的monad为IOp需要为某些IO a提供a类型,但它是String。看起来您想要使用let代替:

main = 
    do
        args <- getArgs
        let p = args !! 0
        ...