2015-11-18 11 views
9

次のサンプルプログラムでは、map2を定義することを避ける方法はありますか?また、Haskellのを話す人々のため2つのオプションを「結合」する方法はありますか?

fn map2<T, U, V, F: Fn(T, U) -> V>(f: F, a: Option<T>, b: Option<U>) -> Option<V> { 
    match a { 
     Some(x) => match b { 
      Some(y) => Some(f(x, y)), 
      None => None, 
     }, 
     None => None, 
    } 
} 

fn main() { 
    let a = Some(5); 
    let b = Some(10); 
    let f = |a, b| { 
     a + b 
    }; 
    let res = map2(f, a, b); 
    println!("{:?}", res); 
    // prints Some(15) 
} 

、私は、この質問はまた言うこともできたと思います「私たちはルーストにliftM2の代わりに使用することができます任意のツールはありますか?」

答えて

12

私はliftM2への直接同等の機能があります信じていませんが、あなたは、このようなOption::and_thenOption::mapを組み合わせることができます。

fn main() { 
    let a = Some(5); 
    let b = Some(10); 
    let f = |a, b| { 
     a + b 
    }; 

    println!("{:?}", a.and_then(|a| b.map(|b| f(a, b)))); 
} 

出力:あなたはOptionという事実を使用することができます

Some(15) 
+0

おかげで、それは実際にあなただけ必要なときのためにかなり良い解決策ですこれを1回または2回行う。しかし、場合によっては関数を定義する価値があるかもしれません。 –

4

sは繰り返し処理できます。両方のオプションを繰り返し処理し、それらを一緒に圧縮し、結果のイテレータを関数にマップします。

fn main() { 
    let a = Some(5); 
    let b = Some(10); 
    let f = |(a, b)| { 
     a + b 
    }; 
    let res = a.iter().zip(b.iter()).map(f).next(); 
    println!("{:?}", res); 
    // prints Some(15) 
} 

これはfの変更を必要とするので、引数は単一のタプル引数にマージされています。 |args| f.call(args)を直接マッピングしてfを変更しなくても可能ですが、specify the closure kind of fにする必要があります。

+0

代替: 'map(|(a、b)| f(a、b))' – sellibitze

+0

はい、私は関数呼び出しを繰り返さないようにしようとしていました。あなたがそれを繰り返すなら、@ Dogbertの解決策が良いです。 –

2

あなたは1行に降りることができるかどうかは分かりませんが、あなたはタプルにマッチングすることにより、ネストされたmatchを避けることができます。

let a = Some(5); 
let b = Some(10); 
let f = |a, b| { 
    a + b 
}; 
let res = match (a, b) { 
    (Some(a), Some(b)) => Some(f(a, b)), 
    _ => None, 
}; 
println!("{:?}", res); 
// prints Some(15) 
関連する問題