簡體   English   中英

Haskell 中的“無法將類型 '[]' 與 'IO' 匹配”錯誤

[英]“Couldn't match type ‘[]’ with ‘IO’” error in Haskell

我正在嘗試使用 Points(我創建的一種數據類型)制作一個列表,這個想法是在每次迭代中添加一個元素。 出了點問題。

我試圖將p排除在myLoop ,但它似乎也不起作用。

main = myLoop 
myLoop  = do 
            let p = []
            done <- isEOF
            if done
              then putStrLn ""
              else do inp <- getLine
                      let (label:coord) = words inp
                      p ++  [Point label (map getFloat coord)]
                      -- print (pointerList)
                      myLoop 

我得到這個 output

trabalho.hs:30:23: error:
    • Couldn't match type ‘[]’ with ‘IO’
      Expected type: IO Point
        Actual type: [Point]
    • In a stmt of a 'do' block:
        p ++ [Point label (map getFloat coord)]
      In the expression:
        do inp <- getLine
           let (label : coord) = words inp
           p ++ [Point label (map getFloat coord)]
           myLoop
      In a stmt of a 'do' block:
        if done then
            putStrLn ""
        else
            do inp <- getLine
               let (label : coord) = ...
               p ++ [Point label (map getFloat coord)]
               ....
   |
30 |                       p ++  [Point label (map getFloat coord)]
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

首先,do-notation 是具有以下規則的語法糖:

do x <- mA
   mB

大致* 脫糖為mA >>= \x -> do mB ,其中mA的類型為Monad m => ma並且do mB的類型為Monad m => mb對於某些類型的mab

do mA
   mB

脫糖到mA >> do mB ,其中mA的類型為Monad m => ma並且do mB的類型為Monad m => mb對於某些類型mab

do a

脫糖a .

main是代表程序入口點的特殊名稱,對於某些類型a ,它的類型為IO a a 。 因為您定義main = myLoopmyLoop還必須具有類型IO a

因此,在您的myLoop function 中:

myLoop  = do 
            let p = []
            done <- isEOF
            if done
              then putStrLn ""
              else do inp <- getLine
                      let (label:coord) = words inp
                      p ++  [Point label (map getFloat coord)]
                      -- print (pointerList)
                      myLoop 

do -block 使用m = IO類型。 Therefore, when you write p ++ [Point label (map getFloat coord)] , the typechecker expects a value of type IO c , for some type c .

但是, p ++ [Point label (map getFloat coord)]的類型為[Point] ,導致類型錯誤Cannot match type '[]' with 'IO'

正如類型不匹配所表明的那樣,您的代碼沒有意義。 我假設您想將 append Point label (map getFloat coord)p ++不會改變p 會創建一個新列表! 慣用的 Haskell 使用遞歸來實現您想要的。 修復代碼的最直接方法是執行以下操作:

main = myLoop []
myLoop p = do
    done <- isEOF
    if done
    then putStrLn ""
    else do inp <- getLine 
            let (label:coord) = words inp
            let p' = p ++  [Point label (map getFloat coord)]
            myLoop  p'

這里, myLoopp作為參數,並在讀取輸入后遞歸地將更新的p傳遞給自身。 main使用參數[]調用myLoop ,這是p的初始值。

Haskell Wikibook對 do-notation 有很好的解釋 一般來說,我建議閱讀 Haskell Wikibook 以更好地理解 Haskell。

*我說“大致”是因為這些不是確切的規則。 Wikibook 文章深入解釋了 do-notation。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM