Open xkikeg opened 1 week ago
With GAT, we can almost use higher kinded type.
use std::fmt::Display; use core::fmt::Formatter; trait X { type Wrapped<T: AsRef<T>>: AsRef<T>; } struct Foo<T: X> { value: T::Wrapped<Bar>, } impl<T: X> Display for Foo<T> { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { write!(f, "Foo({:#?})", (self.value.as_ref())) } } #[derive(Debug)] struct Bar { value: i32, } struct IdentityX; impl X for IdentityX { type Wrapped<T: AsRef<T>> = T; } impl AsRef<Bar> for Bar { fn as_ref(&self) -> &Bar {&self } } struct TrackedX; struct Tracked<T>(T, usize); impl X for TrackedX { type Wrapped<T: AsRef<T>> = Tracked<T>; } impl<T> AsRef<T> for Tracked<T> { fn as_ref(&self) -> &T {&self.0 } } fn parse_foo(x: &str) -> Foo<TrackedX> { Foo { value: Tracked(parse_bar(x), 0), } } fn parse_bar(x: &str) -> Bar { let x: i32 = x.parse().unwrap(); Bar { value: x } } fn main() { let wrapped = parse_foo("23"); println!("{}", wrapped); let naked: Foo<IdentityX> = Foo{value: Bar{value: 34}}; println!("{}", naked); }
With GAT, we can almost use higher kinded type.