Optional parameters in Fsharp records - properties

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

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.

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

Related

Spock Extension - Extracting variable names from Data Tables

In order to extract data table values to use in a reporting extension for Spock, I am using the
following code:
#Override
public void beforeIteration(IterationInfo iteration) {
Object[] values = iteration.getDataValues();
}
This returns to me the reference to the objects in the data table. However, I would like to get
the name of the variable that references the value.
For example, in the following test:
private static User userAge15 = instantiateUserByAge(15);
private static User userAge18 = instantiateUserByAge(18);
private static User userAge19 = instantiateUserByAge(19);
private static User userAge40 = instantiateUserByAge(40);
def "Should show popup if user is 18 or under"(User user, Boolean shouldShowPopup) {
given: "the user <user>"
when: "the user do whatever"
...something here...
then: "the popup is shown is <showPopup>"
showPopup == shouldShowPopup
where:
user | shouldShowPopup
userAge15 | true
userAge18 | true
userAge19 | false
userAge40 | false
}
Is there a way to receive the string “userAge15”, “userAge18”, “userAge19”, “userAge40” instead of their values?
The motivation for this is that the object User is complex with lots of information as name, surname, etc, and its toString() method would make the where clause unreadable in the report I generate.
You can use specificationContext.currentFeature.dataVariables. It returns a list of strings containing the data variable names. This should work both in Spock 1.3 and 2.0.
Edit: Oh sorry, you do not want the data variable names ["a", "b", "expected"] but ["test1", "test1", "test2"]. Sorry, I cannot help you with that and would not if I could because that is just a horrible way to program IMO. I would rather make sure the toString() output gets shortened or trimmed in an appropriate manner, if necessary, or to (additionally or instead) print the class name and/or object ID.
Last but not least, writing tests is a design tool uncovering potential problems in your application. You might want to ask yourself why toString() results are not suited to print in a report and refactor those methods. Maybe your toString() methods use line breaks and should be simplified to print a one-line representation of the object. Maybe you want to factor out the multi-line representation into other methods and/or have a set of related methods like toString(), toShortString(), toLongString() (all seen in APIs before) or maybe something specific like toMultiLineString().
Update after OP significantly changed the question:
If the user of your extension feels that the report is not clear enough, she could add a column userType to the data table, containing values like "15 years old".
Or maybe simpler, just add an age column with values like 15, 18, 19, 40 and instantiate users directly via instantiateUserByAge(age) in the user column or in the test's given section instead of creating lots of static variables. The age value would be reported by your extension. In combination with an unrolled feature method name using #age this should be clear enough.
Is creating users so super expensive you have to put them into static variables? You want to avoid statics if not really necessary because they tend to bleed over side effects to other tests if those objects are mutable and their internal state changes in one test, e.g. because someone conveniently uses userAge15 in order to test setAge(int). Try to avoid premature optimisations via static variables which often just save microseconds. Even if you do decide to pre-create a set of users and re-use them in all tests, you could put them into a map with the age being the key and conveniently retrieve them from your feature methods, again just using the age in the data table as an input value for querying the map, either directly or via a helper method.
Bottom line: I think you do not have to change your extension in order to cater to users writing bad tests. Those users ought to learn how to write better tests. As a side effect, the reports will also look more comprehensive. 😀

Are extensible records useless in Elm 0.19?

Extensible records were one of the most amazing Elm's features, but since v0.16 adding and removing fields is no longer available. And this puts me in an awkward position.
Consider an example. I want to give a name to a random thing t, and extensible records provide me a perfect tool for this:
type alias Named t = { t | name: String }
„Okay,“ says the complier. Now I need a constructor, i.e. a function that equips a thing with specified name:
equip : String -> t -> Named t
equip name thing = { thing | name = name } -- Oops! Type mismatch
Compilation fails, because { thing | name = ... } syntax assumes thing to be a record with name field, but type system can't assure this. In fact, with Named t I've tried to express something opposite: t should be a record type without its own name field, and the function adds this field to a record. Anyway, field addition is necessary to implement equip function.
So, it seems impossible to write equip in polymorphic manner, but it's probably not a such big deal. After all, any time I'm going to give a name to some concrete thing I can do this by hands. Much worse, inverse function extract : Named t -> t (which erases name of a named thing) requires field removal mechanism, and thus is not implementable too:
extract : Named t -> t
extract thing = thing -- Error: No implicit upcast
It would be extremely important function, because I have tons of routines those accept old-fashioned unnamed things, and I need a way to use them for named things. Of course, massive refactoring of those functions is ineligible solution.
At last, after this long introduction, let me state my questions:
Does modern Elm provides some substitute for old deprecated field addition/removal syntax?
If not, is there some built-in function like equip and extract above? For every custom extensible record type I would like to have a polymorphic analyzer (a function that extracts its base part) and a polymorphic constructor (a function that combines base part with additive and produces the record).
Negative answers for both (1) and (2) would force me to implement Named t in a more traditional way:
type Named t = Named String t
In this case, I can't catch the purpose of extensible records. Is there a positive use case, a scenario in which extensible records play critical role?
Type { t | name : String } means a record that has a name field. It does not extend the t type but, rather, extends the compiler’s knowledge about t itself.
So in fact the type of equip is String -> { t | name : String } -> { t | name : String }.
What is more, as you noticed, Elm no longer supports adding fields to records so even if the type system allowed what you want, you still could not do it. { thing | name = name } syntax only supports updating the records of type { t | name : String }.
Similarly, there is no support for deleting fields from record.
If you really need to have types from which you can add or remove fields you can use Dict. The other options are either writing the transformers manually, or creating and using a code generator (this was recommended solution for JSON decoding boilerplate for a while).
And regarding the extensible records, Elm does not really support the “extensible” part much any more – the only remaining part is the { t | name : u } -> u projection so perhaps it should be called just scoped records. Elm docs itself acknowledge the extensibility is not very useful at the moment.
You could just wrap the t type with name but it wouldn't make a big difference compared to approach with custom type:
type alias Named t = { val: t, name: String }
equip : String -> t -> Named t
equip name thing = { val = thing, name = name }
extract : Named t -> t
extract thing = thing.val
Is there a positive use case, a scenario in which extensible records play critical role?
Yes, they are useful when your application Model grows too large and you face the question of how to scale out your application. Extensible records let you slice up the model in arbitrary ways, without committing to particular slices long term. If you sliced it up by splitting it into several smaller nested records, you would be committed to that particular arrangement - which might tend to lead to nested TEA and the 'out message' pattern; usually a bad design choice.
Instead, use extensible records to describe slices of the model, and group functions that operate over particular slices into their own modules. If you later need to work accross different areas of the model, you can create a new extensible record for that.
Its described by Richard Feldman in his Scaling Elm Apps talk:
https://www.youtube.com/watch?v=DoA4Txr4GUs&ab_channel=ElmEurope
I agree that extensible records can seem a bit useless in Elm, but it is a very good thing they are there to solve the scaling issue in the best way.

Internal fileds (columns) in Room's Entity

I'd like to mark some Room entity's properties as internal. E.g.
#Entity(tableName = "users")
class User {
// ...
#ColumnInfo(name = "admin_id")
internal var adminId: String? = null
}
However, this produce compile errors like:
Error:(10, 1) error: Cannot find getter for field.
The only way how to make this works seems to use lateinit modifier, though, it can't be used for nullable neither primitive fields.
I've tried a "hack": a private field with internal getter/setter, but that doesn't work either.
The compiled generated version obviously adds some suffix to the generated methods (setAdminId$sdk_debug) that doesn't work with room. The "lateinited" field's setters/getters have this suffix too, but the field stay itself public.
Is there any way how to make columns internal?
It seems its getting supported in latest Room 2.5.0-alpha01
Old answer: I didn't solve this and I have to define new set of entities and mapper between them.
The internal names get mangled by Kotlin, so I made it work by just making sure the correct name is used with #JvmName:
#Entity(tableName = "users")
class User {
// ...
#ColumnInfo(name = "admin_id")
#get:JvmName("adminId")
internal var adminId: String? = null
}
Note: This might make it easier to accidentally use this from Java then.

F# Record vs Class

I used to think of a Record as a container for (immutable) data, until I came across some enlightening reading.
Given that functions can be seen as values in F#, record fields can hold function values as well. This offers possibilities for state encapsulation.
module RecordFun =
type CounterRecord = {GetState : unit -> int ; Increment : unit -> unit}
// Constructor
let makeRecord() =
let count = ref 0
{GetState = (fun () -> !count) ; Increment = (fun () -> incr count)}
module ClassFun =
// Equivalent
type CounterClass() =
let count = ref 0
member x.GetState() = !count
member x.Increment() = incr count
usage
counter.GetState()
counter.Increment()
counter.GetState()
It seems that, apart from inheritance, there’s not much you can do with a Class, that you couldn’t do with a Record and a helper function. Which plays better with functional concepts, such as pattern matching, type inference, higher order functions, generic equality...
Analyzing further, the Record could be seen as an interface implemented by the makeRecord() constructor. Applying (sort of) separation of concerns, where the logic in the makeRecord function can be changed without risk of breaking the contract, i.e. record fields.
This separation becomes apparent when replacing the makeRecord function with a module that matches the type’s name (ref Christmas Tree Record).
module RecordFun =
type CounterRecord = {GetState : unit -> int ; Increment : unit -> unit}
// Module showing allowed operations
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module CounterRecord =
let private count = ref 0
let create () =
{GetState = (fun () -> !count) ; Increment = (fun () -> incr count)}
Q’s: Should records be looked upon as simple containers for data or does state encapsulation make sense? Where should we draw the line, when should we use a Class instead of a Record?
Note the model from the linked post is pure, whereas the code above is not.
I do not think there is a single universal answer to this question. It is certainly true that records and classes overlap in some of their potential uses and you can choose either of them.
The one difference that is worth keeping in mind is that the compiler automatically generates structural equality and structural comparison for records, which is something you do not get for free for classes. This is why records are an obvious choice for "data types".
The rules that I tend to follow when choosing between records & classes are:
Use records for data types (to get structural equality for free)
Use classes when I want to provide C#-friendly or .NET-style public API (e.g. with optional parameters). You can do this with records too, but I find classes more straightforward
Use records for types used locally - I think you often end up using records directly (e.g. creating them) and so adding/removing fields is more work. This is not a problem for records that are used within just a single file.
Use records if I need to create clones using the { ... with ... } syntax. This is particularly nice if you are writing some recursive processing and need to keep state.
I don't think everyone would agree with this and it is not covering all choices - but generally speaking, using records for data and local types and classes for the rest seems like a reasonable method for choosing between the two.
If you want to achieve data hiding in a record, I feel there are better ways of going about it, like abstract data type "pattern".
Take a look at this:
type CounterRecord =
private {
mutable count : int
}
member this.Count = this.count
member this.Increment() = this.count <- this.count + 1
static member Make() = { count = 0 }
The record constructor is private, so the only way of constructing an instance is through the static Make member,
count field is mutable - not something to be proud about, but I'd say fair game for your counter example. Also it's not accessible from outside the module where it's defined due to private modifier. To access it from outside, you have the read-only Count property.
Like in your example, there's an Increment function on the record that mutates the internal state.
Unlike your example, you can compare CounterRecord instances using auto-generated structural comparisons - as Tomas mentioned, the selling point of records.
As for records-as-interfaces, you might see that sometimes in the field, though I think it's more of a JavaScript/Haskell idiom. Unlike those languages, F# has the interface system of .NET, made even stronger when coupled with object expressions. I feel there's not much reason to repurpose records for that.

What is a "field"? "Field" vs "Field Value"

In a passport there is a field: First Name, and that field has a value John.
I assert that it is correct to describe the relationship as follows:
Field First Name:
Has a name (First Name).
Has a set of valid values (e.g. defined by regex [A-Za-z. ]{1,30}
Has a description (name that stands first in the person's full name)
And Passport is a set of pairs (field : field value), such that:
passport has a field "First Name"
passport has a value for field "First Name"
Point here is that it is incorrect to say:
"First Name value is John";
The correct way (conceptually/academically) is to say:
"passport has a value 'John' for field 'First Name'".
In practical terms it means (pseudo C#):
struct Passport {
Map<Field, object> fieldValues;
}
struct Field {
string Name;
string Description;
bool IsValidValue(object value);
}
Q: Does this make sense? Any thoughts?
This is pretty subjective and entirely context sensitive, and seems like a silly thing to nitpick over.
Correct or not, if I'm discussing "passport" with a co-worker, I'd throw something at them if they corrected me every time I said "firstName is 'john'", and told me to say it as "passport's firstname field is 'john'". You'd just come across as annoying.
Well..not really in c# see Scott Bellware's answer to my question about C# not being Object Oriented (kinda).
In C# passport is a class so it makes perfect sense to say
"The Passport has a field FirstName"
For a particular instance "FirstName value is John".
Here the first clause describes the class and the next one the object. In a more OO language like ruby I think saying "passport has a value 'John' for field 'First Name'" would be equivalent, you're just describing two objects - the Passport prototype, and the instance of it in the same sentence.
I'm getting pretty confused in it myself though. The question is oddly phrased since there would doubtless be much more to a passport than just its fields, for example a long-standing and persisted identity.
If you are going to model such thing, then you may take a look at reflection API of java or c#. It is pretty similar to what you described. Class has set of fields, field has name, type and other attributes, not value. Object is an instance of class and you can ask object for the value of specified field. Different objects of the same class have values for the same fields, so you may say they share fields. So if you are trying to model class-based OOP then you are probably right.
However this is not the only way to do OOP. There is prototype-based OOP which looks differently, as there are no classes, only objects, so objects contain field with values so there is not much difference if you say that object contain field and field has a value.
So the answer to "Does this make sense?" I think is "yes" because similar thing is in reflection and is used widely. If it is right or wrong - depends on your needs.
UPD: regarding "value = Passport[Field]" vs "value = Passport.Field.Value"
I'd introduce one more passport to make it clear
firstNameField = PassportClass.Fields["FirstName"]
myName = myPassport[firstNameField]
yourName = yourPassport[firstNameField]
assumes that both passport have same fields, that makes sense. Having different passports with different fields may have a sense, just a different one.
No. At least in OOP, it's the field's responsibility to retain the value. Although the object is responsible for ensuring that value is consistent with the other fields or the object's constraints, the actual "containing of the value is the field's job.
Using your example:
Field First Name:
Has a name (First Name).
Has a type (int, string, object)
Has a description (optional)
Has a value
And Passport is a set fields:
May define constraints on such a field as defined by the model, ensuring the value and the object's state as a whole is valid