繁体   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