Haskell IO:无法匹配期望的类型`IO a0'与实际类型

时间:2012-08-18 06:27:49

标签: haskell

我是Haskell的新手,我试图了解如何正确地执行IO。

以下工作正常:

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"

以下结果导致编译错误:

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

错误在于:

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

这里发生了什么?为什么第一个版本有效,而第二个版本没有?

我知道在Stack Overflow中有一些类似的问题,但是它们似乎都没有向我解释这个问题。

2 个答案:

答案 0 :(得分:8)

usernameString,但promptUsernameIO String。您需要执行以下操作:

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

答案 1 :(得分:0)

这是另一种变体。

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

问题在于promptUsername操作而不是字符串。动作'返回一个字符串',因此它具有类型IO String,但它本身就像一个字符串。由于Entry x y在x位置需要String,因此动作形状的某些东西不能比数字或布尔值更合适。因此,在定义复杂动作main时,必须“提取”在任何执行情况下由更简单的动作promptUsername产生的字符串,并将String作为第一个参数入口。然后,对结果persist

执行Entry操作