我正在努力展示信息并将它们格式化为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”的函数:
Casino Royale,Daniel Craig,Eva Green,Judi Dench,2006,5
牛仔& Aliens,Harrison Ford,Daniel Craig,Olivia Wilde,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")
但它似乎没有编译但我似乎无法找到我的代码有什么问题...是类型错误?
提前致谢!
答案 0 :(得分: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]
这里我使用list comprehension来制作一个带有分隔符的字符串列表,然后concat
将它们连接在一起。最后你会得到一个备用的", "
,但这没关系,因为我们需要一个演员和一年之间。
现在我们可以把它放在一起,使用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和第二个,{ {1}}很方便:
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"