Overriding static properties in F# with extension methods - f#

F# extension methods can be defined on types with the same name and type signature as existing instance and static methods to effectively override the default implementation of these methods, however I can't get this to work on static properties.
In particular, I'm trying to create an extension method for DateTime that returns a more precise time as follows:
#nowarn "51"
open System
module DateTimeExtensions =
open System.Runtime.InteropServices
[<DllImport("Kernel32.dll", CallingConvention = CallingConvention.Winapi)>]
extern void private GetSystemTimePreciseAsFileTime(int64*)
type System.DateTime with
// example showing that static methods can be overridden
static member IsLeapYear(_: DateTime) =
printfn "Using overridden IsLeapYear!"
true
// more accurate UtcNow method (note: not supported by older OS versions)
static member UtcNow =
printfn "Using overridden UtcNow!"
let mutable fileTime = 0L
GetSystemTimePreciseAsFileTime(&&fileTime)
DateTime.FromFileTimeUtc(fileTime)
However, the output when executing
open DateTimeExtensions
let _ = DateTime.IsLeapYear(DateTime.UtcNow)
is just
Using overridden IsLeapYear!
which shows that the static method 'override' is working, but not the static property.
(Note: I'm using F# 4.0)

This statement seems to be incorrect:
F# extension methods can be defined on types with the same name and
type signature as existing instance and static methods to effectively
override the default implementation of these methods, however I can't
get this to work on static properties.
No, they don't override.
You might be confused because in fact your signature of IsLeapYear is wrong, it should take an integer, that's why it works I mean you are not overriding anything, just adding a new (extension) method.
If you try it with the original signature you'll see that it doesn't work either:
type System.DateTime with
// example showing that static methods can NOT be overridden
static member IsLeapYear(_: int) =
printfn "Using overridden IsLeapYear!"
false
> DateTime.IsLeapYear(2000);;
val it : bool = true
Which is consistent with the behavior of the static property extension.
Anyway I'm not sure why it was decided not to override, if there was such decision at all when designing the language. I think it would be an interesting feature and if there is a good reason not to implement it at least it should emit a warning saying that since the method already exists it will never be called.
Maybe I will open an issue or a suggestion for the F# compiler.

Related

Fable: how to override a JS class method imported from a JavaScript external library? (typed)

What is the expected way to extend a class imported from a Javacript library while at the same being capable to call parent's members?
I tried several alternatives, using abstract classes apparently worked without errors but the child cannot call parent's abstract method, with interfaces there were no errors either but I cannot call to parent's class as there is no reference.
The best method I found is the following one overriding the mezhods, and althought the yielt code works, the compiler still emits an error:
error FSHARP: No abstract or interface member was found that corresponds to this override (code 855)
My current code:
[<Import("DataManager", from="library/data")>]
type DataManager<'Model> (conf:obj) =
class
member this.insert(_:'Model):Promise<obj> = jsNative
member this.update (_:'Model):Promise<obj> = jsNative
end
type MyAdaptor<'Model> (conf, inst)=
inherit DataManager<'Model> (conf)
let DB:obj = inst
do
printf "I've been created"
override this.insert(o:'Model):Promise<obj> =
printf "insert method comes with object:"
console.log o
base.insert o
//Constructors.Promise.Create o
override this.update(o:'Model): Promise<obj> =
printf "Update method comes with object:"
console.log o
base.update o
//Constructors.Promise.Create o
Previously I also tried to use just members and still call base's method but althought it compiled without issue, when calling instance's methods only parent's code was executed. I am afraid it might be a bug.
I also had several tries callint the inheritance manually in a self-made constructor but it usually fails to compile because the imported JS was either not recognize as a valid constructor or then I couldn't include the method definitions (I care about type safety).
It turns out that in F# people cannot override a method which has not been declared previously as abstract.
For that the solution was to declare the methods as abstract and provide a default implementation before override.
[<Import("DataManager", from="library/data")>]
type DataManager<'Model> (conf:obj) =
class
abstract member insert: 'Model -> Promise<obj>
default this.insert(_:'Model):Promise<obj> = jsNative
abstract member update:'Model -> Promise<obj>
default this.update (_:'Model):Promise<obj> = jsNative
end
After that it is possible to override the child class without issues.

F#: get source files to evaluate automatically

I'm making a project where there are separate source files/modules that add functions to a single Dictionary contained in a higher level file. However, I find that nothing in these source files evaluates on its own, even functions that take no arguments/code that isn't even inside a function.
As a result nothing is being added to the Dictionary. Is there a way to forcibly evaluate complete function calls in a module automatically? I'll give an example of what I'm trying to do:
Registry.fs:
let private functions = Dictionary<string, MessageHandler>()
let add type handler =
functions.Add(type, handler)
Handler1.fs:
Registry.add "type1" (fun m -> ....
)
Handler2.fs:
Registry.add "type2" (fun m -> ....
)
I believe you need to see this relevant topic. Loose method calls would get compiled as method calls inside of a static constructor for the enclosing type/module, when the F# code gets compiled to IL. This would roughly be equivalent to the following C# code, just to see the picture:
static class Handler1 {
static Handler1() {
// this is the static constructor
Registry.add "type1" ....
}
}
In .NET static constructors are not eagerly initialized1. This means, if you want to cause the .NET runtime to call the Handler1 static constructor, you need to access a static member of the type Handler1.
An example of using the type in a static context would be to
Expose a sufficiently accessible static member/method:
module Handler1 =
[<Literal>]
let Name = "Handler1"
Access that static member from your code, such as the main method:
[<EntryPoint>]
let main args =
printf Handler1.Name
The above line will force the .NET runtime to load the Handler1 type's static context, which will result in invoking the static constructor if the type is encoutered by your code for the first time. If your code never encounters a given type's static context (any static member or method), then it will never be initialized -- the static constructors will never get called.
This behaviour is by design of the .NET framework (and that is regardless of the chosen language -- C#, F#, VB, others -- they all compile to similar IL). The point is to not allocate unnecessary resources by types that are never actually used.
1 Until .NET 4, static type context was initialized when the given type was first encountered by the executing code, regardless if the user code is interacting with instace or static members of that type. After .NET 4, this slightly changed -- the static context is initialized only when the user code interacts with static members of the type.

F# Val without Self Identifier

Just curious why F# has:
member val Foo = ... with get, set
While omitting the self identifier (e.g. this.).
This is still an instance property. Maybe I am the only one confused when using it. But just bothered me enough to query whoever knows how the language was defined.
With this syntax, the property is almost totally auto-implemented -- all you provide is the initialization code, which essentially runs as part of the constructor.
One of the best-practice guard rails F# puts in place is that it does not let you access instance members before the instance is fully initialized. (wow, crazy idea, right?).
So you would have no use for a self-identifier in auto-props, anyways, since the only code you get to write is init code that can't touch instance members.
Per the MSDN docs (emphasis mine):
Automatically implemented properties are part of the initialization of
a type, so they must be included before any other member definitions,
just like let bindings and do bindings in a type definition. Note that
the expression that initializes an automatically implemented property
is only evaluated upon initialization, and not every time the property
is accessed. This behavior is in contrast to the behavior of an
explicitly implemented property. What this effectively means is that
the code to initialize these properties is added to the constructor of
a class.
Btw, if you try to be a smartass and use the class-level self-identifier to get around this, you'll still blow up at runtime:
type A() as this =
member val X =
this.Y + 10
with get, set
member this.Y = 42
let a = A()
System.InvalidOperationException: The initialization of an object or value resulted in an object or value being accessed recursively before it was fully initialized.
at Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions.FailInit()
at FSI_0013.A.get_Y()
at FSI_0013.A..ctor()
at <StartupCode$FSI_0014>.$FSI_0014.main#()
Edit: Worth noting that in upcoming C# 6, they also now allow auto-props with initializers (more F# features stolen for C#, shocker :-P), and there is a similar restriction that you can't use the self-identifier:
class A
{
// error CS0027: Keyword 'this' is not available in the current context
public int X { get; set; } = this.Y + 10;
public int Y = 42;
public A() { }
}

Working with SafeHandles in F#

I'm working with some F# code that uses platform invoke. One of the APIs I'm using returns a handle. Instead of using a nativeint, I've implemented my own SafeHandle (specifically SafeHandleMinusOneIsInvalid.) This makes working with the module containing the pinvoke signature a little clunky. Here is an example:
type MySafeHandle() =
inherit SafeHandleZeroOrMinusOneIsInvalid(true)
override this.ReleaseHandle() =
NativeMethods.FreeHandle(base.handle)
true
module NativeMethods =
[<DllImport("mylibrary.dll")>]
extern void GetHandle([<Out>]MySafeHandle& handle)
[<DllImport("mylibrary.dll")>]
extern void FreeHandle(nativeint handle)
This won't compile because the module and the class recursively reference each other, which doesn't work. If I move the module above MySafeHandle, then GetHandle won't see the SafeHandle.
I can't move the platform invoke methods inside of MySafeHandle since it appears that extern methods in F# must be in modules (even though the compiler won't stop you from trying to put them in a class).
It also appears that F#'s recursive types don't work between a module and a class, just classes.
Is there a solution to this problem that does not require declaring two different modules? Ideally I'd like to keep all of my platform invoke code organized into one module.
Well I know of one, because I had the same problem myself.
The thing is, it's kinda ugly I guess:
It involves a static reference that you set to the imported function later in the module.
type MySafeHandle() =
inherit SafeHandleZeroOrMinusOneIsInvalid(true)
static let freeHandle = ref Unchecked.defaultof<_>
static member internal SetFreeHandleRef value = freeHandle := value
override this.ReleaseHandle() =
!freeHandle base.handle
true
module NativeMethods =
[<DllImport("mylibrary.dll")>]
extern void GetHandle([<Out>]MySafeHandle& handle)
[<DllImport("mylibrary.dll")>]
extern void FreeHandle(nativeint handle)
MySafeHandle.SetFreeHandleRef FreeHandle

Static extension methods supporting member constraints

I need to implement a static extension method supporting member constraints on some basic primitive types like integers, floats, etc. Here's my code for signed integers:
module MyOperators =
let inline foo (x : ^T) = (^T : (static member Foo : ^T -> int) (x))
type System.Int32 with
static member Foo(x : Int32) = 7 // static extension
Test code:
open MyOperators
let x = foo 5 // x should be 7
But compiler complains with error:
The type 'System.Int32' does not
support any operators named 'Foo'
What am I missing here? Thanks!
Static member constraints in F# never find 'extension methods', they can only see intrinsic methods on types (and a few special cases called out in the F# language spec).
Perhaps you can use method overloading instead? What is your ultimate goal?
F#'s static type constraints don't work with extension methods. Extension methods cannot statically be checked at compile time, and even so, you can have multiple definitions for Int32::Foo (depending on which namespace you imported).
Unfortunately, to solve your problem you might have to resort to using reflection.

Resources