Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to combine type constraints in Rust?

I've been working in quite a number of statically-typed programming languages (C++, Haskell, ...), but am relatively new to Rust.

I often end up writing code like this:

struct LeafNode<K: Ord + Default + Clone, V: Default + Clone> {
  keys: Vec<K>,
  values: Vec<V>,
}

impl <K: Ord + Default + Clone, V: Default + Clone> LeafNode<K, V> {
  // ...
}

There is a lot of repetition here in the type constraints. This is compounded further when LeafNode is used inside something else (say, when building a tree of nodes). Whenever one of these constraints changes during implementation, there are many places where the code needs to be altered as they are named in many of the different struct definitions and impl blocks.

Is there a way to create some kind of 'type constraint alias' from K: Ord + Default + Clone and V: Default + Clone?

If it exists, it probably has some name that I am not aware of, which makes searching for this technique very difficult. Hence this question.

like image 340
Qqwy Avatar asked Dec 16 '21 11:12

Qqwy


People also ask

Does Rust support generic types?

Because Rust compiles generic code into code that specifies the type in each instance, we pay no runtime cost for using generics.

What are generics Rust?

In Rust, generics refer to the parameterization of data types and traits. Generics allows to write more concise and clean code by reducing code duplication and providing type-safety. The concept of Generics can be applied to methods, functions, structures, enumerations, collections and traits.


2 Answers

You can accomplish this by making your own trait that takes the other traits as a bound, then add a blanket implementation for it:

trait MyConstraint: Ord + Default + Clone {}
impl <T: Ord + Default + Clone> MyConstraint for T {}

struct LeafNode<K: MyConstraint> {
    keys: Vec<K>
}

impl<K: MyConstraint> LeafNode<K> {
    fn keys(&self) -> &[K] {
        &self.keys
    }
}
like image 130
Aplet123 Avatar answered Oct 20 '22 12:10

Aplet123


As a complement answer.

You can use trait alias (currently unstable):

#![feature(trait_alias)]

trait MyConstraint = Ord + Default + Clone;

struct LeafNode<K: MyConstraint> {
    keys: Vec<K>
}

impl<K: MyConstraint> LeafNode<K> {
    fn keys(&self) -> &[K] {
        &self.keys
    }
}

Playground

like image 38
Netwave Avatar answered Oct 20 '22 13:10

Netwave