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
Run Code Online (Sandbox Code Playgroud)
我得到这个输出
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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
首先,do表示法是语法糖,它具有以下规则:
do x <- mA
mB
Run Code Online (Sandbox Code Playgroud)
大约* desugars来mA >>= \x -> do mB,其中mA有一个类型Monad m => m a和do mB具有类型Monad m => m b对于某些类型的m,a和b。
do mA
mB
Run Code Online (Sandbox Code Playgroud)
desugars到mA >> do mB,其中mA有一个类型Monad m => m a和do mB具有类型Monad m => m b对于某些类型的m,a和b。
do a
Run Code Online (Sandbox Code Playgroud)
讨价还价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
Run Code Online (Sandbox Code Playgroud)
该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'
Run Code Online (Sandbox Code Playgroud)
此处,myLoop以p参数为参数,并p在读取输入后将更新递归传递给它自己。以的初始值main调用。myLoop[]p
Haskell Wikibook 对do-notation有很好的解释。通常,我建议阅读Haskell Wikibook,以更好地了解Haskell。
*我之所以说是“大致”,是因为这些规则并不确切。Wikibook文章深入解释了do标记。