【发布时间】:2014-03-30 00:10:52
【问题描述】:
我正在尝试用这个概念实现一个 IO 代码:
- 向用户询问电影名称
- 检查影片是否存在,如果不存在则返回主菜单
- 如果是,程序会询问用户评分
- 它检查它是否是一个有效的整数,如果是的话
- 程序会检查用户是否已经为这部电影投票
- 如果他这样做了,然后询问他是否要修改评级
- 如果用户的输入不等于“y”,则程序应返回主菜单
- 如果用户键入“y”,则应使用当前评级更新数据库。
我试过这个:
if input /= "y"
then do return (username, database)
else do putStrLn "Your vote will be modified."
但我收到此错误:
Couldn't match expected type `()'
with actual type `(String, Database)'
In the first argument of `return', namely `(username, database)'
In a stmt of a 'do' block: return (username, database)
In the expression: do { return (username, database) }
Failed, modules loaded: none.
如果这样运行:
if input /= "y"
then do return (username, database)
else do putStrLn "Your vote will be modified."
即使用户的输入不等于“y”,数据库也会被更新。 我不知道返回(用户名,数据库)的问题出在哪里
代码是:
options 7 (username, database) = do
putStrLn "******************"
putStrLn " Rate a film "
putStrLn "******************"
putStrLn ""
putStr "Enter the title of the film or nothing to return to the main menu: "
title <- getLine
if title == ""
then return(username, database)
else do
let filmCheck = findFilm title database
if filmCheck == []
then do
putStrLn "That film does not exists."
return (username, database)
else do
putStr "Enter your rate: "
tempRate <- getLine
case reads tempRate :: [(Integer, String)] of
[(n, "")] -> do
let rate = read tempRate :: Int
let tempFilm = rateFilm username (username, rate) filmCheck
when (checkIfRated username tempFilm == True) $ do
putStrLn "You already voted for this film\n"
putStrLn "Do you want to modify your vote?\n"
putStrLn "Press y to modify or nothing to return to the main menu:"
input <- getLine
if input /= "y"
then do return (username, database)
else do putStrLn "Your vote will be modified."
let database = tempFilm:database
putStrLn "You rating has been sumbited successfully!"
putStrLn (displayFilm tempFilm)
return (username, database)
_ -> do
putStrLn "The number you entered is invalid."
return (username, database)
【问题讨论】:
-
您是否希望
return (username, database)退出该功能?它所做的只是在单子上下文中包装一个值,代码f = do { return "hello"; return "world"; return 1; putStrLn "Returned 1"; return 2 }将返回2,因为这是在该块中执行的最后一条语句。其他的returns 只是普通的函数调用。 -
我发现的另一个错误,
let database = tempFilm:database不会像您预期的那样工作。它不会将database值重新绑定到新值。相反,您正在为database定义一个递归绑定,它将扩展为等效于repeat tempFilm。相反,您应该执行let newDatabase = tempFilm : database之类的操作,然后执行return (username, newDatabase)。 -
这正是我想要做的。而不是 return 如何强制 haskell 退出函数?有什么办法吗?并感谢发现的错误。
标签: haskell