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

时间:2015-06-10 08:33:22

标签: 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>;
}

是否可以实施ActorSpawner::spawn或实现与其他签名相似的内容?

想法

简化了问题中的代码,将其缩减为我无法解决的核心部分。

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

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

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

我试图解决它

我们假设我们为ActorActorRef设置了一些虚拟实现:

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

struct DeadRef;
impl<Message> ActorRef<Message> for DeadRef {}

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

这是我的第一次尝试:

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)
    }
}

导致此错误:

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`

或另一个:

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

导致此错误:

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>`

我尝试了许多其他方面无济于事,包括为MessageActor中的ActorRef使用关联类型。

1 个答案:

答案 0 :(得分:4)

  

是否可以实施ActorSpawner::spawn

Yes,但我看来没有有用的实施

  

或用其他签名实现类似的东西

我相信你期待归还Arc<ActorRef<Message>>。因此,您可以在不知道DeadActorSpawner *类型的情况下使用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)
    }
}

Playground example