Reputation: 2795
I'm trying to have a go with Microsoft.ML.Probabilistic, and the examples are in C#.
e.g.
static void Main(string[] args)
{
var firstHeads = Variable.Bernoulli(0.5);
var secondHeads = Variable.Bernoulli(0.5);
var bothHeads = firstHeads & secondHeads;
}
now there's a bit of magic going on in there, the & operator is resolved by the C# compiler as
Variable<bool>.operator &(Variable<bool> a, Variable<bool> b)
(actually I even though I've been using C# for over 15 years, I don't actually know how to explicitly reference this operator, I just let the compiler do the hard work...but that's an aside)
I want to do this in F#, so I write
let main argv =
let firstCoinHeads = Variable.Bernoulli 0.5
let secondCoinHeads = Variable.Bernoulli 0.5
let bothHeads = firstCoinHeads & secondCoinHeads
0
but this doesnt compile, because the F# compiler "this expression was expected to be a bool" for the subexpressions "firstCoinHeads" and "secondCoinHeads".
thats sort of irritating....so how do I explicitly make F# use the correct operator?
Upvotes: 2
Views: 84
Reputation: 57159
The given answer by @Fyodor Soikin is not wrong, but the proposed solution is unnecessary. There seems to be a bit of confusion about the operators:
op_BitwiseAnd
&
.&&&
. This is the one you want.&
is used in match expressions, meaning "and", and as the unary address-of
operator. There is no default mapping for this operator. (if overridden, it becomes op_Amp
).&&
.You are certainly allowed to redefine &&&
in F#. To redefine the address-of operator not so much (you get a warning).
However, if a type overloads an operator, F# will simply select that operator if you use the proper matching syntactic operator. In this case, &&&
. Yes, this is indeed confusing.
If I install Microsoft.ML.Probabilistic
and Microsoft.ML.Probabilistic.Compilers
, I can do the following (the nuget
syntax is available with --langversion:preview
):
> #r "nuget: Microsoft.ML.Probabilistic";;
> open Microsoft.ML.Probabilistic;;
[Loading C:\Users\Me\AppData\Local\Temp\nuget\10644\Project.fsproj.fsx]
namespace FSI_0138.Project
> #r "nuget: Microsoft.ML.Probabilistic.Compiler";;
> open Microsoft.ML.Probabilistic.Models;;
[Loading C:\Users\Me\AppData\Local\Temp\nuget\10644\Project.fsproj.fsx]
namespace FSI_0143.Project
>let firstCoinHeads = Variable.Bernoulli 0.5
let secondCoinHeads = Variable.Bernoulli 0.5;;
Binding session to 'C:\Users\Abel\.nuget\packages\microsoft.ml.probabilistic\0.3.1912.403\lib\netstandard2.0\Microsoft.ML.Probabilistic.dll'...
val firstCoinHeads : Variable<bool> = vbool0
val secondCoinHeads : Variable<bool> = vbool1
> let bothHeads = firstCoinHeads &&& secondCoinHeads;;
val bothHeads : Variable<bool> = vbool2
As you can see, no need to create "your own" special operator here, just use the actual "bitwise and" operator: &&&
.
If you run into this again, there's a list of what operator is matched to what method: https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/operator-overloading. Notably:
Upvotes: 1
Reputation: 80744
In .NET (and in F#, to a greater extent) operators are compiled to methods named op_Xyz
where Xyz
describes the operator itself (for .NET overloadable operators) or the characters included in the operator (for the richer F# operators).
Specifically, the operator &
is compiled to op_BitwiseAnd
, and that's how you can access it:
let bothHeads = Variable.op_BitwiseAnd(firstCoinHeads, secondCoinHeads)
The original problem you're experiencing comes from the fact that in F#, operator &
is "special" (for backward compatibility with Ocaml, one assumes). It's treated specially by the compiler, forcing the arguments to be bool
and issuing a warning if you try to redefine it. This is a bit of an annoyance, yes, but here we are.
But you could define yourself a different operator as an extension for the Variable
type:
type Variable<'t> with
static member (&.)(a, b) = Variable<bool>.op_BitwiseAnd(a, b)
And then use it like this:
let bothHeads = firstCoinHeads &. secondCoinHeads
Upvotes: 4