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

インデントを修正しました(ヒント:インデントには4つのスペースを使用してください!)が、他にも問題があります。

  • この線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すべてを1行で返すことができます。

だからあなたは書くことができます:

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は、少しやりすぎです。書籍のリストを取得するためのすべてのルールと、それらを検索するためのルールが含まれています。これらは2つの別個のタスクであるため、2つの別個の機能に含まれている必要があります。それでは、本のリストを取得する関数を書いてみましょう。

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それ以外の場合は、魔法のようなことをします。最初に、1冊の本の情報を取得するために呼び出します。次に、本のリストを取得するために自分自身を呼び出します!これは再帰の例です。最後に、最初の本を本のリストに追加し、リスト全体を返します。


プログラムの残りの部分を今すぐ自分で作成する必要があります。詳細を追加するために、この回答を1日かそこらで再検討する場合があります。何を試したのか、どこで行き詰まったのかをコメントで教えていただければ、そうする可能性が高くなります。覚えて:

  • コードを正しくインデントしてください!4つのスペースを使用します。インデントの処理方法を知っているSublimeText2のようなエディターを入手してください。

  • 小さな(10行未満)関数を作成し、それらをチェーンして完全なプログラムを作成してみてください。これにより、思いついた400行の怪物をデバッグしようとしたときに気が狂うのを防ぐことができます。

  • タイプをチェックしてください!たとえば、ghciとtypeをロードして:t read、関数のタイプを確認できreadます。

于 2012-07-21T21:56:00.923 に答える