简体   繁体   中英

Haskell IO Function -> Type Match Error

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.

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