If I look at Control.IEvent<'Delegate,'Args>, it imposes on 'Args that
IEvent<'Delegate,'Args when 'Delegate : delegate<'Args,unit>...>
Looking at WorkbookBase.NewSheet Event, to which WorkbookEvents_NewSheetEventHandler, of type obj-> unit, can subscribe, I would have expected 'Args to be of type obj in its F# type.
However, I see that the event NewSheet is of type IEvent<WorkbookEvents_NewSheetEventHandler, unit>
What can explain this ?
Adding the extract of the spec mentioned in the answer :
5.2.8 Delegate Constraints
An explicit delegate constraint has the following form:
typar : delegate
During constraint solving (§14.5), the constraint type : delegate is met if type is a delegate type D with declaration type D = delegate of object * arg1 * ... * argN and tupled-arg-type = arg1 * ... * argN. That is, the delegate must match the CLI design pattern where the sender object is the first argument to the event.
Note: This constraint form exists primarily to allow the definition of certain F# library functions that are related to event programming. It is rarely used directly in F# programming.
The delegate constraint does not imply anything about subtypes. In particular, a ‘delegate’ constraint does not imply that the type is a subtype of System.Delegate.
The delegate constraint applies only to delegate types that follow the usual form for CLI event handlers, where the first argument is a “sender” object. The reason is that the purpose of the constraint is to simplify the presentation of CLI event handlers to the F# programmer.
Look at how the spec defines the delegate constraint: the obj sender argument is implicit.
Related
Normally in Perl 6, only roles are allowed to be parametric. Here, we'll be attempting to make classes, a kind (referred to from here on out as a metaobject) that isn't normally allowed to be parametric, parametric.
If you try to make a class parametric the naive way, this happens:
bastille% perl6 -e 'class Foo[::T] {}'
===SORRY!=== Error while compiling -e
Unable to parse class definition
at -e:1
------> class Foo⏏[::T] {}
expecting any of:
generic role
But if you take a look at what metaobject the CArray type from NativeCall uses, you'll find that it's in fact a class, not a role, yet it's still parametric!
bastille% perl6 -MNativeCall -e 'say CArray[int32].HOW.^name'
Perl6::Metamodel::ClassHOW+{<anon>}+{<anon>}
How is this done?
Making classes parametric takes a little bit of metaprogramming to accomplish. A simple parametric container class can be implemented like so:
use v6.d;
class Container {
my role ContainerImpl[::T] {
has T $.value;
method new(Container: T $value) {
self.bless: :$value
}
multi method gist(Container:D: --> Str:D) {
$!value.gist
}
multi method Str (Container:D: --> Str:D) {
$!value.Str
}
multi method perl(Container:D: --> Str:D) {
self.^name ~ '.new(' ~ $!value.perl ~ ')'
}
}
method ^parameterize(Mu:U \this, Mu \T) {
my $type := this.^mixin: ContainerImpl[T];
$type.^set_name: this.^name ~ '[' ~ T.^name ~ ']';
$type
}
}
say Container[Int].new(1).perl;
# OUTPUT: Container[Int].new(1)
So how does this work?
Metaclasses that do the Perl6::Metamodel::MetaMethodContainer role, such as Perl6::Metamodel::ClassHOW, can have additional metamethods mixed in with the type's knowhow (which describes how a specific kind of type, such as a class or role, behaves). Rakudo's grammar invokes the parameterize metamethod on any given type with the parametric type and any parameterized types as arguments when parsing a type's name. Normally, types that are parametric are supposed to implement the parametric archetype, but this doesn't get checked here, which allows any type to be parameterized as long as it implements a parameterize metamethod.
The mixin metamethod is specific to the Perl6::Metamodel::Mixins role, which Perl6::Metamodel::ClassHOW also does. The method mixes in a role by reblessing the class so it's considered to be the same type as the (parameterized in this case) role passed to it.
Combining the parameterize and mixin metamethods allows you to implement parametric behaviour in a role, then use it in a class by parameterizing it before mixing it in. This allows the class to behave as if it actually were a parametric type, even though it's still technically not one.
TL;DR This answer is a "simplified" version of #Kaiepi++'s. It only covers the core bit of code shown below that's extracted from their answer. It's written so that it should work as a standalone explanation, or as an introduction or complement to their answer.
Making a class parametric
The titular question is very broad. But the body of the question boils down to making a class parametric and that's what this answer (and #Kaiepi's) focuses on.
Classes, as a kind of type, don't support parametricity out of the box. But P6 is fully metaprogrammable. So you can just metaprogram a class to add parametricity. NB. This is not an officially supported technique!1
(You could add parametricity at the kind level, such that either all classes, or some new kind of type that you derive from classes, are parametric. But I think that would take considerable effort.2 In the meantime a half dozen lines of fairly straight-forward metaprogramming is all that's required to make a single class parametric. So that's all we'll do in this answer.)
The code
class foo {
my role bar[::T] {}
method ^parameterize(Mu:U \this, Mu \T) {
my $type := this.^mixin: bar[T];
$type.^set_name: this.^name ~ '[' ~ T.^name ~ ']';
$type
}
}
say foo[Int].new.perl;
# OUTPUT: foo[Int].new
The above code is extracted from #Kaiepi's answer, leaving out what I considered non-essential. The rest of this answer explains the code in detail.
role bar[::T]
A role collects attributes and methods together just like a class. The key difference in the context of this SO is that a role is parameterizable and can be added to a class so that the class becomes parameterized.
The bit between the [ and ] is a signature. The ::T is a type variable. The signature can be as complex as you want it to be, just like a regular function signature.
The bar role I've shown has an empty body. In an actual application of this technique you would write the attributes and methods that you want added to the foo class. These would be attributes and methods that need to make use of the parameterization, plus other attributes and methods that it's reasonable to include in the same role.
^some-method-name
A ^ at the start of a method name signals that it will not be a call on its explicit invocant but rather a call "up to" the invocant's "higher order workings" as embodied in a knowhow object that knows how that kind of type works.
Declaring a method with an initial ^ causes the knowhow object for the containing class to be customized to include that method.
^parameterize
If you write foo[...] where the compiler expects a type, the compiler calls (the equivalent of) foo.^parameterize which turns into a call to parameterize on foo's knowhow object.
And foo's knowhow object has been customized to include our method:
method ^parameterize(Mu:U \this, Mu \T) {
my $type := this.^mixin: bar[T];
$type.^set_name: this.^name ~ '[' ~ T.^name ~ ']';
$type
}
\this
What's this all about? (The \ just means "slash the sigil"; I don't mean that aspect.)
this is the foo type object, i.e. the same type object associated with self in ordinary methods in foo that don't start with ^.3
Adding bar to foo so that foo gets parameterized
We've now arrived at the point where we can generate a parameterized foo:
my $type := this.^mixin: bar[T];
Starting with an unparameterized foo held in this we "mix" in bar parameterized with the T passed to ^parameterize.
Following protocol for P6's nominal type system
This line ensures our new parameterized type plays well with the system:
$type.^set_name: this.^name ~ '[' ~ T.^name ~ ']';
Moving on to #Kaiepi's answer
This answer is a simplified version of #Kaiepi's answer.
It isn't sufficient to cover issues such as ensuring that .perl works correctly if an actual implementation is a class with parameterized public attributes.
Footnotes
1 Many details of the metamodel are not part of official P6. The .^parameterize method is not.
2 I'm pretty confident that, with suitable (learning about guts and) metaprogramming, one could make all classes, or a new kind derived from classes, behave like roles inasmuch as being a kind of type that supports parameterization "out of the box" using the obvious syntax:
class foo[::T] { ... }
3 I strongly concur with #Kaiepi's decision not to use \self as the first parameter of a ^ method. That would be a lie and shadow the usual self. Presumably #Kaiepi's thinking is that this is often used as a synonym of self but, if you know P6, clearly isn't the same as self because it's the first parameter but not the invocant parameter.
I'm trying to create a record where one of the fields has a type that is not exported, since it's using a smart constructor. Using the smart constructor as the type does not work.
Not in scope: type variable `domain'
Maybe there is a language extension that allows me to do this, or something similar?
Exporting the constructor along with the smart constructor would allow me to solve this problem, but that in turn creates the possibility of creating values that the smart constructor wouldn't allow.
The (non-working) code I have right now:
import Domain (domain) -- Domain is not exported, and domain is a smart constructor for Domain
data Rec = Rec
{ dint :: domain Int -- what do I do here? I want it to be `Domain Int` but `Domain` isn't exported.
...
}
The issue here is confusion between the concept of a type constructor and a data constructor. For brevity, I will illustrate the difference with an example.
data Foo a = Bar [a]
In the expression above, Foo is the type constructor and Bar is the data constructor. The key difference is that Foo is a value in Haskell's type space and Bar is a value in its data space. A value in type space cannot be used in data space, and vice versa. For example, the compiler would error at the following expressions.
someVariable :: Bar Int
someVariable = Foo [15]
The next expression, however, is completely valid.
someVariable :: Foo Int
someVariable = Bar [15]
Additionally, all type constructors must start with an upper case letter. Any types starting with a lower case letter will be considered type variables, not type constructors (the a in our definition above is an example of this).
The introduction of smart constructors add another layer to this problem, but the key thing to understand is that smart constructors are data constructors, not type constructors. In your definition of Rec, you tried to use your smart constructor, domain, in the type declaration for dint field. However, because domain is a data constructor not a type constructor, and it is lower case, the Haskell compiler tried to interpret domain as the name of a type variable. Because you never specified a variable named domain in your definiton of the Rec type, the compiler raised an error.
You don't actually need to export the data constructor for Domain to solve the issue, just the type itself. This can be accomplished with the following.
module Domain (
Domain(), domain,
...
) where
Including Domain() in the export definition tells Haskell to export the Domain type constructor, but not any of its data constructors. This preserves the safety you wanted with the safe constructor, and allows you to define types correctly. You can now use your newly exported type in your definition of Rec.
import Domain (Domain(), domain)
data Rec = Rec
{ dint :: Domain Int
...
}
For more information, I strongly recommend you read the HaskellWiki articles on constructors and smart constructors.
I am trying to write a module in F#, making it easier working with Excel, by extracting rows, columns, etc. along with type casting and so on. One of the first things I wanted to do, was to extend various classes/types to implement the IDisposable interface. I tried to write something like the following
type Excel.ApplicationClass with
interface IDisposable with
member this.Dispose() =
this.excel.Quit()
Marshal.ReleaseComObject(this.excel) |> ignore
What I wasn't aware of, was that I would get the following error "All implemented interfaces should be declared on the initial declaration of the type".
My question is the following: Since I am not allow to extend a type with an interface - what else could I do?
If you inherit from the base class it can work, like this
type myAppClass() =
inherit Excel.ApplicationClass() //may not be correct signature - you need to match the base constructor
interface IDisposable with
member this.Dispose() =
//function body
What exactly are we telling the compiler in this line of code ?
public abstract class RepositoryBase<T> where T:class
Are we saying that when we create an object that inherits from RepositoryBase, the object must take a class in the constructor otherwise there will be a compile error ?
It's saying that when you inherit from RepositoryBase<T>, the type T which you specify must be some type of class (or interface or etc., but not a value type). For example RepositoryBase<int> is illegal and won't compile: see Constraints on Type Parameters (C# Programming Guide).
Binding times can be classified between two types: static and dynamic. What is the difference between static and dynamic binding?
Could you give a quick example of each to further illustrate it?
In the most general terms, static binding means that references are resolved at compile time.
Animal a = new Animal();
a.Roar(); // The compiler can resolve this method call statically.
Dynamic binding means that references are resolved at run time.
public void MakeSomeNoise(object a) {
// Things happen...
((Animal) a).Roar(); // You won't know if this works until runtime!
}
It depends when the binding happens: at compile time (static) or at runtime (dynamic). Static binding is used when you call a simple class method. When you start dealing with class hierarchies and virtual methods, compiler will start using so called VTABLEs. At that time the compiler doesn't know exactly what method to call and it has to wait until runtime to figure out the right method to be invoked (this is done through VTABLE). This is called dynamic binding.
See Wikipedia article on Virtual tables for more details and references.
I came accross this perfect answer of a quora user "Monis Yousuf". He explain this perfectly. I am putting it here for others.
Binding is mostly a concept in object oriented programming related to Polymorphism.
Firstly, understand what Polymorphism is. Books say that it means "one name and multiple forms". True, but too abstract. Let us take a real-life example. You go to a "Doctor", a doctor may be an eye-specialist, ENT specialist, Neuro-Surgeon, Homeopath etc.
Here, a "doctor" is a name and may have multiple types; each performing their own function. This is polymorphism in real life.
Function Overloading: This concept depicts Static Binding. Function overloading may be roughly defined as, two or more methods (functions) which have the same name but different signatures (including number of parameters, types of parameters, differt return types) are called overloaded methods (or functions).
Suppose you have to calculate area of a rectangle and circle. See below code:-
class CalculateArea {
private static final double PI = 3.14;
/*
Method to return area of a rectangle
Area of rectangle = length X width
*/
double Area(double length, double width) {
return (length * width);
}
/*
Method to return area of circle
Area of circle = π * r * r
*/
double Area(double radius) {
return PI * radius * radius;
}
}
In above code, there are two methods "Area" with different parameters. This scenario qualifies as function overloading.
Now, coming to the real question: How is this static binding?
When you call any of the above functions in your code, you have to specify the parameters you are passing. In this scenario, you will pass either:
Two parameters of type double [Which will call the first method, to
calculate are of a rectangle]
Single parameter of type double [Which will call the second method, to calculate area of a circle]
Since, at compile time the java compiler can figure out, WHICH function to call, it is compile-time (or STATIC) binding.
Function Overriding: Function overriding is a concept which is shown in inheritance. It may roughly be defined as: when there is a method present in a parent class and its subclass also has the same method with SAME signature, it is called function overriding. [There is more to it, but for the sake of simplicity, i have written this definition] It will be easier to understand with below piece of code.
class ParentClass {
int show() {
System.out.println("I am from parent class");
}
}
class ChildClass extends ParentClass{
int show() {
System.out.println("I am from child class");
}
}
class SomeOtherClass {
public static void main (String[] s) {
ParentClass obj = new ChildClass();
obj.show();
}
}
In above code, the method show() is being overridden as the same signature (and name) is present in both parent and child classes.
In the third class, SomeOtherClass, A reference variable (obj) of type ParentClass holds the object of ChildClass. Next, the method show() is called from the same reference variable (obj).
Again, the same question: How is this Dynamic Binding?
At compile time, the compiler checks that the Reference variable is of type ParentClass and checks if the method show() is present in this class. Once it checks this, the compilation is successful.
Now, when the programs RUNS, it sees that the object is of ChildClass and hence, it runs the show() method of the ChildClass. Since this decision is taken place at RUNTIME, it is called Dynamic Binding (or Run-time Polymorphism).
Link for original answer
Static Binding: is the process of resolving types, members and operations at compile-time.
For example:
Car car = new Car();
car.Drive();
In this example compiler does the binding by looking for a parameterless Drive method on car object. If did not find that method! search for methods taking optional parameters, and if did not found that method again search base class of Car for that method, and if did not found that method again searches for extension methods for Car type. If no match found you'll get the compilation error!
I this case the binding is done by the compiler, and the binding depends on statically knowing the type of object. This makes it static binding.
Dynamic Binding: dynamic binding defers binding (The process of resolving types, members and operations) from compile-time to runtime.
For example:
dynamic d = new Car();
d.Drive();
A dynamic type tells the compiler we expect the runtime type of d to have Drive method, but we can't prove it statically. Since the d is dynamic, compiler defers binding Drive to d until runtime.
Dynamic binding is useful for cases that at compile-time we know that a certain function, member of operation exists but the compiler didn't know! This commonly occurs when we are interoperating with dynamic programming languages, COM and reflection.
Binding done at compile time is static binding and binding done at run time is dynamic binding.In static binding data type of the pointer resolves which method is invoked.But in dynamic binding data type of the object resolves which method is invoked.
* Execution time:-* bindings of variables to its values,as well as the binding of variable to particular storage location at the time of execution is called execution time binding.
IT MAY BE OF TWO TYPES
on entry to a subprogram.
At arbitrary points during execution time.
COMPILE TIME BINDING :- (TRANSLATION TIME)
It consist of the following.
Binding chosen by programmer.
Binding chosen by the translator.
Binding chosen by the loader.