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) } }
end
end
irb(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?
toplevel
, it produces... [1; 2; 3] |> List.map (fun x -> x + 1) |> List.map (fun x -> x * 2) |> List.map (fun x -> float_of_int x /. 3.);; - : float list = [1.33333333333333326; 2.; 2.66666666666666652] – Carlisle[1; 2; 3] |> List.map (fun x -> float_of_int ((x + 1) * 2) /. 3.)
, but that wouldn't be challenging, and thus no fun. – Feck;
instead of,
. – Feck