-
Notifications
You must be signed in to change notification settings - Fork 21
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
Specialization for generics #1399
Comments
As F# language evolves I would like to see it |
This looks a lot like a well known concept in type theory called Generalized Algebraic Data Types (GADT). It is implemented in Haskell and OCaml, notably. It is more complex to implement than it may seem at first glance though. Notably because when you match on a value of type See this previous proposal, where the difficulties in implementing this are discussed. |
Thanks for introducing the 'Generalized Algebraic Data Types (GADT)' concept to me as I didn't know about what it's called and I'm happy I can talk to people about it. I thought bit further to provide the actual way it would be used after implemented : type origin<'a> = unit -> 'a
type asyncOrigin <'a> = unit -> Async<'a>
type construct<'generic> =
| A of A : 'generic<construct<'generic>>
| B of B : int
| C of C : construct<'generic> //not allowed in F# union, since 'generic is expected to be a generic itself, it can not too have expectation that it's not or we do not get strong typing on union case matches
static member op_Implicit (arg : origin<construct<'generic>>) = A(arg)
static member op_Implicit (arg : asyncOrigin<construct<'generic>>) = A(arg)
static member op_Implicit (arg : int) = B(arg)
type platform<'origin> =
struct
val x : int
new (arg : construct<'origin>) = {x = 0}
end
let killSwitch () =
let c1 = platform(fun construct -> async {return 0})
//typeof<c1> = platform<(asyncOrigin<construct<:>>)>, ':' meaning it's recursive. 0 would be implicitly casted to (construct<asyncOrigin<:>>) like usual.
match c1 with
| A asyncOp -> asyncOp |> Async.RunSynchronously
| B integer -> ()
let c2 = platform(fun construct -> 0)
//typeof<c2> = platform<(origin<construct<:>>)>, ':' meaning it's recursive. 0 would be implicitly casted to (construct<asyncOrigin<:>>) like usual.
match c2 with
| A Op -> ()
| B integer -> () Specialization for generic was allowing me to write a construct that's async and not async without me actually having two types or two cases like I would today. Generics are basically still generics and Meanwhile how it would be implemented is exactly having multiple types (likely) or multiple cases of construct for as many specialization as needed, after detecting generic specialization usages. For example, type construct_Sync =
| A of A : unit -> construct_sync
| B of B : int
type construct_Async =
| A of A : unit -> Async<construct_Async>
| B of B : int So far I've not seen a problem of the type recursion in my example, since it's not immediate recursion, so the construct can be a struct and recursion is allowed like it's allowed today when For people who are really curious about benefits, I can say specialization on generics can for example, be easier for library authors to write both sync and async version of their infrastructures without adding new types and just let codes written without async in design to adopt the new features like async programming that's available in moving forward I haven't studied #179 yet and I am going to now |
I propose we allow specialization on generics :
And for now the construct<'generic> (types using specialization for generic) is not directly usable (???usable???) and more like a template
Functions would either use
usage_
orasyncUsage_
It helps by introducing possibility of template programming (meta programming) to reduce code usage (writing codes) in one scenario (as specialized generics are accepted on more places it helps more) :
For now one can just write this instead :
This might be a way to overload functions with identical argument types but different return types
Now people can write that template and depending on return type expected select the function smartly
Specialization for generics would be the missing piece needed to start writing C++ style templates in F#
The text was updated successfully, but these errors were encountered: