-
Notifications
You must be signed in to change notification settings - Fork 9
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
Adding polymorphism to ksc #711
base: master
Are you sure you want to change the base?
Conversation
The big changes are these: * A Type can now contain a type variable * A top-level Def binds type variables, def_qvars :: [TyVar] * The concrete syntax and parser supports polymorphic definitions. E.g. here is the identity function: (def id [a] a ( x : a ) x) * In a Call, the TFun has a field tf_targs :: [Type], which are the types at which the function is instantiated. Of course tf_targs is usually empty. * A BaseUserFun is contains an ArgTypeDescriptor, rather than a mere Type (as previosly): data ArgTypeDescriptor = Mono Type | Poly So we can can have BaseUserFuns like [f Int], [f Bool], but also [f poly]. * The GblSymTab can contain - either a polymorphic definition - or multiple monomorphic ones Its structure reflects this: type GblSymTab = M.Map (DerivedFun BaseUserFunName) FunBindings data FunBindings = PolyBind TDef | MonoBinds (M.Map Type TDef) Everything else is driven by these changes in the data types.
@toelli-msft, we have polymorphism! Would you like to take a look? I should write a Note, but I don't think you'll find any surprises. There is a tiny test in poly1.ks, but perhaps you can try others? I have done nothing about back ends. |
Great! It would be good to elaborate the benefits. Off the top of my head:
|
Yes indeed. Where would be a good place to enumerate these benefits? Buried in an MR comment stream doesn't seem the right place.
For me this is a driver -- it'll let us implement reverse-mode AD via the "backpropagator" method, which we've been discussing with Neel and Faustyna. My plan is to do a proof-of-concept AD transformation using this idea. |
4.GNN can process polymorphic definitions, instead of running over many different implementations. |
I think starting in an MR comment stream is fine. Pertinent points get transferred somewhere more permanent such as the OneNote. Alternatively the OneNote is a good place to start.
Just as a point of information, I don't think polymorphism is required to get that AD transformation to work. It could be done with a transformation that takes a type as a parameter. On the other hand it's much easier to do with polymorphism otherwise one has to conjure up names for functions that differ only in that type parameter. |
(And @simonpj I'm sorry that I haven't had a chance to look at this yet, but thanks for the walkthrough yesterday and will get to it when I can.) |
[This may be just my ignorance] I have seen challenge in AD due to polymorphism in the rank of inputs to ONNX's MatMul Op. That is, basically you can call MatMul on two n-dimensional tensors (n >= 2) and you can get broadcasting automatically. See OnnxRuntime's AD implementation here: I am curious if polymorphism in KSC will cause similar headache for us or we have a different plan (for example, we have a better type inference or other mechanism to resolve type before AD) so we are ok. More concretely, the backward for
would be
which is different from the backward for
|
I think that your two add functions, namely
are simply two entirely separate functions, just shorthand for
As a programming convenience we allow you to call them both "add", but that's rapidly resolved into two completely distinct functions No polymorphism here! |
@simonpj - can you take a look at Prim.hs and see what actually gets removed? |
The big changes are these:
A Type can now contain a type variable
A top-level Def binds type variables, def_qvars :: [TyVar]
The concrete syntax and parser supports polymorphic
definitions. E.g. here is the identity function:
(def id [a] a ( x : a ) x)
In a Call, the TFun has a field tf_targs :: [Type], which
are the types at which the function is instantiated. Of course
tf_targs is usually empty.
A BaseUserFun is contains an ArgTypeDescriptor, rather than
a mere Type (as previosly):
data ArgTypeDescriptor = Mono Type | Poly
So we can can have BaseUserFuns like [f Int], [f Bool],
but also [f poly].
The GblSymTab can contain
Its structure reflects this:
type GblSymTab = M.Map (DerivedFun BaseUserFunName)
FunBindings
data FunBindings = PolyBind TDef
| MonoBinds (M.Map Type TDef)
Everything else is driven by these changes in the data types.