在Haskell中,列表理解的内部工作原理是什么?

m0meni

我对Haskell相当陌生,并且在这里查看此帖子:Haskell中2个列表的笛卡尔积

在答案中有以下代码片段:

cartProd xs ys = [(x,y) | x <- xs, y <- ys]

与这两个列表:

xs = [1,2,3]
ys = [4,5,6]

会屈服

[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]

如果我没有看到这个结果,我会以为它会返回

[(1,4),(2,5),(3,6)]

因为它会同时遍历两个列表。

但是现在,对于我更了解的编程语言而言,它看起来像是用于遍历矩阵的double for循环:

for (int x = 1; x < 4; x++)
    for(int y = 4; y < 7; y++)
        //make tuple (x,y)

是什么导致列表理解以这种方式表现?

威廉·范昂塞姆

简介介绍了列表理解语法基本上可以说,每种x <- list方法意味着一个附加的嵌套“ for”循环来生成元组,并且每个谓词都经过了简单的测试。因此表达式:

[(x,y) | x <- xs, even x, y <- ys, even 3*y-div x 2]

将以命令式语言翻译为:

for (var x : xs) {
    if(even(x)) {
    for(var y : ys) {
        if(even(3*y-x/2)) {
            yield (x,y)
        }
    }
}

yield是有时与协同例程一起使用的关键字。此外,yield评估是懒惰的。例如,这可以生成所有偶数整数,如下所示:

[x|x <-[2..],even x]

列出单子

为了从根本上理解列表理解,需要知道什么是Monads每个列表理解都可以转换为列表monad例如,您的示例被翻译为:

do x <- xs
   return
      (do y <- ys
          return (x,y))

这又是语法糖:

xs >>= (\x -> (ys >>= \y -> return (x,y)))

monad是函数式编程中的一个重要概念(也许最好阅读Wikipedia页面),因为它有点难以掌握。有时说一个单子都像卷饼,...

一旦您或多或少地理解了monad:monad是带有return语句和>>通道语句的类型类现在return内部语句很简单:

return x = [x]

这样就意味着每一次xy设定,您将创建一个元组(x,y)并返回它作为一个单独列表:这样[(x,y)]现在的“绑定”运营商>>=需要的“胶水”ys\y -> return (x,y)在一起。通过将其实现为:

(>>=) xs f = concat $ map f xs

换句话说,您进行映射并连接映射结果。

现在,如果考虑到未使用表达式的第二部分:

ys >>= \y -> return (x,y)

这意味着对于给定的x(我们现在将其抽象掉),我们将把每个元素映射ys到一个元组(x,y)并返回它。因此,我们将生成一个列表列表,每个列表都是一个包含元组的单例。类似于(如果ys=[1,2]):

[[(x,1)],[(x,2)]]

现在,>>=它将进一步concat变为:

\x -> [(x,1),(x,2)]

到现在为止,我们已经对抽象对象进行x抽象(假设它是一个)。但是现在我们可以采用该表达式的第一部分:

xs >>= \x -> [(x,1),(x,2)]

如果为xs=[3,5],则表示我们将再次创建列表:

[[(3,1),(3,2)],[(5,1),(5,2)]]

并在concat之后:

[(3,1),(3,2),(5,1),(5,2)]

我们期望的是:

[(x,y)|x<-[3,5],y<-[1,2]]

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

fileWriter在javascript中的工作原理是什么

来自分类Dev

在Spring Framework中,setter的工作原理是什么?

来自分类Dev

python“列表理解”中的“理解”是什么意思

来自分类Dev

链接rel =“ preload”的工作原理是什么?

来自分类Dev

取消订阅标签的工作原理是什么?

来自分类Dev

雅虎Messenger的工作原理是什么?

来自分类Dev

事件冒泡的工作原理是什么?

来自分类Dev

ES6类内部工作原理:原型分配理解

来自分类Dev

在Python中,对列表的理解与对元组的区别是什么?

来自分类Dev

Python列表理解中的“或”是什么意思?

来自分类Dev

此列表如何理解其自身的工作原理?

来自分类Dev

angularjs中真正返回的$ watch方法及其工作原理是什么?

来自分类Dev

getrusage的工作原理以及rusage结构中的真正含义是什么?

来自分类Dev

Jinja中的列表索引工作原理

来自分类Dev

Haskell中的((+)。(+))是什么?

来自分类Dev

haskell中的<|>是什么?

来自分类Dev

Grep内部工作原理

来自分类Dev

“列表理解”是什么意思?它是如何工作的,我该如何使用?

来自分类Dev

Spring Security拦截URL的工作原理是什么?

来自分类Dev

以下Chrome扩展javascript代码段的工作原理是什么?

来自分类Dev

电源关闭时ROM的工作原理是什么?

来自分类Dev

Spring Security拦截URL的工作原理是什么?

来自分类Dev

禁用顶点属性数组后,glDrawArrays()的工作原理是什么?

来自分类Dev

在此示例中无法理解递归的工作原理

来自分类Dev

为什么Haskell列表理解比循环快

来自分类Dev

以下列表理解的解释是什么?

来自分类Dev

难以理解ASCII的工作原理

来自分类Dev

为什么Haskell中的列表理解不包含大小<n的列表

来自分类Dev

如果Clojure中唯一不消耗堆栈的循环构造是“ recur”,那么这个lazy-seq的工作原理是什么?

Related 相关文章

  1. 1

    fileWriter在javascript中的工作原理是什么

  2. 2

    在Spring Framework中,setter的工作原理是什么?

  3. 3

    python“列表理解”中的“理解”是什么意思

  4. 4

    链接rel =“ preload”的工作原理是什么?

  5. 5

    取消订阅标签的工作原理是什么?

  6. 6

    雅虎Messenger的工作原理是什么?

  7. 7

    事件冒泡的工作原理是什么?

  8. 8

    ES6类内部工作原理:原型分配理解

  9. 9

    在Python中,对列表的理解与对元组的区别是什么?

  10. 10

    Python列表理解中的“或”是什么意思?

  11. 11

    此列表如何理解其自身的工作原理?

  12. 12

    angularjs中真正返回的$ watch方法及其工作原理是什么?

  13. 13

    getrusage的工作原理以及rusage结构中的真正含义是什么?

  14. 14

    Jinja中的列表索引工作原理

  15. 15

    Haskell中的((+)。(+))是什么?

  16. 16

    haskell中的<|>是什么?

  17. 17

    Grep内部工作原理

  18. 18

    “列表理解”是什么意思?它是如何工作的,我该如何使用?

  19. 19

    Spring Security拦截URL的工作原理是什么?

  20. 20

    以下Chrome扩展javascript代码段的工作原理是什么?

  21. 21

    电源关闭时ROM的工作原理是什么?

  22. 22

    Spring Security拦截URL的工作原理是什么?

  23. 23

    禁用顶点属性数组后,glDrawArrays()的工作原理是什么?

  24. 24

    在此示例中无法理解递归的工作原理

  25. 25

    为什么Haskell列表理解比循环快

  26. 26

    以下列表理解的解释是什么?

  27. 27

    难以理解ASCII的工作原理

  28. 28

    为什么Haskell中的列表理解不包含大小<n的列表

  29. 29

    如果Clojure中唯一不消耗堆栈的循环构造是“ recur”,那么这个lazy-seq的工作原理是什么?

热门标签

归档