简体   繁体   中英

Haskell IO: Couldn't match expected type `IO a0' with actual type

I am new to Haskell, and I try to understand how to do IO correctly.

The following works ok:

main = do
  action <- cmdParser
  putStrLn "Username to add to the password manager:"
  username <- getLine
  case action of
    Add -> persist entry
      where
        entry = Entry username "somepassword"

Whereas the following results in compilation error:

main = do
  action <- cmdParser
  case action of
    Add -> persist entry
      where
        entry = Entry promptUsername "somepassword"

promptUsername = do
  putStrLn "Username to add to the password manager:"
  username <- getLine

The error is here:

Couldn't match expected type `IO b0' with actual type `[Char]'
Expected type: IO b0
  Actual type: String
In the expression: username
[...]

What is going on here? Why the first version works, while the second one does not?

I know that in Stack Overflow there are a few similar questions like this, but none of them seemed to explain this problem to me.

username is a String , but promptUsername is an IO String . You need to do something like:

username <- promptUsername
let entry = Entry username "somepassword"
persist entry

Here's another variant.

main = do
  action <- cmdParser
  case action of
    Add -> do username <- promptUsername
              let entry = Entry username "somepassword"
              persist entry

promptUsername :: IO String
promptUsername = do
  putStrLn "Username to add to the password manager:"
  getLine

-- fake definitions to make things compile

persist :: Entry ->  IO ()
persist = print

cmdParser :: IO Add
cmdParser = fmap (const Add) getLine

data Add = Add deriving Show
data Entry = Entry String String deriving Show

The problem is just that promptUsername is an action not a String. The action 'returns a String', so it has type IO String , but it is itself nothing like a String. Since Entry xy requires a String in the x position, something in the shape of an action could no more fit there than a number or boolean could. So in defining your complex action, main , you must 'extract' the string that will result from the simpler action promptUsername in any case of execution, and give the String as the first argument the entry. Then you do the persist action on the resulting Entry

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