Function polymorphism #285
Replies: 16 comments 17 replies
-
Another possibility is we (somehow) have only monomorphic graphs in core, but we have some kind of polymorphic graph type as an opaque type in the Tierkreis extension (with its own, internal, encoding of type variables - so probably repeating much of the core type system PLUS variables, but at least it keeps variables out of core). Then either |
Beta Was this translation helpful? Give feedback.
-
Discussion today - I think this might be enough to mark the discussion "resolved" and convert to a tracking issue but I'll post here now:
Otherwise I think we are looking at:
|
Beta Was this translation helpful? Give feedback.
-
Ok, so there is a bigger issue, still, relating to the difference between graphs ("type application" by substitution into a schema) and ops ("type application" by custom binary code). Say we have a graph polymorphic over a type or indeed over a USize. How do we typecheck the graph (or indeed, do we not typecheck it at all)? There are two main options:
Another concern is if we wanted a Graph polymorphic over different widths of integer from the arithmetic extension. This requires checking that the width ( This suggests to me that
|
Beta Was this translation helpful? Give feedback.
-
Or, ok, another compromise. Split OpDef into two stages: Static parameters to OpDef, which must be instantiated by static TypeArgs (no type variables, even in a polygraph). This performs custom binary Roughly, this translates as - rather than an OpDef being either a custom binary Still a compromise: we can substitute into types (as we have no custom binary validity check there), and we could be polymorphic over array sizes or even tensor rank (no, e.g., sum over the first dimension), but we cannot be polymorphic over e.g. arithmetic-extension integer width (as that requires computation). |
Beta Was this translation helpful? Give feedback.
-
And the " |
Beta Was this translation helpful? Give feedback.
-
I'm leaning towards: Polymorphic functions in core HUGR is too much for an IR. They will be very useful in Guppy, but for HUGR purposes some level of templating over types in the tooling (with something like PolyGraphType as an internal struct that can be type-applied) is enough. If we need it, we can take your polymorphic-extension-type function later and use binary type computation. If there are use cases for which we definitely need polymorphic functions in core that I'm not recalling, please let me know. |
Beta Was this translation helpful? Give feedback.
-
More discussion today. There are a few arguments for supporting something like this in core hugr.
|
Beta Was this translation helpful? Give feedback.
-
Proposal 1
Note (limitation): does not rule out |
Beta Was this translation helpful? Give feedback.
-
Simpler Non-proposal 1a
Simpler Non-proposal 1b
|
Beta Was this translation helpful? Give feedback.
-
Proposal 2This strengthens Proposal 1 above to rule out runtime failure of custom binary Beyond Proposal 1, we extend OpDef's We then statically enforce that all arguments passed to (That is, if a type variable could be passed in as a TypeArg to a particular TypeParam, simple substitution for that typevar is all that can happen at runtime, so it is all that compute_signature can be allowed to do statically. Thus, |
Beta Was this translation helpful? Give feedback.
-
When I think of examples where function polymorphism is useful, there is almost always some further parametrization beyond merely the free type, usually an associated operation with certain properties. For example, a "sort" function requires a type with a (suitably constrained) order relation. Have we thought about how such "parameters" would be passed around? |
Beta Was this translation helpful? Give feedback.
-
Besides runtime failure of |
Beta Was this translation helpful? Give feedback.
-
Proposal 3No polymorphism in Hugr. There are certain type system features from frontends that we don't want to support in the IR (e.g. dependent types from Brat). We could treat polymorphism as one of those non-supported features and make it entirely the frontend's job to do type checking and rule out runtime errors. To this end, we could use an I think one of the questions to consider is whether supporting polymorphic types in Hugr would enable optimisations that we want to do that would be harder otherwise? |
Beta Was this translation helpful? Give feedback.
-
We should also consider adopting Proposal 3 (HUGR is monomorphic), and leave open the possibility of a future polymorphic HUGR 2.0. It's not clear to me how much we gain from having this feature in the IR, and how much extra complexity it would add.
I actually can't see that it would. Any optimization pass that you can do on a polymorphic function you can do on its monomorphization, and you'd probably want to anyway to take advantage of the specialization. |
Beta Was this translation helpful? Give feedback.
-
Proposal 2 above was implemented by #630. However maybe there was a less-polymorphic intermediate that we didn't consider.
This is a lot like ML, etc. - "TLDs can be polymorphic but nothing else". No polymorphic lambdas. (If you want to make a lambda, i.e. a Graph, that calls a polymorphic function, the lambda has to instantiate that by supplying a list of TypeArgs - I'd say "fixed list of TypeArgs", they could contain type variables but only in that a In terms of code complexity, we get to drop the funky cases of Why didn't we think of this? Well, we were thinking about the Tierkreis standard library use case, but I don't think we really talked(/thought) about the other big change that Hugr brings from TierkreisGraph, i.e. the ability to have a load of FuncDefns/TLDs.... |
Beta Was this translation helpful? Give feedback.
-
Conclusion will be enacted by #904 |
Beta Was this translation helpful? Give feedback.
-
Operations defined in resources are polymorphic over types.
Are functions (defined in Hugrs) also polymorphic? Or are they monomorphic?
This also determines what happens to type variables, i.e.
ClassicTypeHashableType::Variable.If functions are polymorphic, we need to indicate what type (variables) are bound by each function; and we should probably move Variable into Container, alongside Alias, reflecting that we can have variables that are constrained to each
TypeTag
.If functions are monomorphic, then I think type variables can be removed from the SimpleType hierarchy - they exist only within the "YAML Type Scheme Interpreter", in its own internal representation of type schemes; the Hugr sees only that it passes some TypeArgs to the YSTI and gets back a Signature (sans variables).
Beta Was this translation helpful? Give feedback.
All reactions