Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optional parameters in Fsharp records

I need to modify and add new property for my F Sharp record. but then it gives errors for the previous instances which are made without this new field. I made it as Nullable ,but still the same error occures, Please help me to solve this

like image 921
Heshan Avatar asked Dec 13 '22 23:12

Heshan


2 Answers

I presume you mean "optional" as in "a field that I don't provide when instantiating the record". However, there is no such thing as an optional field in F# records unfortunately (or fortunately, depending on your point of view). All record fields that you specify must be present at the point when you instantiate it.

See also this closely related question.

You may consider this trade-off:

  • Use a record. Each time you update the record, the F# compiler will scream and alert you about all places where you used this record, and you need to now provide the additional information. The additional information can be a None for the fields you added, if they are options. The big advantage: Your code itself will not have to handle all of the possibly many cases of "what to do if field1 is missing? What if field2 is missing, too?"

  • Use a class. When you update the class, the F# compiler will not enforce any sort of completeness check about the information you put into the class. (You can view records as classes where all fields are constructor arguments, and all must be provided). Hence, updating the class definition causes no overhead, but your code needs handle all the missing values.

I personally prefer records just because it forces me to think through the implications of adding a new field.

There is of course a middle ground: You can use records, but instantiate all of them via static members or something alike:

type Name = 
    { 
        First: string
        Family: string
    }        
    static member Create(first, family) = { First = first; Family = family}

If, in your code, you always use Name.Create to instantiate the record, you will of course be able to add a MiddleName field without any consumer code noticing.

like image 110
Anton Schwaighofer Avatar answered Jan 27 '23 19:01

Anton Schwaighofer


The Option type is preferred over null in F#, for the simple reason that "uninitialized variables" do not exist in the functional way of thinking.

Let's start by building a record that represents a VacationRequest, which has to be approved by the boss.

type VacationRequest =
   {Name : string
    Date : DateTime
    Approval : string option}

The problem with your approach is that all fields have to be assigned on construction, so this won't compile:

let holiday =
   {Name = "Funk"
    Date = DateTime(2020,12,31)}

You can work around this using a helper function, which implicitly sets the option value.

let fillInRequest name date =
   {Name = name 
    Date = date 
    Approval = None}

Now you can build the record using the helper function.

let holiday = fillInRequest "Funk" <| DateTime(2020,12,31)

Did notice something funny when sending the code to FSI.

val holiday : VacationRequest = {Name = "Funk";
                                 Date = 31/12/2020 12:00:00 ;
                                 Approval = null;}

The boss could then update the request (creating a new record)

let approvedHoliday =
    {holiday with Approval = Some "boss' name"}
val approvedHoliday : VacationRequest = {Name = "Funk";
                                         Date = 31/12/2020 12:00:00 ;
                                         Approval = Some "boss' name";}

or send it back unaltered

let betterLuckNextTime = holiday
like image 34
Funk Avatar answered Jan 27 '23 17:01

Funk