haskell 从无限数字列表中过滤(减少)重复序列的优雅方法

haskell elegant way to filter (reduce) sequences of duplicates from infinte list of numbers

这是一个生成无限随机数列表的函数

import System.Random
values :: [Int]
values = map fst $ scanl (\(r, gen) _ -> randomR (1,10) gen) (randomR (1,10) (mkStdGen 1)) $ repeat ()

我想将重复元素的序列减少为一个元素,例如 [2,3,4,1,7,7,7,3,4,1,1,1,3,..] -> [2,3,4,1,7,3,4,1,3 ,..]

所以,我需要一些来自 [Int] -> [Int] 的优雅函数 "f" 来执行此操作。 此外,它必须懒惰地处理无限列表,所以如果我 运行

f values

一定不能挂,实时输出数据

您可以使用 group :: Eq a => [a] -> [[a]] 来制作群组列表。因此对于给定的示例数据,这将生成:

Prelude> import Data.List(group)
Prelude Data.List> group [2,3,4,1,7,7,7,3,4,1,1,1,3]
[[2],[3],[4],[1],[7,7,7],[3],[4],[1,1,1],[3]]

然后我们可以为每个子列表只产生第一个元素head,我们知道这样的元素存在,否则它永远不会首先构造一个新组:

Prelude Data.List> map head (group [2,3,4,1,7,7,7,3,4,1,1,1,3])
[2,3,4,1,7,3,4,1,3]

这意味着您可以将 f 定义为:

import Data.List(group)

f :: Eq a => [a] -> [a]
f = map head . group

这也适用于无限列表。例如,如果我们以 5 的无限列表结束列表,那么它会处理列表直到那五个并继续寻找新值:

Prelude Data.List> map head (group (2 : 3 : 4 : 1 : 7 : 7 : 7 : 3 : 4 : 1 : 1 : 1 : 3 : repeat 5))
[2,3,4,1,7,3,4,1,3,5

或者我们可以利用 Data.List.NonEmptygroup :: (Foldable f, Eq a) => f a -> [NonEmpty a]:

import Data.List.NonEmpty(group)
import qualified Data.List.NonEmpty as NE

f :: Eq a => [a] -> [a]
f = map NE.head . group