Getting object instance by string name in scala - reflection

I need the object (or "singleton object" or "companion object"... anything but the class) defined by a string name. In other words, if I have:
package myPackage
object myObject
...then is there anything like this:
GetSingletonObjectByName("myPackage.myObject") match {
case instance: myPackage.myObject => "instance is what I wanted"
}

In scala 2.10 we can do like this
import scala.reflect.runtime.universe
val runtimeMirror = universe.runtimeMirror(getClass.getClassLoader)
val module = runtimeMirror.staticModule("package.ObjectName")
val obj = runtimeMirror.reflectModule(module)
println(obj.instance)

Scala is still missing a reflection API. You can get the an instance of the companion object by loading the companion object class:
import scala.reflect._
def companion[T](implicit man: Manifest[T]) : T =
man.erasure.getField("MODULE$").get(man.erasure).asInstanceOf[T]
scala> companion[List$].make(3, "s")
res0: List[Any] = List(s, s, s)
To get the untyped companion object you can use the class directly:
import scala.reflect.Manifest
def companionObj[T](implicit man: Manifest[T]) = {
val c = Class.forName(man.erasure.getName + "$")
c.getField("MODULE$").get(c)
}
scala> companionObj[List[Int]].asInstanceOf[List$].make(3, "s")
res0: List[Any] = List(s, s, s)
This depends on the way scala is mapped to java classes.

Adjustment to Thomas Jung's answer above: you would do better to say companion[List.type] because a) this should be a stable way to refer to it, not dependant on the name mangling scheme and b) you get the unerased types.
def singleton[T](implicit man: reflect.Manifest[T]) = {
val name = man.erasure.getName()
assert(name endsWith "$", "Not an object: " + name)
val clazz = java.lang.Class.forName(name)
clazz.getField("MODULE$").get(clazz).asInstanceOf[T]
}
scala> singleton[List.type].make(3, "a")
res0: List[java.lang.String] = List(a, a, a)

Barring reflection tricks, you can't. Note, for instance, how the method companion is defined on Scala 2.8 collections -- it is there so an instance of a class can get the companion object, which is otherwise not possible.

Scala 2:
val runtimeMirror = universe.runtimeMirror(this.getClass.getClassLoader)
val objectClass = Class.forName("org.test.MyObject$")
val moduleSymbol = runtimeMirror.staticModule(objectClass.getName)
val moduleMirror = runtimeMirror.reflectModule(moduleSymbol)
val instance = moduleMirror.instance
Or just use Java API to get the value from the static field:
val instance = objectClass.getField("MODULE$").get(null)
Mind the $ in the object name.

Related

F#: How to call Expression.Call for a method with discriminated union in a generic type using a case type?

Let's say, I have a discriminated union type AccountEvent and a class Aggregate that carries two methods:
Apply1(event : AccountEvent)
Apply2(event : Event<AccountEvent>)
Event<'TEvent> being just a dummy class for sake of having a generic type.
I am trying to create an Expression that represents the call to Apply1 and Apply2 supporting for the parameter type the Discriminated union case type.
That is allowing:
AccountEvent.AccountCreated type for Apply1
Event<AccountEvent.AccountCreated> type for Apply2
I want to achieve that without changing the signature of Apply1, Apply2 and the definition the discriminated union.
The code
type AccountCreation = {
Owner: string
AccountId: Guid
CreatedAt: DateTimeOffset
StartingBalance: decimal
}
type Transaction = {
To: Guid
From: Guid
Description: string
Time: DateTimeOffset
Amount: decimal
}
type AccountEvent =
| AccountCreated of AccountCreation
| AccountCredited of Transaction
| AccountDebited of Transaction
type Event<'TEvent>(event : 'TEvent)=
member val Event = event with get
type Aggregate()=
member this.Apply1(event : AccountEvent)=
()
member this.Apply2(event : Event<AccountEvent>)=
()
let createExpression (aggregateType: Type)(eventType: Type)(method: MethodInfo) =
let instance = Expression.Parameter(aggregateType, "a")
let eventParameter = Expression.Parameter(eventType, "e")
let body = Expression.Call(instance, method, eventParameter)
()
[<EntryPoint>]
let main argv =
let accountCreated = AccountEvent.AccountCreated({
Owner = "Khalid Abuhakmeh"
AccountId = Guid.NewGuid()
StartingBalance = 1000m
CreatedAt = DateTimeOffset.UtcNow
})
let accountCreatedType = accountCreated.GetType()
let method1 = typeof<Aggregate>.GetMethods().Single(fun x -> x.Name = "Apply1")
createExpression typeof<Aggregate> typeof<AccountEvent> method1
createExpression typeof<Aggregate> accountCreatedType method1
let method2 = typeof<Aggregate>.GetMethods().Single(fun x -> x.Name = "Apply2")
let eventAccountCreatedType = typedefof<Event<_>>.MakeGenericType(accountCreatedType)
createExpression typeof<Aggregate> typeof<Event<AccountEvent>> method2
createExpression typeof<Aggregate> eventAccountCreatedType method2
0
With my current solution it does not work to generate an expression for Apply2:
System.ArgumentException: Expression of type 'Program+Event`1[Program+AccountEvent+AccountCreated]' cannot be used for parameter of type 'Program+Event`1[Program+AccountEvent]' of method 'Void Apply2(Event`1)'
Parameter name: arg0
at at System.Dynamic.Utils.ExpressionUtils.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arguments, ParameterInfo pi, String methodParamName, String argumentParamName, Int32 index)
at at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, Expression arg0)
at at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
at at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, Expression[] arguments)
at Program.doingStuff(Type aggregateType, Type eventType, MethodInfo method) in C:\Users\eperret\Desktop\ConsoleApp1\ConsoleApp1\Program.fs:40
at Program.main(String[] argv) in C:\Users\eperret\Desktop\ConsoleApp1\ConsoleApp1\Program.fs:61
I am wondering how I can adjust the creation of my expression to accept the Event<AccountEvent.AccountCreated>?
I am thinking that maybe there is a need to have an intermediate layer to have a conversion layer from AccountEvent.AccountCreated to its base classAccountEvent (this is how discriminated unions are compiled), or more precisely considering the generic, from Event<AccountEvent.AccountCreated to Event<AccountEvent>.
hard to say if this answers your question.
open System
open System
type AccountCreation = {
Owner: string
AccountId: Guid
CreatedAt: DateTimeOffset
StartingBalance: decimal
}
type Transaction = {
To: Guid
From: Guid
Description: string
Time: DateTimeOffset
Amount: decimal
}
type AccountEvent =
| AccountCreated of AccountCreation
| AccountCredited of Transaction
| AccountDebited of Transaction
type CheckinEvent =
| CheckedIn
| CheckedOut
type Event<'T> = AccountEvent of AccountEvent | OtherEvent of 'T
let ev : Event<CheckinEvent> = AccountEvent (AccountCreated {
Owner= "string"
AccountId= Guid.NewGuid()
CreatedAt= DateTimeOffset()
StartingBalance=0m
})
let ev2 : Event<CheckinEvent> = OtherEvent CheckedOut
let f ev =
match ev with
| AccountEvent e -> Some e
| OtherEvent (CheckedOut) -> None
| OtherEvent (CheckedIn) -> None
let x = f ev
let y = f ev2
afterwards, a match statement like this might simplify all that. Honestly it's a little complicated for me to follow what precisely what you're doing there, but using a function instead of a method and using a match statement appears to accomplish the same goal. Ideally you should probably fully spell out the types in a DU instead of using a generic so that you'll get compile time checks instead of run time errors and can know for certain that your code is fully covered by the compiler.

OCaml: how to create an inductive type with Set argument of same type

In OCaml I can define the following type:
type mytype = Base of int
| Branch of (int * (collection -> collection))
and collection = mytype list
Assuming I define a comparison function based on the int value of each constructor, how can I transform collection to be a Set instead of a list?
This is one of the cases where you will need to use recursive modules. In fact you can see that this is the actual example you get in the documentation of the feature. So something along these lines should do it:
module rec Mytype : sig
type t = Base ...
val compare : t -> t -> int
end = struct
type t = Base ...
let compare v0 v1 = ...
end
and Collection : Set.S with type elt = Mytype.t
= Set.Make (Mytype)

How make .NET Mutable Dictionary<T, T> with StructuralComparison & Equality in F#

I Know F# have the MAP, but I wanna use the .NET Dictionary. This dict have key as string and values as F# values + the dict, ie:
type ExprC =
| StrC of string
| BoolC of bool
| IntC of int32
| DecC of decimal
| ArrayC of int * array<ExprC>
| RelC of RelationC
and RelationC = Dictionary<string, ExprC>
Now, the problem I wanna solve is how provide the RelationC type with structural equality. If is required to encapsulate the actual storage, how create a container that is a replacement for Dictionary, use it for mutable operations and have structural equality?
With the current answer, this code not work (of curse the implementation is not complete, however, this not even compile):
[<CustomEquality; CustomComparison>]
type MyDict() =
inherit Dictionary<string, ExprC>()
override this.Equals x =
match x with
| :? MyDict as y -> (this = y)
| _ -> false
override this.GetHashCode () =
hash this
interface System.IComparable with
member x.CompareTo yobj =
match yobj with
| :? MyDict as y -> compare x y
| _ -> invalidArg "MyDict" "cannot compare values of different types"
and [<StructuralEquality;StructuralComparison>] ExprC =
| IntC of int
| StrC of string
| MapC of MyDict
This is the error:
Error FS0377: This type uses an invalid mix of the attributes
'NoEquality', 'ReferenceEquality', 'StructuralEquality',
'NoComparison' and 'StructuralComparison' (FS0377)
If you absolutely must use Dictionary<string, ExprC>, you could derive from Dictionary<'k, 'v> and override Equals:
type MyDict() =
inherit Dictionary<string, ExprC>()
override this.Equals x =
true // real implementation goes here
override this.GetHashCode () =
0 // real implementation goes here
Here, you'd need to implement Equals to have structural equality, and you'll need to implement GetHashCode to match you Equals implementation.
Another alternative, if you don't need the concrete class Dictionary<'k, 'v>, is to define your own class that implements IDictionary<TKey, TValue>.
While possible, this sounds like a lot of work. It'd be much easier to use a Map, which has structural equality by default:
let m1 = Map.ofList [("foo", 1); ("bar", 2); ("baz", 3)]
let m2 = Map.ofList [("bar", 2); ("foo", 1); ("baz", 3)]
let m3 = Map.ofList [("bar", 2); ("foo", 1); ("baz", 4)]
> m1 = m2;;
val it : bool = true
> m1 = m3;;
val it : bool = false
Regarding the question at the end of the updated original post: What is the reason for "This type uses an invalid mix..."? This is a bug in the F# compiler, the error message is misleading, see Github. The solution is to simply remove all attributes from MyDict.

How to get the name of function argument in F#?

Can I write a function which returns the name of the function given as the argument?
let funName f: string =
// returns the name of f.
For example, if I pass printfn as an argument to funName, it returns "printfn".
> funName printfn;;
val it : string = "printfn"
EDIT: I wanted to write a function doc which returns the XML documentation associated with the given function.
let doc f = // returns the XML documentation of the function `f`.
To retrieve the summary of the function using something like NuDoq, I wanted to know the name of the function.
I cannnot imagine why you would want to do this and I do not think that there's a way to do this with reflection, but F# Code Quotations might get you halfway there.
open Microsoft.FSharp.Quotations
let rec funName = function
| Patterns.Call(None, methodInfo, _) -> methodInfo.Name
| Patterns.Lambda(_, expr) -> funName expr
| _ -> failwith "Unexpected input"
let foo () = 42
funName <# foo #> // "foo"
But note that certain predefined library functions have a divergent internal name.
funName <# printfn #> // "PrintFormatLine"
funName <# id #> // "Identity"
Note that as of F# 4.0, class types can automatically quote their arguments, simplifying the call site compared to kaefer's answer:
open Microsoft.FSharp.Quotations
type DocumentGetter =
static member GetName([<ReflectedDefinition>]x:Expr<_->_>) =
match x with
| DerivedPatterns.Lambdas(_, Patterns.Call(_,methodInfo,_)) ->
methodInfo.Name
let f x y = x + y
DocumentGetter.GetName f

F# Type Provider Referencing Custom Types

I'm constructing a simple type provider, but I seem to be running into problems when referencing types I created. For instance, given
namespace Adder
type Summation = Summation of int
module QuickAdd =
let add x y = x + y |> Summation
I want to make the following test case pass:
module Adder.Tests
open Adder
open NUnit.Framework
type Simple = QuickAddProvider<1, 2>
[<Test>]
let ``Simple sample is 3`` () =
let foo = Simple()
Assert.AreEqual(foo.Sample, Summation 3)
With the following type provider:
namespace Adder
open Microsoft.FSharp.Core.CompilerServices
open ProviderImplementation.ProvidedTypes
open System.Reflection
[<TypeProvider>]
type public QuickAddProvider (config : TypeProviderConfig) as this =
inherit TypeProviderForNamespaces ()
let ns = "Adder"
let asm = Assembly.GetExecutingAssembly()
let paraProvTy = ProvidedTypeDefinition(asm, ns, "QuickAddProvider", Some typeof<obj>)
let buildTypes (typeName:string) (args:obj[]) =
let num1 = args.[0] :?> int
let num2 = args.[1] :?> int
let tpType = ProvidedTypeDefinition(asm, ns, typeName, Some typeof<obj>)
let result = QuickAdd.add num1 num2
let orig = ProvidedProperty("Sample", typeof<Summation>, GetterCode = (fun args -> <## result ##>))
tpType.AddMember(orig)
tpType.AddMember(ProvidedConstructor([], InvokeCode = (fun args -> <## () ##>)))
tpType
let parameters =
[ProvidedStaticParameter("Num1", typeof<int>)
ProvidedStaticParameter("Num2", typeof<int>)]
do paraProvTy.DefineStaticParameters(parameters, buildTypes)
do this.AddNamespace(ns, [paraProvTy])
[<TypeProviderAssembly>]
do()
I run into unexpected errors in the test file:
The type provider 'Adder.QuickAddProvider' reported an error in the context of provided type 'Adder.QuickAddProvider,Num1="1",Num2="2"', member 'get_Sample'. The error: Unsupported constant type 'Adder.Summation'
With the following errors in the generated file:
The type "Summation" is not defined
The namespace or module "Adder" is not defined
The test case compiles and passes when replacing the Summation type with int, so I know my type provider isn't terribly wrong. Do I need to somehow "import" the Summation type somewhere?
This error usually means that you are creating a quotation that contains a value of custom type. The quotations in type providers can only contain values of primitive types - the compiler knows how to serialize these - but it cannot handle custom types.
In the snippet, this happens here:
let result = QuickAdd.add num1 num2
let orig = ProvidedProperty("Sample", typeof<Summation>, GetterCode = (fun args ->
<## result ##>))
Here, the GetterCode returns a quotation containing value of type Summation which is not supported. To make this work, you can do various things - generally, you'll need to come up with some other quoted expression that produces the value you want.
One option is to do the calculation inside the quotation rather than outside:
<## QuickAdd.add num1 num2 ##>
The other option would be to re-create the Summation value in the quotation:
let (Summation n) = result
<## Summation n ##>
This works, because it only needs to serialize a primitive int value and then generate a call to the Summation case constructor.

Resources