Haskell,在输入和输出IO上使用多个if语句

时间:2013-04-23 17:23:38

标签: haskell if-statement input io output

这是我当前的代码,我希望能够创建一个充当接口的MAIN IO,并允许用户根据他们的选择选择要执行的功能。

type Title = String
type Actor = String
type Cast = [Actor]
type Year = Int
type Fan = String
type Fans = [Fan]
type Period = (Year, Year)
type Film = (Title, Cast, Year, Fans)
type Database = [Film]
title (t, _, _, _) = t
cast (_, c, _, _) = c
year (_, _, y, _) = y
fans (_, _, _, fs) = fs

testDatabase :: Database
testDatabase = [("Casino Royale", ["Daniel Craig", "Eva Green", "Judi Dench"], 2006, ["Garry", "Dave", "Zoe", "Kevin", "Emma"]),
    ("Cowboys & Aliens", ["Harrison Ford", "Daniel Craig", "Olivia Wilde"], 2011, ["Bill", "Jo", "Garry", "Kevin", "Olga", "Liz"]),     
        ("Catch Me If You Can", ["Leonardo DiCaprio", "Tom Hanks"], 2002, ["Zoe", "Heidi", "Jo", "Emma", "Liz", "Sam", "Olga", "Kevin", "Tim"])]

功能1:

displayAllFilms' :: [Film] -> String -> String
displayAllFilms' [] filmString = filmString
displayAllFilms' ((title,cast,year,fans):films) filmString = 
       displayAllFilms' films (filmString ++ "\n" ++ title ++ ", " ++ listStuff cast ", " ++ (show year) ++ ", " ++ show (length fans))

功能2:

filmsByFan f = map title $ filter (elem f . fans) testDatabase

以上代码100%正常工作,我可以从给定的数据库中提取信息。

以下是我创建的示例MAIN IO:

main :: IO ()
main = do putStrLn "What function would you like to execute? 1. addFilm / 2.displayAllFilms / 3. filmsByYear / 4. filmsByFan / 5. filmsByActor Period / 6. becomeFan: "
          str <- getLine
          if str /= "2"
            then return ()
            else do putStrLn (displayAllFilms' testDatabase str)
          if str /= "4"
            then return ()
            else do putStrLn "Enter an existing fan: "
                    name <- getLine
                    putStrLn filmsByFan name  <<< **error here**
                    main

我遇到的问题是当IO if语句应用了两个以上的函数时,当用户输入分配'name'时它似乎没有注册,因此其他代码来自name&lt; - getLine无法编译。

我的问题是:用户是否有办法根据他们选择的内容选择要执行的功能并执行相应的功能......?

提前致谢!

编辑:

关于我希望代码如何执行的示例:

Main
which function would you like to execute...1,2,3,4,5,6?
user enters: 1
displayFilms will execute.

IF USER ENTERS 4

user enters: 4
Enter an existing fan:
user enters: Liz"
execute filmsByFan

2 个答案:

答案 0 :(得分:1)

您说您收到的错误消息是

ExampleSolution.hs:167:12: parse error on input `do'

你没有说第167行是哪一行。

您似乎在混合空格和标签。这可能是问题的原因。用空格替换源代码中的所有选项卡。

编辑:我说你似乎在混合空格和制表符,因为你问题中的源代码混合了空格和制表符。例如带有错误的行的缩进以制表符结束,而它上面的行中的缩进以8个空格结尾,并且似乎没有缩进。

这与行

一致
name <- getLine
putStrLn filmsByFan name

实际上是

name <- getLine
        putStrLn filmsByFan name

并被解释为

name <- getLine putStrLn filmsByFan name

会导致您现在报告的错误:

ExampleSolution.hs:174:61: Not in scope: `name'

由于name的左侧定义<-,因此无法在右侧使用:它仅可用于块中的后续行。

检查编辑器在保存文件时是否未将空格转换为标签,这与您的意愿相反。或者,确保它使用8个空格宽的标签(我猜你可能正在使用4个空格的标签)。

n.b。您可能打算将这些行读取

name <- getLine
putStrLn (filmsByFan name)

答案 1 :(得分:1)

您可以将所有功能放在表格中,然后使用lookup选择要运行的功能。

table = [(1, addFilm)
        ,(2, displayAllFilms)
        ,(3, filmsByYear)
        ,(4, filmsByFan)
    ]

我将您的filmsByFan重命名为filmsByFan'(素数),因此我可以添加一个图层来提示输入密钥并调用您的orig函数:

filmsByFan = do putStr "Enter Fan"
                f <- getLine
                print $ filmsByFan' f               
filmsByFan' f = map title $ filter (elem f . fans) testDatabase
main :: IO ()
main = do putStrLn "What function would you like to execute? 1. addFilm / 2.displayAllFilms / 3. filmsByYear / 4. filmsByFan / 5. filmsByActor Period / 6. becomeFan: "
          str <- getLine
          let n = (read str)::Int
              cmd = lookup n table
          case cmd of
            Just doIt -> doIt
            Nothing   -> do print "sorry"
                            main