fsprojects / FSharp.Data.Adaptive

On-demand adaptive/incremental data for F# https://fsprojects.github.io/FSharp.Data.Adaptive/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bind does not work with mapNonAdaptive

hyazinthh opened this issue · comments

Currently, combining AVal.bind and AVal.mapNonAdaptive will lead to updates being lost, due to how the BindVal type detects if its input changed. The following unit test demonstrates this behavior:

[<Test>]
let ``[AVal] Map non-adaptive and bind``() =
    let v = AVal.init true
    let a = AVal.constant 0
    let b = AVal.constant 1

    let output = v |> AVal.mapNonAdaptive id |> AVal.bind (fun flag -> if flag then a else b)

    output |> AVal.force |> should equal 0

    transact (fun () -> v.Value <- false)
    output |> AVal.force |> should equal 1

I just made 3 different attempts to fix this, but it seems this sort of decorator node is not easy to integrate s.t. no-one can notice...

However I think with enough thought it will be fixable in a few lines of code...

For interested readers: it's related to the MapNonAdaptiveVal not being part of the dependency tree and some dirty-checks failing due to this..

Hey @hyazinthh I finally found a fix for this and the change is pretty small, basically we need to smuggle a tuple of IAdaptiveObjects around in evaluate/transact.
I did it via a custom DecoratedObject that sadly also had to implement IAdaptiveObject (hence the ugliness)

Nonetheless it solves the issue in such a way that InputChanged will be called with the MapNonAdaptiveVal instead of the actual cell causing the marking. Of course this only happens when the evaluation used the decorated thing.

@haraldsteinlechner @luithefirst @aszabo314 could someone think this through and check if i missed something?

Sorry for the force push (the latest commit is even more condensed)