@aud To be a little more precise, a function like `void foo(Bar bar)` and one like `fn foo<T: Bar>(bar: T) -> ()` are morally quite similar, if extremely different in literal meaning. They're both ways of saying "this function takes a value of any type that's Bar-like," but the former *also* adds that any individual value of a Bar-like type can be referred to by a binding of type Bar.
That's a very heavy additional assumption, and places severe constraints on how you organize code.
@aud So you can solve that with `T add<T>(T a, T b)`, but now you've lost the `Addable` constraint. The most common solution I've seen is to have `T add<T: Addable>(T a, T b)`.
But there's a word for "a collection of types that can be used to satisfy a constraint on valid type parameters." It's a typeclass, or in Rust terminology, a trait. Or in C++ terminology, a concept.