Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use a state type for normalised points #10

Open
wrnrlr opened this issue May 11, 2023 · 0 comments
Open

Use a state type for normalised points #10

wrnrlr opened this issue May 11, 2023 · 0 comments

Comments

@wrnrlr
Copy link
Owner

wrnrlr commented May 11, 2023

Some operations are only sensible when the point in normalised and rust has a way of refining what methods can be called on a trait/struct based on some extra type info. Investigate and if possible implement the use of this "generic state type" for normalised points.

Example from https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=24c550bb3e2b129c38fff338017b49f4

struct Point<State>{
    x: f32,
    y: f32,
    _s: State
}

trait PointState {}

struct Normalized;
impl PointState for Normalized{}

struct PossiblyNormalized;
impl PointState for PossiblyNormalized{}

impl Point<PossiblyNormalized>{
    fn new(x: f32, y: f32) -> Self {
        Self {x, y, _s: PossiblyNormalized}
    }
}

// all Points can be added to
impl<State: PointState> Point<State> {
    // we can see from this function signature that adding a constant may break normalization
    fn add(&self, z: f32) -> Point<PossiblyNormalized> {
        Point {
            x: self.x + z,
            y: self.y + z,
            _s: PossiblyNormalized
        }
    }
    
    // any Point can be re-normalized and applied back, and we can encode that into the type system
    fn normalize(self) -> Point<Normalized>{
        let m = self.magnitude();
        Point {
            x: self.x/m,
            y: self.y/m,
            _s: Normalized
        }
    }
    fn magnitude(&self) -> f32 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

// this method will only apply to Points that are known to be Normalized
impl Point<Normalized>{
    fn print_normalized(&self){
        println!(" we know that this one has only normalized fields");
        // do stuff that depends on it being normalized
    }
}

fn main(){
    let p: Point<PossiblyNormalized> = Point::new(4.0, 5.0);
    // we can't call print_normalized yet
    
    let p: Point<Normalized> = p.normalize();
    p.print_normalized();
}

What methods besides normalize can benefit from this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant