过滤用户定义的类型

时间:2017-11-04 22:32:00

标签: list haskell filter

我正在尝试编写一个函数,该函数接受Artist s和Genre字符串列表作为参数,并输出具有该类型的所有Artist s。我已将数据类型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"]

然而,我的功能是输出类型匹配错误,我不确定为什么。非常感谢任何帮助!

2 个答案:

答案 0 :(得分:3)

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包含SELECT PI.PRODUCT_NAME FROM DEMO_PRODUCT_INFO PI ( SELECT OI.PRODUCT_ID FROM DEMO_ORDER_ITEMS ( SELECT O.ORDER_ID FROM DEMO_ORDERS ( SELECT C.CUSTOMER_ID FROM DEMO_CUSTOMERS WHERE IN (‘Willam Hartsfield’)

答案 1 :(得分:3)

以下代码应该有效。如果您发布类型错误,这将有所帮助,以便人们可以更好地了解正在进行的操作。我可以看到您的代码存在一些问题。

一,你试图过滤类型,这是一个字符串,而不是一个布尔。您需要使用(==)来比较字符串。

其次,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"]}]