Hi, is this behaviour a known bug? Or is this supp...
# announcements
j
Hi, is this behaviour a known bug? Or is this supposed to happen?
Copy code
generateSequence(0) { it + 1 }.take(100000).fold(emptySequence<Int>()) { acc, v ->
        acc + v
      }.first() => stackoverflows
Also this works fine:
Copy code
generateSequence(0) { it + 1 }.take(100000).fold(emptySequence<Int>()) { acc, v ->
        sequenceOf(v) + acc
      }.first() => works fine
👍🏼 1
k
this is to be expected. to get the first value it has to get the first value for the last addition, which gets the first value of the second addition, which gets the value for the third addition ... all the way to the first addition. Each of these is a function call, causing he stack to overflow.
What are you trying to do exactly?
j
By that reason it sounds like the stackoverflow should be coming from
fold
but that is not the case:
Copy code
generateSequence(0) { it + 1 }.take(100000).fold(0) { acc, v ->
        acc + v
      }.also(::println) => 704982704
This works fine. The problem is that
fun Sequence<A>.plus(a: A): Sequence<A>
blows the stack when the resulting sequence is forced (at least with the example above)
What are you trying to do exactly?
Nothing in particular, just investigating a stackoverflow someone had with arrow a while back which turned out to be a more general problem
k
no it does not come from fold. The step in fold just makes a new sequence which will first itererate through acc and then return v. but the
hasNext()
function on the iterator, will have to check the
hasNext()
of the previous addition, which whill also call `hasNext()`etc, etc.
A fold is just the wrong operator here
j
So why doesn't this fail on the other example with
fun Sequence<A>.plus(a: Sequence<A>): Sequence<A>
? Also this sounds like something that can be avoided, not sure how tho
k
do you mean
fold(0) { acc, v ->acc + v}
?
j
The second example from the original message:
Copy code
generateSequence(0) { it + 1 }.take(100000).fold(emptySequence<Int>()) { acc, v ->
        sequenceOf(v) + acc
      }.first() => works fine
k
oh because it will get the value of the last addition
calling
last()
will cause a stackoverflow
j
.last()
doesn't instantly crash with a soe either, it just takes ages
k
soe
?
j
stackoverflowerror
k
oh it doesn't crash?
Oh right i see
j
who knows ^-^ It runs for far too long to tell
k
It might actually still happen
j
Likely, I'll let it run for a while and let you know when/if it finishes
Btw it finally crashed a few minutes ago. Overflow as expected. Sucks, but you explained pretty well why that happens thanks 👍 I still think this should somehow be avoidable, but 🤷 For the problem in arrow, there is no good solution, I am pretty sure we need the fold there, unless
Sequence
offers a similar method like
traverse
which I highly doubt as that's a very arrow specific method
k
I am pretty sure we need the fold there
Well the first case you is a nop that crashes if that crashes if the input is too big.
I'll have a look at traverse
❤️ 1
j
Sec
That is the fixed variant for sequenceK.
If you have questions about any of it just ask, there are some confusing things in there if you are not familiar with
Applicatives
k
this feels like a scan
j
It is very similar
Just more general afaik
The end result depends heavily on the applicative instance you use. For example with
Either<E, A>
you can short circuit the when you encounter a
Left(e: E)
. Different datatypes result in very different behaviour. It is a very useful combinator to have
k
Also if it "evaluate the sequence", then why is internally using sequences?
j
Only to match the resulting type, ideally this would not even evaluate a sequence (will change that tomorrow)
This function implements https://github.com/arrow-kt/arrow/blob/master/modules/core/arrow-core-data/src/main/kotlin/arrow/typeclasses/Traverse.kt which is much more general. So yeah, the inner sequence is literally just to match the type