Generics 不带类型参数的泛型类型上的泛型结构
有可能在生锈的地方做这样的事情吗Generics 不带类型参数的泛型类型上的泛型结构,generics,rust,higher-kinded-types,Generics,Rust,Higher Kinded Types,有可能在生锈的地方做这样的事情吗 trait Foo<T> {} struct A; struct B; struct Bar<T: Foo> { a: T<A>, b: T<B> } trait Foo{} 结构A; 结构B; 结构条{ a:T, b:T } 我知道我可以使用两个参数来设置Bar,但我认为必须有更好的方法来实现这一点 我想实现一个图结构。因为我不能只将节点和边绑定到它们的父生命周期,所以我想要类似于Rc的东
trait Foo<T> {}
struct A;
struct B;
struct Bar<T: Foo> {
a: T<A>,
b: T<B>
}
trait Foo{}
结构A;
结构B;
结构条{
a:T,
b:T
}
我知道我可以使用两个参数来设置Bar
,但我认为必须有更好的方法来实现这一点
我想实现一个图
结构。因为我不能只将节点和边绑定到它们的父生命周期,所以我想要类似于Rc
的东西。但是,有时可能需要一个具有多线程访问权限的图。因此,我必须同时使用Rc
和Arc
实现
这就是Foo
的好处:我为Rc
和Arc
实现Foo
(Foo
需要Deref
),并使用绑定到Foo
的参数T
。这就是我希望单线程和多线程使用一个结构的原因。⇒ 这是目前无法在Rust的类型系统中表达的☹
幸运的是,由于中提出的“泛型关联类型”,这将在将来成为可能。您可以跟踪中的实施和稳定状态
这里的重要术语是“HKT”(higherkindedtypes)。这是尚未在Rust中实现的类型系统的一个特性。Haskell提供HKTs。在C++世界中,HTTS被称为“模板模板”。上述泛型关联类型也是HKTs的一种形式
但什么是HKT,真的?
让我们慢慢开始:我们所知道的简单类型是什么?让我们列出一些类型:i32
,bool
,String
。这些都是类型。。。您可以有这些类型的值(变量)。那Vec呢?这也是一个简单的类型!您可以使用Vec
类型的变量,没问题
我们想把这些类型组合在一起;我们称这种分类为“一种类型”。如果我们想以一种非常抽象的方式谈论(关于类型的类型),我们可以选择其他的词,在本例中是kind。甚至还有各种类型的符号。对于上面的简单类型,我们说:这些类型的类型是
*
是的,只是一颗星星,很简单。这个符号以后会更有意义
让我们搜索与简单类型不同的类型<代码>互斥体
?不,它可能相当复杂,但它仍然是一种*
,我们仍然可以有这种类型的变量
那Vec呢?是的,我们省略了尖括号。是的,这确实是另一种类型!我们可以有一个Vec
类型的变量吗?不什么向量
这类捐款的形式如下:
* -> *
这只是说:给我一个普通类型(*
),我会返回一个普通类型!给这个东西(Vec
)一个普通类型i32
),它将返回一个普通类型Vec
!它也称为类型构造函数,因为它用于构造类型。我们甚至可以更进一步:
* -> * -> *
这有点奇怪,因为它与非Haskell程序员有关,读起来很奇怪。但这意味着:给我两种类型,我将返回一种类型。让我们考虑一个例子<代码>结果!Result
类型构造函数将返回一个具体的类型结果。在某种程度上,Rust确实有一个看起来很像HKT的东西(请参阅Lukas的答案,了解它们是什么),尽管有一些可以说是笨拙的语法
首先,您需要为所需的指针类型定义接口,这可以使用泛型特征来完成。例如:
trait SharedPointer<T>: Clone {
fn new(v: T) -> Self;
// more, eg: fn get(&self) -> &T;
}
最后,我们可以使用它:
struct A;
struct B;
struct Foo<P: Param<A> + Param<B>> {
a: <P as Param<A>>::Pointer,
b: <P as Param<B>>::Pointer,
}
impl<P: Param<A> + Param<B>> Foo<P> {
fn new(a: A, b: B) -> Foo<P> {
Foo {
a: <P as Param<A>>::Pointer::new(a),
b: <P as Param<B>>::Pointer::new(b),
}
}
}
fn main() {
// Look ma, we're using a generic smart pointer type!
let foo = Foo::<RcParam>::new(A, B);
let afoo = Foo::<ArcParam>::new(A, B);
}
结构A;
结构B;
struct Foothanks回答了这么长的问题!非常有趣。只有
的
语法对我来说似乎有点混乱,但我肯定会阅读关于itThanks的章节。很好地解释了这个问题。我认为真正的力量来自相关类型的类型省略。
trait SharedPointer<T>: Clone {
fn new(v: T) -> Self;
// more, eg: fn get(&self) -> &T;
}
trait Param<T> {
type Pointer: SharedPointer<T>;
}
impl<T> SharedPointer<T> for Rc<T> {
fn new(v: T) -> Self {
Rc::new(v)
}
}
impl<T> SharedPointer<T> for Arc<T> {
fn new(v: T) -> Self {
Arc::new(v)
}
}
struct RcParam;
struct ArcParam;
impl<T> Param<T> for RcParam {
type Pointer = Rc<T>;
}
impl<T> Param<T> for ArcParam {
type Pointer = Arc<T>;
}
struct A;
struct B;
struct Foo<P: Param<A> + Param<B>> {
a: <P as Param<A>>::Pointer,
b: <P as Param<B>>::Pointer,
}
impl<P: Param<A> + Param<B>> Foo<P> {
fn new(a: A, b: B) -> Foo<P> {
Foo {
a: <P as Param<A>>::Pointer::new(a),
b: <P as Param<B>>::Pointer::new(b),
}
}
}
fn main() {
// Look ma, we're using a generic smart pointer type!
let foo = Foo::<RcParam>::new(A, B);
let afoo = Foo::<ArcParam>::new(A, B);
}