Невозможно создать последовательность Ints в Kotlin через функцию succesor. Говорит "Ошибка вывода типа"

Я пытаюсь создать поток / последовательность натуральных чисел из числа 0 и функции-преемника S через функцию generateSequence.

Вот что у меня есть:

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())
}

Я знаю, что это может показаться не лучшим способом решения этой проблемы, поскольку уже есть операторы инкремента и что уже есть ярлык для генерации первых n натуральных чисел, но я хочу, чтобы S был классом или, по крайней мере, объектом для некоторые другие причины позже.

Когда я его компилирую, я получаю следующие сообщения:

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)

а также

Слишком много аргументов для открытого конструктора S(), определенного в core.

Другие вещи, которые я пробовал, переписывает S как

class S: Function<Int> {
    operator fun invoke(x: Int) = x + 1
}

или изменив функцию generateSequence на

fun sequenceOfNumbers(start: Int): Sequence<Int> {
    return generateSequence(seed = start, nextFunction = (x: Int) -> S(x))
}

что тоже не сработало. Последняя функция получила сообщения компиляции "Неожиданная спецификация типа" и "Неожиданные токены (используйте ';' для разделения выражений в одной строке").

Любой способ решить это так, чтобы println Функция выводит первые 10 натуральных чисел и все еще использует класс преемника?

1 ответ

Решение

Проблема в вашем коде, что вы на самом деле вызываете конструктор S, скорее, чем invoke(), Вы должны перейти на следующее, чтобы это работало:

return generateSequence(0){x -> S()(x)}

Конечно, будет лучше, если вы храните S в локальной переменной и повторно использовать его в генераторе последовательности:

fun sequenceOfNumbers(): Sequence<Int> {
    val s = S()
    return generateSequence(0){x -> s(x)} //generateSequence(0, s::invoke)
}

Или даже лучше сделать S синглтон:

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
}

В итоге ваш код будет выглядеть так, как в вашем примере.

Другие вопросы по тегам