Haskell:如果输入验证失败,我希望它再次请求相同的输入

时间:2018-03-06 12:48:21

标签: haskell

registerUser1  userDb =
  putStrLn "Enter the email " >>  getLine >>= \email -> 
    putStrLn "Enter the name " >> getLine >>= \name ->
      putStrLn "Enter the password " >> getLine >>= \password ->
        putStrLn "Enter the postal code " >> getLine >>= \postalcode -> 
          let newuser = MkNewUser{nuserEmail = MkEmail email, nuserFullName = name, nuserPassword = password, nuserPostalCode = postalcode}
              output =   (registerUser newuser userDb)
          in case output of
                Left err -> putStrLn err >> registerUser1 userDb
                Right udb -> pure udb

如果我输入一个名称并且验证功能失败,我希望用户重新输入名称,直到它通过验证功能。我该怎么办?

1 个答案:

答案 0 :(得分:4)

而不是getLine来获取名称,您可以使用辅助函数重复,直到输入有效名称。

getName = do
  putStrLn "Enter the name"
  name <- getLine
  if null name  -- Replace with your own validation.
    then do
      putStrLn "Invalid name"
      getName
    else pure name

这也可以在let绑定或where子句中本地定义。如果您要在所有这些字段上执行验证,那么抽象帮助程序将提示和验证函数作为参数进行验证:

getParameter label valid = loop
  where
    loop = do
      putStrLn $ "Enter the " ++ label
      value <- getLine
      if valid value
        then pure value
        else do
          putStrLn $ "Invalid value for " ++ label
          loop

您还可以使用do表示法使registerUser1的定义更少噪音和嵌套 - 它可以解释为您在上面编写的相同代码。

registerUser1 userDb = do
  putStrLn "Enter the email"
  email <- getLine
  putStrLn "Enter the name"
  name <- getName
  putStrLn "Enter the password"
  password <- getLine
  putStrLn "Enter the postal code"
  postalcode <- getLine
  let
    newuser = MkNewUser
      { nuserEmail = MkEmail email
      , nuserFullName = name
      , nuserPassword = password
      , nuserPostalCode = postalcode
      }
    output = registerUser newuser userDb
  case output of
    Left err -> do
      putStrLn err
      registerUser1 userDb
    Right udb -> pure udb

使用上面的辅助函数:

registerUser1 userDb = do
  email <- getParameter "email" validEmail
  name <- getParameter "name" validName
  password <- getParameter "password" validPassword
  postalcode <- getParameter "postal code" validPostalCode
  …