ponyc
ponyc copied to clipboard
Vary capabilities on generics
The following code compiles fine:
actor KVState[In: OSCEncodable val, Out: OSCEncodable val] is ThroughStep[In, Out]
let _f: StateComputation[In, Out]
var _output: (ComputeStep[Out] tag | None) = None
let _state: Map[I32, I32]
new create(state: Map[I32, I32] iso, f: StateComputation[In, Out] iso) =>
_state = consume state
_f = consume f
be add_output(to: ComputeStep[Out] tag) =>
_output = to
be apply(input: Message[In] val) =>
let r = _f(_state, input)
match _output
| let c: ComputeStep[Out] tag => c(r)
end
However, if we want to make this generic and just be a Store where we pass in any sort of data structure, not just a Map, then we hit a problem:
actor State[In: OSCEncodable val, Out: OSCEncodable val, DataStructure: Any] is ThroughStep[In, Out]
let _f: StateComputation[In, Out, DataStructure]
var _output: (ComputeStep[Out] tag | None) = None
let _state: DataStructure
new create(state: DataStructure iso, f: StateComputation[In, Out, DataStructure] iso) =>
_state = consume state
_f = consume f
be add_output(to: ComputeStep[Out] tag) =>
_output = to
be apply(input: Message[In] val) =>
let r = _f(_state, input)
match _output
| let c: ComputeStep[Out] tag => c(r)
end
The issue is, that we need to be able to say DataStructure iso in our constructor but can't as that is currently disallowed. If we put it on our type params, then our _state variable is no longer a ref and the code can't work as intended. We don't want an iso, we want a ref.
I talked this over with @sylvanc and he agrees its a very reasonable thing to want to do.
We discussed this on the sync call, and the consensus was that treating a type parameter in the same way as a type alias (as @jemc said "a localised type alias") makes sense.
Note that after adopting George Steed's viewpoint adaptation model, the example above could be solved with a viewpoint-adapted type.
For example, you could have the type parameter A: Any ref, then have your constructor accept an iso->A argument, which would come out to be the equivalent of A iso under the new viewpoint adaptation model.
@jemc Did you mean something like this:
class Foo[A: Any ref]
let _state: A
new create(state: iso->A) =>
_state = consume state
And would you expect that work now?
It doesn't. I assume that is because https://github.com/ponylang/ponyc/issues/2815 is still open and not fully implemented, would that be a correct assumption?
Yes, that code snippet is what I mean, and no, I'd not expect it to work right now because our viewpoint adaptation rules don't match #2815 (and there are now questions in that ticket as to whether we should continue with it).