Haskell:Desugar List理解

时间:2018-03-22 14:35:03

标签: haskell list-comprehension

我如何去除糖尿病

λ: [[b|(a,b)<-[(1,"A"),(2,"B")], mod x 2 == 0]|x <- [1..10]]
[[],["A","B"],[],["A","B"],[],["A","B"],[],["A","B"],[],["A","B"]]

我试过了

do 
  x <- [1..10]
  do 
    (a,b) <- [(1,"A"),(2,"B")]
    guard $ mod x 2 == 0
    return b

但这似乎会自动join结果。

["A","B","A","B","A","B","A","B","A","B"]

3 个答案:

答案 0 :(得分:4)

请记住,嵌套do构造“崩溃”:

do
 A
 do B
    C

相同
do
 A
 B
 C

(或者更确切地说,多行do构造desugar到嵌套的do构造。)所以你想要构建子列表并添加到外部列表,而不是使用构建单个列表嵌套的do构造来填充它。

使用混合中间方法,您可以分别通过return每个内部列表构建外部列表。

do
  x <- [1..10]
  return [[b|(a,b)<-[(1,"A"),(2,"B")], mod x 2 == 0]

然后你去了解 理解:

do
  x <- [1..10]
  return (do
      (a, b) <- ...
      guard $ mod x 2 == 0
      return b)

答案 1 :(得分:2)

由于您返回列表理解,因此需要额外return

do 
  x <- [1..10]
  return $ do 
    (a,b) <- [(1,"A"),(2,"B")]
    guard $ mod x 2 == 0
    return b

否则,你构造它就像:

[b|x <- [1..10], (a,b)<-[(1,"A"),(2,"B")], mod x 2 == 0]

由于您在外部do中使用了do作为拖尾元素,因此do是多余的。

答案 2 :(得分:0)

我对你原来的列表理解做了一些小修改。

[ (x,[(b) | (a,b) <- [(1,"A"),(2,"B")], mod x 2 == 0]) | x <- [1..10] ]

导致了

[(1,[]),(2,["A","B"]),(3,[]),(4,["A","B"]),(5,[]),(6,["A","B"]),(7,[]),(8,["A","B"]),(9,[]),(10,["A","B"])]

因此,使用这些参数,它产生b(a,b)或a []。

这转化为以下地图。

map (\x -> if mod x 2 == 0 then [x] else [] ) [1..10]

哪个产生了

[[],[2],[],[4],[],[6],[],[8],[],[10]]

列表理解的以下部分

[b|(a,b)<-[(1,"A"),(2,"B")]]

简单生成

["A","B"]

以下地图生成相同的内容。

map snd [(1,"A"),(2,"B")]

用前面的地图替换第一张地图中的[x]

map (\x -> if mod x 2 == 0 then map snd [(1,"A"),(2,"B")] else [] ) [1..10]

完全符合你的列表理解。更改参数会产生相同的结果。