如何实现返回具有匹配类型参数的通用值的工厂特征?

Pet*_*och 5 rust

请考虑以下代码(简化但可编译):

use std::sync::Arc;

pub trait ActorRef<Message> { /* ... */ }
pub trait Actor<Message> { /* ... */ }
pub trait ActorSpawner {
    /// Spawns a new actor returning an actor ref 
    /// for passing messages to it.
    fn spawn<Message,A,R>(actor: A) -> Arc<R>
        where R: ActorRef<Message>, A: Actor<Message>;
}
Run Code Online (Sandbox Code Playgroud)

是否可以实现ActorSpawner::spawn或实现与其他签名类似的东西?

这个想法

问题中的代码被简化以将其减少到我无法解决的核心部分.

通常,Actor应该具有由处理消息改变的可变状态(示例中缺少处理方法).您可以生成一个Actor并可以通过它与它通信ActorRef(示例中缺少send方法).

我想允许不同的"产卵"方式Actor.例如,消息处理可能发生在每个actor的一个线程上.或者可以在由其他actor共享的线程池上完成处理.

其他代码可能依赖于创建更多actor.使用的基础机制应该是抽象的.既然有特质ActorSpawner.

我试图解决它

让我们假设我们有一些虚拟实现ActorActorRef:

struct NoopActor;
impl<Message> Actor<Message> for NoopActor {}

struct DeadRef;
impl<Message> ActorRef<Message> for DeadRef {}
Run Code Online (Sandbox Code Playgroud)

现在应该可以使用这些虚拟实现以某种方式实现特征.

这是我的第一次尝试:

struct DeadActorSpawner;
impl ActorSpawner for DeadActorSpawner {
    fn spawn<Message,A,R>(actor: A) -> Arc<R>
        where R: ActorRef<Message>, A: Actor<Message> 
    {
        Arc::new(DeadRef)
    }
}
Run Code Online (Sandbox Code Playgroud)

导致此错误:

error[E0308]: mismatched types
  --> src/main.rs:29:18
   |
29 |         Arc::new(DeadRef)
   |                  ^^^^^^^ expected type parameter, found struct `DeadRef`
   |
   = note: expected type `R`
              found type `DeadRef`
Run Code Online (Sandbox Code Playgroud)

或另一个:

struct DeadActorSpawner;
impl ActorSpawner for DeadActorSpawner {
    fn spawn<Message,A,R>(actor: A) -> Arc<DeadRef>
    {
        Arc::new(DeadRef)
    }
}
Run Code Online (Sandbox Code Playgroud)

导致此错误:

error[E0053]: method `spawn` has an incompatible type for trait
  --> src/main.rs:25:42
   |
12 |     fn spawn<Message, A, R>(actor: A) -> Arc<R>
   |                                          ------ type in trait
...
25 |     fn spawn<Message, A, R>(actor: A) -> Arc<DeadRef> {
   |                                          ^^^^^^^^^^^^ expected type parameter, found struct `DeadRef`
   |
   = note: expected type `fn(A) -> std::sync::Arc<R>`
              found type `fn(A) -> std::sync::Arc<DeadRef>`
Run Code Online (Sandbox Code Playgroud)

我已经尝试了许多其他的东西无济于事,包括使用相关类型的Messagein ActorActorRef.

oli*_*obk 4

是否可以实施ActorSpawner::spawn

是的,但据我所知没有有用的实现

或者用另一个签名来实现类似的效果

我相信您正在等待Arc<ActorRef<Message>>返回。因此,您可以在不了解 * 类型的情况下使用DeadActorSpawnerthrough特征。ActorSpawnerDead

您实际上所做的是尝试专门化该spawn函数以返回Arc<DeadRef>. 我修改了你的ActorSpawner返回一个特征对象:

pub trait ActorSpawner {
    fn spawn<Message, A>(actor: A) -> Arc<ActorRef<Message>> where A: Actor<Message>;
}

struct DeadActorSpawner;
impl ActorSpawner for DeadActorSpawner {
    fn spawn<Message, A>(actor: A) -> Arc<ActorRef<Message>>
        where A: Actor<Message>
    {
        Arc::new(DeadRef)
    }
}
Run Code Online (Sandbox Code Playgroud)

游乐场示例