Kotlin中的高阶(或递归?)泛型类型参数

8
我正在原型化一些高度声明性的代码, Kotlin 提供的类型推断和类型安全帮助了很多。其中一个目标是使主要类型的扩展(子类)容易实现。为了保持丰富的类型推断和表达性,我发现通过针对子类定义泛型扩展函数可以取得一定的成功。所有子类方法的类型信息都没有额外的子类实现,这太棒了。
因此,我试图编写一个保留尽可能多类型信息的丰富泛型函数。问题在于这个函数操作潜在递归的泛型类型,并且我想重新排列泛型类型参数。
如果没有示例,这将是不可能描述的。所以考虑以下内容:
open class G<in T>
class A<in T> : G<T>()
class B<in T> : G<T>()
class C<in T> : G<T>()
val ba = B<A<*>>()
val cb = C<B<*>>()

我们希望有一个通用的函数能够有效地实现这个功能。
fun B<A<*>>.doTransitiveThing(c: C<B<*>>) : C<A<*>>
{
    // implement
}

val ca = ba.doTransitiveThing(cb) // Returns C<A<*>>

目标标准:

  • C为参数并返回C,但泛型类型参数不同
  • 我想将此行为概括为G的所有子类的扩展函数
    • 它必须是扩展函数,这样使用泛型类型时我们可以拥有子类的类型,并确保参数具有接收器类型的泛型类型参数。
    • 换句话说,我们希望为G的子类编写一个扩展函数,因此在调用时,参数必须是C<B<*>>而不是C<G<*>>

这描述了问题的要点。我不确定语言是否支持我想要的,也不确定类型擦除是否是不可能实现的因素,但迄今为止我找不到这个因素(如果是这样,也许我需要帮助)。


以下内容接近题意:

fun <
    TargetGenericType, 
    Arg1Type: G<*>, 
    ReceiverType: G<TargetGenericType>, 
    Arg2Type: G<Arg1Type>, 
    ResultType: G<TargetGenericType>
    >
    ReceiverType.doTransitiveThingGeneric(x: Arg2Type): ResultType
{
    //implement
}
val ca2 = ba.doTransitiveThingGeneric(cb)

但是还有一些问题

  • 它返回G<A<*>>而不是C<A<*>>。如果它能返回C并且不丢失类型信息的话,那就太好了(否则我其实也没用这个函数)
  • 技术上讲,ReceiverType不一定是Arg1Type

往前想,如果以下类似的代码在Kotlin中是有效的,我认为它可以解决我的问题

fun <
    TargetGenericType,
    ReceiverBaseType<T>: G<T>,
    typealias ReceiverType = ReceiverBaseType<TargetGenericType>,
    ParamBaseType<U>: G<U>,
    typealias ParamType = ParamBaseType<ReceiverBaseType<*>>,
    ResultType: ParamBaseType<TargetGenericType>
    >
    ReceiverType.doTransitiveThingHigherOrderGeneric(x: ParamType): ResultType
{
    //implement
}

有没有不行的理由?例如,将它作为语言功能添加进去?我很同情物流原因反对的观点,但我很好奇在原则上是否可能。
最后注意事项: - 这让我想起了类型别名,除了通用类型参数本身。实际上,我在示例中包含了该关键字,以帮助消化。不过,这不是唯一部分,请注意语法中的 和 。 - 它几乎让我想起单子,只不过是针对类定义本身,如果这在一种手势摇摆、直观的方式下有意义的话。 - 我还不知道如何实现主体,但我还没有那么远,因为我仍然在尝试看看签名是否可能:p

你尝试过在 Kotlin 中使用具体化的泛型吗?inline fun <reified T> B<A<T>>.doTransitiveThing(c: C<B<T>>) : C<A<T>> - Just another metaprogrammer
1个回答

1

我最终追寻的是更高级别的类型。我试图将所有内容都强行塞进一个过于嵌套的类型构造器中。我想要完成的操作无法通过这种方式实现,必须使用多个类型参数来完成。函数库Arrow关于更高级别类型的描述帮助我认识到了这一点。

在形状为Kind<F, A>的更高级别类型中,如果A是内容的类型,则F必须是容器的类型。

畸形的更高级别类型会使用整个类型构造器来定义容器,重复内容的类型Kind<Option<A>, A>。这种不正确的表示在处理部分应用类型和嵌套类型时有大量问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接