【问题标题】:Haskell types missmatchHaskell 类型不匹配
【发布时间】:2014-03-02 15:42:54
【问题描述】:

我想创建一个函数,它接受一个字符串“path”,这是一个只有一行的文件的路径,我想取这一行并检查它是否是一个正确的表达式,是否要构建一个从这个字符串中取出树,这是代码 `

loadExpression :: String -> Tree Char
loadExpression path = do
 contents <- readFile path
 if checkIfProper $ filter (/=' ') contents
    then buildTreeFromString contents
    else EmptyTree  

`

但它给了我错误 "Couldn't match type IO' withTree'" 。我知道 IO 字符串与普通字符串不同,但 &lt;- 不应该这样做吗?将 IO 字符串转换为普通字符串。如果我用"(1+2)*3" 之类的字符串调用buildTreeFromString,它可以正常工作,checkIfProper 也是如此。

整个错误是:

Couldn't match type `IO' with `Tree'
Expected type: Tree String
  Actual type: IO String
In the return type of a call of `readFile'
In a stmt of a 'do' block: contents <- readFile path

【问题讨论】:

    标签: string haskell types match loading


    【解决方案1】:

    readFile 的类型为FilePath -&gt; IO String,因此您的do 块位于IO monad 中。因此,您的整个函数返回 IO (Tree Char),而不是 Tree Char,因此您需要更改类型签名。

    编辑:您可以通过创建一个从输入字符串加载树的函数来分离函数的有效部分和纯部分。然后,您可以将 readFile 中的字符串传递给此函数:

    readTree :: String -> Tree Char
    readTree contents =
     if checkIfProper $ filter (/=' ') contents
        then buildTreeFromString contents
        else EmptyTree
    

    loadExpression 然后变成:

    loadExpression :: FilePath -> IO (Tree Char)
    loadExpression path = do
      contents <- readFile path
      return (readTree contents)
    

    或者你可以使用fmap:

    loadExpression = fmap readTree readFile
    

    【讨论】:

    • 我可以创建第二个函数,只从文件中加载字符串并返回一个正常的,然后在我创建的这个函数中使用这个正常的吗?我问这个是因为我不完全明白要改变什么,你能给我举个例子吗?我真的很抱歉我对 Haskell 很陌生。
    • "so your do block is in the IO monad" 似乎具有误导性:问题在于他 不在 IO monad 中(因为他声称返回一个Tree),但他需要(为了从文件中读取)。根据需要更改返回类型使他进入 IO monad。
    • @amalloy - 我不明白这有多令人困惑 - IO 中的 OP is 因为readFile 返回一个IO String。它们的显式类型签名表明它们不是,但它们是并且需要修复它们的声明以匹配。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-04
    • 2018-03-16
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 2011-11-30
    • 1970-01-01
    相关资源
    最近更新 更多