I'm trying to implement a simple recursive structure in Rust where the type of data stored can change with each recursion. The change occurs from any function that is also part of the structure:
// Type of function can receive Operation::Change
type ChangeFunction<T, U> = fn(T) -> U;
// Recursive structure
enum Operation<T, U, F = ChangeFunction<T, U>>
where
F: Fn(T) -> U,
{
Cons(Vec<T>),
Change(F, Box<Operation<T, U>>),
}
// In each recursion if there are operations "Operation::Change", the return type change!
fn eval<T, U>(operation: &Operation<T, U, ChangeFunction<T, U>>) -> Vec<T>
where
std::vec::Vec<T>: std::iter::FromIterator<U>,
{
match operation {
Operation::Cons(vector) => *vector,
Operation::Change(a_function, recursion) => eval(&recursion)
.into_iter()
.map(a_function)
.collect::<Vec<T>>(),
}
}
fn main() {
// I define a function that will change my data
let a_map_funcion = |x| (1, x + 2);
// I define recursive enum with the function
let operation = Operation::Change(
a_map_funcion,
Box::new(Operation::Cons(vec![1, 2, 3])),
);
let result = eval(&operation);
println!("Result -> {:?}", result); // Expected [(1,3),(1,4),(1,5)]
}
I've finished Rust's book and I still can't come up with a solution to this kind of problem. In Haskell I solved it in an extremely simple way and without any drama using GADTs
:
data Operation a where
Cons :: [a] -> (Operation a)
Change :: (a -> b) -> (Operation a) -> (Operation b)
eval :: Operation a -> [a]
eval (Cons vector) = vector
eval (Change f recursion) = map f (eval recursion)
With that program I can do eval (Change (\x -> (1, x + 2)) (Cons [1, 2, 3]))
and effectively throw [(1,3),(1,4),(1,5)]
which is what I expected.
But I don't know if there will be an equivalent in Rust or I will have to face the problem with another approach.
Any light on the subject is going to be very grateful