8
votes

I want to write the equivalent of this C# in F#:

struct Vector2 {
    public readonly int X;
    public readonly int Y;
    public Vector2(int x, int y) {
        X = x;
        Y = y;
    }
}

This forces the user to supply arguments to create an instance [EDIT: this is wrong for value types - all value types have a default constructor]. A default Vector2 could be provided with a static readonly field as well, i.e. Vector2.Zero.

It looks like the only way to get public fields is via the "val" keyword, but doesn't seem to let me initialize them with the default constructor, and I don't want to have two constructors:

  [<Struct>]
  type MyInt(value) =
        val public Value : int = value;;

          val public Value : int = value;;
  -------------------------------^

stdin(7,32): error FS0010: Unexpected symbol '=' in member definition

I know this can be done with member bindings but this creates properties, not fields, if I understand well.

2

2 Answers

6
votes

According to this http://msdn.microsoft.com/en-us/library/vstudio/dd233233.aspx, that could be done as

type Vector2 =
   struct 
      val public X: int
      val public Y: int
      new(x: int, y: int) = { X = x; Y = y }
   end
2
votes

If an F# Record would work for you, then this will work:

type MyInt = {
    Value: int
};;

Then to initialize:

let i = {Value=1};;

Since I'm not completely sure of your use case, I'm not sure how helpful this is.

EDIT: For what it's worth, if your reason for preferring a value type is that you want value type equality semantics, records support that (even though they are reference types). Consider this:

type Vector2 = {
     X:int;
     Y:int
};;

type Vector2 =
  {X: int;
   Y: int;}

let v = {X=1;Y=1};;

val v : Vector2 = {X = 1;
                   Y = 1;}

let v2 = {X=1;Y=1};;

val v2 : Vector2 = {X = 1;
                    Y = 1;}

v = v2;;
val it : bool = true

let v3 = {X=2;Y=2};;
v = v3;;
val it: bool = false

I mean to say that even though records are reference types, one of the reasons that people use value types (the equality semantics) is not a problem with records. Even though it's a reference type, I believe it's a lot closer to the behavior of the C# code you're trying to emulate--for what it's worth.