Bi-directional binding
https://scrapbox.io/files/682c77e6e27e13eece0f7147.png
Suppose you have a value a: A, and there’s a system that reactively computes a value b: B from it. The mapping function f: A -> B isn’t necessarily bijective, so its inverse function fInv: B -> A might not be well-defined.
However, to achieve a kind of bi-directional binding, I tried to implement a mechanism like this:
code:ts
type F = (a: A) => B
type FInv = (b: B, currentA: A) => A
That is, the inverse function is defined as a function that takes both a value b: B and the current value currentA: A, then returns a value a such that:
f(a) is as close as possible to b
a is as close as possible to currentA
When the corresponding a for b does not exist, simply return currentA
Example 1: square
code:typescript
const f = a => a * a
const fInv = (b: number, currentA: number) => {
if (b < 0) return 0
return Math.sign(currentA) * Math.sqrt(b)
}
Example 2: floor
code:typescript
const f = Math.floor
const fInv = (b: number, currentA: number) => {
if (Math.floor(currentA) === b) return currentA
return b
}
Example 3: Number.toString
code:ts
const f = (a: number) => a.toString()
const fInv = (b: string, currentA: number) => {
const parsed = parseFloat(b)
if (isNaN(parsed)) return currentA
return parsed
}
Related
Inverse Evaluation
Haskell - Lens / Prism