1

入力として同じタイプを受け入れ、出力として異なるタイプを受け入れる関数のリストがあります

 [ f_i :  Mytype -> res:Sometype_i ] 

それらを次のタイプの 1 つの関数にマージできる操作はどれですか?

 f : Mytype -> \Product_i Mytype_i

同様に、同じ型を返す関数のリストがある場合

 [ f_i : Mytype_i -> res:Sometype ] 

それらを次のタイプの 1 つの関数にマージできる操作はどれですか?

 f : \Product_i Mytype_i ->  Mytype list

標準的な「preCombinator」または「postCombinator」になります。(FPに名前があると思います..)

4

2 に答える 2

3

最初の質問に対する答えは、一般的にはできないということです。リストは動的な長さを持つデータ構造ですが、結果のタプルの長さはコンパイル時に静的にわかっている必要があります。(リフレクションを使用して結果のタプルを構築し、それを として使用することもできますがobj、それはあまり役に立ちません。)

2 番目のケースでは、関数のリストを関数を返すリストに変換する必要があります。これは可能です (どちらも動的な長さです)。次のように書くことができます:

let funcs =
  [ (fun n -> n + 1)
    (fun n -> n * 2) ]

let merged =
  funcs |> List.fold (fun agg f ->
    fun inp -> (f inp)::(agg inp)) (fun _ -> [])

プリミティブ操作 ( に渡される) は、型の関数foldと関数を取り、それらを組み合わせて、より長いリストを返す関数にする関数です。したがって、次のように書くこともできます。TInp -> TOut listTInp -> TOut

// val addResult : ('a -> 'b list) -> ('a -> 'b) -> 'a -> 'b list  
let addResult agg f inp = (f inp)::(agg inp)

// val merge : ('a -> 'b) list -> ('a -> 'b list)
let merge funcs = funcs |> List.fold addResult (fun _ -> [])
于 2012-02-23T10:31:45.017 に答える