Alan Wayne
Alan Wayne

Reputation: 5394

In F#, how to update optional nested records?

(Newbie question).

I have been struggling with updating nested records with options in F#. How is this done?

Please assume:

module Visit =
    type Model =
        {
            Id: int
            Name: string
        }
    let initWithTime (t:DateTime) =
        {
            Id = 0
            Name = sprintf "Time is %A" t
        }

module Cell =
    type Model =
       {
            Id: int
            Visit: Visit.Model option
       }

let setVisitFromInteger (i:int, m:Model) =
        let appointmentTime = 
            DateTime.Today + TimeSpan.FromMinutes(float i)
        { m with Visit = { m.Visit 
                           match m.Visit with
                           | Some x -> x with Name = sprintf "New appointment time %A" appointmentTime
                           | None -> Visit.initWithTime appointmentTime
                         }
        }

Clearly, setVisitFromInteger is all wrong. How is a nested optional record correctly updated?

TIA

Upvotes: 1

Views: 225

Answers (1)

Phillip Carter
Phillip Carter

Reputation: 5005

I think you just have a little confusion with the syntax. This is a correct version:

open System

module Visit =
    type Model =
        {
            Id: int
            Name: string
        }
    let initWithTime (t:DateTime) =
        {
            Id = 0
            Name = sprintf "Time is %A" t
        }

module Cell =
    type Model =
       {
            Id: int
            Visit: Visit.Model option
       }

open Cell

let setVisitFromInteger (i:int, m:Model) =
        let appointmentTime = 
            DateTime.Today + TimeSpan.FromMinutes(float i)
        { m with
            Visit =
                match m.Visit with
                | Some x ->  { x with Name = sprintf "New appointment time %A" appointmentTime }
                | None -> Visit.initWithTime appointmentTime
                |> Some
        }

Note that the Visit in the record update expression is an option, not a record, so it doesn't need record syntax. However, the record syntax is required inside the pattern match since you're trying to do a nested record update expression.

Upvotes: 2

Related Questions