我无法将字符串列表从文本文件转换为我创建的名为Film
的数据类型。我将在下面显示以下代码:
Inside the films.txt
"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"
}
我的Haskell代码:
type Title = String
type Actor = String
type Cast = [Actor]
type Year = Int
type Fan = String
type Fans = [Fan]
type Film = (Title, Cast, Year, Fans)
main :: IO()
main = do
putStr "What is your name?: "
name <- getLine
firstdatabase <- readFile "films.txt"
putStr firstdatabase
let database = read firstdatabase :: [Film]
mainLoop database name
关于我将要做什么的任何想法?
答案 0 :(得分:4)
使用parsec非常容易实现:
import Text.Parsec
( Parsec, ParseError, parse -- Types and parser
, between, noneOf, sepBy, many1 -- Combinators
, char, spaces, digit, newline -- Simple parsers
)
-- Parse a string to a string
stringLit :: Parsec String u String
stringLit = between (char '"') (char '"') $ many1 $ noneOf "\"\n"
-- Parse a string to a list of strings
listOfStrings :: Parsec String u [String]
listOfStrings = stringLit `sepBy` (char ',' >> spaces)
-- Parse a string to an int
intLit :: Parsec String u Int
intLit = fmap read $ many1 digit
-- Or `read <$> many1 digit` with Control.Applicative
film :: Parsec String u Film
film = do
-- alternatively `title <- stringLit <* newline` with Control.Applicative
title <- stringLit
newline
cast <- listOfStrings
newline
year <- intLit
newline
fans <- listOfStrings
newline
return (title, cast, year, fans)
-- Alternatively, you can define it all in one go (with Control.Applicative) as
-- film = (,,,)
-- <$> stringlit <* newline
-- <*> listOfStrings <* newline
-- <*> intLit <* newline
-- <*> listOfStrings <* newline
-- Which makes it look very much like your actual file
films :: Parsec String u [Film]
films = film `sepBy` newline
然后你可以用它作为
loadDB :: FilePath -> IO (Either ParseError [Film])
loadDB filename = do
db <- readFile filename
return $ parse films "films" db
main :: IO ()
main = do
putStr "What is your name?"
name <- getLine
db' <- loadDB "films.txt"
case db of
Left err -> do
putStrLn "Error loading film database:"
print err
Right db -> mainLoop db name