Adding this as a tracking issue to implement unspecialized lambda sets in Roc, which I intend to do next. This should unblock some troubles we currently have during monomorphization of abilities and get us closer to an end-in-sight.
I implemented this in cor and it works so I think it should be fine in Roc too.
Some ideas after this is done:
We may be able to use lambda sets as the source-of-truth always in mono, rather than relying on the symbol a function call makes. Monomorphization in cor/uls is done by exclusively looking at the lambda set of a function being called and determining the call site based off that, rather than what the symbol is actually named. For example, the cor/uls program (source)
proto thunkDefault a : () -> () -> a
# ^^^^^^^^^^^^
let thunkDefault = \() -> \() -> T1
# ^^^^^^^^^^^^
let useT1 = \T1 -> ()
entry test =
let alias = thunkDefault in
# ^^^^^
useT1 (alias () ())
# ^^^^^
is inferred as
> cor-out +solve -elab
> proto thunkDefault a : () -> () -> a
> # ^^^^^^^^^^^^ () -[~1:a:thunkDefault]-> () -[~2:a:thunkDefault]-> a
>
> let thunkDefault = \() -> \() -> T1
> # ^^^^^^^^^^^^ () -[[`3]]-> () -[[`2]]-> T1
>
> let useT1 = \T1 -> ()
>
> entry test =
> let alias = thunkDefault in
> # ^^^^^ () -[[] + ~1:?13:thunkDefault]-> () -[[] + ~2:?13:thunkDefault]-> ?13
> useT1 (alias () ())
> # ^^^^^ () -[[`3]]-> () -[[`2]]-> T1
>
Notice that alias was completely irrelevant here, and was eliminated during monomorphization! So we got a very cheap optimization. Today we do this elimination in Roc, but it's done syntactically - we keep a look-aside table of identifier aliases. With this technique, we can instead eliminate aliases automatically by inlining lambda set names where singleton aliases are used. To be more clear, in useT1 (alias () ()), alias was aliasing the closure with name `3, and the type of alias in that position tells us that it definitely resolves to `3, so we can fully replace alias with `3 - that means when time comes, let alias = ... can also be eliminated.
Adding this as a tracking issue to implement unspecialized lambda sets in Roc, which I intend to do next. This should unblock some troubles we currently have during monomorphization of abilities and get us closer to an end-in-sight.
I implemented this in cor and it works so I think it should be fine in Roc too.
Some ideas after this is done:
is inferred as
which then monomorphizes as
Notice that
alias
was completely irrelevant here, and was eliminated during monomorphization! So we got a very cheap optimization. Today we do this elimination in Roc, but it's done syntactically - we keep a look-aside table of identifier aliases. With this technique, we can instead eliminate aliases automatically by inlining lambda set names where singleton aliases are used. To be more clear, inuseT1 (alias () ())
,alias
was aliasing the closure with name`3
, and the type ofalias
in that position tells us that it definitely resolves to`3
, so we can fully replacealias
with`3
- that means when time comes,let alias = ...
can also be eliminated.