0

Filmタイプをデータタイプに変更しようとしています。これにより、注文、保存、ファイルへのロードが簡単になります。関数を正しい引数に一致させるのに問題があります。タイプの操作がはるかに簡単でした。 。

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
4

1 に答える 1

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

または、ポイントフリースタイルに不安がある場合

filmsByDirector name = filter (\f -> director f == name) testDatabase

Filmvs [Film]inに関するエラーについてはaddFilm、最後のフィルムをにラップする必要があります[]

addFilm title director year db = db ++ [Film title director year []]
于 2012-05-01T11:04:49.953 に答える