F# Interface with static member - interface

How to define a static member in an Interface?
Why it is not possible?
I want to force a F# type (class) to have a static method to create an instance of itself from a string (JSON parsing).
I want this Interface example:
[<Interface>]
type public ILikeJson<'T> =
abstract member ToJson: unit -> string // OK
static abstract member FromJson: string -> 'T // <-- "static" is not valid here !
Alternatively a constructor from a string can do the work but a static method sounds better because it will have an appropriate name and I don't know how to define a constructor in the Interface too.

The present CLR specification states that interfaces are only implemented for object instances and do not apply for the types themselves.
C# 8 has a proposal for defining static interface members, but it is required to provide an implementation for the static methods within the interface definition itself. So you won't be able to implement a FromJson method per class.
If you try this in F#, you'll get:
FS0868: Interfaces cannot contain definitions of concrete members. You may need to define a constructor on your type to indicate that the type is a class.
One solution to this problem is to use static type constraints. They allow you to look up the existence of a method on a type.
let inline create< ^T when ^T : (static member FromJson: string -> ^T)> json =
(^T : (static member FromJson: string -> ^T) (json))
This supports any type which has a static method FromJson with the string -> T signature.
type Number(num: double) =
member _.Value = num
static member FromJson (json) = new Number(Double.Parse(json))
and to use:
create<Number> "1.5" //creates a Number(1.5)

Related

What exactly is a metatype in Swift?

I am very confused around the concept of "metatype" in the Swift language.
Suppose I have:
class SomeClass {
class func callClassMethod() {
print("I'm a class method. I belong to my type.")
}
func callInstanceMethod() {
print("I'm an instance method. I belong to my type instance.")
}
}
According to the definition:
A metatype type refers to the type of any type, including class types,
structure types, enumeration types, and protocol types.
SomeClass is already a type called SomeClass, then what exactly is the type of SomeClass?
I can create a SomeClass.Type variable:
let var1 : SomeClass.Type = SomeClass.self
var1.doIt();//"I'm a class method. I belong to my type."
but I can also call the static/class function this way:
SomeClass.doIt();//"I'm a class method. I belong to my type."
Are they the same?
They are the same because the compiler guarantees that class names are unique (Swift is name spaced by module), so there is only one thing that is of SomeClass.Type and that is the class SomeClass. The meta type is often useful when you just want to pass the type of something to a function but you don't want to pass an instance. Codable does this for instance:
let decoded = try decoder.decode(SomeType.self, from: data)
If you could not pass the meta type here then the compiler could still infer the return type based on an annotation on the left, but it would be less readable:
let decoded: Sometype = try decoder.decode(data)
Some libraries do use the type inference style instead, although the Apple preference seems to be to use the meta type as its clearer what the right side of the assignment is on its own, without relying on type inference from the left side of the assignment.

Swift protocol used as type in method not accepting instances of same protocol

I've encountered a problem with a method which I cannot explain. Here is some test code which shows the problem:
protocol Base {}
protocol Extended: Base {}
struct Instance:Extended {}
let anInstance = Instance()
let instanceOfBase = anInstance as Base
let instanceOfExtended = anInstance as Extended
func aMethod<T:Base>(_ instance:T) {}
aMethod(anInstance)
aMethod(instanceOfBase) // Error - Cannot invoke 'aMethod' with an argument list of type '(Base)'
aMethod(instanceOfExtended) // Error - Cannot invoke 'aMethod' with an argument list of type '(Extended)'
According to the Apple doco I've read on protocols, generics, etc. aMethod() should accept any object that conforms to the Base protocol. Yet it rejects both instances where I have cast them to either Base or Extended.
Can anyone explain this?
Also:
func aMethod2(_ instance:Base) {}
aMethod2(anInstance)
aMethod2(instanceOfBase)
aMethod2(instanceOfExtended)
Works fine so the difference seems to be whether the instance argument is based (excuse the pun) on Base or <T:Base>.
For anyone questioning why I would declare a generic here. The original code looked like this:
func addViewController<T:ModelObject>(_ stack:inout [UIViewController],
object:T?,
controller:DetailsViewController<T>?,
storyboardId:String) {...
As you can see, I want to constrain several arguments to the same type. Hence the use of a generic rather than just specifying base.
T is a constraint on a concrete type
<T:Base> is a constraint on the placeholder type T. T must be a concrete type (a class, enum or struct such as Instance) that conforms to the Base protocol. The placeholder type T cannot be the Base protocol.
aMethod<T:Base>(:) must be called with a variable that is of a type that conforms to the Base protocol at compile time. aMethod<T:Base>(:) cannot be called with a variable that is only known to be of type Base.
The following line of code instantiates a variable named anInstance that is of struct type Instance.
let anInstance = Instance()
aMethod(anInstance) compiles because anInstance is of a concrete type Instance that conforms to the Base protocol.
The following line of code instantiates a variable named instanceOfBase that is of protocol type Base.
let instanceOfBase: Instance = anInstance as Base
aMethod(instanceOfBase) does not compile because instanceOfBase is not of a concrete type that conforms to the Base protocol. It is of the protocol type Base.
Here is another snippet that fails to illustrate the issue. In this case the base argument is only known to be of the protocol type Base.
func aMethod(base: Base) {
aMethod(base) // Cannot invoke 'aMethod' with an argument list of type '(Base)'
}
Hmm, I don't really get why you're doing this.
Let's say:
you want aMethod to accept any instance that conforms to Base protocol, then you can just make it func aMethod(_ instance: Base) {}
You want preserve type information inside the function then you use the generic method but pass in an instance of a concrete implementation of the protocol.
Please note that func aMethod<T:Base>(_ instance:T) {} means it's expecting an instance of type T that conforms Base. Neither Base or Extended is a valid type.
What you're doing here is using generics without its power...Which, IMHO, doesn't make sense. Unless you can provide a more realistic scenario?

Haxe java.lang.Object Equivalent

Haxe allows class inheritance hierarchies
class Honda extends Car {
...
}
is there a common inheritance hierarchy root for all objects? I have a generic container class that could contain any object and I want to be able to declare
var _contents:Object; //Any class instance in _contents
How can I do this?
You can also use {} as a type, which will accept class instances as well as anonymous objects :
var _contents:{};
We also have Dynamic, which basically means "anything" (not only objects, but also primitives like Bool, Int, etc).
If your class is a generic container, you may want to type its content, though, using type parameters:
class Container<T> {
var _contents:T;
public function new(contents:T):Void {
_contents = contents;
}
}
And then:
var arrayContainer = new Container([]);
var stuffContainer = new Container({foo:"bar"});
var classContainer = new Container( new Stuff() );
The inheritance root for classes is Class<T> so the following should work:
var _contents:Class<T>;
However, to store an Enum, you would have to use Enum<T> instead.
From the manual:
There is a special type in Haxe which is compatible with all classes:
Define: Class<T>
This type is compatible with all class types which means that all classes (not their instances) can be assigned to it. At compile-time, Class<T> is the common base type of all class types. However, this relation is not reflected in generated code.
This type is useful when an API requires a value to be a class, but not a specific one. This applies to several methods of the Haxe reflection API.

How to pass protocol with associated type (generic protocol) as parameter in Swift?

I have to pass an interface as a parameter to a function. Interface is generic a.k.a. has a associated type. I couldn't find a good way to do that. Here is my code:
protocol IObserver : class {
typealias DelegateT
...
}
class Observer: IObserver {
typealias DelegateT = IGeneralEventsDelegate // IGeneralEventsDelegate is a protocol
...
}
func notify(observer: IObserver) { ... } // here I need a type for observer param
I found that this will work:
func notify<T: IObserver where T.DelegateT == IGeneralEventsDelegate>(observer: T) { ... }
, but come on that is too complicated. What if I want to save this param in class variable, should I make the whole class generic, just because of this function.
It is true that I'm C++ developer and I'm new to the Swift language, but the way the things are done are far too complicated and user unfriendly ... or I'm too stupid :)
If you use typealias in a protocol to make it generic-like, then you cannot use it as a variable type until the associated type is resolved. As you have probably experienced, using a protocol with associated type to define a variable (or function parameter) results in a compilation error:
Protocol 'MyProtocol' can only be used as a generic constraint because it has Self os associated type requirements
That means you cannot use it as a concrete type.
So the only 2 ways I am aware of to use a protocol with associated type as a concrete type are:
indirectly, by creating a class that implements it. Probably not what you have planned to do
making explicit the associated type like you did in your func
See also related answer https://stackoverflow.com/a/26271483/148357

Define an abstract class that inherits an infterface, but does not implement it

incorporating leppies feedback it compiles - but IMO some drawbacks I want each sub class to be forced by the compiler to define their own Uri property. Code as it is now:
[<AbstractClass>]
type UriUserControl() =
inherit UserControl()
interface IUriProvider with
member this.Uri with get() = null
Interesting enough, the class I defines which inerits from above does not show a public Uri property:
type Page2() as this =
inherit UriUserControl()
let uriStr = "/FSSilverlightApp;component/Page2.xaml"
let mutable uri = new System.Uri(uriStr, System.UriKind.Relative)
do
Application.LoadComponent(this, uri)
member public this.Uri with get () = uri
I would like to define an abstract class that inherits from UserControl and my own Interface IUriProvider, but doesn't implement it. The goal is to be able to define pages (for silverlight) that implement UserControl but also provide their own Uri's (and then stick them in a list / array and deal with them as a set:
type IUriProvider =
interface
abstract member uriString: String ;
abstract member Uri : unit -> System.Uri ;
end
[<AbstractClass>]
type UriUserControl() as this =
inherit IUriProvider with
abstract member uriString: String ;
inherit UserControl()
Also the Uri in the definition - I would like to implement as a property getter - and am having issues with that as well.
this does not compile
type IUriProvider =
interface
abstract member uriString: String with get;
end
Here is a way to do it:
type IUriProvider =
abstract member UriString: string
abstract member Uri : System.Uri
[<AbstractClass>]
type UriUserControl() as this =
inherit System.Windows.Controls.UserControl()
abstract member Uri : System.Uri
abstract member UriString : string
interface IUriProvider with
member x.Uri = this.Uri
member x.UriString = this.UriString
Note that you have to provide an implementation of the interface (since all interface implementations in F# are explicit), but this can just refer back to abstract members in the class. Then you can subclass thusly:
type ConcreteUriUserControl() =
inherit UriUserControl()
override this.Uri = null
override this.UriString = "foo"
From a .NET point of view, you would need to at least provide an abstract implementation for the interface. But that again could proof problematic due to default interface accessibility, which would require some more glue again for an explicit implementation.