2

すべてのタイプ(float-> float-> float-> float)であるF#の関数のリストがあります。すべての関数の合計を返す単一の関数を取得するために、シーケンスに対して何らかのフォールドを実行したいと思います。

たとえば、リスト内のすべての関数に値1.0、2.0、および3.0を渡し、それぞれから戻り値を取得できます。次に、これらすべての値の合計を計算できます。ただし、これを一般化したいと思います。

これを再帰的に行う方法は知っていますが、1行で実行できるはずだと思います。このタスクを実行するための簡潔な方法はありますか?

4

3 に答える 3

8

@Leeによる解決策は、あなたが探しているワンライナーです。数文字を保存したい場合は、List.sumBy最初に特定の関数をリストの要素に適用し(と同様List.map)、次に結果を合計する(と同様)を使用できますList.sum

let sumAll (fs:(_ -> _ -> _ -> float) list) a b c = 
  List.sumBy (fun f -> f a b c) fs

これとLeeのバージョンはどちらも、型アノテーションを使用して、リスト内の関数がを返すように指定していますfloat。これが必要なのは、そうでない場合、コンパイラは、使用して合計する数値の種類List.sum(浮動小数点数、整数など)を認識しないためです。関数をコンパイルするには、このあいまいさを解決する必要があります。

または、関数をとしてマークして、inline呼び出すときにインライン化することもできます(複数の異なる数値タイプで機能します)。fsパラメータを最後のパラメータとして渡し、部分機能アプリケーションを使用することもできます。

let inline sumAll a b c = List.sumBy (fun f -> f a b c)

これで、パイプラインを使用して次のように呼び出すことができます fs |> sumAll 1 2 3

于 2013-01-15T20:39:53.453 に答える
4
let sumAll (fs: (float -> float -> float -> float) list) a b c = List.map (fun f -> f a b c) fs |> Seq.sum
于 2013-01-15T20:13:40.697 に答える
4

@Leeと@Tomasの回答は素晴らしいですが、もっと短い方法があります。

(a, b, c)呼び出し時にトリプルとして渡す余裕がある場合:

let inline sumAll() = (|||>) >> List.sumBy
// usage
let predicates =
    [
        fun a b c -> a
        fun a b c -> b * 42.0 - c
    ]
let ret1 = predicates |> sumAll()(1.0, 2.0, 3.0)

また、一般的です:

let predicates2 =
    [
        fun a b c -> c - 10
        fun a b c -> a + c * 42
    ]
let ret2 = predicates2 |> sumAll()(1, 2, 3)

カレー引数をサポートするより読みやすい方法:

let sumAllCurried a b c = (a,b,c) |> (|||>) |> List.sumBy<_, float> 
// usage
let ret3 = predicates |> sumAllCurried 1.0 2.0 3.0

List.sumByの型指定全体を入力するよりも短く見えるため、型パラメーターをオンに使用していることに注意してくださいf

于 2013-01-16T01:40:04.103 に答える