xkikeg / okane

Plain text accounting software supporting ledger-cli format using Rust
MIT License
4 stars 0 forks source link

Tracked proposal #180

Open xkikeg opened 1 week ago

xkikeg commented 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);
}