让我们'考虑一下:
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。
答案 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
中返回值。您可以使用IO
或pure
将计算“提升”到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 !! 0
是String
。由于main
中的monad为IO
,p
需要为某些IO a
提供a
类型,但它是String
。看起来您想要使用let
代替:
main =
do
args <- getArgs
let p = args !! 0
...