Haskell在嵌套列表中过滤数据构造函数

时间:2018-02-12 23:59:00

标签: list haskell functional-programming

我有以下自定义数据类型:

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是必需的(我一直在玩它们,但无法得到正确的顺序),但我似乎无法正确实现这一点。

编辑:已解决。我不得不把更多的时间投入到列表理解中。谢谢。

1 个答案:

答案 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 -}
]

Try it here