简体   繁体   English

Haskell 中的“无法将类型 '[]' 与 'IO' 匹配”错误

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

I am trying to make a list with Points (a datatype that I created), the idea is add an element in each iteration.我正在尝试使用 Points(我创建的一种数据类型)制作一个列表,这个想法是在每次迭代中添加一个元素。 Something is wrong.出了点问题。

I have tried to put p out of myLoop but it doesn't seems to work either.我试图将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 

I am getting this output我得到这个 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)]
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

First of all, do-notation is syntactic sugar with the following rules:首先,do-notation 是具有以下规则的语法糖:

do x <- mA
   mB

roughly* desugars to mA >>= \x -> do mB , where mA has type Monad m => ma and do mB has type Monad m => mb for some types m , a , and b .大致* 脱糖为mA >>= \x -> do mB ,其中mA的类型为Monad m => ma并且do mB的类型为Monad m => mb对于某些类型的mab

do mA
   mB

desugars to mA >> do mB , where mA has type Monad m => ma and do mB has type Monad m => mb for some types m , a , and b .脱糖到mA >> do mB ,其中mA的类型为Monad m => ma并且do mB的类型为Monad m => mb对于某些类型mab

do a

desugars to a .脱糖a .

main is a special name that represents the entrypoint of the program, and it has type IO a for some type a . main是代表程序入口点的特殊名称,对于某些类型a ,它的类型为IO a a 。 Because you define main = myLoop , myLoop must also have type IO a .因为您定义main = myLoopmyLoop还必须具有类型IO a

Therefore, in your myLoop function:因此,在您的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 

the do -block is working with the type m = IO . 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 . Therefore, when you write p ++ [Point label (map getFloat coord)] , the typechecker expects a value of type IO c , for some type c .

However, p ++ [Point label (map getFloat coord)] has type [Point] , resulting in the type error Cannot match type '[]' with 'IO' .但是, p ++ [Point label (map getFloat coord)]的类型为[Point] ,导致类型错误Cannot match type '[]' with 'IO'

As the type mismatch indicates, your code does not make sense.正如类型不匹配所表明的那样,您的代码没有意义。 I assume that you want to append Point label (map getFloat coord) to p .我假设您想将 append Point label (map getFloat coord)p ++ does not mutate p ; ++不会改变p it creates a new list!会创建一个新列表! Idiomatic Haskell uses recursion to achieve what you want.惯用的 Haskell 使用递归来实现您想要的。 The most direct way of fixing your code would be to do the following:修复代码的最直接方法是执行以下操作:

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'

Here, myLoop takes p as a parameter and recursively passes an updated p to itself after reading input.这里, myLoopp作为参数,并在读取输入后递归地将更新的p传递给自身。 main calls myLoop with an argument of [] , which is the initial value of p . main使用参数[]调用myLoop ,这是p的初始值。

The Haskell Wikibook has a good explanation of do-notation . Haskell Wikibook对 do-notation 有很好的解释 In general, I would recommend reading the Haskell Wikibook to better understand Haskell.一般来说,我建议阅读 Haskell Wikibook 以更好地理解 Haskell。

*I say "roughly" because these aren't the exact rules. *我说“大致”是因为这些不是确切的规则。 The Wikibook article explains do-notation in depth. Wikibook 文章深入解释了 do-notation。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM