Reputation: 9835
I have a list of functions accepting the same type as an input, different types as output
[ f_i : Mytype -> res:Sometype_i ]
Which operation can merge them into one function of the following type ?
f : Mytype -> \Product_i Mytype_i
Identically, if I have a list of functions returning the same type
[ f_i : Mytype_i -> res:Sometype ]
Which operation can merge them into one function of the following type ?
f : \Product_i Mytype_i -> Mytype list
It would be some canonical "preCombinator" or "postCombinator". (I imagine it has a name in FP..)
Upvotes: 1
Views: 497
Reputation: 25526
An alternative to Tomas' solution for the second problem with the added bonus of returning the functions in the same order as they were initially
let funcs =
[ (fun n -> n + 1)
(fun n -> n * 2) ]
let merged = fun input -> funcs |> List.map (fun f -> f input)
Upvotes: 3
Reputation: 243126
The answer to your first question is that you cannot do that in general. A list is a data structure with dynamic length, but the length of the resulting tuple has to be known statically at compile time. (You could construct the resulting tuple using reflection and use it as obj
, but that's not really useful.)
In the second case, you want to turn a list of functions into a function returning list, which can be done (both have dynamic length). You can write something like:
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 _ -> [])
The primitive operation (passed to fold
) is a function that takes a function of type TInp -> TOut list
and a function TInp -> TOut
and combines them into a function returning a longer list. So you could also write:
// 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 _ -> [])
Upvotes: 3