A very common pattern in functional programming is to chain a series of calls to map
on lists. A contrived, simple example:
[1; 2; 3] |> List.map (fun x -> x + 1) |> List.map (fun x -> x * 2)
Where the result is:
[4; 6; 8]
Now it's easy enough to flip this on its head and avoid the creation of lists at each stage, if the types never change: simply have map
take a list of functions to apply in order:
let list_map_chained : 'a. ('a -> 'a) list -> 'a list -> 'a list = let rec apply x chain = begin match chain with | [] -> x | f :: chain' -> apply (x |> f) chain' end in fun chain xs -> List.map (fun x -> apply x chain) xs
Which we can use like this:
[1; 2; 3] |> list_map_chained [ (fun x -> x + 1) ; (fun x -> 2 * x) ]
But if we want to do the same thing to a sequence like the following:
[1; 2; 3] |> List.map (fun x -> x + 1) |> List.map (fun x -> x * 2) |> List.map (fun x -> float_of_int x /. 3.)
Now the types do change, but because of the heterogenous nature of the types, the functions cannot be stored in anything like a list that expects (and requires) homogenous types. Obviously this is very straightforward in a less strictly typed programming language like Ruby:
class Array def inverted_map(*lambdas) self.map { |x| lambdas.inject(x) { |sum, l| l.call(sum) } } endendirb(main):032:0> [1,2,3].inverted_map(lambda { |x| x + 1 }, lambda { |x| x * 2 }, lambda { |x| x.to_f / 3})=> [1.3333333333333333, 2.0, 2.6666666666666665]
I know a fair amount about Ocaml, but I am open to not knowing it all. Is there a way to accomplish this within Ocaml's type system that is not more trouble than it's worth?