More on the overloaded conversion operators in 1.9.1.9

F# 1.9.1.9 includes an addition that can substantially simplify F# numeric code. This provides a solution for a problem that has been present in F# programming from the start, but is not present in many other languages.

In particular, the functions int, float, float32 etc. are now defined as overloaded conversion operators. For example, you can replace Int32.of_float and Int32.of_int64 and all similar operators by just int (or int32, which is equivalent). Likewise for sbyte, byte, int16, uint16int32, uint32, int64, uint64, nativeint, unativeint, float, float32, single, double. For example, you can write code in thi style:

let

twos = byte 20 + byte 2

let

seven = uint16 7

let

pi = float twos / float seven

instead of:

let twos = Byte.of_int 20 + Byte.of_int 2

let

seven = UInt16.of_int 7

let pi = Float.of_int (Int32.of_byte twos) / Float.of_int (Int32.of_uint16 seven)

The functions sbyte, byte, int16, uint16, int, ``int32, uint32, int64, uint64, nativeint, unativeint, float, float32, single,  double can all be used as first class functions, e.g. [1;2;3] |> List.map float. Overloads of this kind were provided in the 1.9.1.8 release for functions abs, sin, cos, asin, acos, atan, atan2, ceil, floor, log, log10, sqrt, cosh, sinh, tanh, and **. The last operator is "pow" - we will add a named version of this operator to the next release, as people have had trouble finding it.

Like all operator overloads the type involved in the use of the operator must be resolved statically. The operators are also extensible in the sense that they will work with any class that defines a corresponding static member, e.g. using int16 on a value of your own type MyBigInteger requires a static member ToInt16 : MyBigInteger -> int16 in your MyBigInteger type. The use of static members for this purpose derives from design patterns already in the F# library (e.g. the System.Decimal type).

The definition of the operators is in the F# library and they use the library-only "operator overload constraints", along with some special cases in the compiler to pretend that various constraints hold for the built-in .NET base types.

Enjoy!

Don