1

这是我当前的代码,我希望能够创建一个充当接口的 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"])]

功能一:

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))

功能二:

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

我遇到的问题是当超过 2 个函数应用于 IO if 语句时,当用户输入分配“名称”时,它似乎没有注册,因此 name <- 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
4

2 回答 2

1

您可以将所有函数放在一个表中,并使用lookup它来选择要运行的函数。

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

我将您重命名filmsByFanfilmsByFan'(prime),因此我可以添加一个图层来提示输入密钥并调用您的 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
于 2013-04-23T20:07:30.077 回答
1

你说你得到的错误信息是

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

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

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

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

这与线条一致

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 个空格宽的标签)。

nb您可能打算阅读这些行

name <- getLine
putStrLn (filmsByFan name)
于 2013-04-23T18:59:48.017 回答