我正在对一些高度声明性的代码进行原型设计,而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<*>>
而不是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)
但是有一些问题
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
}
有没有理由不能这样做?例如添加为语言的功能?我很同情后勤原因,但我很好奇原则上是否有可能。
最后的说明:
<T>
和<U>
。答案 0 :(得分:0)
最终我要找的是higher kinds。我试图将它全部强制为一个过度嵌套的类型构造函数。我想要实现的操作无法以这种方式实现,必须使用多个类型参数来完成。功能库Arrow's description of higher kinds帮助我意识到了这一点。
在形状为
Kind<F, A>
的较高种类中,如果A
是内容的类型,则F
必须是容器的类型。格式错误的Higher Kind将使用整个类型构造函数来定义容器,并复制内容
Kind<Option<A>, A>
的类型。在处理部分应用的类型和嵌套类型时,这种不正确的表示有很多问题。