无法通过succesor函数在Kotlin中创建Ints序列。称“类型推断失败”

时间:2018-01-21 19:00:13

标签: lambda kotlin sequence peano-numbers

我正在尝试通过generateSequence函数从数字0和后继函数S创建一个自然数的流/序列。

这就是我所拥有的:

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()的参数太多。

我尝试过的其他事情是将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))
}

也不起作用。最后一个函数得到了编译消息“Unexpected type specification”和“Unexpected tokens”(使用';'来分隔同一行上的表达式。)

有什么方法可以解决这个问题,以便println函数打印出前10个自然数,并仍使用后继类?

1 个答案:

答案 0 :(得分:2)

您的代码中实际调用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
}

所以最后你的代码看起来就像你的例子。