haskell - groupBy 的奇怪行为
问题描述
我想知道为什么下面的调用groupBy
不起作用:我的谓词是x < y
,所以我希望[1, 6]
成为一个组,但是 Haskell 却把[1, 6, 4, 2]
它放到了一个组中。
Prelude Data.List> groupBy (\x y -> x < y) [8,5,3,2,1,6,4,2]
[[8],[5],[3],[2],[1,6,4,2]]
更奇怪的是,当我将最后一个数字更改为 -2 时,我期望与上面示例中的行为相同。也就是说,由于 2 和 -2 都小于 4,我希望结果[1, 6, 4, -2]
会组成一个组。但是,这一次,Haskell 将 -2 设置为一个组。
Prelude Data.List> groupBy (\x y -> x < y) [8,5,3,2,1,6,4,-2]
[[8],[5],[3],[2],[1,6,4],[-2]]
我对 的理解有误groupBy
吗?
解决方案
在实现中groupBy
,x
始终是子列表的第一项。实际上,groupBy
实现为:
groupBy :: (a -> a -> Bool) -> [a] -> [[a]] groupBy _ [] = [] groupBy eq (x:xs) = (x:ys) : groupBy eq zs where (ys,zs) = span (eq x) xs
在这里尤其span (eq x)
重要,因为x
它将是新组的第一项。
因为x
不是列表中的先前值。如果我们因此groupBy
使用 list运行[5, 3, 2, 1, 6, 4, -2]
,我们会得到:
列表 | 当前列表 | x=? | 检查 | 结果 |
---|---|---|---|---|
[5,3,2,1,6,4,-2] |
[8] |
8 |
/ |
/ |
[5,3,2,1,6,4,-2] |
[8] |
8 |
5 |
False |
[3,2,1,6,4,-2] |
[5] |
5 |
/ |
/ |
[3,2,1,6,4,-2] |
[5] |
5 |
3 |
False |
[3,2,1,6,4,-2] |
[3] |
3 |
/ |
/ |
[2,1,6,4,-2] |
[3] |
3 |
2 |
False |
[2,1,6,4,-2] |
[2] |
2 |
1 |
False |
[1,6,4,-2] |
[2] |
2 |
/ |
/ |
[1,6,4,-2] |
[2] |
2 |
1 |
False |
[6,4,-2] |
[1] |
1 |
/ |
/ |
[4,-2] |
[1,6] |
1 |
6 |
True |
[-2] |
[1,6,4] |
1 |
4 |
True |
[] |
[-2] |
-2 |
/ |
/ |
尤其是我们比较重要的x=1
情况y=4
。如果x
只是以前的值,我们应该开始生成一个新列表,但由于x
是列表的第一项,情况并非如此。
通常你应该只使用等价关系 ~ [wiki],这样的关系是:
- 反身的:
x ~ x
确实如此; - 对称:所以
x ~ y
当且仅当y ~ x
;和 - 及物: 所以
x ~ y
和y ~ z
暗示 那个x ~ z
.
您的等价关系不是自反的,也不是对称的。因此,这不是一个可以使用的有效函数groupBy
。
推荐阅读
- python - 装饰器导致所有函数返回 True
- function - Two colons before the array`s toString() method
- braintree - BrainTree Drop In 3D Secure - payload.liabilityShifted 不在有效载荷中
- java - CQRS 中不同聚合之间的交互
- php - 如何在 XPath (PHP) 中使用像 jQuery 这样的 CSS 选择器
- azure - Azure 搜索 - 导入 .md 文件中的数据
- algorithm - 将坐标设置为一后找到最大的
- java - AWS Classic ELB 立即向客户端返回 504(仅限 apache commons 或本地 java 客户端),而后端没有收到请求
- javascript - 仅更改按下项目的状态
- php - PHP:如何在 foreach 中为数组添加值