Search code examples
c#f#computed-propertiesc#-7.0c#-to-f#

F#: How can I define a computed property in a type?


In C#, I can define a computed property as such:

public class MyViewModel
{
    public DateTime StartDate { get; set; }
    public string StartDateFormatted => StartDate.ToString("yyyy.MM.dd h:mm tt");
}

How can I do this in F#?

[<DataContract>]
[<CLIMutable>]
type MyViewModel = {
    [<DataMember>] StartDate            : DateTime
    [<DataMember>] StartDateFormatted   : string // How can I make this a computed property?
 }

Solution

  • It's very similar in F#:

    open System
    
    type MyViewModel() =
        member val StartDate = DateTime.Now
        member this.StartDateFormatted =
            this.StartDate.ToString("yyyy.MM.dd h:mm tt")
    
    let model = MyViewModel()
    printfn "%A" model.StartDateFormatted   // "2022.04.27 2:56 tt"
    

    Note that I've used F#'s object syntax to define the type, rather than its record syntax. This is closer to what you're familiar with in C#.

    If you want to use a record type, it would look something like this instead:

    type MyViewModel =
        {
            mutable StartDate : DateTime
        }
        member this.StartDateFormatted =
            this.StartDate.ToString("yyyy.MM.dd h:mm tt")
    
    let model = { StartDate = DateTime.Now }
    printfn "%A" model.StartDateFormatted
    

    Note that records are immutable by default, so aren't usually used for view-models (which, in an MVVM design, are updated to track changes made in the UI).