haskell - 继续进入元组

标签 haskell io syntax-error

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

  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

我究竟做错了什么?

最佳答案

似乎您正在尝试编写一个程序以将书籍列表读入某种数据库,然后搜索书籍。您可以从存储书籍信息的数据类型开始:

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试图做太多事情。它包含获取书籍 list 的所有规则以及搜索书籍的规则。这是两个单独的任务,因此它们应该处于两个单独的功能中。因此,让我们编写一个获取书籍 list 的函数:
    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函数的类型。
  • 关于haskell - 继续进入元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11595935/

    相关文章:

    scala - 在 Scala 中,是否可以对类型进行别名但不允许交叉使用像 Haskell 这样的别名/非别名类型?

    haskell - 找不到模块 `Yesod'

    C#读取文件

    java - JTextArea txt; txt.getText() 跳过 "\n"

    php - 在 mysql 中附加以逗号分隔的字符串时出现语法错误

    haskell - Haskell 中的函数组合

    haskell - 具有更高种类类型的 GADT 类型推断

    java.io.IOException : Permission denied Error when writing to removable SD card

    REPLACE() 触发器中的 MySQL 语法错误

    python-2.7 - 尝试编写Python闭包的语法无效