我实现了一个TList
,可以收集任何类型的H
。但我发现它不能包含更高订单类型H[_]
。所以我拷贝了整个东西,并把[_]
添加到尊重的地方。如何抽象类型类型?
虽然出现在我的脑海里。如果我需要存储H[_[_]]
,H[_[_,_]]
甚至H[_[_[_]]]
,该怎么办?我应该随时复制代码吗?有没有什么方法可以抽象出类型的好意?
我实现了一个TList
,可以收集任何类型的H
。但我发现它不能包含更高订单类型H[_]
。所以我拷贝了整个东西,并把[_]
添加到尊重的地方。如何抽象类型类型?
虽然出现在我的脑海里。如果我需要存储H[_[_]]
,H[_[_,_]]
甚至H[_[_[_]]]
,该怎么办?我应该随时复制代码吗?有没有什么方法可以抽象出类型的好意?
在Scala中没有rank-2多态性。它意味着方法(除此之外甚至不是多态的函数)除了具有通用量词的参数之外不能(除了方法级别的所有通用量化)。因此,我们可以有一个像
def f[A, B[_], C[_[_]]](x: A, y: B[A], z: C[B]) = ???
方法,但不喜欢(伪)
def f(x: [A] A, y: [A1, B[_]] B[A1], z: [B1[_], C[_[_]]] C[B1]) = ???
而且这意味着我们无法替代型构造到特定类型的预期的地方(实际上是一个类型构造函数B[_]
可以认为是[A] B[A]
,C[_[_]]]
,作为[B[_]] C[B]
或[[A] B[A]] C[B]
)。
但是为了让类型和类型构造函数看起来更加一致,你可以使用特征类型来包装一个类型构造函数。例如,你可以看看下面的编码(这是肯定罗嗦,你必须包装,拆开包装类型所有的时间):
trait Type
trait ConcreteType extends Type {
type T
}
trait TypeConstructor[U] extends Type {
type l[X <: U] <: ConcreteType
}
type Type0 = ConcreteType
type Type1 = TypeConstructor[Type0]
type Type2 = TypeConstructor[Type1]
type Type3 = TypeConstructor[Type2]
// type A = Int
type A = Type0 {type T = Int}
// type B[X] = List[X]
type B = Type1 {
type l[X <: Type0] = Type0 {type T = List[X#T]}
}
trait Functor[F[_]]
// type C[F[_]] = Functor[F]
type C = Type2 {
type l[F <: Type1] = Type0 {
type T = Functor[
({
type ll[X] = (F#l[Type0 {type T = X}])#T
})#ll
]
}
}
trait Generic[FF[_[_]]] // like shapeless.Generic1, shapeless.IsHCons1, shapeless.IsCCons1
// Generic1[F[_], FR[_[_]]], IsHCons1[L[_], FH[_[_]], FT[_[_]]], IsCCons1[L[_], FH[_[_]], FT[_[_]]]
// Generic1[F, Functor], IsHCons1[L, Monad, Monad], IsCCons1[L, Applicative, Applicative]
// type D[FF[_[_]]] = Generic[FF]
type D = Type3 {
type l[FF <: Type2] = Type0 {
type T = Generic[
({
type ll[F[_]] = (
FF#l[Type1 {
type l[X <: Type0] = Type0 {type T = F[X#T]}
}]
)#T
})#ll
]
}
}
import shapeless.{::, HNil}
type lst = A :: B :: C :: D :: HNil
一些链接:
https://wiki.haskell.org/Rank-N_types
https://en.wikibooks.org/wiki/Haskell/Polymorphism#Higher_rank_types
https://apocalisp.wordpress.com/2010/07/02/higher-rank-polymorphism-in-scala/
我习惯于这样的结构:'[X,U [_ <:X],H [Y <:X] <:U [Y ]]'。它看起来非常难看,特别是当它连续发生两次时 – ayvango
认为您正在寻找:https://underscore.io/blog/posts/2016/12/05/type-lambdas.html。你也可以展示你到目前为止? – pedromss
没什么特别的,就像正常的无形练习。尽管如此,类型lambdas仍然会键入类型。它允许'*,* - > *'到'* - > *'¸,但它无法编写容易同时接受'*','* - > *','* - > * - > *' – ayvango
不,但它有助于编写使用具有特定数量类型的类型的could。我所说的是,而不是重复执行改变你使用它的方式。你的一个片段'TList'和几个你想达到的例子会有所帮助。 – pedromss