首页 > 解决方案 > Haskell 电影搜索

问题描述

我是 Haskell 的新手,我有一个项目需要在列表中满足条件时给出 True,我已经创建了另一个函数来检查分数是否高于或导演是否相同但现在我需要合并这个条件在一起,但我被困住了,不知道该怎么做。

该功能需要为该测试用例返回 true:

search (director "Christopher Nolan") movies == [("Inception", 8.8, "Christopher Nolan"), ("The Dark Knight", 9.0, "Christopher Nolan")]

search (imdbAtLeast 8.2) movies == [("Green Book", 8.3, "Peter Farrelly"), ("Inception", 8.8, "Christopher Nolan"), ("The Dark Knight", 9.0, "Christopher Nolan")]

search (and_ (director "Christopher Nolan") (imdbAtLeast 8.9)) movies == [("The Dark Knight", 9.0, "Christopher Nolan")]

search (or_ (imdbAtLeast 7.5) (director "Rian Johnson")) [("The Last Jedi", 7.2, "Rian Johnson"), ("Sicario", 7.6, "Denis Villeneuve")] == [("The Last Jedi", 7.2, "Rian Johnson"), ("Sicario", 7.6, "Denis Villeneuve")]

search (\_ -> True) [] == []

search (\_ -> False) movies == []

我的代码直到那部分:

type Movie = (String, Double, String)

-- movies :: [(String, Double, String)]
movies :: [Movie]
movies = [ ("Green Book", 8.3, "Peter Farrelly")
         , ("Inception", 8.8, "Christopher Nolan")
         , ("Incredibles 2", 7.7, "Brad Bird")
         , ("The Dark Knight", 9.0, "Christopher Nolan")
         ] 
imdbAtLeast :: Double -> (String,Double,String) -> Bool 
imdbAtLeast pointgive (_, point, _) =  point >= pointgive

director  :: String  -> (String,Double,String) -> Bool 
director  directorgive  (_, _, director) =  director == directorgive

and_ :: (Movie -> Bool) -> (Movie -> Bool) -> Movie -> Bool
and_ p q m = p m && q m

or_ :: (Movie -> Bool) -> (Movie -> Bool) -> Movie -> Bool
or_ p q m = p m || q m

标签: haskell

解决方案


好的,看来您走在正确的轨道上。您对搜索功能的类型有一个想法,所以让我们把它写下来:

search :: (Movie -> Bool) -> [Movie] -> [Movie]

让我们尝试从基本原理中弄清楚这一点。

第一个参数是一个函数。我们称它为predicatep。这个函数我们无能为力。最明显的是将它应用到电影中,但到目前为止我们还没有。

第二个参数是电影列表。让我们对其进行模式匹配。第一种情况是[]

search p [] = (??)

好吧,我们需要在这里返回一个电影列表,我认为我们不应该凭空捏造一个,所以我们可能不应该返回一个。事实上,如果你搜索一个没有电影的列表,你肯定会得到什么。在这种情况下,我们不使用谓词参数,所以让我们写_一下,你可以清楚地表明我们不使用它:

search _ [] = []

另一种情况是列表的头部和其余部分。让我们将电影m的头部称为头部,按照惯例,尾部将被称为:ms

search p (m:ms) = (??)

至此,我们现在有了一个可以调用函数的电影p,所以让我们这样做并考虑结果:

search p (m:ms) =
    if p m
    then (??)
    else (??)

那么我们在这里做什么呢?如果p m为真,那么我们应该m在输出中包含,如果为假,那么我们不应该包含它。r让我们调用result的其余输出:

search p (m:ms) = if p m then p:r else r
  where r = (??)

现在我们需要做的就是弄清楚剩下的结果是什么。我们知道r必须是类型[Movie],如果我们考虑一下,r应该是ms满足谓词的电影列表p。我对如何思考这个问题没有很好的解释,但我能给出的最好建议是,通过阅读和编写大量像这样的小递归函数,人们对如何解决这些问题产生了一种直觉:

search p (m:ms) = if p m then p:r else r
  where r = search p ms

另一种解决方案是使用filter :: (a -> Bool) -> [a] -> [a]前奏中的功能:

search = filter

推荐阅读