views:

190

answers:

4

I have a F# record type and want one of the fields to be optional:

type legComponents = {
    shares : int<share> ;
    price : float<dollar / share> ;
    totalInvestment : float<dollar> ;
}

type tradeLeg = {
    id : int ;
    tradeId : int ;
    legActivity : LegActivityType ;
    actedOn : DateTime ;
    estimates : legComponents ;
    ?actuals : legComponents ; 
}

in the tradeLeg type I would like the the actuals field to be optional. I can't seem to figure it out nor can I seem to find a reliable example on the web. It seem like this should be easy like

let ?t : int = None

but I realy can't seem to get this to work. Ugh - thank you

T

A: 
actuals : legComponents option;
Jon Harrop
+3  A: 

How about Option?

type tradeLeg = {
    id : int option;
    tradeId : int option;
    legActivity : LegActivityType option;
    actedOn : DateTime option;
    estimates : legComponents option;
    actuals : legComponents option; 
}
ChaosPandion
let me = StrangleMyself !optionI seriously thought I tried this, this afternoon. Busy running in and out of meeting - I guess I need to do a better job of taking notes and reading the specs. I humbly thank youTodd
akaphenom
A: 

as a comment to the existing posts, here's an example for option type:

..
id: int option;
..

match id with
  | Some x -> printfn "the id is %d" x
  | None -> printfn "id is not available" 

you can blind id with a option value:

let id = Some 10

or

let id = None

and refer this MSDN page: http://msdn.microsoft.com/en-us/library/dd233245%28VS.100%29.aspx.

Here's another example for option type, and you probably will be interested with Seq.unfold.

Yin Zhu
+3  A: 

As others pointed out, you can use the 'a option type. However, this doesn't create an optional record field (whose value you don't need to specify when creating it). For example:

type record = 
  { id : int 
    name : string
    flag : bool option }

To create a value of the record type, you still need to provide the value of the flag field:

let recd1 = { id = 0; name = "one"; flag = None }     
let recd2 = { id = 0; name = "one"; flag = Some(true) } 

// You could workaround this by creating a default record 
// value and cloning it (but that's not very elegant either):
let defaultRecd = { id = 0; name = ""; flag = None }     
let recd1 = { defaultRecd  with id = 0; name = "" }

Unfortunately, (as far as I know) you can't create a record that would have a truly option field that you could omit when creating it. However, you can use a class type with a constructor and then you can use the ?fld syntax to create optional parameters of the constructor:

type Record(id : int, name : string, ?flag : bool) = 
  member x.ID = id
  member x.Name = name
  member x.Flag = flag

let rcd1 = Record(0, "foo")
let rcd2 = Record(0, "foo", true)

The type of rcd1.Flag will be bool option and you can work with it using pattern matching (as demonstrated by Yin Zhu). The only notable difference between records and simple classes like this one is that you can't use the with syntax for cloning classes and that classes don't (automatically) implement the structural comparison semantics.

Tomas Petricek
Got it! thx:type record = { i : int flag : bool option } let recd1 = { i = 0; flag = None } let recd2 = { i = 0; flag = Some(true) } type record2 = { r1: record ; r2: record option}let recd3 = { r1 = { i = 0; flag = None } ; r2 = Some({ i = 0; flag = Some(true)}) }let recd4 = { r1 = { i = 0; flag = None } ; r2 = None }
akaphenom
@akaphenom: Code in comments isn't particularly readable. But I guess that your example using classes could look like this: `let recd4 = Record2(Record(0))` (without setting `r2` and `flag`) or for example `recd5 = Record2(Record(0, true), Record(1, false))` when setting all properties.
Tomas Petricek