By now, you’ve probably heard the standard line. Functional programming is all sweetness and light; if we merely cast off the detritus of bad habits we’ve learned from C, C++ and Java we’ll find ourselves in a different world, a better world. Without state, and by dint of a civilized logical system of analysis, all wishes will come true.
Yet, in the world of F# (and OCaml in a slightly different case), we encounter some logical anomalies:
> (+);;
val it : (int -> int -> int)
> 3.2 + 5.4;;
val it : float = 8.6
Which is the truth here? Initially we’re told that the “+” operator expects two int values, but it seems to happily accept two floats. Worse yet, if we expect to rely on this magical addition, our hopes are soon dashed:
> let twice x = x + x;;
> twice 9.4;;
——^^^
stdin(2,5): error FS0001: This expression has type
float
but is here used with type
int.
Our only chance for generic arithmetic (over ints, floats, vectors, etc) is to explicitly pass the necessary arithmetic functions around:
> let twice fn x = fn x x;;
val twice : (’a -> ‘a -> ‘b) -> ‘a -> ‘b
> twice (+) 1;;
val it : int = 2
> twice (+) 1.2;;
val it : float = 2.4
> twice (fun (a,b) (c,d) -> (a+c,b+d)) (1,2.3);;
val it : int * float = (2, 4.6)
And although this works, it has a kind of Jerry Seinfeld “why don’t you just tell me the function you want to call?” feel to it. There must be a better way. Read more...