The error associated type defaults are unstable
states that it is unstable to assign a default type to associated types on a trait, but you can still add associated traits without default values. So just... don't. Even if you add a default, it won't stop someone from not following your vector length requirements and changing the types upon implementing the trait.
After some tinkering here is what I came up with. I ended up shortening StateVector
to States
since the long name was almost as bad as the original. Plus who knows, maybe I want to try implementing your trait for my type using std::collections::LinkedList<f64>
to hold my data.
pub trait Cost<const NUM_STATES: usize, const NUM_CONTROLS: usize> {
type States;
type Controls;
fn stage_cost(&self, x: &Self::States, u: &Self::Controls) -> f64;
fn stage_grad(
&self,
x: &Self::States,
u: &Self::Controls,
grad_x: &mut Self::States,
grad_u: &mut Self::Controls,
);
fn terminal_cost(&self, x: &Self::States) -> f64;
fn terminal_grad(&self, x: &Self::States, grad: &mut Self::States);
}
But then again, if we are changing the trait signature, why not skip the constants?
pub trait Cost<States, Controls> {
fn stage_cost(&self, x: &States, u: &Controls) -> f64;
fn stage_grad(&self, x: &States, u: &Controls, grad_x: &mut States, grad_u: &mut Controls);
fn terminal_cost(&self, x: &States) -> f64;
fn terminal_grad(&self, x: &States, grad: &mut States);
}
However, this does come at the cost of making usages of this trait longer.
// Example usage of origional
where A: Cost<S, C>,
// First suggestion
where B: Costs<S, C, States=SVector<f64, S>, Controls=SVector<f64, C>>,
// Second suggestion
where C: Costs<SVector<f64, S>, SVector<f64, C>>,
It may be best to leave your original as-is. That being said, one change I would make would be to import use nalgebra::SVector
so you can remove the na::
prefixes for the vectors.