Haskell groupBy应该做什么?

Haskell groupBy应该做什么?,haskell,haskell-platform,Haskell,Haskell Platform,我用Data.List.groupBy写了一些东西。它没有像预期的那样工作,因此我最终编写了自己版本的groupBy:毕竟我不确定Data.List是否应该这样做(没有真正的文档) 无论如何,我的测试通过了我的groupBy版本,而失败的是Data.List。 我发现(感谢quickcheck)两个函数的行为不同,但我仍然不明白为什么这两个版本之间存在差异。Data.List版本是错误的还是我的?(当然,我的实现很幼稚,可能不是最有效的实现方式) 代码如下: import qualified D

我用
Data.List.groupBy
写了一些东西。它没有像预期的那样工作,因此我最终编写了自己版本的
groupBy
:毕竟我不确定
Data.List
是否应该这样做(没有真正的文档)

无论如何,我的测试通过了我的
groupBy
版本,而失败的是
Data.List
。 我发现(感谢
quickcheck
)两个函数的行为不同,但我仍然不明白为什么这两个版本之间存在差异。
Data.List
版本是错误的还是我的?(当然,我的实现很幼稚,可能不是最有效的实现方式)

代码如下:

import qualified Data.List as DL
import Data.Function (on)
import Test.QuickCheck

groupBy' :: (a -> a ->  Bool) -> [a] -> [[a]]
groupBy' _ [] = []
groupBy' eq (x:xs) = xLike:(groupBy' eq xNotLike) where
    xLike = x:[ e | e <- xs, x `eq` e  ]
    xNotLike = [ e | e <- xs, not $ x `eq` e  ]

head' [] = Nothing
head'  (x:xs) = Just x

prop_a s = (groupBy' by s) == (DL.groupBy by s) where
    types = s :: [String]
    by = (==) `on` head'
发生了什么事?我不敢相信haskell平台中有bug。

您的版本是O(n2)-在实际使用中速度慢得令人无法接受1

标准版本通过仅将相邻图元分组(如果相邻图元相等)来避免这种情况。因此,

*Main>groupBy((==)`on`head')[“”、“”、”a“]

会产生你想要的结果

使用
groupBy
获得“通用分组”的一种简单方法是,如果对数据类型可行,首先对列表进行排序

*Main>groupBy((==)`on`head')$DL.sort[“”,“a”,“”]

其复杂性仅为O(n logn)


1这并没有阻止委员会将
nub
指定为O(n2)…

您的版本是O(n2)–在实际使用中速度可能慢得令人无法接受1

标准版本通过仅将相邻图元分组(如果相邻图元相等)来避免这种情况。因此,

*Main>groupBy((==)`on`head')[“”、“”、”a“]

会产生你想要的结果

使用
groupBy
获得“通用分组”的一种简单方法是,如果对数据类型可行,首先对列表进行排序

*Main>groupBy((==)`on`head')$DL.sort[“”,“a”,“”]

其复杂性仅为O(n logn)



1这并没有阻止委员会将
nub
指定为O(n2).

Haskell中的Data.List.groupBy是一个可用性错误!用户友好型groupBy的行为应如下所示:

groupByWellBehaved p = foldr (\x rest -> if null rest
                                     then [[x]]
                                     else if p x (head (head rest))
                                          then (x : head rest) : (tail rest)
                                          else [x] : rest) []

也许有更好的实现,但至少这是O(n)。

Haskell中的Data.List.groupBy是一个可用性错误!用户友好型groupBy的行为应如下所示:

groupByWellBehaved p = foldr (\x rest -> if null rest
                                     then [[x]]
                                     else if p x (head (head rest))
                                          then (x : head rest) : (tail rest)
                                          else [x] : rest) []

也许有更好的实现,但至少这是O(n)。

函数
groupBy
将一个列表分成若干部分,例如
concat。groupBy f==id
(除其他定律外)。
groupBy
函数将一个列表分成若干部分,以便
concat。groupBy f==id
(除其他法律外)。阅读
groupBy
文档时,我意识到它确实与我所需要的组相邻,行为也不同:一个正常的
groupBy
。我确实可以做一件事,但没有意识到这是必要的。我的版本没有假装在realword中可用,也没有在参数上添加不必要的约束。除了明显的性能原因外,“Ord”约束在功能上是不必要的。阅读
groupBy
文档时,我意识到它实际上是相邻的,行为与我需要的不同:一个正常的
groupBy
。我确实可以做一件事,但没有意识到这是必要的。我的版本没有假装在realword中可用,也没有在参数上添加不必要的约束。除了明显的性能原因外,“Ord”约束在功能上是不必要的。