微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

我正在努力理解如何在 Haskell 中读取 concat

如何解决我正在努力理解如何在 Haskell 中读取 concat

concat 的代码

concat :: [[a]] -> [a]
concat xss = [x | xs <- xss,x <- xs]

我不明白它是如何被阅读的。 xss 如何拆分为 xsx?还是我误读了?

例如,给定:

concat [[1,2,3],[4],[5]]

[1,3,4,5] 是如何实现的?

解决方法

在列表推导式中,位 a <- b 表示“对于 a 中的每个 b”。

因此,在您的情况下,xs <- xss 应该读作“for each xs in xss”,然后 x <- xs 应该读作“ 对于 x 中的每个 xs”,这也是有效的,因为 xs 本身是一个列表,因为 xss 是一个列表的列表。

因此,随着列表推导式的展开,xs 首先绑定到 [1,2,3],然后绑定到 [4],然后绑定到 [5],并且在 {{1} 的每次迭代中}}、xs 绑定到 x12,然后绑定到 3,最后绑定到 4

,

如果非要和命令式编程相比,我们可以想到

[ expr | x1 <- list1,x2 <- list2,....]

作为一个嵌套的 for 循环,将 expr 产生的值累积到一个列表中,如下所示:

result = []
for x1 in list1:
  for x2 in list2:
    ...
    result.append(expr)

在你的情况下,我们有

result = []
for xs in xss:
  for x in xs:
    result.append(x)

所以,当 xss = [[1,3],[4],[5]] 我们有:

  • xs = [1,3]
    • x = 1 被附加到结果中
    • x = 2 被附加到结果中
    • x = 3 被附加到结果中
  • xs = [4]
    • x = 4 被附加到结果中
  • xs = [5]
    • x = 5 被附加到结果中

因此最终结果是 [1,3,4,5]

这种比较并不是一个完全忠实的描述,因为它没有考虑惰性,而且 Haskell 并没有像上面那样通过将数据附加到可变列表来真正计算最终列表。也许 Python 的 yield 和生成器会更接近。不过,上面的比较应该说明了基本机制。

,

有了明显的身份,

[ E | P <- (xs ++ ys),Q ]  ===  [ E | P <- xs,Q ] ++ [ E | P <- ys,Q ]

[ x | xs <- [E],x <- xs ]  ===  [ x | x <- E ]

[ x | x <- [E] ]  ===  [E]

我们可以跟着代码走,

concat        [[1,[5]]
 = {- by definition of `concat` -}
   [x | xs <- [[1,[5]],x <- xs]
 = {- by definition of `++`     -}
   [x | xs <- [[1,3]] ++ [[4],x <- xs]
 = {- by the first identity     -}
   [x | xs <- [[1,3]],x <- xs] ++ [x | xs <- [[4],x <- xs]
 = {- by the second identity    -}
   [x | x <-   [1,3]          ] ++ [x | xs <- [[4],x <- xs]
 = {- by definition of `++`     -}
   [x | x <-   [1,3]          ] ++ [x | xs <- [[4]] ++ [[5]],x <- xs]
 = {- by the first identity     -}
   [x | x <-   [1,3]] ++ [x | xs <- [[4]],x <- xs] ++ [x | xs <- [[5]],3]] ++ [x | x <-   [4]          ] ++ [x | x <-   [5]          ]
 = {- and by the third          -}
   [x | x <-   [1,3]] ++ [            4           ] ++ [            5           ]
 = {- repeating as before       -}
   [x | x <- [1]] ++ [x | x <- [2]] ++ [x | x <- [3]] ++ [4] ++ [     5           ]
 = {- by the third identity     -}
   [          1 ] ++ [          2 ] ++ [          3 ] ++ [4] ++ [     5           ]
 = {- by definition of `++`     -}
   [          1,5           ]

因此 concat 应用于列表列表时,具有“打开”并消除其中的内括号的效果。

在这个过程中我们也发现了另一个身份,

[ x | x <- Q ]  ===  Q

从上面的和++的属性得出,其中

[A,B,C,...,Z]  ===  [A] ++ [B] ++ [C] ++ ... ++ [Z]

另见:

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?