-1

Haskellのデータベースを指定して、情報を表示し、それらを別々の行にフォーマットするのに苦労しています..以下は私が現在使用しているものです..

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]

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」を作成することです。

カジノ・ロワイヤル、ダニエル・クレイグ、エヴァ・グリーン、ジュディ・デンチ、2006、5

カウボーイ & エイリアン, ハリソン フォード, ダニエル クレイグ, オリビア ワイルド, 2011, 6

注: フォーマットは重要であり、各映画は、ファンのリストではなく、別の行と最後にファンの数に関する情報と共に表示されます。

これは、この問題を解決するための私の試みです -

displayAllFilms :: [Film] -> String -> String
displayAllFilms [] filmString = filmString
displayAllFilms ((Title cast year fans _):films) filmString = displayAllFilms films (filmString ++ title ++ "\n" ++ (show cast) ++ "\n" ++ (show year) ++ "\n") 

しかし、コンパイルされていないようですが、コードに問題があるようには見えません...タイプエラーですか?

前もって感謝します!

4

1 に答える 1

3

いくつかの間違い:

testDatabase :: Database
testDatabase = [("Casino Royale", ["Daniel Craig", "Eva Green", "Judi Dench"], 2006,          ["Garry", "Dave", "Zoe", "Kevin", "Emma"]),
    -- indentation should be consistent - this next line was too far left:
    ("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 ++ title ++ "\n" ++ (show cast) ++ "\n" ++ (show year) ++ "\n")

(Title cast year fans)あなたが意味したとき、ここにありました(title,cast,year,fans)

Haskell では大文字と小文字が区別され、大文字はTitleコンストラクターを意味しますが、変数であることを意味します。あなたのFilm型はタプルなので、ここでもコンマをタプルにする必要があります。

出力を正しくする

これで、次の出力が得られます

putStrLn $ displayAllFilms testDatabase "=========="
==========Casino Royale
["Daniel Craig","Eva Green","Judi Dench"]
2006
Cowboys & Aliens
["Harrison Ford","Daniel Craig","Olivia Wilde"]
2011
Catch Me If You Can
["Leonardo DiCaprio","Tom Hanks"]
2002

これは必要な出力と一致しません。

Casino Royale, Daniel Craig, Eva Green, Judi Dench, 2006, 5

コンマの代わりに改行があり、不要な括弧があるためです。

listStuff:: [String] -> String -> String
listStuff strings separator = concat [string++separator| string <-strings]

ここでは、リスト内包表記を使用して、末尾にセパレーターを含む文字列のリストを作成し、concatそれらを結合しています。最後にスペアを取得しますが", "、キャストと年の間に 1 つ必要なので問題ありません。

length fansこれで、ファンの数を表示するために使用して、それをまとめることができます。

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

これは次のようにテストされます

>putStrLn $ displayAllFilms' testDatabase ""

Casino Royale, Daniel Craig, Eva Green, Judi Dench, 2006, 5
Cowboys & Aliens, Harrison Ford, Daniel Craig, Olivia Wilde, 2011, 6
Catch Me If You Can, Leonardo DiCaprio, Tom Hanks, 2002, 9

コードを少し整理する

displayAllFilms再帰的である必要はないと思います - 再利用することはできlistStuffますが、私たちが望む以上のことを行うライブラリ関数があります。hoogle で検索する[String] -> String -> Stringと、次の結果が得られます http://www.haskell.org/hoogle/?hoogle=[String]+-%3E+String+-%3E+String と 2 番目の結果intercalateが便利です。

> intercalate "_" ["Hello","Mum,","how","are","you?"]
"Hello_Mum,_how_are_you?"

あなたが入れなければならない

import Data.List

コードの先頭で使用します。だから今私たちはできる

commas :: [String] -> String
commas = intercalate ", "

したがって、個々のフィルムを表示し、それを使用してフィルムのリストを表示できます。

showFilm :: Film -> String
showFilm (title,cast,year,fans) = commas [title, commas cast, show year, show (length fans)]

そして、私たちは書くことができました

showDatabase :: Database -> String
showDatabase fs = intercalate "\n" [showFilm f | f<-fs]

しかし、それはより良いだろう

showDatabase :: Database -> String
showDatabase = unlines.map showFilm

showFilmそれぞれのフィルムで使用したいだけで、とにかく見やすいunlinesという意味です。intercalate "\n"

> putStrLn $ showDatabase testDatabase
Casino Royale, Daniel Craig, Eva Green, Judi Dench, 2006, 5
Cowboys & Aliens, Harrison Ford, Daniel Craig, Olivia Wilde, 2011, 6
Catch Me If You Can, Leonardo DiCaprio, Tom Hanks, 2002, 9
于 2013-04-20T14:16:01.833 に答える