haskell - 当代码中没有可见列表时,为什么推断类型是 [String]?

标签 haskell type-inference

我有这个测试:

testReadFile = runTestTT $ TestLabel "InteractionDomain.readFileContentsToList" (TestList [
    (TestLabel "testing infrastructure: read test file" (TestList [
        TestCase (withTempFileContainingText (\fileHandle ->
            assertEqual "contents as expected" "The dog barks at midnight." (do 
                content <- hGetContents fileHandle
                return content)))]))])

并且(如果有帮助)withTempFileContainingText 就是这个函数

withTempFileContainingText lambda = 
        bracketOnError 
            (do (path, fileHandle) <- openTempFile "." "input.txt"
                return fileHandle)
            (deleteFile)
            (\fileHandle -> do 
                hPutStr fileHandle "The dog barks at midnight."
                hClose fileHandle --hoping this flushes buffers
                return (lambda fileHandle))

ghc 提示说

InteractionDomain.hs:36:4:
    Couldn't match expected type `IO String'
           against inferred type `[String]'
    In a stmt of a 'do' expression: content ≤- hGetContents fileHandle

我不明白。为什么会推断content是一个String列表?这段代码应该是什么样的?

最佳答案

嗯,我立即看到的是您的断言中的类型不匹配。

assertEqual 是 String -> a -> a -> Assertion 。您通过 String作为第二个参数,意思是 String也应该是第三个参数。然而,你的do表达式未返回String ,而是IO String

编辑:要扩展,一旦你搞乱 IO ,你永远无法抛弃它。您可以使用 <- 正确地从 IO 中提取值,但随后立即将其包装回 IOreturn 。如果要使用字符串,必须在 IO 内进行,类似:

do
  contents <- hGetContents handle
  assertEqual "They're equal" "Expected string" contents

请注意,然后您的 do将返回 IO Assertion 。如果您想使用断言值,则需要以类似的方式将其解包,依此类推。 Haskell 不会让你摆脱(隐藏的)副作用!

关于haskell - 当代码中没有可见列表时,为什么推断类型是 [String]?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3287529/

相关文章:

java - JDK8 javac/Eclipse Luna 类型推断的差异?

java - 可以将具有推断类型的局部变量重新分配给不同的类型吗?

haskell - 在 Haskell 中生成笛卡尔积

c# - 编译器在传递值类型时不调用适当的泛型重载

Scala 没有推断出适当的方法

haskell - Parsec 函数 'parse' 和类 'Stream' 的类型签名

c# - 如何正确地将 lambda 表达式的 "var"结果转换为具体类型?

haskell - 没有仿函数的应用程序

haskell - 如何在 TemplateHaskell 引用中捕获类型变量

haskell - Data.Stream 的 Monad 实例的定义