2012-05-01 20 views
0

フィルムの種類をデータ型に変更しようとしているので、注文して保存してファイルに読み込みが容易になるため、関数を適切な引数と一致させるのに問題があります。多くの種類の作業が簡単です。Haskellデータに入力する

type Rating = (String, Int) 
--type Film = (String, String, Int, [Rating]) 
data Film = Film String String Int [Rating] 
     deriving (Show,Ord,Eq, Read) 

testDatabase :: [Film] 
testDatabase = [] 

testFilm = ("Test","Test",2012,[("Test",8),("Test",5)]) 

saveToFile :: IO() 
saveToFile = do 
    putStrLn "Enter the output filename: " 
    name <- getLine 
    writeFile name (show testDatabase) 
    putStrLn "Done" 

loadFromFile :: IO() 
loadFromFile = do 
    putStrLn "Enter the input filename: " 
    name <- getLine 
    contents <- readFile name 
    let testDatabase = length contents `seq` (read contents :: [Film]) 
    putStrLn formatDatabase 
    putStrLn "Done" 


average xs = realToFrac (sum xs)/genericLength xs 

addFilm :: String -> String -> Int -> [Film] -> [Film] 
addFilm title director year db = db ++ Film title director year [] 

filmsByDirector :: String -> [Film] 
filmsByDirector name = filter (\(a,_,_,_) -> a == name) testDatabase 

filmsByRating :: Float -> [Film] 
filmsByRating rating = filter (\(_,_,_,a) -> filmRating a > rating) testDatabase 

filmsByYear :: Int -> [Film] 
filmsByYear year = filter (\(_,_,a,_) -> a == year) testDatabase 

filmRating :: [(String,Int)] -> Float 
filmRating ratings = average (map snd ratings) 

formatString :: Film -> String 
formatString (dir, film, year, rat) = printf "\n\nDirector: %s \nFilm Name: %s \nYear: %s \nRating: %4.2f" (show dir) (show film) (show year) (filmRating rat) 

formattedByYear :: Int -> String 
formattedByYear year = concatMap formatString $ filmsByYear year 

formattedByDirector :: String -> String 
formattedByDirector dir = concatMap formatString $ filmsByDirector dir 

formatDatabase = concatMap formatString $ testDatabase 
+1

は 'Film'がコード内のデータ型である、あなたはより多くの詳細を提供する必要があります。 (また、[レコードの構文](http://book.realworldhaskell.org/read/defining-types-streamlining-functions.html#deftypes.record)に興味があるかもしれません – huon

+0

file.hs:43:40: 実際の型 'Film 'と期待される型' Film'を一致させることができませんでした 'Film 'の呼び出しの戻り型で '(++)'の第2引数、すなわち '映画タイトル監督年[ ] ' 式の中で:db ++映画タイトル監督年[] – JamieB

答えて

7

代わりにあなたがパターンを(,,,)コンストラクタを使用

filmsByDirector name = filter (\(a,_,_,_) -> a == name) testDatabase 

の、必然的に変更することがあまりありません、あなたはFilmコンストラクタを使用

filmsByDirector name = filter (\(Film a _ _ _) -> a == name) testDatabase 

と同様のため他の機能。

しかし、それは名前付きフィールド(またはレコード)構文を使用して

data Film = Film { director, title :: String, year :: Int, ratings :: [Rating] } 

を定義することがはるかに便利だとあなたが不快にしているならば、関数は単に

filmsByDirector name = filter ((name ==) . director) testDatabase 

か、だろうポイントフリースタイル

Filmとの誤差についてはで、あなたが[]に最後のフィルムをラップする必要があり、

addFilm title director year db = db ++ [Film title director year []] 
+0

ありがとう!変数として映画を受け取るにはどうすればいいですか?以前は別の変数にフィルムを分けることができましたが、フィルム - >ストリング - >ストリング - >インター - > [定格] - >ストリングをする必要がありますか? – JamieB

+0

わかりません。たとえば取得したい場合タイトル(2番目の 'String')はレコード構文で、セレクタ' title :: Film - > String'をすでに持っています。レコードの構文がなければ、 'title(_、t、_、_)= t'だったタプルのように' title(Film _t _ _)= t'になります。 –

+0

申し訳ありませんが私は十分に明確ではなかった。 \ n \ nフィルム名:%s \ nフィルム名:%s \ n年齢:%s \ nレート:%4.2f "(ショー・フィルム)(ショー・フィルム)(ショー・フィルム)(フィルム・レーティング・ラット)I以前と同じようにdir/film/yearやratに直接アクセスすることはできません。そのため、私は仮パラメータを変更する必要があるかどうか尋ねました。 – JamieB

関連する問題