#haskell #filter #sequence
#haskell #Фильтр #последовательность
Вопрос:
Это функция, которая создает бесконечный список случайных чисел
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,..]
Итак, мне нужна какая-нибудь элегантная функция «f» из [Int] -> [Int], которая это делает. Кроме того, он должен работать с бесконечным списком лениво, поэтому, если я запускаю
f values
он не должен зависать и выводить данные в режиме реального времени
Комментарии:
1.
f = map head . group
2. Ваше выражение для
values
может быть упрощено доrandomRs (1,10) (mkStdGen 1)
Ответ №1:
Вы можете работать с 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
s, то он обрабатывает список до этих пяти и продолжает искать новое значение:
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
или мы можем воспользоваться group :: (Foldable f, Eq a) => f a -> [NonEmpty a]
Data.List.NonEmpty
:
import Data.List.NonEmpty(group)
import qualified Data.List.NonEmpty as NE
f :: Eq a => [a] -> [a]
f = map NE.head . group
Комментарии:
1. в целом безопасный способ сделать то же
map head
самое , что и естьconcatMap (take 1)
.2. @WillNess: но здесь мы знаем, что подсписки не будут пустыми, есть вариант
group
, который генерируетNonEmpty
s…3. ну, технически, я не сказал «технически». 🙂