объединение функций / комбинатор в fsharp - PullRequest
1 голос
/ 23 февраля 2012

У меня есть список функций, принимающих один и тот же тип в качестве ввода, разные типы в качестве вывода

 [ f_i :  Mytype -> res:Sometype_i ] 

Какая операция может объединить их в одну функцию следующего типа?1006 * Идентично, если бы у меня был список функций, возвращающих один и тот же тип

 [ f_i : Mytype_i -> res:Sometype ] 

Какая операция может объединить их в одну функцию следующего типа?канонический «прекомбинатор» или «посткомбинатор».(Я полагаю, у него есть имя в FP ..)

Ответы [ 2 ]

3 голосов
/ 23 февраля 2012

Альтернатива решению Томаса для второй задачи с дополнительным бонусом возврата функций в том же порядке, в котором они были изначально

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

let merged = fun input -> funcs |> List.map (fun f -> f input)
3 голосов
/ 23 февраля 2012

Ответ на ваш первый вопрос заключается в том, что вы не можете сделать это вообще. Список - это структура данных с динамической длиной, но длина результирующего кортежа должна быть известна статически во время компиляции. (Вы можете создать полученный кортеж, используя отражение, и использовать его как obj, но это не очень полезно.)

Во втором случае вы хотите превратить список функций в функцию, возвращающую список, что можно сделать (обе имеют динамическую длину). Вы можете написать что-то вроде:

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 list и функцию TInp -> 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 _ -> [])
...