【问题标题】:Filtering User-Defined Types过滤用户定义的类型
【发布时间】:2017-11-04 22:31:59
【问题描述】:

我正在尝试编写一个函数,该函数接受Artists 列表和Genre 字符串作为参数,并输出具有该类型的所有Artists。我已经定义了数据类型Artist如下:

data Artist = Artist Name Genres
  deriving Show
type Name   = String
type Genres = [Genre]
type Genre  = String

我实现该功能的代码如下:

getFilteredArtists :: [Artist] -> Genre -> [Artist]
getFilteredArtists xs genre = filter (genre) (map getGenres xs)

下面是一个示例函数调用:

artists = [
  Artist "Grimes" ["Electropop", "Dream Pop", "Synthpop"],
  Artist "My Bloody Valentine" ["Shoegaze", "Noise Pop", "Post Punk"],
  Artist "David Bowie" ["Art Rock", "Pop Rock", "Glam Rock", "New Wave"]
  ]

getFilteredArtists artists "Art Rock"

应该返回[Artist "David Bowie" ["Art Rock", "Pop Rock", "Glam Rock", "New Wave"]

但是,我的函数正在输出类型匹配错误,我不确定原因。非常感谢任何帮助!

【问题讨论】:

    标签: list haskell filter


    【解决方案1】:

    下面的代码应该可以工作。如果您发布类型错误会有所帮助,以便人们可以更好地了解正在发生的事情。我可以看到您的代码存在一些问题。

    第一,您正在尝试过滤流派,这是一个字符串,而不是布尔值。您需要使用 (==) 来比较字符串。

    其次,getGenres 没有定义,但假设它需要一个艺术家,并返回所有流派,将它映射到艺术家不会做你的代码想要它做的事情。它只会为您提供流派,而无需添加艺术家的背景。

    我认为您想要做的是过滤流派是当前艺术家元素的艺术家。

    您还可以使用数据声明来自动为您创建访问器函数,而无需手动编写它们。

    data Artist = Artist {
        getName :: String,
        getGenres :: Genres
    } deriving (Show)
    
    type Name   = String
    type Genres = [Genre]
    type Genre  = String
    
    getFilteredArtists :: [Artist] -> Genre -> [Artist]
    getFilteredArtists xs genre = filter (\x -> genre `elem` getGenres x) xs
    
    artists = [
      Artist "Grimes" ["Electropop", "Dream Pop", "Synthpop"],
      Artist "My Bloody Valentine" ["Shoegaze", "Noise Pop", "Post Punk"],
      Artist "David Bowie" ["Art Rock", "Pop Rock", "Glam Rock", "New Wave"]
      ]
    
    main = print $ getFilteredArtists artists "Art Rock"
    

    上面的代码会输出:

    [Artist {getName = "David Bowie", getGenres = ["Art Rock","Pop Rock","Glam Rock","New Wave"]}]
    

    【讨论】:

      【解决方案2】:
      genre :: Genre
      filter :: (a -> Bool) -> [a] -> [a]
      filter genre :: ???
      

      相反,你需要的是一个谓词

      getFilteredArtists xs genre = filter hasGenre xs where
          hasGenre :: Artist -> Bool
      

      hasGenre怎么写?好吧,你已经有了一个getGenres 函数,标准库有一个

      elem :: Eq a => a -> [a] -> Bool
      

      功能。 genre `elem` genres == True 如果genre 包含在genres 中,则False 否则。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-23
        • 1970-01-01
        • 2020-11-17
        • 2019-11-24
        • 1970-01-01
        • 1970-01-01
        • 2017-01-05
        • 2021-01-06
        相关资源
        最近更新 更多