我有以下自定义数据类型:
data Particle = Foo String | Goo String
通过以下电话:
func [[Foo "a"], [Goo "b", Foo "a"], [Goo "a"], [Foo "d"]]
功能定义是:
func :: [[Particle]] -> [[Particle]]
我想过滤粒子的嵌套列表,以便输出如下:
[[], [Goo "b"], [Foo "d"]]
用语言解释func正在做什么,它会看一下第一个列表中的第一个粒子,它被确定为Foo“a”。它从所有列表中删除了Foo“a”,如果碰巧在任何列表(包括第一个)中找到Goo“a”,它就会完全破坏包含它的列表。
但我的输出似乎是错误的。我正在
[[Goo "a"], [Foo "d"]]
什么时候我应该
[[], [Goo "b"], [Foo "d"]]
(这是因为从第一个和第二个列表中删除了Foo“a”,Goo“a”销毁了第三个列表,第四个列表保持不变,请参阅下面的列表)
列表的可读性副本
[[Foo "a"], [Goo "b", Foo "a"], [Goo "a"], [Foo "d"]]
有任何帮助吗?我知道filter和elem是必需的(我一直在玩它们,但无法得到正确的顺序),但我似乎无法正确实现这一点。
编辑:已解决。我不得不把更多的时间投入到列表理解中。谢谢。答案 0 :(得分:4)
这看起来像列表理解的一个很好的例子,在这种情况下是一个嵌套的。
data Particle = Foo String | Goo String
deriving (Eq, Show)
func :: [[Particle]] -> [[Particle]]
func [] = []
func xss@(x:_) = [[y | y <- ys, y /= badParticle] | ys <- xss, worseParticle `notElem` ys]
where
(badParticle: _) = x
worseParticle = case badParticle of
Foo s -> Goo s
Goo s -> undefined -- what do you do in this case?
让我首先打破理解,where
条款。
(badParticle: _) = x
-- this is equivalent to `badParticle = head x`
worseParticle = case badParticle of
Foo s -> Goo s
Goo s -> undefined
-- Just some case matching to go Foo -> Goo
然后是列表理解本身。
[ [y | y <- ys, y /= badParticle]
{- a list of every y from ys, where y is not the bad particle
this is equivalent to `filter (/= badParticle) ys` -}
| ys <- xss
{- where ys draws from xss -}
, worseParticle `notElem` ys
{- and worseParticle is not an element of ys -}
]