Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constraints on associated trait types

Here's a (somewhat contrived) example to illustrate what I would like to do

pub trait Node: Eq + Hash {
    type Edge: Edge;
    fn get_in_edges(&self)  -> Vec<&Self::Edge>;
    fn get_out_edges(&self) -> Vec<&Self::Edge>;
}

pub trait Edge {
    type Node: Node;
    fn get_src(&self) -> &Self::Node;
    fn get_dst(&self) -> &Self::Node;
}

pub trait Graph {
    type Node: Node;
    type Edge: Edge;
    fn get_nodes(&self) -> Vec<Self::Node>;
}

pub fn dfs<G: Graph>(root: &G::Node) {
    let mut stack = VecDeque::new();
    let mut visited = HashSet::new();

    stack.push_front(root);
    while let Some(n) = stack.pop_front() {
        if visited.contains(n) {
            continue
        }
        visited.insert(n);
        for e in n.get_out_edges() {
            stack.push_front(e.get_dst());
        }
    }
}

Is there a way to express in the Graph trait that Graph::Node must be the same type as Graph::Edge::Node and that Graph::Edge must be the same type as Graph::Node::Edge?

I remember reading something about a feature (not implemented at the time) that would allow richer constraints for this sort of thing, but I don't remember its name and cannot find it.

like image 589
ynimous Avatar asked Nov 04 '15 10:11

ynimous


People also ask

What is an associated Type?

What is an associated type? An associated type can be seen as a replacement of a specific type within a protocol definition. In other words: it's a placeholder name of a type to use until the protocol is adopted and the exact type is specified.

What are generic associated types?

GATs (generic associated types) were originally proposed in RFC 1598. As said before, they allow you to define type, lifetime, or const generics on associated types. If you're familiar with languages that have "higher-kinded types", then you could call GATs type constructors on traits.

What is a trait object?

A trait object is an opaque value of another type that implements a set of traits. The set of traits is made up of an object safe base trait plus any number of auto traits. Trait objects implement the base trait, its auto traits, and any supertraits of the base trait.

Where is trait rust?

A trait in Rust is a group of methods that are defined for a particular type. Traits are an abstract definition of shared behavior amongst different types. So, in a way, traits are to Rust what interfaces are to Java or abstract classes are to C++. A trait method is able to access other methods within that trait.


1 Answers

In Graph's definition, you can constrain each associated type's associated type (!) to be equal to the corresponding associated type in Graph.

pub trait Graph {
    type Node: Node<Edge = Self::Edge>;
    type Edge: Edge<Node = Self::Node>;
    fn get_nodes(&self) -> Vec<Self::Node>;
}
like image 174
Francis Gagné Avatar answered Oct 29 '22 13:10

Francis Gagné