scalacheck: определить генератор для бесконечного потока с некоторой зависимостью от предыдущих элементов
Я пытаюсь определить Gen[Stream[A]]
для бесконечного (лениво оцененного) потока A
где каждый элемент A
может зависеть от предыдущих элементов.
В качестве минимального случая мы можем взять Gen[Stream[Int]]
где следующий элемент либо +1
или же +2
предыдущего элемента. Для справки вот реализация haskell:
increasingInts :: Gen [Int]
increasingInts = arbitrary >>= go
where
go seed = do
inc <- choose (1,2)
let next = seed + inc
rest <- go next
return (next : rest)
я пытался Gen.sequence
на Stream[Gen[A]]
но получил переполнение стека. Я также попытался определить Gen
с нуля, но конструктор gen
за Gen
является частным и работает с закрытыми методами / типами.
Эта попытка также дает переполнение стека.
def go(seed: Int): Gen[Stream[Int]] =
for {
inc <- Gen.choose(1, 2)
next = seed + inc
rest <- Gen.lzy(go(next))
} yield next #:: rest
val increasingInts: Gen[Stream[Int]] = go(0)
increasingInts(Gen.Parameters.default, Seed.random()).get foreach println
Так что я застрял. Есть идеи?
1 ответ
То, что вы хотите, может быть достигнуто с этим:
val increasingInts = {
val increments = Gen.choose(1, 2)
val initialSeed = 0
for {
stream <- Gen.infiniteStream(increments)
} yield stream.scanLeft(initialSeed)(_ + _)
}
.scanLeft
это как .foldLeft
но сохраняет промежуточные значения, что дает вам еще один Stream
,
Я писал о scanLeft
здесь: https://www.scalawilliam.com/most-important-streaming-abstraction/