2014-02-05 141 views
0

我想创建一个接受字符串“path”的函数,这是一个只有一行的文件的路径,我想采用这一行并检查它是否是正确的表达式,如果它是建立一个树出这个字符串,这里是代码 `Haskell类型错配

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

`

,但它给了我错误“无法匹配类型IO' with树””。我知道IO字符串是不同于正常的,但不是<- suppost做到这一点?将IO字符串转换为普通字符串。如果我打电话buildTreeFromString与像"(1+2)*3"这样的字符串,它工作正常,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 

回答

4

readFile的类型为FilePath -> IO String,所以你do块处于IO单子。因此,您的整个功能将返回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 
+0

我可以做第二功能,只有从文件中加载字符串并返回一个正常的字符串,然后使用这个函数中的这个正常的一个呢?我在问这个,因为我不完全明白要改变什么,你能举个例子吗?我非常抱歉,我对Haskell很新。 – user3129475

+0

@ user3129475 - 是的,你可以看到更新。 – Lee

+0

“所以你的''''块在'IO' monad中”似乎有误导性:问题在于他*不在IO单元中(因为他声称要返回一个'Tree'),但他需要(为了从文件中读取)。根据需要更改返回类型让他进入IO monad。 – amalloy