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
push
transition does not work in ArrayType
#75
Comments
ArrayType
push
transition does not work in ArrayType
Among other things, it appears that the problem is that we don't allow transitions returning just the value to update the tree. https://github.com/cowboyd/microstates.js/blob/fix-array-transitions/src/typeclasses.js#L13 As you can see there, we update the value, but not the tree. However, in the case of Arrays and Objects the tree can update with a transition as well. It seems as though we need to do some sort of "re analysis". |
So for example let's say you're pushing The value of the array node will get updated to have [1,2,3,4], but the tree will still only have 3 children. |
@cowboyd we must not have compounded transition tests for arrays, because our test suite should have caught this. |
Our existing tests couldn't have caught it because you don't see this problem until you add parameterized types because for non-parameterized arrays, there is no tree below the array... The array itself is a leaf, so the value is the state. However, once you start parameterizing, then the tree can extend beyond the array node, and so it's important to keep the tree in sync. |
One way to brute-force it, would be to have array transitions that change the structure of the array actually return a completely new microstate, and not just a new value. However in order to create a new Array with the correct type, we need to somehow be able to pass the type of the current array to the transition so that it can create the correct type. One way to do this would be to have all array transitions return a function that takes the type of the array, and the current value of the array, so that it can return a new microstate instance. That way, it will use the entire microstate tree returned. class ArrayType {
pop() {
return (T, value) => create(T, value.slice(0, -1));
}
} There are two problems with this. One is that it doesn't do any structural sharing between versions of the array. For example, if I have an array The other problem that arises is how do we type-shift? In other words, how can we have a heterogeneous set of types occupying an array if popping off an item, resets the type to the original parameter. In other words, If I have an array of We could define pop in terms of a class ArrayType {
pop() {
//kick the can down to hypothetical slice transition
return this.slice(0, -1);
}
slice(start, end) {
let { tree, value } = reveal(this);
let nextTree = new Tree({
data: _ => tree.data,
children: _ => tree.children.slice(start, end)
});
let nextValue = value.slice(start, end);
return new Microstate(nextTree, nextValue);
} That is a solution for class ArrayType {
push(value) {
let index = this.valueOf().length;
let { tree, value } = reveal(this);
let { T } = params(tree.data.Type);
let { tree: pushedTree } = reveal(create(T, value));
let nextTree = new Tree({
data: _ => tree.data,
children: _ => tree.children.concat(graft([index], pushedTree))
});
let nextValue = value.concat(value);
} yikes! How to abstract this? 🤔 |
This issue is addressed by the introduction of Structural Sharing in #113. It is now possible to perform operations on the tree that the microstate is created from. To do this, you can map the microstate and flatMap the tree. You can see this in the Array & Object types https://github.com/microstates/microstates.js/blob/cl/a-tree-for-all-seasons/src/types/array.js#L52 |
This has been crushed in like 3 re-writes :) |
It appears that a push for a parameterized array does not work, and the following testcase fails.
The
valueOf()
only contains the last thing pushed on:Furthermore, the
state
property completely fails insofar as it is equal to[]
The text was updated successfully, but these errors were encountered: