0

我希望用户输入一个元组列表以在其上搜索这样的键我可以这样说吗

  data BookInfo = Book Int String [String]
  deriving(Show)
  findbook :: [BookInfo] -> Int -> BookInfo
  findbook vs key = (booker (vs!!(bookFinding vs  key 0 (length vs))) key)

  getBookInfo = do
    putStrLn "Enter book id :"
    k <- read
    putStrLn "Enter book name : "
    r <- getLine
    putStrLn "Enter book subject :"
   m <- getLine 
   let Book book = enter k r [m] 
   return  book
 main = do
   putStr "Enter you first info is :"
   v <- getBookInfo
   let Book vs = v:[]
   c <- getLine
   if c == "N"
   then     
     putStr "You  done"   
   else
    Book booke = getBookInfo
    vs = booke:vs
  putStr "Do you want to search ? :" 
     m <- getch
      if m == 'y'
        then  
         putStr " Enter your key :"  
         s <- readNum  

 let Book w =  findBook vs s
 putStrLn" The result is: " ++ show(w)

但这给了我一个错误:

 The last statement in do must be m <- getch

我究竟做错了什么?

4

1 回答 1

5

看起来您正在尝试编写一个程序来将书籍列表读入某种数据库,然后搜索书籍。你开始很好,使用存储书籍信息的数据类型:

data BookInfo = Book Int String [String] deriving (Show)

现在让我们看看你的函数,它从用户那里读取书籍信息。

getBookInfo = do
    putStrLn "Enter book id :"
    k <- read
    putStrLn "Enter book name : "
    r <- getLine
    putStrLn "Enter book subject :"
    m <- getLine 
    let Book book = enter k r [m] 
    return book

我为您修复了缩进(这里有一个提示:使用四个空格进行缩进!)但还有其他问题:

  • 这条线k <- read没有任何意义。读取的类型是,read :: Read a => String -> a但您正在使用它,就好像它是一个 I/O 操作一样。您需要该功能readLn

  • 这条线let Book book = enter k r [m]没有任何意义。看起来您习惯于使用 C 或 Java 之类的语言编写,您必须在其中指定类型。你不必在 Haskell 中这样做!此外,该enter功能是不必要的。你可以只写let book = Book k r [m],这会很好。事实上,您根本不需要临时变量book- 您可以Book在一行中创建并返回它。

所以你可以写:

getBookInfo :: IO BookInfo
getBookInfo = do
    putStrLn "Enter book id: "
    bookid <- readLn 
    putStrLn "Enter book name: "
    name <- getLine
    putStrLn "Enter book subject: "
    subject <- getLine 
    return (Book bookid name [subject])

现在可以正常编译了。请注意,我还添加了一个类型声明(这是可选的)。


您的下一个功能 ,main试图做的太多了。它包含获取书籍列表的所有规则,以及搜索它们的规则。这是两个独立的任务,所以它们应该在两个独立的函数中。因此,让我们编写一个获取书籍列表的函数:

getBookList :: IO [BookInfo]
getBookList = do
    putStr "Any more books? "
    answer <- getLine
    if answer == "N"
        then return []
        else do
            book  <- getBookInfo
            books <- getBookList
            return (book:books)

花点时间了解这个功能是如何工作的。首先,它会询问您是否还有其他书籍要输入。如果你说“N”,那么它会返回空列表,你就完成了。否则,它会做一些神奇的事情——首先,它调用getBookInfo获取一本书的信息。然后它会调用自己来获取书籍列表!这是递归的一个例子。最后,它将第一本书添加到书籍列表中,并返回整个列表。


您现在应该尝试自己编写程序的其余部分。我可能会在一天左右重新访问这个答案以添加更多细节。如果你发表评论让我知道你尝试了什么,以及你卡在哪里,我更有可能这样做。记住:

  • 正确缩进你的代码!使用四个空格。获得像Sublime Text 2这样知道如何处理缩进的编辑器。

  • 尝试编写小(少于 10 行)函数并将它们链接在一起以构成一个完整的程序。这将防止您在尝试调试您想出的 400 行怪物时失去理智。

  • 检查类型!例如,您可以加载 ghci 并键入:t read以查看read函数的类型。

于 2012-07-21T21:56:00.923 回答