Alv*_*ues -1 haskell list type-mismatch do-notation io-monad
我正在尝试用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 
我得到这个输出
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表示法是语法糖,它具有以下规则:
do x <- mA
   mB
大约* desugars来mA >>= \x -> do mB,其中mA有一个类型Monad m => m a和do mB具有类型Monad m => m b对于某些类型的m,a和b。
do mA
   mB
desugars到mA >> do mB,其中mA有一个类型Monad m => m a和do mB具有类型Monad m => m b对于某些类型的m,a和b。
do a
讨价还价a。
main是一个特殊名称,代表程序的入口点,并且具有IO a某种type的类型a。因为定义main = myLoop,myLoop还必须有类型IO a。
因此,在您的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 
该do嵌段正在与类型m= IO。因此,在编写时p ++  [Point label (map getFloat coord)],类型检查器期望某个type的值为IO ctype c。
但是,p ++  [Point label (map getFloat coord)]具有类型[Point],导致类型错误Cannot match type '[]' with 'IO'。
正如类型不匹配所指示的那样,您的代码没有意义。我假设您要附加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'
此处,myLoop以p参数为参数,并p在读取输入后将更新递归传递给它自己。以的初始值main调用。myLoop[]p
Haskell Wikibook 对do-notation有很好的解释。通常,我建议阅读Haskell Wikibook,以更好地了解Haskell。
*我之所以说是“大致”,是因为这些规则并不确切。Wikibook文章深入解释了do标记。
| 归档时间: | 
 | 
| 查看次数: | 76 次 | 
| 最近记录: |