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
如果我输入一个名称并且验证功能失败,我希望用户重新输入名称,直到它通过验证功能。我该怎么办?
答案 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
…