### Incremental List Operations with Adaptive Lists Source: https://github.com/fsprojects/fsharp.data.adaptive/blob/master/README.md Shows how to use `AList` for adaptive list operations. `AList.map` and `AList.fold` recompute results incrementally, maintaining constant update cost regardless of list length. Use `transact` to modify the list and `AVal.force` to get the computed value. ```fsharp let input = clist [1;2;3] let dependent = input |> AList.map (fun v -> v * v) |> AList.fold (+) 0 dependent |> AVal.force // => 14 transact (fun () -> input.Append 4) dependent |> AVal.force // => 30 ``` -------------------------------- ### Create and Derive Adaptive Values Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt Demonstrates creating changeable inputs (`cval`) and deriving adaptive values (`AVal.map2`, `AVal.bind`). Changes are batched using `transact` and read using `AVal.force`. Use `AVal.bind` for dynamic dependencies. ```F# open FSharp.Data.Adaptive // Create changeable inputs let width = cval 800 let height = cval 600 // Derive values — no computation happens yet let area = AVal.map2 (fun w h -> w * h) width height let diagonal = AVal.map2 (fun w h -> sqrt (float w ** 2.0 + float h ** 2.0)) width height let summary = AVal.map2 (fun a d -> sprintf "area=%d diagonal=%.1f" a d) area diagonal AVal.force summary // => "area=480000 diagonal=1000.0" // Batch multiple changes in one transaction transact (fun () -> width.Value <- 1920 height.Value <- 1080 ) AVal.force summary // => "area=2073600 diagonal=2202.9" // Only affected nodes recomputed; diagonal recalculated, summary recalculated once // Dynamic (bind) dependency — dependency on b only exists when param > 0.66 let a = cval "hello" let b = cval "world" let param = cval 0.5 let result = param |> AVal.bind (fun p -> if p <= 0.33 then a :> aval<_> elif p <= 0.66 then b :> aval<_> else AVal.constant "other" ) AVal.force result // => "world" transact (fun () -> param.Value <- 0.1) AVal.force result // => "hello" (dependency on b is now gone) ``` -------------------------------- ### AList Slicing and Adaptive Window Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt Shows how to perform slicing (take) and create adaptive windows (subA) on AList. The adaptive window uses AVal for offset and size, updating dynamically. ```FSharp // Slicing let top2 = ranked |> AList.take 2 AList.force top2 |> IndexList.toList // => [("Dave",95); ("Alice",90)] // Adaptive window using aval offset+count let pageSize = cval 2 let pageOffset = cval 0 let page = ranked |> AList.subA pageOffset pageSize AList.force page |> IndexList.toList // => [("Dave",95); ("Alice",90)] transact (fun () -> pageOffset.Value <- 2) AList.force page |> IndexList.toList // => [("Carol",88); ("Bob",75)] ``` -------------------------------- ### Adaptive Computation with Aval Source: https://github.com/fsprojects/fsharp.data.adaptive/wiki/Home Demonstrates how to implement adaptive computation using the aval<'T> type and its combinators. Shows how changes to input avals automatically propagate to dependent results. ```fsharp let incremental (a : aval) (b : aval) = a |> AVal.bind (fun a -> if a < 10 then AVal.constant 10 else b |> AVal.map (fun b -> a * b) ) let run() = printfn "a <- 1" let a = AVal.init 1 printfn "b <- 2" let b = AVal.init 2 let res = incremental a b printfn "res: %d" (AVal.force res) printfn "a <- 100" transact (fun () -> a.Value <- 100) printfn "res: %d" (AVal.force res) ``` -------------------------------- ### Create and Use Changeable and Adaptive Cells Source: https://github.com/fsprojects/fsharp.data.adaptive/blob/master/README.md Demonstrates the creation of a changeable cell and an adaptive cell that depends on it. Use `transact` to modify changeable cells and `AVal.force` to retrieve the current value of adaptive cells. ```fsharp let changeable = cval 10 let dependent = changeable |> AVal.map (fun a -> 2 * a) dependent |> AVal.force // => 20 transact (fun () -> changeable.Value <- 1) dependent |> AVal.force // => 2 ``` -------------------------------- ### F# AdaptiveFile and AdaptiveDirectory for Filesystem Reactivity Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt AdaptiveFile and AdaptiveDirectory wrap filesystem operations, automatically marking dependent computations out-of-date when files or directories change. This is useful for reading configuration files, monitoring directory contents, and tracking file existence. Note: This feature is .NET only and not available in Fable. ```fsharp open FSharp.Data.Adaptive // Read a config file as aval> — updates when file changes on disk let configText = AdaptiveFile.TryReadAllText "/etc/myapp/config.json" let configValid = configText |> AVal.map (function | Some text -> text.Contains("\"enabled\": true") | None -> false ) AVal.force configValid // => true/false depending on file content // Subscribe to be notified when config changes let sub = configValid.AddMarkingCallback(fun () -> let v = AVal.force configValid printfn "Config changed, enabled = %b" v ) ``` ```fsharp open FSharp.Data.Adaptive // Adaptively list all .fsx files in a directory (updated on add/remove) let srcDir = AdaptiveDirectory.GetFiles("/src", pattern = @"\.fsx$") let fileCount = srcDir |> ASet.count AVal.force fileCount // => number of .fsx files currently present // aval tracking whether a specific file exists let lockFile = AdaptiveFile.Exists "/tmp/myapp.lock" let isLocked = lockFile |> AVal.map id AVal.force isLocked // => true if file exists // Read all lines of a log file as an adaptive list let logLines = AdaptiveFile.ReadAllLinesAList "/var/log/myapp.log" let lineCount = AList.count logLines AVal.force lineCount // updates whenever the file is modified sub.Dispose() ``` -------------------------------- ### Aval API Overview Source: https://github.com/fsprojects/fsharp.data.adaptive/wiki/Home Provides a high-level overview of the aval<'T> API, including types and common combinators for creating and manipulating adaptive values. ```fsharp val transact : (unit -> 'a) -> 'a type cval<'a> = interface aval<'a> val Value with get, set module AVal = val init : 'a -> cval<'a> val constant : 'a -> aval<'a> val map : ('a -> 'b) -> aval<'a> -> aval<'b> val bind : ('a -> aval<'b>) -> aval<'a> -> aval<'b> val force : aval<'a> -> 'a ``` -------------------------------- ### ASet Set Operations Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt Illustrates standard set operations like union, intersection, difference, and XOR using ASet. These operations also benefit from incremental updates. ```FSharp let a = cset [1; 2; 3] let b = cset [3; 4; 5] let union = ASet.union a b let intersect = ASet.intersect a b let diff = ASet.difference a b let xorSet = ASet.xor a b ASet.force union // => {1;2;3;4;5} ASet.force intersect // => {3} ASet.force diff // => {1;2} ASet.force xorSet // => {1;2;4;5} ``` -------------------------------- ### Reactive vs. Non-Reactive Functions Source: https://github.com/fsprojects/fsharp.data.adaptive/wiki/Home Compares a non-reactive function with a reactive implementation using IObservable. Demonstrates how naive translation of non-reactive logic to reactive streams can lead to unexpected behavior. ```fsharp let nonReactive (a : int) (b : int) = if a < 10 then 10 else a * b let reactive (a : IObservable) (b : IObservable) = a.SelectMany(fun a -> if a < 10 then Observable.Never().StartWith(10) else b.Select(fun b -> a * b) ) let run() = let a = new Subject() let b = new Subject() let res = reactive a b res.Add(printfn "res: %d") printfn "a <- 1"; a.OnNext(1) printfn "b <- 2"; b.OnNext(2) printfn "a <- 100"; a.OnNext(100) ``` -------------------------------- ### Adaptive Computation with Computation Expressions Source: https://github.com/fsprojects/fsharp.data.adaptive/wiki/Home Shows an alternative implementation of adaptive computation using aval's computation expression builders, making the code resemble a non-adaptive style. ```fsharp let incremental (a : aval) (b : aval) = aval { let! va = a if va < 10 then return 10 else let! vb = b return va * vb } ``` -------------------------------- ### AMap Grouping with ofASetMapped Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt Demonstrates how to group elements from an ASet into an AMap using AMap.ofASetMapped. The resulting map's values are sets, and it updates incrementally as the source set changes. ```FSharp // groupBy equivalent via AMap.ofASetMapped let words = cset ["apple"; "ant"; "banana"; "bear"; "cherry"] let byFirst = words |> AMap.ofASetMapped (fun w -> w.[0]) // => amap> AMap.force byFirst // => { 'a' = {"apple","ant"}; 'b' = {"banana","bear"}; 'c' = {"cherry"} } ``` -------------------------------- ### Dynamic Adaptive Dependencies with Bind Source: https://github.com/fsprojects/fsharp.data.adaptive/blob/master/README.md Illustrates dynamic dependencies using `AVal.bind`. The adaptive cell `result` conditionally depends on `a` or `b` based on the value of `param`. Dependencies only exist when the condition is met, preventing unnecessary recomputations. ```fsharp let a = cval "some dependency" let b = cval "other input" let param = cval 0.5 let result = param |> AVal.bind (fun p -> if p <= 0.33 then a :> aval<_> elif p <= 0.66 then b :> aval<_> else AVal.constant "invalid" ) ``` -------------------------------- ### F# Callbacks and Change Notifications Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt Use AddMarkingCallback for persistent notifications or OnNextMarking for one-shot callbacks. Both allow subscribing to out-of-date notifications without pulling values, enabling side-effecting integrations. Remember to dispose of subscriptions when no longer needed. ```fsharp open FSharp.Data.Adaptive let counter = cval 0 let message = counter |> AVal.map (fun n -> sprintf "count = %d" n) // Fires every time message is marked out-of-date (i.e. on every transact) let sub = message.AddMarkingCallback(fun () -> printfn "message is stale, current forced value: %s" (AVal.force message) ) transact (fun () -> counter.Value <- 1) // prints: message is stale, current forced value: count = 1 transact (fun () -> counter.Value <- 2) // prints: message is stale, current forced value: count = 2 // Unsubscribe sub.Dispose() transact (fun () -> counter.Value <- 3) // nothing printed // One-shot callback let onceSub = message.OnNextMarking(fun () -> printfn "fired once: %s" (AVal.force message) ) transact (fun () -> counter.Value <- 10) // prints once transact (fun () -> counter.Value <- 11) // silent onceSub.Dispose() ``` -------------------------------- ### Adaptive Computation Expression Builders Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt Utilizes computation expression builders (`aval`, `alist`, `aset`) for writing adaptive code with familiar `let!`, `yield`, and `for` syntax. `let!` pulls values, `yield` adds items, and `for` iterates over adaptive collections. ```F# open FSharp.Data.Adaptive let a = cval 5 let b = cval 3 // aval CE — use let! to pull values, return computes map/bind automatically let product = aval { let! x = a if x > 0 then let! y = b return x * y else return 0 } AVal.force product // => 15 transact (fun () -> a.Value <- -1) AVal.force product // => 0 (b no longer a dependency) // alist CE — yield and yield! to build adaptive lists let items = clist [1; 2; 3] let extra = cval 99 let combined = alist { yield! items yield! [10; 20] let! v = extra yield v } AList.force combined |> IndexList.toList // => [1; 2; 3; 10; 20; 99] // aset CE — for-comprehension over adaptive sets let tags = cset ["fsharp"; "dotnet"] let sizes = cval [| 1; 2; 3 |] let result = aset { for tag in tags do yield tag.ToUpper() yield! sizes } ASet.force result // => HashSet { "FSHARP"; "DOTNET"; 1; 2; 3 } ``` -------------------------------- ### ASet Adaptive Predicate Filtering Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt Shows how ASet.filterA can use an adaptive predicate (an AVal) to dynamically update the filtered set when the predicate's threshold changes. ```FSharp let threshold = cval 3 let large = numbers |> ASet.filterA (fun n -> threshold |> AVal.map (fun t -> n > t)) AVal.force (ASet.count large) // => 2 (4,5,6 > 3... wait, numbers has {1;3;4;5;6}) transact (fun () -> threshold.Value <- 4) // large automatically updates without re-scanning all elements ``` -------------------------------- ### AMap Adaptive Lookup Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt Shows how AMap.tryFind creates an adaptive lookup that returns an AVal>. This value updates automatically when the key's presence or value changes in the map. ```FSharp // Adaptive lookup — aval> tracks a single key let appleCount = inventory |> AMap.tryFind "apples" AVal.force appleCount // => Some 15 transact (fun () -> inventory.Remove "apples" |> ignore) AVal.force appleCount // => None ``` -------------------------------- ### AList Incremental Sorting Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt Demonstrates incremental sorting with AList. Adding or removing elements only requires repositioning the affected item, not re-sorting the entire list. ```FSharp open FSharp.Data.Adaptive let scores = clist [("Alice", 90); ("Bob", 75); ("Carol", 88)] // Incremental sort — inserting one element only repositions that element let ranked = scores |> AList.sortByDescending snd // sort by score descending AList.force ranked |> IndexList.toList // => [("Alice",90); ("Carol",88); ("Bob",75)] transact (fun () -> scores.Append("Dave", 95) |> ignore // only Dave is inserted into the right position ) AList.force ranked |> IndexList.toList // => [("Dave",95); ("Alice",90); ("Carol",88); ("Bob",75)] ``` -------------------------------- ### ASet Incremental Operations Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt Demonstrates incremental map, filter, and fold operations on ASet. Changes to the source set only recompute affected elements. ```FSharp open FSharp.Data.Adaptive let numbers = cset [1; 2; 3; 4; 5] // Map, filter, fold are all incremental let evens = numbers |> ASet.filter (fun n -> n % 2 = 0) let doubled = evens |> ASet.map (fun n -> n * 2) let total = doubled |> ASet.fold (+) 0 // => aval AVal.force total // => 12 (2*2 + 4*2) transact (fun () -> numbers.Add 6 |> ignore // only 6 flows through the pipeline numbers.Remove 2 |> ignore ) AVal.force total // => 20 (4*2 + 6*2) ``` -------------------------------- ### C# Interop with CSharp.Data.Adaptive Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt Utilize `CSharp.Data.Adaptive` for C# integration, providing fluent extension methods for adaptive types, LINQ-style operators for collections, and `IDisposable`-based subscriptions for change notifications. Batching is achieved via the static `Adaptive.Transact` method. ```C# using FSharp.Data.Adaptive; using CSharp.Data.Adaptive; // Create changeable values var width = new ChangeableValue(800); var height = new ChangeableValue(600); // Derive values using C# extension methods var area = width.Map(w => w).Map2(height, (w, h) => w * h); Console.WriteLine(area.GetValue()); // => 480000 // Batch changes Adaptive.Transact(() => { width.Value = 1920; height.Value = 1080; }); Console.WriteLine(area.GetValue()); // => 2073600 // Adaptive sets with LINQ-style operators var numbers = new ChangeableHashSet(new[] { 1, 2, 3, 4, 5 }); var evens = numbers.Filter(n => n % 2 == 0); var total = evens.Fold(0, (acc, n) => acc + n); Console.WriteLine(total.GetValue()); // => 6 // Subscribe to changes using var sub = total.AddMarkingCallback(() => Console.WriteLine($"total changed to {total.GetValue()}") ); Adaptive.Transact(() => numbers.Add(6)); // prints: total changed to 12 ``` -------------------------------- ### F# AdaptiveReduction for Efficient Incremental Aggregations Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt AdaptiveReduction enables efficient incremental aggregations for sets, lists, and maps. Built-in reductions like sum and average update in O(delta) time. Custom reductions can be defined using group, add, and subtract functions. Parallel reductions allow computing multiple aggregates simultaneously. ```fsharp open FSharp.Data.Adaptive let prices = cset [10.0; 20.0; 30.0] // Built-in group reductions: sum/average update in O(delta) not O(n) let total = prices |> ASet.sum let average = prices |> ASet.average AVal.force total // => 60.0 AVal.force average // => 20.0 transact (fun () -> prices.Add 40.0 |> ignore prices.Remove 10.0 |> ignore ) AVal.force total // => 90.0 (one add, one subtract — no full rescan) AVal.force average // => 30.0 ``` ```fsharp open FSharp.Data.Adaptive // Custom group reduction (count of even numbers) let evenCount = AdaptiveReduction.group 0 // seed (fun s x -> if x % 2 = 0 then s + 1 else s) // add (fun s x -> if x % 2 = 0 then s - 1 else s) // subtract let nums = cset [1; 2; 3; 4; 5; 6] let evens = nums |> ASet.reduce evenCount AVal.force evens // => 3 transact (fun () -> nums.Add 8 |> ignore) AVal.force evens // => 4 (only the new element processed) ``` ```fsharp open FSharp.Data.Adaptive // Parallel reductions: compute sum and count simultaneously let sumReduction = AdaptiveReduction.sum () let countReduction = AdaptiveReduction.count let sumAndCount = AdaptiveReduction.par sumReduction countReduction let floats = cset [1.0; 2.0; 3.0] let result = floats |> ASet.reduce sumAndCount AVal.force result // => (6.0, 3) ``` -------------------------------- ### AList Pairwise Operation Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt Illustrates the pairwise operation on AList, which creates a list of consecutive (previous, current) tuples. This list updates incrementally. ```FSharp // Pairwise let pairs = ranked |> AList.pairwise // => alist of consecutive (prev, curr) tuples, updated incrementally ``` -------------------------------- ### AMap Union with Resolve Function Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt Illustrates merging two maps using AMap.unionWith, providing a resolve function to handle duplicate keys. The resulting map updates incrementally. ```FSharp // Merge two maps with a resolve function let stock1 = cmap [("a", 1); ("b", 2)] let stock2 = cmap [("b", 10); ("c", 3)] let merged = AMap.unionWith (fun _key v1 v2 -> v1 + v2) stock1 stock2 AMap.force merged // => HashMap { "a"=1; "b"=12; "c"=3 } ``` -------------------------------- ### AMap Incremental Map Operation Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt Demonstrates an incremental map operation on AMap. When values are updated, only the changed entries are reprocessed by the mapping function. ```FSharp open FSharp.Data.Adaptive let inventory = cmap [("apples", 10); ("bananas", 5); ("cherries", 3)] // Derived map — only changed entries are reprocessed let doubled = inventory |> AMap.map' (fun qty -> qty * 2) AMap.force doubled // => HashMap { "apples"=20; "bananas"=10; "cherries"=6 } transact (fun () -> inventory["apples"] <- 15 // only "apples" entry is re-mapped inventory.Add("dates", 8) |> ignore ) AMap.force doubled // => HashMap { "apples"=30; "bananas"=10; "cherries"=6; "dates"=16 } ``` -------------------------------- ### Batching Changes with F# Transactions Source: https://context7.com/fsprojects/fsharp.data.adaptive/llms.txt Use `transact` to group multiple value updates into a single atomic operation. This ensures that dependent values are recomputed only once after all changes in the transaction are applied, unlike separate transactions which can lead to redundant recomputations. ```F# open FSharp.Data.Adaptive let x = cval 1 let y = cval 2 let sum = AVal.map2 (+) x y let product = AVal.map2 (*) x y let mutable recomputeCount = 0 let tracked = AVal.map2 (fun s p -> recomputeCount <- recomputeCount + 1; s, p) sum product AVal.force tracked |> ignore // initial evaluation recomputeCount <- 0 // Without batching — two separate transactions, tracked recomputed twice transact (fun () -> x.Value <- 10) transact (fun () -> y.Value <- 20) printfn "recomputes: %d" recomputeCount // => 2 recomputeCount <- 0 // With batching — one transaction, tracked recomputed once transact (fun () -> x.Value <- 100 y.Value <- 200 ) printfn "recomputes: %d" recomputeCount // => 1 // Transaction.using for explicit control let t = new Transaction() Transaction.using t (fun () -> x.Value <- 5 y.Value <- 5 ) t.Commit() // propagate all changes at once ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.