作为初步步骤,让我们为您的类型派生 Eq 和 Show 实例:
data Joke = Funny String | Lame String
deriving (Eq, Show)
Eq 可以测试Jokes 的(不)相等性,而Show 可以在 GHCi 中显示您的测试结果。
filter 是正确的工具:
excludeHaha :: [[Joke]] -> [[Joke]]
excludeHaha = filter (notElem (Funny "Haha"))
这会过滤(外部)列表,以便只保留所有元素都不同于Funny "Haha" 的内部列表。
试一试:
GHCi> excludeHaha [[Funny "Haha", Lame "boo"], [Funny "Haha"], [Lame "BOO"]]
[[Lame "BOO"]]
如果您不想硬编码"Haha",请添加一个参数并将其传递给测试:
excludeAFunnyJoke :: String -> [[Joke]] -> [[Joke]]
excludeAFunnyJoke s = filter (notElem (Funny s))
GHCi> excludeAFunnyJoke "LOL" [[Funny "LOL", Lame "boo"], [Funny "Haha"], [Lame "BOO"]]
[[Funny "Haha"],[Lame "BOO"]]
如果您想排除所有 Funny 笑话,无论包含的 String 是什么,您都可以使用模式匹配来定义适当的测试:
excludeFunny :: [[Joke]] -> [[Joke]]
excludeFunny = filter (all (not . isFunny))
where
isFunny :: Joke -> Bool
isFunny joke = case joke of
Funny _ -> True
_ -> False
此处的过滤测试使用all,它将自己的测试(此处为(/= Funny "Haha"))应用于(内部)列表的元素,然后将生成的[Bool] 与(&&) 折叠起来。
(您不妨定义 isLame 并使用它而不是 not . isFunny ——但请注意,这只会起作用,因为您恰好只有两个构造函数。)
GHCi> excludeFunny [[Funny "LOL", Lame "boo"], [Funny "Haha"], [Lame "BOO"]]
[[Lame "BOO"]]
P.S.:Eq 实例的手动实现如下所示:
instance Eq Joke where
Funny x == Funny y = x == y
Lame x == Lame y = x == y
Funny _ == Lame _ = False
Lame _ == Funny _ = False
你可以用一个包罗万象的 (_ == _ = False) 替换最后两种情况,如果你向Joke 添加更多构造函数,则可以更容易忘记更新实例的代价节省一行。无论如何,这样的定义都是无聊的工作,所以我们避免使用deriving,除非需要进行不明显的相等测试。