Type.GetType() not working for F# type in C# code - reflection

I have an F# assembly called Assembly1
I have the following module:
namespace Assembly1
module MyModule =
type MyClass(x: int, y: int) =
new() = MyClass(0, 0)
In a C# assembly that references this F# assembly, the following code gives me a value of 'null' back:
var myType = Type.GetType("Assembly1.MyModule.MyClass, Assembly1");
Is what I am trying to do not possible?

To add to Mark's answer, it's also worth noting that a lot of modules in F# are represented by different names in IL (and therefore non-F# languages) than they appear with in F# itself.
For example, this piece of code:
open System
open System.Reflection
open Microsoft.FSharp.Reflection
let private core =
AppDomain.CurrentDomain.GetAssemblies()
|> Seq.find (fun a -> a.GetName().Name = "FSharp.Core")
let private seqMod =
core.GetTypes()
|> Seq.filter FSharpType.IsModule
|> Seq.find (fun t ->
t.FullName = "Microsoft.FSharp.Collections.SeqModule")
Will find the Seq module in FSharp.Core.
The FSharp.Reflection namespace has a bunch of helper methods to make working with F# specific types with System.Reflection a little bit less painful, so it's worth loading up a couple of assemblies in FSI and having a play with those if you're going to be doing a lot of reflection work with F# code.
You can create modules with "mismatching" names like this yourself using the CompiledName attribute - this is especially useful for those times where you want a type and a module with the same name. The normal convention (as shown with the Seq type/module) is to annotate the module with Compiled name.
[<CompiledName("MyTypeModule")>]
module MyType =
let getString m =
match m with
| MyType s -> s

Since you've put MyClass into a module, it's compiled as a nested class. Its name is Assembly1.MyModule+MyClass.
From C#, you should be able to load it like this:
var myType = Type.GetType("Assembly1.MyModule+MyClass, Assembly1");
If you don't want to have nested classes (which are generally frowned upon in C#), you can define it directly in a namespace:
namespace Assembly1.LibraryXyz
type MyClass(x: int, y: int) = class end
This class will have the name Assembly1.LibraryXyz.MyClass.

Related

Get struct property from inside struct function errors out

Recently started to try and learn Julia through examples. I am basically trying to figure out how to access a struct property from within a function inside the struct itself. E.g:
struct Test
a::Int
foo::Function
function Test()
return new(777, xfoo)
end
function xfoo()
println(a)
end
end
t = Test()
t.foo()
I get:
ERROR: LoadError: UndefVarError: a not defined
Stacktrace:
[1] (::var"#xfoo#1")()
# Main /tmp/j.jl:10
[2] top-level scope
# /tmp/j.jl:15
in expression starting at /tmp/j.jl:15
Am I using Julia wrong or am I missing something?
Julia is not object oriented language so object oriented patterns are usually not a good idea.
Hence xfoo should be outside of Test:
function xfoo(t::Test)
println(t.a)
end
There are packages that try to emulate OOP with Julia (however this is not a Julian pattern): https://github.com/Suzhou-Tongyuan/ObjectOriented.jl
You can also easily find quite a lot of discussion behind the design decision no to make Julia OOP. Start with: https://discourse.julialang.org/t/why-there-is-no-oop-object-oriented-programming-in-julia/86723
Workaround
Just out of curiosity one can find some workaround to attach a function to a struct (not a recommended design pattern!). For an example:
mutable struct MyTest
a::Int
foo::Function
function MyTest()
s = Ref{MyTest}()
s[] = new(777, () -> println(s[].a))
s[]
end
end
And some sample usage:
julia> t = MyTest();
julia> t.foo()
777
julia> t.a = 900;
julia> t.foo()
900

Can you create a singleton in Julia?

I know that Julia does not have OOP but that multiple dispatch enables similar ideas. Given how seemingly contentious the use of singletons are in Python, I am wondering if there is a similar idea Julia (i.e. a struct that can only be instantiated once).
I am wondering if there's a way to have the constructor keep track of the number of times an object was instantiated with a global var or something like that? Or it's altogether not be possible?
The main way people make singletons in Julia is to define an empty struct (which means that it has 0 size), and define methods that return information for it.
struct Singleton
end
data(::Singleton) = "whatever you want it to do"
etc.
From this book, a singleton can be defined as a type without fields:
struct MySingleton end
julia> MySingleton() === MySingleton()
true
You can also use Val, which can receive any value (of bit type):
julia> Val(1) === Val(1)
true
julia> Val(:foo) === Val(:foo)
true
using Val you can write something like this:
julia> do_something(::Val{:asymbol}) = println("foo")
julia> do_something(::Val{:anothersymbol}) = println("bar")
julia> do_something(s::String) = do_something(Val{Symbol(s)})
julia> do_something("asymbol")
foo
The definition of Val is:
struct Val{x} end
So, for a more clear readability of your code, you could define your own singleton type as, for example:
struct Command{x} end

Try to further understanding the interface/module of OCaml

I understand in OCaml there are concepts of interfaces and module.
And I understand how to use them now.
However, what I don't understand is how to fully utilise them.
For example, in Java, let's say we have a interface Map and we also have Hashtable and HashMap that implement Map.
In code, I can do like:
Map m = new Hashtable();
m.put("key", value);
Someday, if I change my mind, I can change to Hashmap very quickly by changing Map m = new Hashtable(); to Map m = new HashMap();, right?
But how can I easily do that in Ocaml?
For example, I have MapSig and 'HashMap:MapSigand "Hashtable:MapSig in OCaml.
How can I change the implementation easily?
I don't think I can because in OCaml I have to do like:
let m = Hashtable.create ();;
Hashtable.put m key value;;
if I want to use HashMap instead, I have to replace every Hashtable with HashMap in the code, right?
Edit:
I am not only seeking a way to make a alias to modules. I also consider the validity of implementations, i.e., whether the implementation follow the desired interface.
For example, in above Java example, only if HashMap has implemented Map interface, I can replace Hashtable with HashMap. otherwise, Java compiler will complain.
but if I do module M = Hashtable in OCaml, and if HashMap does not follow MapSig and I replace Hashtable with HashMap, what will happen? I think compiler won't complain, right?
Here's an example that shows what I think you're asking for:
# module type HASH = sig type t val hash : t -> int end ;;
module type HASH = sig type t val hash : t -> int end
# module I = struct type t = int let hash i = i end ;;
module I : sig type t = int val hash : 'a -> 'a end
# module J = struct type t = int end ;;
module J : sig type t = int end
# module M : HASH = I ;;
module M : HASH
# module N : HASH = J ;;
Error: Signature mismatch:
Modules do not match: sig type t = int end is not included in HASH
The field `hash' is required but not provided
The extra ": HASH" specifies that the module must match the HASH signature (and it also restricts it to that signature).
Just as a side comment, I believe the OCaml module system is world famous for its expressivity (at least in module system circles). I'm still a beginner at it, but it is worth studying.
Since 3.12.1 OCaml allows this syntax for opening and aliasing modules:
let foo .... =
let module HashTable = HashMap in (* magic is here *)
let h = HashTable.create () in
....
So u just need to rename module what you are using where you are using it.
The most direct correspondence between your Java example and OCaml is using a functor (what OCaml calls a static function from a module to a module). So suppose you have the following implemented in OCaml:
module type Map = sig
(* For simplicity assume any key and value type is allowed *)
type ('k, 'v) t
val make : unit -> ('k, 'v) t
val put : ('k, 'v) t -> ~key:'k -> ~value:'v -> unit
end
module Hashtable : Map = struct ... end
module HashMap : Map = struct ... end
Then you would write a functor like this:
module MyFunctor(Map : Map) = struct
let my_map =
let map = Map.make () in
Map.put map ~key ~value;
map
end
Then you would instantiate a module using the functor:
module MyModule = MyFunctor(Hashtable)
And voila, changing the implementation is a one-line diff because both the module implementations conform to the Map signature:
module MyModule = MyFunctor(HashMap)

Type extension errors for Dictionary<'K, 'V>

The following type extension
module Dict =
open System.Collections.Generic
type Dictionary<'K, 'V> with
member this.Difference(that:Dictionary<'K, 'T>) =
let dict = Dictionary()
for KeyValue(k, v) in this do
if not (that.ContainsKey(k)) then
dict.Add(k, v)
dict
gives the error:
The signature and implementation are not compatible because the declaration of the type parameter 'TKey' requires a constraint of the form 'TKey : equality
But when I add the constraint it gives the error:
The declared type parameters for this type extension do not match the declared type parameters on the original type 'Dictionary<,>'
This is especially mysterious because the following type extension doesn't have the constraint and works.
type Dictionary<'K, 'V> with
member this.TryGet(key) =
match this.TryGetValue(key) with
| true, v -> Some v
| _ -> None
Now I'm having weird thoughts: is the constraint required only when certain members are accessed?
module Dict =
open System.Collections.Generic
type Dictionary<'K, 'V> with
member this.Difference(that:Dictionary<'K, 'T>) =
let dict = Dictionary(this.Comparer)
for KeyValue(k, v) in this do
if not (that.ContainsKey(k)) then
dict.Add(k, v)
dict
EDIT:
As per F# spec (14.11 Additional Constraints on CLI Methods)
Some specific CLI methods and types are treated specially by F#, because they are common in F# programming and cause extremely difficult-to-find bugs. For each use of the following constructs, the F# compiler imposes additional ad hoc constraints:
x.Equals(yobj) requires type ty : equality for the static type of x
x.GetHashCode() requires type ty : equality for the static type of x
new Dictionary<A,B>() requires A : equality, for any overload that does not take an IEqualityComparer<T>
as far as I can see the following code does the trick:
module Dict =
open System.Collections.Generic
type Dictionary<'K, 'V> with
member this.Difference(that: Dictionary<'K,'V2>) =
let diff =
this
|> Seq.filter (fun x -> not <| that.ContainsKey(x.Key))
|> Seq.map (fun x -> x.Key, x.Value)
System.Linq.Enumerable.ToDictionary(diff, fst, snd)
The problem is your use of the Add method. If you use this method of Dictionary<TKey, TValue> then F# will enforce that TKey has the equality constraint.
After playing around a bit I'm not sure that it's even possible to write this extension method. The F# type system appears to force the declaration type of the extension method to have no additional constraints than the original type (i get an error whenever I add the equality constraint). Additionally the type listed in the individal extension methods cannot differ than the listed type. I've tried a number of ways and can't get this to function correctly.
The closest I've come is the non-extension method as follows
let Difference (this : Dictionary<'K, 'T>) (that:Dictionary<'K, 'T> when 'K : equality) =
let dict = Dictionary()
for KeyValue(k, v) in this do
if not (that.ContainsKey(k)) then
dict.Add(k, v)
dict
Perhaps another F# ninja will be able to prove me wrong
(EDIT: CKoenig has a nice answer.)
Hm, I didn't immediately see a way to do this either.
Here's a non-type-safe solution that might provide some crazy inspiration for others.
open System.Collections.Generic
module Dict =
type Dictionary<'K, 'V> with
member this.Difference<'K2, 'T when 'K2 : equality>(that:Dictionary<'K2, 'T>) =
let dict = Dictionary<'K2,'V>()
for KeyValue(k, v) in this do
if not (that.ContainsKey(k |> box |> unbox)) then
dict.Add(k |> box |> unbox, v)
dict
open Dict
let d1 = Dictionary()
d1.Add(1, "foo")
d1.Add(2, "bar")
let d2 = Dictionary()
d2.Add(1, "cheese")
let show (d:Dictionary<_,_>) =
for (KeyValue(k,v)) in d do
printfn "%A: %A" k v
d1.Difference(d2) |> show
let d3 = Dictionary()
d3.Add(1, 42)
d1.Difference(d3) |> show
let d4 = Dictionary()
d4.Add("uh-oh", 42)
d1.Difference(d4) |> show // blows up at runtime
Overall it seems like there may be no way to unify the types K and K2 without also forcing them to have the same equality constraint though...
(EDIT: seems like calling into .NET which is equality-constraint-agnostic is a good way to create a dictionary in the absence of the extra constraint.)

How to get type of the module in F#

How to get 'System.Type' of the module?
For example module:
module Foo =
let bar = 1
And this does not work:
printfn "%s" typeof<Foo>.Name
Error is:
The type 'Foo' is not defined
You could add a marker type to the module and then discover the module's type from that:
module Foo =
type internal Marker = interface end
let t = typeof<Marker>.DeclaringType
It would certainly be nice to have a moduleof operator... Since there's not one, the easiest way to do what you want is probably to use the Metadata library in the F# PowerPack:
#r "FSharp.PowerPack.Metadata.dll"
open Microsoft.FSharp.Metadata
// get .NET assembly by filename or other means
let asm = ...
let fasm = FSharpAssembly.FromAssembly asm
let t = fasm.GetEntity("Foo").ReflectionType
Unfortunately, this won't work with dynamic assemblies (such as those generated via F# Interactive). You can do something similar using vanilla System.Reflection calls, but that's more dependent on having a good understanding of the compiled form that your module takes.
It can also be done using Quotations. First, define this helper function somewhere:
open Microsoft.FSharp.Quotations.Patterns
let getModuleType = function
| PropertyGet (_, propertyInfo, _) -> propertyInfo.DeclaringType
| _ -> failwith "Expression is no property."
Then, you can define a module and get its type like this:
module SomeName =
let rec private moduleType = getModuleType <# moduleType #>
Hope this helps.
module name is not a type.
List in List.map and let (a:List<int>) = [1;2;3] are different.
The first List is a module name, the second is a type.

Resources