Haskell使用特定的数据构造函数过滤嵌套列表 [英] Haskell filtering a nested list with specific data constructors

查看:160
本文介绍了Haskell使用特定的数据构造函数过滤嵌套列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有数据类型

  data Joke = Funny String | Lame String 

并说我有以下嵌套列表

  [[有趣的哈哈,Lameboo],[有趣的哈哈],[LameBOO]] 

我将如何过滤这样的嵌套列表,以便嵌套列表中包含滑稽哈哈 / code>被删除?换句话说,我试图过滤列表,以便我收到以下结果:

  [[LameBOO ]] 

任何包含滑稽哈哈的列表

感谢任何帮助,我有一个糟糕的时间学习Haskell,以及如何处理列表和自定义数据类型。

解决方案

作为一个初步步骤,让我们派生 Eq Show



 数据笑话=有趣的字符串| Lame String 
deriving(Eq,Show)

code>可以测试 Joke s的等于(in),而 Show 使它成为可能在GHCi中显示您的测试结果。

filter 在这里是正确的工具:

  excludeHaha :: [[笑话]]  - > [[笑话]] 
excludeHaha = filter(notElem(FunnyHaha))

这会过滤(外部)列表,以便只保留所有元素不同于 Funny哈哈的内部列表。



<试试看:

  GHCi>排除哈哈[[滑稽哈哈,拉姆嘘],[滑稽哈哈],[拉姆BOO]] 
[[LameBOO]]

如果你不想硬编码哈哈,添加一个参数并传递它在测试中:

  excludeAFunnyJoke :: String  - > [[笑话]]  - > [[笑话]] 
excludeAFunnyJoke s =过滤器(notElem(Funny s))





  GHCi> excludeAFunnyJokeLOL[[有趣的LOL,Lameboo],[有趣的哈哈],[LameBOO]] 
[[有趣的哈哈],[LameBOO]]

如果您想要排除所有 Funny 无论包含什么 String ,您都可以使用模式匹配来定义一个合适的测试:

  excludeFunny :: [[笑话]]  - > [[笑话]] 
excludeFunny = filter(all(not。isFunny))
其中
isFunny :: Joke - > Bool
isFunny笑话=案例笑话
滑稽_ - > True
_ - > False

这里的过滤测试使用 all ,它应用自己的测试在这里,(/ =有趣的哈哈))添加到(内部)列表的元素中,然后折叠得到的 [Bool] (&& amp;)



<你也可以定义 isLame 并使用它而不是 not。isFunny - 但请注意,这只会起作用,因为您碰巧只有两个构造函数。)

  GHCi> excludeFunny [[有趣的LOL,Lameboo],[有趣的哈哈],[LameBOO]] 
[[LameBOO]]






PS:手动执行 Eq 实例看起来像这样:

 实例方程式笑话其中
滑稽x ==滑稽y = x == y
Lame x == Lame y = x == y
Funny _ == Lame _ = False
Lame _ == Funny _ = False

您可以用一个全部替换( _ == _ = False ),如果你添加了更多的构造函数给 Joke ,那么节省一行的代价是让它更容易忘记更新实例。在任何情况下,这些定义都是枯燥无味的,所以我们避免使用派生,除非需要进行非显而易见的相等性测试。


Suppose I have the data type

data Joke = Funny String | Lame String

and say I have the following nested list

[[Funny "Haha", Lame "boo"], [Funny "Haha"], [Lame "BOO"]]

How would I go about filtering such a nested list so that any list within the nested list that contains Funny "Haha" is removed? In other words, I'm trying to filter the list so that I receive the following result:

[[Lame "BOO"]] 

Any list that contains Funny "Haha" is removed.

Would appreciate any help, I'm having a terrible time learning Haskell and how to do things with lists and custom data types.

解决方案

As a preliminary step, let's derive Eq and Show instances for your type:

data Joke = Funny String | Lame String
    deriving (Eq, Show)

Eq makes it possible to test the (in)equality of Jokes, while Show makes it possible to display the results of your tests in GHCi.

filter is the right tool here:

excludeHaha :: [[Joke]] -> [[Joke]]
excludeHaha = filter (notElem (Funny "Haha"))

This filters the (outer) list so that only inner lists with all elements different from Funny "Haha" are kept.

Trying it out:

GHCi> excludeHaha [[Funny "Haha", Lame "boo"], [Funny "Haha"], [Lame "BOO"]]
[[Lame "BOO"]]

If you don't want to hardcode "Haha", add a parameter and pass it on to the test:

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"]]

If you wanted instead to exclude all Funny jokes, regardless of what the contained String is, you could use pattern matching to define an appropriate test:

excludeFunny :: [[Joke]] -> [[Joke]]
excludeFunny = filter (all (not . isFunny))
    where
    isFunny :: Joke -> Bool
    isFunny joke = case joke of
        Funny _ -> True
        _ -> False

The filtering test here uses all, which applies its own test (here, (/= Funny "Haha")) to the elements of the (inner) list and then folds the resulting [Bool] with (&&).

(You might as well define isLame and use it instead of not . isFunny -- note, though, that that would only work because you happen to have just two constructors.)

GHCi> excludeFunny [[Funny "LOL", Lame "boo"], [Funny "Haha"], [Lame "BOO"]]
[[Lame "BOO"]]


P.S.: A manual implementation of the Eq instance would look like this:

instance Eq Joke where
    Funny x == Funny y = x == y
    Lame x == Lame y = x == y
    Funny _ == Lame _ = False
    Lame _ == Funny _ = False

You might replace the last two cases by a catch-all (_ == _ = False), saving one line at the cost of making it a little easier to forget updating the instance if you ever add more constructors to Joke. In any case, such definitions are boring busywork, so we avoid it with deriving unless there is a need for a non-obvious equality test.

这篇关于Haskell使用特定的数据构造函数过滤嵌套列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆