我有两个基本等效的特质,但其中一个提供比另一个更低级别的接口。通过使用更高级别的特质,可以轻松实现更低级别的特质。我想编写一个库,该库接受任意一种特质的实现。
我的具体情况是用于遍历树的特质:
// "Lower level" version of the trait
pub trait RawState {
type Cost: std::cmp::Ord + std::ops::Add<Output = Self::Cost> + std::marker::Copy;
type CulledChildrenIterator: Iterator<Item = (Self, Self::Cost)>;
fn cull(&self) -> Option<Self::Cost>;
fn children_with_cull(&self) -> Self::CulledChildrenIterator;
}
// "Higher level" version of the trait
pub trait State: RawState {
type ChildrenIterator: Iterator<Item = (Self, Self::Cost)>;
fn children(&self) -> Self::ChildrenIterator;
}
// Example of how RawState could be implemented using State
fn state_children_with_cull<S: State> (s: S)
-> impl Iterator<Item = (S, S::Cost)>
{
s.children()
.filter_map(move |(state, transition_cost)|
state.cull().map(move |emission_cost|
(state, transition_cost + emission_cost)
)
)
}
在这里,State trait提供了一个接口,你需要定义.children()函数来列出子节点和.cull()函数以潜在地裁减状态。
RawState trait提供了一个接口,你需要定义一个函数.children_with_cull(),它会在单个函数调用中遍历子节点并剔除其中被裁减的节点。这使得RawState的实现可以避免生成已知将被剔除的子节点。
我希望大多数用户只需实现State trait,而RawState的实现则根据他们的State实现自动生成。然而,在实现State时,trait的某些部分仍是RawState的一部分,例如:
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
struct DummyState {}
impl State for DummyState {
type Cost = u32;
type ChildrenIterator = DummyIt;
fn emission(&self) -> Option<Self::Cost> {
Some(0u32)
}
fn children(&self) -> DummyIt {
return DummyIt {};
}
}
由于类型“Cost”是在RawState中定义的而不是在State中定义的,因此会出现错误。一个潜在的解决方法是重新定义State内涉及到的所有相关部分的RawState,即将State定义为
pub trait State: RawState {
type Cost: std::cmp::Ord + std::ops::Add<Output = Self::Cost> + std::marker::Copy;
type ChildrenIterator: Iterator<Item = (Self, Self::Cost)>;
fn cull(&self) -> Option<Self::Cost>;
fn children(&self) -> Self::ChildrenIterator;
}
但是,编译器会抱怨关于模糊的重复定义。例如,在State
实现中的DummyState
,它会抱怨Self::Cost
是不明确的,因为它无法确定您是指<Self as State>::Cost
还是<Self as RawState>::Cost
。
children_with_cull
的默认实现的特质吗? - trentRawState
的类型仍然必须实现children
,即使children
没有被直接使用。 - Francis Gagné