Haskell在元组

时间:2017-03-19 23:01:14

标签: string list haskell tuples

我正在尝试打印给定电影标题的粉丝列表的所有元素,例如“阿凡达”的所有粉丝都不太清楚如何过滤这个并将正确的元素显示为字符串。以下是包含一些测试数据的程序的类型定义。

import Data.Char
import Data.List

--types
type Title = String
type Director = String
type Year = Int
type Fans = [String]

type Film = (Title, Director, Year, Fans)

type Database = [Film]

testDatabase :: [Film]
testDatabase = [
 ("Blade Runner", "Ridley Scott", 1982, ["Zoe", "Heidi", "Jo", "Kate", "Emma", "Liz", "Sam", "Olga", "Tim"]),
 ("The Fly", "David Cronenberg", 1986, ["Garry", "Dave", "Zoe", "Kevin", "Emma"]),
 ("Body Of Lies", "Ridley Scott", 2008, ["Bill", "Olga", "Tim", "Zoe", "Paula"]),
 ("Avatar", "James Cameron", 2009, ["Dave", "Amy", "Liz"]),
 ("Titanic", "James Cameron", 1997, ["Zoe", "Emma", "Paula", "Liz", "Olga", "Dave"])]

1 个答案:

答案 0 :(得分:2)

你真的通过使用类型同义词来解决所有事情。在这种情况下,data Film = Film Title Director Year Fans比使用元组要好得多。定义单独的Film数据类型会将FilmTitleDirectorYearFans元组之间的语义差异带入类型系统。这意味着您可以为它定义实例(如ShowEq),这些实例将以与元组提供的不同的特定方式运行。它还会导致编译器拒绝(可能意外地)将恰好具有类型(String,String,Int,[String])的元组与实际Film混合的代码。这增加了安全性,这是首先使用Haskell的主要原因之一。

也就是说,只列出粉丝非常简单:

listFans :: Film -> String
-- data way
listFans (Film _ _ _ fans) = intersperse ',' fans
-- tuple way
listFans (_,_,_,fans) = intersperse ',' fans

接下来,我们需要一个lookupFilm :: Database -> Title -> Maybe Film来找到我们想要的电影。我们需要Maybe,因为Film可能不在Database中。

lookupFilm :: Database -> Title -> Maybe Film
lookupFilm db t = find (\(Film t' _ _ _) -> t == t') db

请注意,这不会“打印”字符串,只会返回它们,因此您需要putStrLn . listFans :: Film -> IO ()来实际输出它们。

如果您总是按照标题查找电影,也可以使用Data.Map中的Map Title Film

最后:确保您了解findintersperse的工作原理; Data.List就像被给予一条鱼一样,但你需要学习如何为自己捕鱼,以便在出现问题时解决更复杂的问题。