簡體   English   中英

Haskell:對Desugar List的理解

[英]Haskell: Desugar 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"]

請記住,嵌套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)

由於您返回了列表理解,因此需要額外的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是多余的。

我對您的原始列表理解做了些微修改。

[ (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"])]

因此,使用這些參數,它會產生(a,b)或[]的b。

這翻譯成以下地圖。

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]

完全符合您的列表理解能力。 更改參數將得到相同的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM