我正在对一些高度声明性的代码进行原型设计,而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
的子类的扩展函数,所以当在B<A<*>>
上调用时,参数必须是C<B<*>>
而不是C<G<*>>
That describes the gist of the problem. 我'm not sure the language is capable of supporting what I want. I'我不确定类型擦除是否是一个使这不可能的因素,但到目前为止我找不到它(如果是这样的话,也许我可以使用帮助) .
以下是关闭
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>
. -
它几乎让我想起了莫纳德,除了类定义本身,如果这有点像手工波浪,直观的方式 .
-
我还不知道如何实现这个身体,但是我仍然试图看看签名是否可能:p
1 回答
最终我要找的是higher kinds . 我试图将它全部强制为一个过度嵌套的类型构造函数 . 我想要实现的操作无法以这种方式实现,必须使用多个类型参数来完成 . 功能库Arrow's description of higher kinds让我意识到了这一点 .