F# operator not resolving properly - f#

let inline (=~) a b = abs (single a - single b) <= 0.001f
type Vector =
{ x : single; y : single; z : single }
static member (=~) (v1, v2) = (v1.x =~ v2.x) && (v1.y =~ v2.y) && (v1.z =~ v2.z)
let v1, v2 =
{ x = 0.1f; y = single Math.PI; z = 0.f },
{ x = 0.1f; y = 3.14159f; z = 0.0001f }
v1 =~ v2
Compiler complains: The type 'Vector' does not support a conversion to the type 'single'
I don't get it. Clearly, the type-specific operator doesn't take precedence over the generic operator, foiling my intuition. What's the trick to making this work?

When you define a custom operator using let, it will always take precedence over type-defined operators. The simple way of dealing with this is to avoid name clashes in local and global operator names, or to keep the scope of the let-bound operators to a minimum. For example, you could put the global =~ operator in a separate module:
module VectorImplementation =
let inline (=~) a b = abs (single a - single b) <= 0.001f
module Vectors =
open VectorImplementation
type Vector =
{ x : single; y : single; z : single }
static member (=~) (v1, v2) =
(v1.x =~ v2.x) && (v1.y =~ v2.y) && (v1.z =~ v2.z)
open System
open Vectors
let v1, v2 =
{ x = 0.1f; y = single Math.PI; z = 0.f },
{ x = 0.1f; y = 3.14159f; z = 0.0001f }
v1 =~ v2
There is also a somewhat strange hack that you can use to define global let-bound operators that are overloaded. There is some debate whether this is a good idea or not - I think it is usually possible to avoid clashes without resorting to this magic trick, but others might disagree.

Page 97 of the F# 4.0 language specification says that:
If the operator does not resolve to a user-defined or library-defined operator, the name resolution rules (§14.1) ensure that the operator resolves to an expression that implicitly uses a static member invocation expression (§0) that involves the types of the operands. This means that the effective behavior of an operator that is not defined in the F# library is to require a static member that has the same name as the operator, on the type of one of the operands of the operator.
As Tomas Petricek has just pointed out in his answer, that means that the =~ operator you defined globally is "hiding" the =~ operator on your Vector type. His answer suggests a good approach for dealing with the problem. Another way would be to simply make both operators different:
let inline (==~) a b = abs (single a - single b) <= 0.001f
type Vector =
{ x : single; y : single; z : single }
static member (=~) (v1, v2) =
(v1.x ==~ v2.x) && (v1.y ==~ v2.y) && (v1.z ==~ v2.z)
You may find this approach simpler than Tomas's approach, or you may find his approach simpler. It's a matter of style preference; either one should work.

Related

How to invoke function using named parameter arguments in F#

How can I call F# functions by specifying the parameter names in the call site?
I've tried the following:
let add x y =
x + y
add (x = 10) (y = 10) // How to specify the name x and y when calling add?
But it gives this error:
error FS0039: The value or constructor 'x' is not defined.
You can't invoke let-bound functions with named arguments. It's allowed only for methods in classes
Named arguments are allowed only for methods, not for let-bound functions, function values, or lambda expressions.
Documentation
Technically you can declare static class and use method from it, but I think it's wrong. Just wrong. Don't do it
[<AbstractClass; Sealed>]
type MathOperations =
static member Add (x, y) = x + y
open type MathOperations
[<EntryPoint>]
let main argv =
Add(x = 3, y = 4)
|> printfn "%d"
0
This issue confused me too in the beginning. Functions and methods are not alike.
Functions are curried by default to support partial application. They don't support named argument calls.
Methods support named arguments using a single tuple for all parameters.
(EDIT after Bent Tranberg's comment) Methods also support curried declaration member _.Add x y = x + y and even mixed style declaration member _.Add3 (x: int, y: int) (z: int) = x + y + z but these methods cannot be called using named arguments o.Add3 (y=2, x=1) 3 💥
In JavaScript, named arguments can be simulated using an object literal as argument. Let's try do the same in F#, using tuple or record:
1. Tuple: Method arguments are provided all at once with a tuple. Can we use a tuple as function parameter and call the function with named arguments? No ❌
let add (x, y) = x + y
add (x = 1, y = 2) // 💥
// ~ Error FS0039: The value or constructor 'x' is not defined
2. Anonymous record: not possible due to actual limitation in anonymous record deconstruction ❌
let add {| X = x; Y = y |} = x + y
// ~~ Error FS0010: Unexpected symbol '{|' in pattern
3. Named record: ⚠️
type AddParam = { x: int; y: int }
let add { x = x; y = y } = x + y
add { x = 1; y = 2 }
This way, we are able to name the arguments and choose their order ({ y = 2; x = 1 } but we loose the partial application. So it's not idiomatic→ should be avoided, unless in specific cases.
4. Single-case DU: 👌
If we care only about the argument naming but not about the argument re-ordering, we can use discriminated unions, especially single-case DU:
type XParam = X of int
type YParam = Y of int
let add (X x) (Y y) = x + y
add (X 1) (Y 2)
This way, the arguments appeared as named and partial application is preserved.
--
EDIT
☝ I don't recommend creating single-case DU just to simulate named arguments ! It's the other way around: when we have single-case DU in our domain model, we know that they will bring their semantic to document the code and help reasoning about the code, in this case more or less like named arguments.
You have to understand function calling in F#, which is different from traditional imperative languages like C#.
let f x y = x + y // defines a function with this signature:
val f : x:int -> y:int -> int
// this function is full or partially applicable:
let g = f 4 // partial application
val g : (int -> int) // a new function that evaluates f 4 y
g 10
val it : int = 14
In traditional languages functions have a single set of arguments. In F# you express such traditional functions with multiple arguments into a function with a tuple argument:
let f (x, y) = x + y
val f : x:int * y:int -> int
// partial application is no longer possible, since the arguments have been packed into a single tuple
Such traditional tuple-argument functions do not allow calls with named arguments:
f (x=3, y=5) // interpreted as = test expressions
F# language design is sound here, and (x=3, y=5) does not express the desired tuple.
F# has named arguments since a while (this was added in the last years sometime). This is limited to member functions however. Once you translate your function into a member it works:
type A() =
static member f (x,y) = x + y
A.f(y=3, x=4) // yes, this works!

Multiple dispatch behavior for operator overloads

The following gives a duplicate definition error:
let (.*) (m1 : Matrix<float>) (m2 : Matrix<float>) =
m1.Multiply(m2)
let (.*) (v1 : Vector<float>) (v2 : Vector<float>) =
v1.DotProduct(v2)
Is there a way to define an operator overload such that F# recognizes the function I'm trying to call based on the function signature?
For example Julia has this very useful feature:
julia> methods(*)
# 138 methods for generic function "*":
*(x::Bool, y::Bool) at bool.jl:38
*{T<:Unsigned}(x::Bool, y::T<:Unsigned) at bool.jl:53
*(x::Bool, z::Complex{Bool}) at complex.jl:122
*(x::Bool, z::Complex{T<:Real}) at complex.jl:129
...
It would be great if there were a way to replicate something similar in F#.
In this specific case * is already overloaded. For example:
let m = matrix [[ 1.0; 4.0; 7.0 ]
[ 2.0; 5.0; 8.0 ]
[ 3.0; 6.0; 9.0 ]]
let v = vector [ 10.0; 20.0; 30.0 ]
let s = 5.
m * m
//val it : Matrix<float> =
// DenseMatrix 3x3-Double
//30 66 102
//36 81 126
//42 96 150
v * v
//val it : float = 1400.0
With overloading:
type Mult = Mult with
static member inline ( $ ) (Mult, m1:Matrix<float>) = fun (m2:Matrix<float>) -> m1.Multiply(m2)
static member inline ( $ ) (Mult, v1:Vector<float>) = fun (v2:Vector<float>) -> v1.DotProduct(v2)
let inline ( .*. ) v1 v2 = (Mult $ v1) v2
And you can use it like this:
m .*. m
v .*. v
You'll get the same results as above. You can use .*, I just avoided it as not to get confused with the already defined .*. Now this is actually discussed in Global Operator Overloading and Oveload operator in F# but F#'s behavior here is a bit obscure so I re-did the example with the Matrix and Vector types. You can probably make it generic. Maybe someone more familiar with mathdotnet can provide a more idiomatic solution. You should also check if * , .* et al. are already overloaded and function as expected for you since for common operations most of this stuff is already implemented.

How to properly overload global (+) and (*) without breaking support for other types

I have imported a vector math library, and would like to add my own (*) and (+) operators while preserving the existing operators for basic int and float.
I have tried the following:
let inline (*) (x : float) (y : Vector) = y.Multiply(x)
let inline (*) (x : Vector) (y : float) = x.Multiply(y)
let inline (+) (x : Vector) (y : Vector) = x.Add(y)
Which has two problems:
It seems to remove int + int and int * int, and
The 2nd line (which is intended to complete commutativity) does not compile because it is a "duplicate definition".
How can I go about defining some commutative operators on my imported Vector type while also not losing these operations on ints and floats?
(I want to be able to write generic code elsewhere using * and +, without having to specify float/Vector/int type constraints).
If you are able to modify source code of the library, it's simpler to add a few overloads via type extensions:
type Vector with
static member (*) (x : Vector) (y : float) = x.Multiply(y)
static member (+) (x : Vector) (y : Vector) = x.Add(y)
However, if the first operand has a primitive type (e.g your first example), overloading resolution doesn't work any more.
At any rate, you can exploit member overloading and propagate constraints to an inline function:
type VectorOverloadsMult =
| VectorOverloadsMult
static member (?<-) (VectorOverloadsMult, x: float, y: Vector) = y.Multiply(x)
static member (?<-) (VectorOverloadsMult, x: Vector, y: float) = x.Multiply(y)
static member inline (?<-) (VectorOverloadsMult, x, y) = x * y
let inline (*) x y = (?<-) VectorOverloadsMult x y
This works for existing types with (*) since we preserve them in the last static member. You can do the same for (+) operator.
let v: Vector = ... // Declare a Vector value
let a = 2.0 * v
let b = v * 2.0
let c = 2 * 3
let d = 2.0 * 3.0
This technique works even when you cannot modify the Vector type.
You need to define the operators inside your type - i.e.
type Vector =
....
static member (+) (x : Vector) (y : Vector) = x.Add(y)
etc.
Then all will work as you expect

Overloading measure operator (*)

I am stuck attempting to overload the (*) operator for a Measure type.
What I would like to see is :
> let x = 1.0<i> * 1.0<i>;;
val x : float = -1.0
The following definition appears to do the trick :
> let inline (*) (v1 : float<i>) (v2 : float<i>) = float(-1) * float(v1) * float(v2);;
val inline ( * ) : float<i> -> float<i> -> float
Note that the product measure in this example correctly resolves to <1> as which happens for example when multiplying the imaginary unit of a complex number. Without this overloading definition the default product resolves to < i^2>.
But the overloading definition above has the nasty side effect that :
> let y = 1.0 * 1.0;;
let y = 1.0 * 1.0;;
--------^^^
stdin(11,9): error FS0001: This expression was expected to have type
float<i>
but here has type
float
Apparently my overloading definition hides the (*) operator for the float type.
What am I doing wrong?
Note that you are redefining the (*) operator rather than overloading it.
The trick to get it working is to write something using an intermediate type, like this:
type Mult = Mult with
static member ($) (Mult, v1: float<i>) = fun (v2: float<i>) ->
float(-1) * float(v1) * float(v2)
static member inline ($) (Mult, v1 ) = fun v2 -> v1 * v2
static member ($) (Mult, v1: Mult) = fun () -> Mult //Dummy overload
let inline (*) v1 v2 = (Mult $ v1) v2
BTW funny way to use units of measure.

F# Power issues which accepts both arguments to be bigints

I am currently experimenting with F#. The articles found on the internet are helpful, but as a C# programmer, I sometimes run into situations where I thought my solution would help, but it did not or just partially helped.
So my lack of knowledge of F# (and most likely, how the compiler works) is probably the reason why I am totally flabbergasted sometimes.
For example, I wrote a C# program to determine perfect numbers. It uses the known form of Euclids proof, that a perfect number can be formed from a Mersenne Prime 2p−1(2p−1) (where 2p-1 is a prime, and p is denoted as the power of).
Since the help of F# states that '**' can be used to calculate a power, but uses floating points, I tried to create a simple function with a bitshift operator (<<<) (note that I've edit this code for pointing out the need):
let PowBitShift (y:int32) = 1 <<< y;;
However, when running a test, and looking for performance improvements, I also tried a form which I remember from using Miranda (a functional programming language also), which uses recursion and a pattern matcher to calculate the power. The main benefit is that I can use the variable y as a 64-bit Integer, which is not possible with the standard bitshift operator.
let rec Pow (x : int64) (y : int64) =
match y with
| 0L -> 1L
| y -> x * Pow x (y - 1L);;
It turns out that this function is actually faster, but I cannot (yet) understand the reason why. Perhaps it is a less intellectual question, but I am still curious.
The seconds question then would be, that when calculating perfect numbers, you run into the fact that the int64 cannot display the big numbers crossing after finding the 9th perfectnumber (which is formed from the power of 31). I am trying to find out if you can use the BigInteger object (or bigint type) then, but here my knowledge of F# is blocking me a bit. Is it possible to create a powerfunction which accepts both arguments to be bigints?
I currently have this:
let rec PowBigInt (x : bigint) (y : bigint) =
match y with
| bigint.Zero -> 1I
| y -> x * Pow x (y - 1I);;
But it throws an error that bigint.Zero is not defined. So I am doing something wrong there as well. 0I is not accepted as a replacement, since it gives this error:
Non-primitive numeric literal constants cannot be used in pattern matches because they
can be mapped to multiple different types through the use of a NumericLiteral module.
Consider using replacing with a variable, and use 'when <variable> = <constant>' at the
end of the match clause.
But a pattern matcher cannot use a 'when' statement. Is there another solution to do this?
Thanks in advance, and please forgive my long post. I am only trying to express my 'challenges' as clear as I can.
I failed to understand why you need y to be an int64 or a bigint. According to this link, the biggest known Mersenne number is the one with p = 43112609, where p is indeed inside the range of int.
Having y as an integer, you can use the standard operator pown : ^T -> int -> ^T instead because:
let Pow (x : int64) y = pown x y
let PowBigInt (x: bigint) y = pown x y
Regarding your question of pattern matching bigint, the error message indicates quite clearly that you can use pattern matching via when guards:
let rec PowBigInt x y =
match y with
| _ when y = 0I -> 1I
| _ -> x * PowBigInt x (y - 1I)
I think the easiest way to define PowBigInt is to use if instead of pattern matching:
let rec PowBigInt (x : bigint) (y : bigint) =
if y = 0I then 1I
else x * PowBigInt x (y - 1I)
The problem is that bigint.Zero is a static property that returns the value, but patterns can only contain (constant) literals or F# active patterns. They can't directly contain property (or other) calls. However, you can write additional constraints in where clause if you still prefer match:
let rec PowBigInt (x : bigint) (y : bigint) =
match y with
| y when y = bigint.Zero -> 1I
| y -> x * PowBigInt x (y - 1I)
As a side-note, you can probably make the function more efficent using tail-recursion (the idea is that if a function makes recursive call as the last thing, then it can be compiled more efficiently):
let PowBigInt (x : bigint) (y : bigint) =
// Recursive helper function that stores the result calculated so far
// in 'acc' and recursively loops until 'y = 0I'
let rec PowBigIntHelper (y : bigint) (acc : bigint) =
if y = 0I then acc
else PowBigIntHelper (y - 1I) (x * acc)
// Start with the given value of 'y' and '1I' as the result so far
PowBigIntHelper y 1I
Regarding the PowBitShift function - I'm not sure why it is slower, but it definitely doesn't do what you need. Using bit shifting to implement power only works when the base is 2.
You don't need to create the Pow function.
The (**) operator has an overload for bigint -> int -> bigint.
Only the second parameter should be an integer, but I don't think that's a problem for your case.
Just try
bigint 10 ** 32 ;;
val it : System.Numerics.BigInteger =
100000000000000000000000000000000 {IsEven = true;
IsOne = false;
IsPowerOfTwo = false;
IsZero = false;
Sign = 1;}
Another option is to inline your function so it works with all numeric types (that support the required operators: (*), (-), get_One, and get_Zero).
let rec inline PowBigInt (x:^a) (y:^a) : ^a =
let zero = LanguagePrimitives.GenericZero
let one = LanguagePrimitives.GenericOne
if y = zero then one
else x * PowBigInt x (y - one)
let x = PowBigInt 10 32 //int
let y = PowBigInt 10I 32I //bigint
let z = PowBigInt 10.0 32.0 //float
I'd probably recommend making it tail-recursive, as Tomas suggested.

Resources