Can you define your own operators in F#? - f#

Is there a way to define your own operators in F#?
If so can someone give me an example for this? I searched briefly, but couldn't find anything.

Yes:
let (+.) x s = [for y in s -> x + y]
let s = 1 +. [2;3;4]
The characters that can be used in an F# operator are listed in the docs. They are !%&*+-./<=>#^|~ and for any character after the first, ?. Precedence and fixity are determined by the first character of the operator (see the spec).
You can create your own let-bound operators as I've done above, in which case they work just like let-bound functions. You can also define them as members on a type:
type 'a Wrapper = Wrapper of 'a with
static member (+!)(Wrapper(x), Wrapper(y)) = Wrapper(x+y)
let w = (Wrapper 1) +! (Wrapper 2)
In this case, you don't need to have pre-defined a let-bound function to use the operator; F# will find it on the type. You can take particularly good advantage of this using inline definitions:
let inline addSpecial a b = a +! b
let w2 = addSpecial w (Wrapper 3)
Taking this even further, you can make the operators on your types inline as well, so that you can use them on an even wider variety of instances of your class:
type 'a Wrapper = Wrapper of 'a with
static member inline (+!)(Wrapper(x), Wrapper(y)) = Wrapper(x+y)
let wi = (Wrapper 1) +! (Wrapper 2)
let wf = (Wrapper 1.0) +! (Wrapper 2.0)
let wi2 = addSpecial wi wi
let wf2 = addSpecial wf wf

Related

making type aliases non interchangeable in F#

Here is an example:
type T =
TimeSpan
let x (y: T) =
printfn $"{y}"
let a:TimeSpan = TimeSpan.FromSeconds(3)
let b:T = TimeSpan.FromSeconds(3)
let a' = x a
let b' = x b
In this case, I want to make a type which is identical to TimeSpan but is NOT TimeSpan. I would like the ability to cast between one another, but not be equivalent when it comes to function signatures.
For example, the x function takes a type T, so the line:
let a' = x a
shouldn't compile because it passes a TimeSpan
but the line:
let b' = x b
is passing a type T and should compile.
Is there some simple and elegant way to achieve this? the goal for this is to be able to use TimeSpan, but constrain the options to some specific values.
Right now I'm using an enum that needs to be convert to TimeSpan and then TimeSpans get reconvert to the enum if they exist in the enum. It's rather ugly.
I want to make a type which is identical to TimeSpan but is NOT TimeSpan. I would like the ability to cast between one another, but not be equivalent when it comes to function signatures.
That's not possible in F#, but the usual way to accomplish something like it is with single-case unions, such as:
type T = T of TimeSpan
let x (T y) =
printfn "%A" y // y is the inner TimeSpan value
let a:TimeSpan = TimeSpan.FromSeconds(3.0)
let b:T = TimeSpan.FromSeconds(3.0) |> T
let a' = x a // doesn't compile
let b' = x b
The general issue I think you're dealing with here is called "primitive obsession".
You can either use a single cased DU, or you can use units of measure to do this. UMX specifically supports timespans.
https://github.com/fsprojects/FSharp.UMX

F# Or-Tools Sat Solver

I am experimenting with F# and want to do some constraint programming where I use Or-Tools. I have previously used the package together with Python, but I can’t get it to work with F#.
I follow the C# example: https://developers.google.com/optimization/cp/cp_solver#c_5
But get an error when try to add a constraint:
So this is kind of annoying, but it's how consuming operators that were overloaded in C# from F# works.
The reason why you couldn't use != like this is because:
The operator != is (and this is unusual) overloaded in C# as a static operator on the LinearExpr class.
The operator != compiles down to op_Inequality, but op_Inequality in F# is <>, not !=
F# already defines <> as a generic operator that accepts any member that satisfies the equality constraint, which LinearExpr does
The defined operator <> resolves correctly, and produces a bool, which is incompatible with model.Add because it doesn't expect a bool
The solution is to explicitly qualify your access to the operator like so:
LinearExpr.(<>) (x, y)
Note that because it takes tupled arguments in its definition, you must also tuple your arguments and you can't use it like a "normal" operator.
Here is the full F# solution, with a few small tweaks to make it idiomatic:
#r "nuget: Google.OrTools"
open Google.OrTools.Sat
let model = CpModel()
// Creates the variables.
let num_vals = 3L;
let x = model.NewIntVar(0L, num_vals - 1L, "x")
let y = model.NewIntVar(0L, num_vals - 1L, "y")
let z = model.NewIntVar(0L, num_vals - 1L, "z")
// Creates the constraints.
model.Add(LinearExpr.(<>) (x, y))
// Creates a solver and solves the model.
let solver = CpSolver();
let status = solver.Solve(model)
if status = CpSolverStatus.Optimal then
printfn $"x = {solver.Value(x)}"
printfn $"y = {solver.Value(y)}"
printfn $"z = {solver.Value(z)}"
A way to make this a bit nicer from F# is to define a module of operators that map to the LinearExpr operators like so:
module LinearExprOperators =
let ( ^<> ) (x: LinearExpr) (y: LinearExpr) = LinearExpr.(<>) (x, y)
let ( ^= ) (x: LinearExpr) (y: LinearExpr) = LinearExpr.(=) (x, y)
Then you can use those operators instead. Another annoyance is that it appears that + and - and * work just fine, because the F# type doesn't produce a different type like bool.
So in short, this particular API is a little annoying to use from F#.

Using FsCheck with NUnit: receiving exception on using Arbitrary types (or: how to use Arbitrary types with attributes)

In my previous question Kurt pointed me to this code of FsCheck about setting the Arbitrary type.
I have the following Arbitrary (disclaimer: I have no idea what I am doing..., still finding FsCheck notoriously hard to understand but I'm dead set on getting it to work), which in itself is a simplified version of something I created earlier:
type MyArb() =
inherit Arbitrary<DoNotSize<int64>>()
override x.Generator = Arb.Default.DoNotSizeInt64().Generator
And I use it as instructed:
[<Property(Verbose = true, Arbitrary= [| typeof<MyArb> |])>]
static member MultiplyIdentity (x: int64) = x * 1L = x
This gives me a (somewhat hopeful) error message that I'm missing something:
System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
----> System.Exception : No instances found on type Tests.Arithmetic.MyArb. Check that the type is public and has public static members with the right signature.
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at FsCheck.Runner.checkMethod(Config config, MethodInfo m, FSharpOption`1 target) in C:\Users\Kurt\Projects\FsCheck\FsCheck\src\FsCheck\Runner.fs:line 318
at FsCheck.NUnit.Addin.FsCheckTestMethod.runTestMethod(TestResult testResult) in C:\Users\Kurt\Projects\FsCheck\FsCheck\src\FsCheck.NUnit.Addin\FsCheckTestMethod.fs:line 100
Looking back at that Github code I see two Atrbitrary classes but neither with any inheritance and they both have different static members.
How can I create a random-number generator and assign it as an Arbitrary statically to my NUnit tests?
The type you provide in the Property.Arbitrary parameter should have static members (possibly several) of type Arb. As in the code you linked:
type TestArbitrary2 =
static member NegativeDouble() =
Arb.Default.Float()
|> Arb.mapFilter (abs >> ((-) 0.0)) (fun t -> t <= 0.0)
Applying this to your code, it should look like this:
type MyArb() =
static member m() = Arb.Default.DoNotSizeInt64()
The meaning of the Property.Arbitrary parameter is not "an implementation of Arbitrary", but rather "a bucket of typeclass implementations".
You see, the original Haskell implementation of QuickCheck relies on typeclasses to provide values of different types. In order for a particular type to be "quick-checkable", there needs to be an instance of the 'Arbitrary' class defined for that type (for example, here are instances for all basic types).
Since F# doesn't support type classes as such, FsCheck has to fake it, and this is the scheme used there: each type class instance is represented by a static member that returns the function table. For example, if we wanted to simulate the Eq typeclass, we'd define it something like this:
type Eq<'a> = { eq: 'a -> 'a -> bool; neq: 'a -> 'a -> bool }
type EqInstances() =
static member ForInt() : Eq<int> =
{ eq = (=); neq = (<>) }
static member ForMyCustomType() : Eq<MyCustomType> =
{ eq = fun a b -> a.CompareTo(b) = 0
neq = fun a b -> a.CompareTo(b) <> 0 }
But because you can't just scan all static member in all loaded assemblies (that would be prohibitively expensive), there is this little inconvenience of providing the type explicitly (as a bonus, it allows to control the visibility of "instances").
This question demonstrates clearly, IMO, why the Reflection-based API for FsCheck is less than ideal. I tend to avoid that API completely, so I'd instead write the OP property like this:
open FsCheck
open FsCheck.Xunit
[<Property>]
let MultiplyIdentity () =
Arb.Default.DoNotSizeInt64 () |> Prop.forAll <| fun (DoNotSize x) -> x * 1L = x
As the open directives suggest, this uses FsCheck.Xunit instead of FsCheck.NUnit, but AFAIK, there's no difference in the way the API works.
The advantage of this approach is that it's type-safe and more lightweight, because you don't have to implement static classes every time you need to tweak FsCheck.
If you prefer the approach described by Mark Seemann, then you may also consider using plain-FsCheck and get rid of FsCheck.Xunit entirely:
module Tests
open FsCheck
let [<Xunit.Fact>] ``Multiply Identity (passing)`` () =
Arb.Default.DoNotSizeInt64 ()
|> Prop.forAll
<| fun (DoNotSize x) ->
x * 1L = x
|> Check.QuickThrowOnFailure
let [<Xunit.Fact>] ``Multiply Identity (failing)`` () =
Arb.Default.DoNotSizeInt64 ()
|> Prop.forAll
<| fun (DoNotSize x) ->
x * 1L = -1L |# sprintf "(%A should equal %A)" (x * 1L) x
|> Check.QuickThrowOnFailure
xUnit.net testrunner output:
------ Test started: Assembly: Library1.dll ------
Test 'Tests.Multiply Identity (failing)' failed: System.Exception:
Falsifiable, after 1 test (2 shrinks) (StdGen (2100552947,296238694)):
Label of failing property: (0L should equal 0L)
Original:
DoNotSize -23143L
Shrunk:
DoNotSize 0L
at <StartupCode$FsCheck>.$Runner.get_throwingRunner#365-1.Invoke(String me..
at <StartupCode$FsCheck>.$Runner.get_throwingRunner#355.FsCheck-IRunner-On..
at FsCheck.Runner.check[a](Config config, a p)
at FsCheck.Check.QuickThrowOnFailure[Testable](Testable property)
C:\Users\Nikos\Desktop\Library1\Library1\Library1.fs(15,0): at Tests.Multi..
1 passed, 1 failed, 0 skipped, took 0.82 seconds (xUnit.net 2.1.0 build 3179).

How to define compile-time type casting operators in F#?

Given:
let ab = ArgumentBlockSettingStore()
let a = ab :> ISettingStore
Is there a way to define a prefix operator (~~) so that
let ab, a = ~~ArgumentBlockSettingStore() : _ * ISettingStore
becomes possible?
I think you're hitting the compiler restrictions that you mentioned in the comment - you can't write the ~~ operator in a fully generic and safe way meaning that it will only allow casting to an interface that the argument implements. You can define an operator that will cast to any other type, but that's less safe:
let inline (~~) (a:^T) : ^T * ^R = a, (box a) :?> ^R
let reader, (disposable:IDisposable) = ~~(new StreamReader("..."))
I used inline, because the operator is quite simple, but it works the same way with normal operators. This compiles even if you use Random in the type annotation for disposable, which is a bit unfortunate.

Can't get operator overloading to work with Linq Expression Trees

I am creating Linq expression trees from F# that operates on a custom datatype I have. The type is a very simple discriminated union that has the usual arithmetic operators overloaded. But for some reason I cannot create arithmetic linq expression nodes due to the fact that it can't find the correct overload. Thing is, I swear I had this working some time ago but I can't figure out what I changed to make it break.
I'll attach a small code sample showing the problem. The datatype below has the Addition operator overloaded. Using the overloaded operator works like a charm, but when I try to create an addition expression tree node using Expression.Add(lhs, rhs) the system throws an exception complaining that it can't find the overload for the Add operation.
Does anyone have an idea of what I am doing wrong?
Thank you,
Rickard
open System.Linq.Expressions
module DataType =
exception NotImplementedYet of string
type DataCarrier =
| ScalarCarrier of float
| VectorCarrier of float array
member this.Add(other) =
match (this, other) with
| ScalarCarrier(x), ScalarCarrier(y) -> ScalarCarrier(x + y)
| VectorCarrier(u), VectorCarrier(v) ->
VectorCarrier(Array.map2 (fun x y -> x + y) u v)
| _,_ -> raise (NotImplementedYet("No go!"))
static member (+) (lhs:DataCarrier, rhs) =
lhs.Add(rhs)
module Main =
let createAddOp (lhs:DataType.DataCarrier) (rhs:DataType.DataCarrier) =
let clhs = Expression.Constant(lhs)
let crhs = Expression.Constant(rhs)
Expression.Add(clhs, crhs)
(* no problems with this one *)
printf "Testing operator overloading: %A" (DataType.ScalarCarrier(1.0)
+ DataType.ScalarCarrier(2.0))
(* this throws an exception *)
printf "Testing expr construction %A" (Main.createAddOp
(DataType.ScalarCarrier(1.0))
(DataType.ScalarCarrier(2.0)))
One solution is to explicitly type the Expression operands (giving them the static type DataType.DataCarrier instead of their runtime type DataType.DataCarrier.ScalarCarrier):
module Main =
let createAddOp (lhs:DataType.DataCarrier) (rhs:DataType.DataCarrier) =
let clhs = Expression.Constant(lhs, typeof<DataType.DataCarrier>)
let crhs = Expression.Constant(rhs, typeof<DataType.DataCarrier>)
Expression.Add(clhs, crhs)
Another option would be to explicitly pass the addition operator to use:
module Main =
let createAddOp (lhs:DataType.DataCarrier) (rhs:DataType.DataCarrier) =
let clhs = Expression.Constant(lhs)
let crhs = Expression.Constant(rhs)
Expression.Add(clhs, crhs, typeof<DataType.DataCarrier>.GetMethod("op_Addition"))
I am surprised that your original code doesn't work, though. It appears to be a limitation in how expression trees find relevant add operators (that is, it appears that Linq only looks for add operators on the runtime types of operands).

Resources