I am developing a function which reads user input of the form "a 2" and then converts it into a tuple and adds it to a list of tuples. This is supposed to keep happening until the user types in "done".
The code is as follows...
getVectorData vector1 = do
putStrLn "Enter dimension and coefficient separated by a space: Enter \"Done\" to move on to next vector: "
appData <- getLine
if appData == "done" then
putStrLn "That's it"
else do
createVectorTuple (words appData) : vector1
getVectorData vector1
createVectorTuple :: [String] -> (String, Float)
createVectorTuple vectorData = ((head vectorData) , (read (last vectorData) :: Float))
How ever, when trying to execute this file, I get the error
> ERROR file:.\MainApp.hs:13 - Type error in final generator
*** Term : getVectorData vector1
*** Type : IO ()
*** Does not match : [a]
What am I doing wrong?
You are mixing IO
with pure non- IO
functions.
getVectorData vector1 = do
putStrLn "Enter dimension and coefficient separated by a space: Enter \"Done\" to move on to next vector: "
appData <- getLine
if appData == "done" then
putStrLn "That's it"
The above is all IO
else do
createVectorTuple (words appData) : vector1
createVectorTuple
is a non- IO
function. Since the preceding part is an IO
do-block, only expressions of type IO a
may appear in that do-block. However, you get the somewhat strange error message because the precedence of function application is highest, so the above line is parsed
(createVectorTuple (words appData)) : vector1
which is an expression of type [(String, Float)]
(if vector1
has that type). Now []
is a monad too, so expressions of type [a]
can appear in do-blocks, but then all expressions in that block must have list type. But
getVectorData vector1
is an expression of type IO ()
as has been determined from the part above. Thus the types don't match. Admittedly, the reported type error is not the clearest possible in that situation.
You probably want something along the lines of
let vector2 = createVectorTuple (words appData) : vector1
getVectorData vector2
or something completely different, I can't tell from the short snippet.
Its a bit difficult to tell, but "createVectorTuple is not of type "IO ()", so this is probably the real problem. "do" clauses can have many different types, so the type inference is probably making a wrong guess based on "createVectorTuple", and then the error message is because the next line doesn't match its guess.
What you probably want to say is
else
getVectorData $ createVectorTuple (words appData) : vector1
Did you want:
else do
let vector1 = createVectorTuple (words appData)
getVectorData vector1
You will also have to return
something after the putStrLn "That's it." so both branches of the if have the same type. Something like:
if appData == "done" then do
putStrLn "That's it"
return vector1
else getVectorData (createVectorTuple (words appData) : vector1)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.