If you want (or need to?) be generic over the outer Type
, you could use a functor, which I just implemented in the fmap
crate (see long thread here for the genesis).
[dependencies]
fmap = "0.1.0"
use fmap::Functor;
#[derive(Debug, Clone)]
pub struct Curve<T> {
pub x: Vec<T>,
pub y: Vec<T>,
}
impl<'a, A, B> Functor<'a, B> for Curve<A>
where
A: 'a,
B: 'a,
{
type Inner = A;
type Mapped<'b> = Curve<B>
where
'a: 'b;
fn fmap<'b, F>(self, f: F) -> Self::Mapped<'b>
where
'a: 'b,
F: 'b + Fn(Self::Inner) -> B,
{
Curve {
x: self.x.fmap(&f),
y: self.y.fmap(&f),
}
}
}
fn main() {
let vec_a: Vec<i32> = vec![10, 20, 30, 40];
let vec_b: Vec<f64> = vec_a.fmap(Into::into);
println!("{vec_b:?}");
let curve_a = Curve {
x: vec![1, 2, 3],
y: vec![4, 5, 6],
};
let curve_b: Curve<f64> = curve_a.fmap(Into::into);
println!("{curve_b:?}");
}
Output:
[10.0, 20.0, 30.0, 40.0]
Curve { x: [1.0, 2.0, 3.0], y: [4.0, 5.0, 6.0] }
However, this still doesn't implement From
on the outer type. You still have to use .fmap(Into::into)
on outer types, instead of just .into()
. But it is possible to be generic:
fn foo<'a, T, A, B>(curve_or_vec_or_other_functor: T) -> T
where
T: FunctorSelf<'a, A>,
A: 'a + Into<B>,
{
curve_or_vec_or_other_functor.fmap(Into::into)
}
P.S.: But I believe being that generic is non-idiomatic in Rust. Afterall, the standard library also provides all sort of .map
methods, which are unrelated (except sharing the same name).