Accessing an explicit conversion operator from F# - f#

I am getting the following error when reading date values out of postgresql using npgsql:
This expression was expected to have type
DateTime
but here has type
NpgsqlTypes.NpgsqlDate
Now the npgsql docs refer to an explicit operator being defined:
[C#]
public static explicit operator DateTime(
NpgsqlDate date
);
but I can't figure out how to access this from F#.
There are several kludgy, longhand ways of achieving what I need, but I am disappointed and frustrated that I was unable to find a way of accessing the inbuilt cast.
I tried the old Convert.ToDateTime(...), but even that doesn't work.
Anybody got a clue? Thx.

The explicit conversion operator can be accessed by calling the op_Explicit (I had the casing wrong in the earlier comment; I had not tried it myself then) function on the type:
let date = NpgsqlDate.op_Explicit npgsqlDate
I have also found various places (like in Yan Cui's blog here) that define an F# operator like !> for (all!) explicit conversions for convenience, so you can just say
let date = !> npgsqlDate
I think that is a pretty neat way.

Related

Better way to assign a value with nullable field in dart

Is there a better way to do this?
Assignment(
dueAt: json['due_at'] == null ?
null :
DateTime.parse(json['due_at']).toLocal()
)
The attribute "dueAt" in Assignment class can be null and i need to parse the string of json['due_at'] to a DateTime, but json['due_at'] can be null too.
Is not really a problem right now but seems noisy and repetitive.
First and foremost, it looks like you're writing JSON serialization code by hand. Your life will be much easier and less bug-prone if you let a library do this instead. json_serializable is very simple and powerful and 100% worth looking into.
However, this pattern is still common outside of json code.
You could also consider writing an extension method for Object? that behaves like the Kotlin standard library's let function (https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/let.html)
You can then use Dart's ?. syntax to handle the rest of the logic:
// extension on T rather than Object? to maintain type information
extension Example<T> on T {
R let<R>(R Function(T) function) => function(this);
}
This just applies a given function to this, which isn't incredibly useful on it's own, but allows the use of ?.:
final DateTime? dueAt = json['due_at']?.let(DateTime.parse);
If json['due_at'] evaluates to null, the ?. operator short-circuits, and dueAt is set to null. Otherwise, it evaluates to DateTime.parse(json['due_at']).
Or, you could just use package:kt_dart which ports much of the Kotlin standard library to Dart
In this particular case you may want to use tryParse instead of parse. If dueAt is of type DateTime? you can simply call:
Assignment( dueAt: DateTime.tryParse(json['due_at'])?.toLocal() );
Be aware though that tryParse will return null for any invalid date string (be it null or an improperly formatted string). This may or may not be desired behavior depending on your intended use.

What does the "as" keyword do in Dart language?

I'm confused as to the uses of "as" keyword.
Is it a cast operator or alias operator?
I encountered the following code on the internet which looked like a cast operator:
var list = json['images'] as List;
What does this mean?
as means different things in different contexts.
It's primarily used as a type cast operator. From the Dart Language Tour:
as: Typecast (also used to specify library prefixes)
It links to an explanation of how as is also used to add a prefix to an imported library to avoid name collisions. (as was reused to do different things to avoid needing extra keywords.)
just to add the as keyword is now flagged by the linter and they prefer you to use a check like is
if (pm is Person)
pm.firstName = 'Seth';
you can read more here https://github.com/dart-lang/linter/issues/145
As the language tour says:
Use the as operator to cast an object to a particular type if and only if you are sure that the object is of that type.
Following with your example:
var list = json['images'] as List;
You would use as here to cast or convert json['images'] into a <List> object.
From another SO post (talking about explicit cast vs. as):
as ... is more like an assertion, if the values type doesn't match as causes a runtime exception.
You can also use it when importing packages. A common example is the dart:convert as JSON which then can be reached final foo = JSON.jsonDecode(baz)
It's casting, your code is similar as:
List list = json['images'];

Type name as identifier in F#

I just started to study F# and accidentally wrote this binding
let List = 1
Now when I try to obtain List methods such as 'filter' I get this error
error FS0039: The field, constructor or member 'filter' is not defined.
Of course using method with full type name like Microsoft.FSharp.Collections.List.filter is still working.
I'm wondering why it is possible to use type name as identifier in F# and how I can set back name List to type List from Microsoft.FSharp.Collections.
When I tried to reassign like this
type List = Microsoft.FSharp.Collections.List<'T>
I get
Error FS0039: The type parameter 'T is not defined.
Thank you!
In F# you can redefine almost everything and shadow existing definitions. This applies to both types (well actually types have a different behavior regarding shadowing, they shadow their values as you open the namespaces) and values but not interchangeably since values and type (and also modules) can somehow coexist at the same time in the scope. The compiler will do his best to find out which one is.
You are not forced to, but it's a common good practice in F# not to use let bindings in uppercase.
Regarding your second question, you are using a type parameter in the right side which doesn't exist in the left side of the assignment, it should be:
type List<'T> = Microsoft.FSharp.Collections.List<'T>
But notice that filter doesn't belong to the type. It's rather defined in the List module.
You should just rename your let binding from List to something sensible - as Gustavo mentioned, your definition is shadowing the core List module from F# and there is no way to use List to refer both to your integer and to the module. Shadowing core functions will make your code pretty confusing. It's also a good idea to use camelCase for let bindings, but that's a matter of taste.
If you insist on shadowing List, then you won't be able to call List.filter using List.filter. If you wanted something shorter, you could define module alias:
module FsList = Microsoft.FSharp.Collections.List
Note that your attempt to do something similar with List<'T> does not do the same thing, because functions such as filter are in a module named List rather than being static members of the type. With this, you can call filter using FsList.filter.

Why is there a Value property on the Option type in F#?

According to the documentation for Option.Value<'T>:
Get the value of a Some option. A NullReferenceException is raised if
the option is None.
and
This function is for use by compiled F# code and should not be used
directly.
Does the last sentence imply that it's due to interop? What's the use case if so?
Otherwise it seems very strange since the whole point of the Option type is to make the possibility of undefined values explicit and encourage handling of them, which easily can be circumvented:
let none : int option = None
let value = none.Value
I imagine it is there so that
match v with
|Some(t) -> t
works - without that Value property, you wouldn't be able to get the t with any functions which are available to F# code (Note there are some DU properties which are not accesible from F# which are an alternative here). There may also be some very minor speed benifits if you know that the option is Some as you don't check it if you use value directly

Delphi: Generic type inference of reference argument

What's the best way to get around the shortcoming of generic type inferencing of reference arguments, so that I don't have to specify the type in every call?
Update: I don't mind other (including non-generic) solutions as long as it works with multiple (any?) types.
This seems to still not have been resolved, although known for quite some time.
Please vote for a resolution to this on Embarcaderos Quality Central: Issue #78103.
From a comment by Barry Kelly to Generic Methods and Type Inferencing:
PS: Your example, in Tiburon, almost works. Method type inference works well for arguments passed by value. It doesn’t work for arguments passed by reference, unfortunately (the compiler is being too strict).
Now, almost three years later, I'm trying the same thing in Delphi XE, and it complains that:
[DCC Error] INIv1_Parser.pas(81): E2033 Types of actual and formal var parameters must be identical
When calling:
function FindDataItemValue<T>(ItemType: TDataItemType; out Value: T): Boolean;
With:
var MaxG: Real;
...
if Data.FindDataItemValue(PAR_MaxG, MaxG) and (MaxG = 2.5) then ...
Commonly suggested work-around: However, if I add the generalization on the call, it works fine; although annoying that it is even needed.
Update:
Thus far, The best I've come up with is to use either Variants or the TValue record from the Rtti module. Using variants I implement interfaces when I need to use objects, and store a reference to that (interface) in the variant.
Type inference does not currently work for var and out parameters. I agree that it is highly annoying.
There is no workaround. You have to specify the type.
var
MaxG: Real;
...
if Data.FindDataItemValue<Real>(PAR_MaxG, MaxG) and (MaxG = 2.5) then ...
If you want Embarcadero to resolve this, then vote for this QC entry that is about your issue.
The QC entries with the highest votes get more attention.
The best way is to do exactly what's demonstrated in the article you cite: Include the type parameters in the method call:
if Data.FindDataItemValue<Real>(PAR_MaxG, MaxG) ...

Resources