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”约束在功能上是不必要的。