New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow types to be spliced into a typeof keyword to make reflection and meta-programming easier #698

Open
7sharp9 opened this Issue Sep 28, 2018 · 6 comments

Comments

Projects
None yet
2 participants
@7sharp9
Member

7sharp9 commented Sep 28, 2018

Title of Suggestion

I propose we allow types to be spliced into typeof<...> to make reflection and meta-programming in F# easier.

The existing way of approaching this problem in F# is to do this manually with the following code:

Imagine we have a reference to a type fieldType :

type FieldType = class end
let fieldType = typeof<FieldType>

To create an instance of an Option<fieldType> would require the following code:

typedefof<Option<_>>.MakeGenericType(fieldType)

This in itself is not too bad, but what if we needed to make a type which looked more like this:

IReadOnlyDictionary<String, JToken> -> Result<Option<fieldType> -> Option<nextFieldType> -> recordType, String>

This requires substantially more code and can quickly get out of hand : also note the use if a helper function makeFunctionTypeFromElements which is not detailed below :

 let domain = typeof<IReadOnlyDictionary<String, JToken>>
 let range =
     let currentField = typedefof<Option<_>>.MakeGenericType(fieldType)
     let nextField = typedefof<Option<_>>.MakeGenericType(nextFieldType)
     let functionType = makeFunctionTypeFromElements [currentField; nextField; recordType]
     typedefof<Result<_,_>>.MakeGenericType([|functionType; typeof<string>|])
 let decoderType = Reflection.FSharpType.MakeFunctionType(domain, range)

This could be simplified to the following if typeof allowed the splicing of types via a construct like %typeInstance:

typeof<IReadOnlyDictionary<String, JToken> -> Result<Option<%fieldType> -> Option<%nextFieldType> -> %myRecord, String>>

Pros and Cons

The advantages of making this adjustment to F# are simplifying the creation of generic types for meta programming

The disadvantages of making this adjustment to F# are adding extra complexity to F#.

Extra information

Estimated cost (S/M):

Related suggestions: (put links to related suggestions here)
#670 is related as that pertains to splicing of types into an untyped quotation.

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this

@7sharp9 7sharp9 changed the title from Allow types to be spliced into a typeof keyword to make reflection and meta-programming dar easier to Allow types to be spliced into a typeof keyword to make reflection and meta-programming far easier Sep 28, 2018

@7sharp9 7sharp9 changed the title from Allow types to be spliced into a typeof keyword to make reflection and meta-programming far easier to Allow types to be spliced into a typeof keyword to make reflection and meta-programming easier Sep 28, 2018

@dsyme

This comment has been minimized.

Show comment
Hide comment
@dsyme

dsyme Oct 1, 2018

Collaborator

This seems entirely reasonable, though would complicate the code generation for typeof, which is currently very simple. Do you have a prototype?

Collaborator

dsyme commented Oct 1, 2018

This seems entirely reasonable, though would complicate the code generation for typeof, which is currently very simple. Do you have a prototype?

@7sharp9

This comment has been minimized.

Show comment
Hide comment
@7sharp9

7sharp9 Oct 1, 2018

Member

@dsyme Not currently, although I could work towards one

Member

7sharp9 commented Oct 1, 2018

@dsyme Not currently, although I could work towards one

@7sharp9

This comment has been minimized.

Show comment
Hide comment
@7sharp9

7sharp9 Oct 1, 2018

Member

(# "ldtoken !0" type('T) : System.RuntimeTypeHandle #)
Is nice and simple :-)

Member

7sharp9 commented Oct 1, 2018

(# "ldtoken !0" type('T) : System.RuntimeTypeHandle #)
Is nice and simple :-)

@dsyme

This comment has been minimized.

Show comment
Hide comment
@dsyme

dsyme Oct 2, 2018

Collaborator

Yes :)

Collaborator

dsyme commented Oct 2, 2018

Yes :)

@7sharp9

This comment has been minimized.

Show comment
Hide comment
@7sharp9

7sharp9 Oct 2, 2018

Member

@dsyme Im guessing that the work involved would have to be in the parser as the typeof function only recieves a type, or adding a new function

Member

7sharp9 commented Oct 2, 2018

@dsyme Im guessing that the work involved would have to be in the parser as the typeof function only recieves a type, or adding a new function

@dsyme

This comment has been minimized.

Show comment
Hide comment
@dsyme

dsyme Oct 5, 2018

Collaborator

@dsyme Im guessing that the work involved would have to be in the parser as the typeof function only recieves a type, or adding a new function

You'd add a splicing syntax into types, like we do for expressions. it could only be for use in typeof, just like expression splicing is only for use in <@ ... @>. I think the construct may need parantheses in some form since you're moving from type syntax to expression syntax, e.g.

typeof<list<%(ty)>>

To be honest calling <@ ... @> simply exprof(...) would have made a lot of sense but hey.

One simple implementation would be to to emit either a generic utility method and a reflection-instantiate-then-invoke call of that method, e.g.

typeof<list<%(ty)>>

becomes

Type PrivateHelperMethod<T>() { return typeof<list<T>> }

methodinfoof(PrivateHelperMethod).MakeGenericMethod( [| ty |]).Invoke(null)

or something like that.

Collaborator

dsyme commented Oct 5, 2018

@dsyme Im guessing that the work involved would have to be in the parser as the typeof function only recieves a type, or adding a new function

You'd add a splicing syntax into types, like we do for expressions. it could only be for use in typeof, just like expression splicing is only for use in <@ ... @>. I think the construct may need parantheses in some form since you're moving from type syntax to expression syntax, e.g.

typeof<list<%(ty)>>

To be honest calling <@ ... @> simply exprof(...) would have made a lot of sense but hey.

One simple implementation would be to to emit either a generic utility method and a reflection-instantiate-then-invoke call of that method, e.g.

typeof<list<%(ty)>>

becomes

Type PrivateHelperMethod<T>() { return typeof<list<T>> }

methodinfoof(PrivateHelperMethod).MakeGenericMethod( [| ty |]).Invoke(null)

or something like that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment