I'd like to compose functions in a certain way. Please consider these 2 functions in pseudocode (not F#)
F1 = x + y
F2 = F1 * 10 // note I did not specify arguments for F1, 'reverse curry' for lack of a better word
What I would like for F# to do is figure out that since
let F1 x y = x + y
//val F1 : int -> int -> int
the code let F2 = F1 * 10
would give me the same signature as F1: val F2 : int -> int -> int
, and calling F2 2 3
would result in 50: (2 + 3) * 10. That would be rather clever...
What happens is quite different tho. The first line goes as expected:
let F1 x y = x + y
//val F1 : int -> int -> int
but when I add a second line let F2 = F1 * 10
it throws off F#. It complains that the type int does not match the type 'a -> 'b -> 'c
and that F1 now requires member ( + )
.
I could of course spell it out like this:
let F1(x, y) = x + y
let F2(x, y) = F1(x, y) * 10
But now I might as well have used C#, we're not that far away anymore. The tupled arguments break a lot of the elegance of F#. Also my real functions F1 and F2 have a lot more arguments than just 2, so this makes me go cross eyed, exactly what I wanted to dodge by using F#. Saying it like this would be much more natural:
let F1 x y = x + y
let F2 = F1 * 10
Is there any way I can (almost) do that?
For extra credits: what exactly goes on with these error messages? Why does the second line let F2 = F1 * 10
change the typing on the first?
Thanks in advance for your thoughts,
Gert-Jan
update Two apporaches that (almost) do what's described.
One using a tuple. Second line looks a little quirky a first, works fine. Small drawback is I can't use currying now or I'll have to add even more quirky code.
let F1 (a, b) = a + b
let F2 = F1 >> (*) 10
F2(2, 3) // returns 50
Another approach is using a record. That is a little more straight forward and easier to get at first glance, but requieres more code and ceremony. Does remove some of the elegance of F#, looks more like C#.
type Arg (a, b) =
member this.A = a
member this.B = b
let F1 (a:Arg) = a.A + a.B
let F2 (a:Arg) = F1(a) * 10
F2 (Arg(2, 3)) // returns 50