2014-02-05 142 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