I'm trying to create a stream/sequence of natural numbers from the number 0 and a successor function S, through the generateSequence function.
Here's what I've got:
package core
fun sequenceOfNumbers(): Sequence<Int> {
return generateSequence(0){x -> S(x)}
}
class S: (Int) -> Int {
override operator fun invoke(x: Int) = x + 1
}
fun main(args: Array<String>) {
println(sequenceOfNumbers().take(10).toList())
}
I am aware this may not seem like the best way to solve this, as there already are increment operators, and that there already is a shortcut for generating the first n natural numbers, but I want S to be a class or at least object for some other reasons later.
When I compile it I get the following messages:
Type inference failed: Cannot infer type parameter T in
fun <T : Any> generateSequence(
seed: T?,
nextFunction: (T) → T?
) : Sequence<T>
None of the following substitutions
(S?, (S) → S?)
(Int?, (Int) → Int?)
(Any?, (Any) → Any?)
can be applied to
(Int, (Int) → S)
and
Too many arguments for public constructor S() defined in core.
Other things I've tried is rewriting S as
class S: Function<Int> {
operator fun invoke(x: Int) = x + 1
}
or changing the generateSequence function to
fun sequenceOfNumbers(start: Int): Sequence<Int> {
return generateSequence(seed = start, nextFunction = (x: Int) -> S(x))
}
which didn't work either. Last function got the compile messages "Unexpected type specification" and "Unexpected tokens (use ';' to separate expressions on the same line".
Any way to solve this so that the println
function prints out the first 10 natural numbers, and still uses the successor class?
The problem in your code that your actually calling the constructor of S
, rather than invoke()
. You should change to following to make it work:
return generateSequence(0){x -> S()(x)}
Of course it will be better, if you store S
in local variable and reuse it in sequence generator:
fun sequenceOfNumbers(): Sequence<Int> {
val s = S()
return generateSequence(0){x -> s(x)} //generateSequence(0, s::invoke)
}
Or even better to make S
singleton:
fun sequenceOfNumbers(): Sequence<Int> {
return generateSequence(0) { x -> S(x)} //generateSequence(0, S::invoke)
}
object S: (Int) -> Int {
override operator fun invoke(x: Int) = x + 1
}
So in the end your code will look like in your example.