Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# Skip Range Operator

Tags:

f#

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.

like image 672
martinb Avatar asked Jan 08 '23 15:01

martinb


2 Answers

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
like image 68
pad Avatar answered Jan 14 '23 22:01

pad


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.

like image 45
Tomas Petricek Avatar answered Jan 14 '23 20:01

Tomas Petricek