Функция подъема к опции - PullRequest
       37

Функция подъема к опции

0 голосов
/ 05 августа 2020

Есть ли способ поднять простую функцию, например эту

fn add(a:i32, b:i32) -> i32 {a+b}

, для работы с Option (или любым другим типом монади c), аналогично тому, как можно было бы использовать Applicative in Haskell

Мне известно об этом решении:

pub fn add(a: Option<i32>, b: Option<i32>) -> Option<i32> {
  Some(a? + b?)
}

, но для этого мне нужно написать отдельную функцию, которая тесно связана с Option, тогда как то, что я want - иметь возможность поднять произвольную функцию до произвольного типа монади c или каким-либо другим способом повторно использовать функции, работающие с простыми типами с аргументами и возвращаемыми значениями монади c типов

// something like this
let func = Option::lift2(add) //example, not working code                         

Я, очевидно, думаю Haskell, может быть, есть еще идиоматический c способ сделать это в Rust

1 Ответ

2 голосов
/ 05 августа 2020

Вы можете начать с этого:

fn lift<A, B, C>(f: impl Fn(A, B)->C) -> impl Fn(Option<A>, Option<B>)->Option<C> {
    move |oa, ob| {
        match (oa, ob) {
            (Some(a), Some(b)) => Some(f(a,b)),
            _ => None,
        }
    }
}

Или, чтобы сделать его короче:

fn lift<A, B, C>(f: impl Fn(A, B)->C) -> impl Fn(Option<A>, Option<B>)->Option<C> {
    move |a, b| Some(f(a?, b?))
}

Помните, что вам могут понадобиться похожие вещи для FnMut и FnOnce тоже.

Более того, приведенное выше все еще привязано к Option, а не к c над монади c вещам в целом, что довольно громоздко для моделирования в Rust (если возможно на все).

...