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

Wor*_*der 8 generics nested-generics kotlin

我正在对一些高度声明性的代码进行原型设计,而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<*>>()
Run Code Online (Sandbox Code Playgroud)

我们想要一个能够有效地执行此操作的功能,除了一般情况

fun B<A<*>>.doTransitiveThing(c: C<B<*>>) : C<A<*>>
{
    // implement
}

val ca = ba.doTransitiveThing(cb) // Returns C<A<*>>
Run Code Online (Sandbox Code Playgroud)

目标标准:

  • 注意到C作为PARAM并返回C,除了与不同一般类型参数
  • 我想将此行为概括为所有子类的扩展函数 G
    • 它需要是一个扩展函数,以便使用泛型类型,我们可以拥有子类的类型,并确保参数具有接收器类型的泛型类型参数.
    • 或者换句话说,我们想要一个子类的扩展函数,G因此参数必须C<B<*>>代替C<G<*>>调用时B<A<*>>

这描述了问题的要点.我不确定这种语言是否能够支持我想要的东西.我不确定类型擦除是否是导致这种情况不可能的因素,但到目前为止我无法找到它(如果是这样的话,也许我可以使用帮助).


以下是关闭

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

但是有一些问题

  • 它返回G<A<*>>而不是C<A<*>>.如果它可以返回C并且不丢失类型信息将是很好的(否则我无论如何我都没有真正使用此功能)
  • 目前在技术上不能保证ReceiverTypeArg1Type

提前考虑,如果像以下这样的东西是有效的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
}
Run Code Online (Sandbox Code Playgroud)

有没有理由不能这样做?例如,添加为语言的功能?我很同情后勤原因,但我很好奇原则上是否可行.

最后说明:

  • 它让我想起除了泛型类型参数本身之外的类型别名.事实上,我已经在示例中包含了该关键字,以防它有助于消化.这不是唯一的部分,通知<T><U>语法.
  • 它几乎让我想起了莫纳德,除了类定义本身,如果这有点像手工波浪,直观的方式.
  • 我还不知道如何实现这个身体,但我还没有那么远,因为我还在试着看看签名是否可能:p

Wor*_*der 1

最终我所寻找的是更高级的种类。我试图将其全部强制放入一个过度嵌套的类型构造函数中。我想要完成的操作无法以这种方式实现,必须使用多个类型参数来完成。函数库Arrow 对高级类型的描述帮助我认识到了这一点。

在具有 shape 的高级类型中Kind<F, A>,如果A是内容的类型,则F必须是容器的类型。

格式错误的 High Kind 会使用整个类型构造函数来定义容器,从而复制内容的类型Kind<Option<A>, A>。在处理部分应用类型和嵌套类型时,这种不正确的表示会带来很多问题。