Going generic

Wait, your data structures are not specific to i32 values at all! It is perfectly legitimate to have lists and stacks containing different types. Let's make them generic data structures that can do so.

Exercise 4.a: Generalize your implementation of List so that it takes a type parameter T and can hold value of as many different types as possible.

Tip: in the process you will face probably face a dilemma, either give up on some of the features and traits you have implemented in the past for i32 lists, or add trait bounds to restrict the list of types your lists can contain. It's up to you to decide what to do, as long as you understand the implications.

Exercise 4.b: Your lists are nice because they are uniform, each list can contain multiple values of the same type. In some cases is desirable to create non-uniform lists, containing values of different types. By using trait objects, create a new data structure that can contain values of different types, that all share a trait (e.g., Display, so that you can easily show what your lists contain).

Try filling your non-uniform lists with values of different types and verify that you can still pretty-print them to stdout with println!("{}", ...).

Now try to add a .len() method to your non-uniform lists. Can you?
How about a .min() method, analogous to the iterator consumer we have seen in class?

PS No! You don't need to implemented linked lists by hand in Rust, you have doubly-linked lists already available in the stdlib. Also, for most practical purposes, vectors are much better anyway.