Reputation: 80
I am trying to make a list with Points (a datatype that I created), the idea is add an element in each iteration. Something is wrong.
I have tried to put p
out of myLoop
but it doesn't seems to work either.
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
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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Upvotes: 0
Views: 708
Reputation: 1309
First of all, do-notation is syntactic sugar with the following rules:
do x <- mA
mB
roughly* desugars to mA >>= \x -> do mB
, where mA
has type Monad m => m a
and do mB
has type Monad m => m b
for some types m
, a
, and b
.
do mA
mB
desugars to mA >> do mB
, where mA
has type Monad m => m a
and do mB
has type Monad m => m b
for some types m
, a
, and b
.
do a
desugars to a
.
main
is a special name that represents the entrypoint of the program, and it has type IO a
for some type a
. Because you define main = myLoop
, myLoop
must also have type IO a
.
Therefore, in your 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
. 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'
.
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
. ++
does not mutate p
; it creates a new list! Idiomatic Haskell uses recursion to achieve what you want. 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. main
calls myLoop
with an argument of []
, which is the initial value of p
.
The Haskell Wikibook has a good explanation of do-notation. In general, I would recommend reading the Haskell Wikibook to better understand Haskell.
*I say "roughly" because these aren't the exact rules. The Wikibook article explains do-notation in depth.
Upvotes: 5