使用修改后的元素修改并返回列表

时间:2012-05-02 01:38:01

标签: haskell

我正在尝试修改数据库列表中的元素以添加到评级,我想返回一个包含新元素的修改过的数据库。我理解Haskell有不可改变的东西,但与此同时我还不太清楚如何去做。

以下是类型:

data Film = Film Director Title Year Ratings
     deriving (Show,Ord,Eq, Read)

testDatabase :: [Film]

我唯一的代码是:

--addRating :: Rating -> Film -> Film
--addRating rating (Film name director year ratings)= (Film name director year [(ratings : rating)])


--findFilm name = head $ filter (\(Film n _ _ _) -> n == name) testDatabase 

查找电影效果不错,但我无法让addRating工作,即使它确实有效我仍然不明白如何将它们全部网格化以具有调用函数来返回已有的电影列表它上面有新评级的元素。

4 个答案:

答案 0 :(得分:3)

你几乎把它纠正了:

addRating rating (Film name director year ratings)
    = (Film name director year [(ratings : rating)])

目前你有代码:

[(ratings : rating)]

:运算符的类型为a -> [a] -> [a],它需要一个元素并将其附加到列表的 start ,而不是列表的末尾,因此您需要切换你的论点。

此外,语法[x]在您使用时会创建一个由一个元素组成的列表。如果你在这里使用它,它将采取你创建的列表并将其包装在另一个列表中,这不是你想要的。

您只需要制作一个列表,其中rating位于ratings的其余部分之前:

(rating : ratings)

答案 1 :(得分:2)

正如Porges所说,你的ratingratings顺序错误。您可能会根据自己的喜好找到记录语法方法:

data Film = Film {director :: Director, title :: Title, year :: Year, ratings :: Ratings}
                deriving (Show,Ord,Eq, Read)

addRating :: Rating -> Film -> Film
addRating rating film = film {ratings = rating : ratings film}

此处,film {director = "Martin Scorsese"}'更新'director字段,也就是说,表达式指的是具有不同导演的Film,但其他所有内容都相同。但是,在目前的情况下,您需要旧ratings字段的内容,因此您需要将rating添加到ratings film。这种声明类型的方式为派生Show提供了不同的外观。

答案 2 :(得分:0)

  

...我无法让addRating工作,即使它确实有效,我仍然没有   了解如何将它们全部网格化以具有调用的函数   返回具有新评级元素的电影列表。

好像你想要一个能够返回新数据的函数,以一种可以访问的方式“旧数据曾经存在的地方。”

这里要理解的关键是会使其成为可变数据。

函数式编程提供的一件事是保证数据始终相同。在命令式(非功能性)语言中,如果您有多个可能会更改数据的进程,则必须注意它们不会以意外方式修改彼此的数据。不可变数据使这成为一个无问题。

如果你真的想要破坏性的更新,有办法做到这一点。但是,您可能正在寻找的是State monad,这是一种在没有破坏性更新的情况下“随身携带”状态的好方法。

答案 3 :(得分:0)

理解“不可改变的事物”的关键在于你不需要修改你已经给予的东西,你只需创建一个有点不同的“副本”作为结果返回。例如,您有一个包含l的列表[1,2,3]。执行l ++ [4]后,您将返回[1,2,3,4],但l的值未更改

对你的电影记录使用相同的原则 - 你已经很近了。

正如其他人所指出的,你已经在(ratings : rating)表达式中混淆了你的类型。要使用:,元素会排在前面,列表会返回。您可以切换类型,但这会将新的评级放在前面,这可能是您不想要的。另一种方法是使用++,它会附加两个列表。因此,要使用++,您需要从单个元素中创建一个列表,并将其附加到现有的评级中。

addRating :: Rating -> Film -> Film
addRating rating (Film name director year ratings) =
    (Film name director year (ratings ++ [rating]))