martinb
martinb

Reputation: 63

F# Skip Range Operator

I'm trying to generate lists of dates (time periods) in F# and I found my answer at (F# generate a sequence/array of dates) and it works perfectly.

However I cannot wrap my ahead around the definition of the (+) static member.

static member (+) (d:DateTime, Span wrapper) = ...

Particularly the Span wrapper portion. I even re-wrote is as:

static member (+) (d:DateTime, wrapper:Span) = ...

and even though it compiles (fsi) it does not work.

Only when I rewrote it to match the original syntax it does work as expected.

I looked at the MSDN docs as well as some of the F# books I have but I cannot find anything that explains that particular syntax for the (+) operator.

Upvotes: 4

Views: 293

Answers (2)

Tomas Petricek
Tomas Petricek

Reputation: 243041

This is quite subtle syntactic trick that you can use with type definitions of the following form:

type MyNumber = MyNumber of int

This defines a type MyNumber which is an integer wrapped using a constructor that is also named MyNumber. So, we are defining a type and a constructor of the same name. We could use different names:

type MyNumberType = MyNumberCtor of int

The following syntax is used for pattern matching when you are extracting the value. Here, we are using the constructor:

let getNumber (MyNumber n) = n
let getNumber (MyNumberCtor n) = n

The following syntax is type annotation (which uses the type name):

let doNothing (n:MyNumber) = 1
let getNumber (n:MyNumberType) = 1

Here, we cannot do much with n, because it is the wrapped value - so we'd have to use pattern matching to extract it. As you can see in the answer from @pad, the other way to write the pattern matching is to use the match construct. In any case, there is nothing special related to the operators and types - it is just a naming trick that people sometimes use when defining wrappers.

Upvotes: 4

pad
pad

Reputation: 41290

For the context, here is original example:

type Span = 
  | Span of TimeSpan
  static member (+) (d:DateTime, Span wrapper) = d + wrapper
  static member Zero = Span(new TimeSpan(0L))

In (+), the author uses pattern matching directly on the argument. It means that wrapper has type of TimeSpan, and d + wrapper is an operation between DateTime and TimeSpan

The example looks clearer in the following verbose form:

static member (+) (d:DateTime, span: Span) = 
    match span with
    | Span wrapper ->
         d + wrapper

Upvotes: 5

Related Questions