Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Rust, how to "add" `flatten" to Option<Option<T>>? [duplicate]

Tags:

generics

rust

How can I "add" a flatten() method to Option<U>, which would only typecheck if and only if U is an Option<T>, or more simply to add it to Option<Option<T>>? Naively, I am trying to write the following, which doesn't compile:

impl Option<Option<T>> {
    fn flatten(&self) -> Option<T> {
        match self {
            None => None,
            Some(v) => v,
        }
    }
}

fn main() {
    let x = Some(Some(1));
    let y = x.flatten();
    println!("{:?}", y);
}
like image 702
avernet Avatar asked Aug 28 '15 03:08

avernet


1 Answers

You can't write inherent implementations (what you're trying) to types you didn't define, due to coherence (if you could, how do you know someone else hasn't also defined something called flatten?).

Instead, you need to define and implement a trait with the method you want. Anywhere you want the method, you use the trait:

trait Flatten<T> {
    fn flatten(self) -> Option<T>;
}

impl<T> Flatten<T> for Option<Option<T>> {
    fn flatten(self) -> Option<T> {
        match self {
            None => None,
            Some(v) => v,
        }
    }
}

fn main() {
    let x = Some(Some(1));
    let y = x.flatten();
    println!("{:?}", y);
}

Also note that I changed the subject of the method from &self to self: you can't move out of a borrow (especially not an immutable one), so taking self by reference doesn't really make sense here.

like image 84
DK. Avatar answered Nov 15 '22 06:11

DK.