I have a class and a record defined like so:
namespace Foo
type internal MyRecord =
{
aValue1 : int
aValue2 : int
}
static member (+) (left : MyRecord, right : MyRecord) : MyRecord =
{aValue1 = left.aValue1 + right.aValue1; aValue2 = left.aValue2 + right.aValue2;}
type internal Bar() =
member this.Baz() =
let myRecord1 = {aValue1 = 2; aValue2 = 3;}
let myRecord2 = {aValue1 = 7; aValue2 = 5;}
let sum = myRecord1 + myRecord2 //Does not compile
0
This fails to compile with:
The member or object constructor 'op_Addition' is not public. Private members may only be accessed from within the declaring type. Protected members may only be accessed from an extending type and cannot be accessed from inner lambda expressions.
Both types are internal. If I explicitly set the +
operator to public, that doesn't help either:
static member public (+) (left : MyRecord, right : MyRecord) : MyRecord
What does work is just forgoing use of an operator and using a static method:
namespace Foo
type internal MyRecord =
{
aValue1 : int
aValue2 : int
}
static member Add (left : MyRecord, right : MyRecord) : MyRecord =
{aValue1 = left.aValue1 + right.aValue1; aValue2 = left.aValue2 + right.aValue2;}
type internal Bar() =
member this.Baz() =
let myRecord1 = {aValue1 = 2; aValue2 = 3;}
let myRecord2 = {aValue1 = 7; aValue2 = 5;}
let sum = MyRecord.Add(myRecord1, myRecord2) //Does compile
0
Why does the F# compiler struggle with using an operator in this case when using a named member work just fine?
Changing both types to be public instead of internal resolves the compilation error, too.
I'm using Visual Studio 2012 with F# 3.0 targeting .NET Framework 3.5.
I do not know why F# compiler has this problem. This is probably connected to the way operators are handled in F# or maybe how accessibility is handled. You must remember that in this language not everything is what it seems. Some "object oriented" features have been achieved by making some sacrifices. Maybe this is one of them.
But. I know how to resolve this :). Do not make your types internal in implementation file. Instead use Signatures. Define file Foo.fsi like this:
namespace Foo
type internal MyRecord =
{
aValue1 : int
aValue2 : int
}
[<Class>]
type Bar =
member Baz : unit -> int
and Foo.fs like this:
namespace Foo
type MyRecord =
{
aValue1 : int
aValue2 : int
}
static member (+) (left : MyRecord, right : MyRecord) : MyRecord =
{aValue1 = left.aValue1 + right.aValue1; aValue2 = left.aValue2 + right.aValue2;}
type Bar() =
member this.Baz() =
let myRecord1 = {aValue1 = 2; aValue2 = 3;}
let myRecord2 = {aValue1 = 7; aValue2 = 5;}
let sum = myRecord1 + myRecord2 //Compiles
0
This makes your code valid and MyRecord
internal.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With