-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
36b8092
commit 4adffd2
Showing
16 changed files
with
1,144 additions
and
339 deletions.
There are no files selected for viewing
634 changes: 317 additions & 317 deletions
634
src/FSharp.Data.Adaptive.Experimental/AdaptiveArray/Arr.fs
Large diffs are not rendered by default.
Oops, something went wrong.
133 changes: 133 additions & 0 deletions
133
src/FSharp.Data.Adaptive/AdaptiveArray/AdaptiveArray.fs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
namespace FSharp.Data.Adaptive | ||
|
||
open System | ||
open FSharp.Data.Traceable | ||
open FSharp.Data.Adaptive | ||
|
||
/// An adaptive reader for aarr that allows to pull operations and exposes its current state. | ||
type IArrayReader<'T> = | ||
IOpReader<arr<'T>, arrdelta<'T>> | ||
|
||
/// Adaptive array datastructure. | ||
[<Interface>] | ||
type IAdaptiveArray<'T> = | ||
/// Is the array constant? | ||
abstract member IsConstant : bool | ||
|
||
/// The current content of the array as aval. | ||
abstract member Content : aval<arr<'T>> | ||
|
||
/// Gets a new reader to the array. | ||
abstract member GetReader : unit -> IArrayReader<'T> | ||
|
||
/// Gets the underlying History instance for the alist (if any) | ||
abstract member History : option<History<arr<'T>, arrdelta<'T>>> | ||
|
||
/// Adaptive list datastructure. | ||
type aarr<'T> = IAdaptiveArray<'T> | ||
|
||
|
||
/// Functional operators for the alist<_> type. | ||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||
module AArr = | ||
/// Efficient implementation for a constant adaptive array. | ||
[<Sealed>] | ||
type ConstantArray<'T>(content : Lazy<arr<'T>>) = | ||
let value = AVal.delay (fun () -> content.Value) | ||
|
||
member x.Content = value | ||
|
||
member x.GetReader() = | ||
History.Readers.ConstantReader<_,_>( | ||
Arr.trace, | ||
lazy (Arr.computeDelta DefaultEqualityComparer.Instance Arr.empty content.Value), | ||
content | ||
) :> IArrayReader<_> | ||
|
||
interface IAdaptiveArray<'T> with | ||
member x.IsConstant = true | ||
member x.GetReader() = x.GetReader() | ||
member x.Content = x.Content | ||
member x.History = None | ||
|
||
/// Core implementation for a dependent array. | ||
[<Sealed>] | ||
type AdaptiveArray<'T>(createReader : unit -> IOpReader<arrdelta<'T>>) = | ||
let history = History(createReader, Arr.trace) | ||
|
||
/// Gets a new reader to the set. | ||
member x.GetReader() : IArrayReader<'T> = | ||
history.NewReader() | ||
|
||
/// Current content of the set as aval. | ||
member x.Content = | ||
history :> aval<_> | ||
|
||
interface IAdaptiveArray<'T> with | ||
member x.IsConstant = false | ||
member x.GetReader() = x.GetReader() | ||
member x.Content = x.Content | ||
member x.History = Some history | ||
|
||
/// Efficient implementation for an empty adaptive array. | ||
[<Sealed>] | ||
type EmptyArray<'T> private() = | ||
static let instance = EmptyArray<'T>() :> aarr<_> | ||
let content = AVal.constant Arr.empty | ||
let reader = History.Readers.EmptyReader<arr<'T>, arrdelta<'T>>(Arr.trace) :> IArrayReader<'T> | ||
static member Instance = instance | ||
|
||
member x.Content = content | ||
member x.GetReader() = reader | ||
|
||
interface IAdaptiveArray<'T> with | ||
member x.IsConstant = true | ||
member x.GetReader() = x.GetReader() | ||
member x.Content = x.Content | ||
member x.History = None | ||
|
||
module Readers = | ||
type MapReader<'T1, 'T2>(input : aarr<'T1>, mapping : 'T1 -> 'T2) = | ||
inherit AbstractReader<arrdelta<'T2>>(ArrDelta.empty) | ||
|
||
let reader = input.GetReader() | ||
|
||
override x.Compute(token : AdaptiveToken) = | ||
let delta = reader.GetChanges(token) | ||
ArrDelta.map mapping delta | ||
|
||
/// The empty aarr. | ||
[<GeneralizableValue>] | ||
let empty<'T> : aarr<'T> = | ||
EmptyArray<'T>.Instance | ||
|
||
/// A constant aarr holding a single value. | ||
let single (value : 'T) : aarr<'T> = | ||
ConstantArray(Lazy<_>.CreateFromValue(Arr.single value)) :> aarr<_> | ||
|
||
/// Creates an aarr holding the given values. | ||
let ofSeq (elements: seq<'T>) : aarr<'T> = | ||
ConstantArray(Lazy<_>.CreateFromValue(Arr.ofSeq elements)) :> aarr<_> | ||
|
||
|
||
/// Creates an aarr holding the given values. | ||
let ofList (elements: list<'T>) : aarr<'T> = | ||
ConstantArray(Lazy<_>.CreateFromValue(Arr.ofList elements)) :> aarr<_> | ||
|
||
/// Creates an aarr holding the given values. | ||
let ofArray (elements: 'T[]) : aarr<'T> = | ||
ConstantArray(Lazy<_>.CreateFromValue(Arr.ofArray elements)) :> aarr<_> | ||
|
||
/// Creates an aarr holding the given values. | ||
let ofArr (elements: arr<'T>) : aarr<'T> = | ||
ConstantArray(Lazy<_>.CreateFromValue(elements)) :> aarr<_> | ||
|
||
/// Creates an aarr using the given reader-creator. | ||
let ofReader (create : (unit -> #IOpReader<arrdelta<'T>>)) : aarr<'T> = | ||
AdaptiveArray<'T>(fun () -> create() :> IOpReader<arrdelta<'T>>) :> aarr<'T> | ||
|
||
/// Adaptively applies the given mapping function to all elements and returns a new aarr containing the results. | ||
let map (mapping : 'T1 -> 'T2) (input : aarr<'T1>) : aarr<'T2> = | ||
ofReader <| fun () -> | ||
Readers.MapReader(input, mapping) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
namespace FSharp.Data.Adaptive | ||
|
||
open System | ||
open FSharp.Data.Traceable | ||
open FSharp.Data.Adaptive | ||
|
||
/// An adaptive reader for aarr that allows to pull operations and exposes its current state. | ||
type IArrayReader<'T> = | ||
IOpReader<arr<'T>, arrdelta<'T>> | ||
|
||
/// Adaptive array datastructure. | ||
[<Interface>] | ||
type IAdaptiveArray<'T> = | ||
/// Is the array constant? | ||
abstract member IsConstant : bool | ||
|
||
/// The current content of the array as aval. | ||
abstract member Content : aval<arr<'T>> | ||
|
||
/// Gets a new reader to the array. | ||
abstract member GetReader : unit -> IArrayReader<'T> | ||
|
||
/// Gets the underlying History instance for the alist (if any) | ||
abstract member History : option<History<arr<'T>, arrdelta<'T>>> | ||
|
||
/// Adaptive list datastructure. | ||
type aarr<'T> = IAdaptiveArray<'T> | ||
|
||
|
||
/// Functional operators for the alist<_> type. | ||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||
module AArr = | ||
|
||
/// The empty aarr. | ||
[<GeneralizableValue>] | ||
val empty<'T> : aarr<'T> | ||
|
||
/// A constant aarr holding a single value. | ||
val single : value: 'T -> aarr<'T> | ||
|
||
/// Creates an aarr holding the given values. | ||
val ofSeq : elements: seq<'T> -> aarr<'T> | ||
|
||
/// Creates an aarr holding the given values. | ||
val ofList : elements: list<'T> -> aarr<'T> | ||
|
||
/// Creates an aarr holding the given values. | ||
val ofArray : elements: 'T[] -> aarr<'T> | ||
|
||
/// Creates an aarr holding the given values. | ||
val ofArr : elements: arr<'T> -> aarr<'T> | ||
|
||
/// Creates an aarr using the given reader-creator. | ||
val ofReader : create: (unit -> #IOpReader<arrdelta<'T>>) -> aarr<'T> | ||
|
||
/// Adaptively applies the given mapping function to all elements and returns a new aarr containing the results. | ||
val map : mapping: ('T1 -> 'T2) -> input: aarr<'T1> -> aarr<'T2> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
namespace FSharp.Data.Adaptive | ||
|
||
open System.Collections.Generic | ||
open FSharp.Data.Traceable | ||
|
||
/// Changeable adaptive array that allows mutation by user-code and implements aarr. | ||
[<Sealed>] | ||
type ChangeableArray<'T>(state : arr<'T>) = | ||
let history = History<arr<'T>, arrdelta<'T>>(Arr.trace) | ||
|
||
do history.Perform (ArrDelta.single { Index = 0; Count = 0; Elements = state }) |> ignore | ||
|
||
/// is the array currently empty? | ||
member x.IsEmpty = history.State.IsEmpty | ||
|
||
/// the number of elements currently in the array. | ||
member x.Length = history.State.Length | ||
|
||
/// Gets or sets the value for the array. | ||
member x.Value | ||
with get() = | ||
history.State | ||
and set (v : arr<'T>) = | ||
let delta = Arr.computeDelta DefaultEqualityComparer.Instance history.State v | ||
history.Perform delta |> ignore | ||
|
||
member x.Clear() = | ||
let delta = ArrDelta.single { Index = 0; Count = history.State.Length; Elements = Arr.empty } | ||
history.Perform delta |> ignore | ||
|
||
member x.Add (item : 'T) = | ||
let delta = ArrDelta.single { Index = history.State.Length; Count = 0; Elements = Arr.single item } | ||
history.Perform delta |> ignore | ||
|
||
member x.Insert (index : int, value : 'T) = | ||
if index < 0 || index > history.State.Length then raise <| System.IndexOutOfRangeException() | ||
let delta = ArrDelta.single { Index = index; Count = 0; Elements = Arr.single value } | ||
history.Perform delta |> ignore | ||
|
||
member x.RemoveAt(index : int) = | ||
if index < 0 || index >= history.State.Length then raise <| System.IndexOutOfRangeException() | ||
let delta = ArrDelta.single { Index = index; Count = 1; Elements = Arr.empty } | ||
history.Perform delta |> ignore | ||
|
||
member x.CopyTo(array, arrayIndex) = history.State.CopyTo(array, arrayIndex) | ||
|
||
member x.Item | ||
with get (index : int) = | ||
history.State.[index] | ||
and set (index : int) (value : 'T) = | ||
let delta = ArrDelta.single { Index = index; Count = 1; Elements = Arr.single value } | ||
history.Perform delta |> ignore | ||
|
||
new(elements : seq<'T>) = ChangeableArray<'T>(Arr.ofSeq elements) | ||
new() = ChangeableArray<'T>(Arr.empty) | ||
|
||
member x.GetEnumerator() = history.State.GetEnumerator() | ||
|
||
interface System.Collections.IEnumerable with | ||
member x.GetEnumerator() = history.State.GetEnumerator() | ||
|
||
interface System.Collections.Generic.IEnumerable<'T> with | ||
member x.GetEnumerator() = history.State.GetEnumerator() | ||
|
||
interface System.Collections.Generic.ICollection<'T> with | ||
member x.Add(item) = x.Add item | ||
member x.Clear() = x.Clear() | ||
member x.Contains(item) = history.State |> Arr.exists (fun v -> DefaultEquality.equals v item) | ||
member x.CopyTo(array, arrayIndex) = x.CopyTo(array, arrayIndex) | ||
member x.Remove(item) = | ||
match Arr.tryFindIndex (fun v -> DefaultEquality.equals v item) history.State with | ||
| Some index -> x.RemoveAt index; true | ||
| None -> false | ||
member x.Count = x.Length | ||
member x.IsReadOnly = false | ||
|
||
interface System.Collections.Generic.IList<'T> with | ||
member x.IndexOf(item) = | ||
match Arr.tryFindIndex (fun v -> DefaultEquality.equals v item) history.State with | ||
| Some index -> index | ||
| None -> -1 | ||
member x.Insert(index,item) = x.Insert(index, item) | ||
member x.RemoveAt(index) = x.RemoveAt(index) | ||
member x.Item | ||
with get(i : int) = x.[i] | ||
and set (i : int) (value : 'T) = x.[i] <- value | ||
|
||
interface IAdaptiveArray<'T> with | ||
member x.IsConstant = false | ||
member x.GetReader() = history.NewReader() | ||
member x.Content = history :> aval<_> | ||
member x.History = Some history | ||
|
||
|
||
/// Changeable adaptive array that allows mutation by user-code and implements aarr. | ||
type carr<'T> = ChangeableArray<'T> |
33 changes: 33 additions & 0 deletions
33
src/FSharp.Data.Adaptive/AdaptiveArray/ChangeableArray.fsi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
namespace FSharp.Data.Adaptive | ||
|
||
open System.Collections.Generic | ||
open FSharp.Data.Traceable | ||
|
||
/// Changeable adaptive array that allows mutation by user-code and implements aarr. | ||
[<Sealed>] | ||
type ChangeableArray<'T> = | ||
interface IAdaptiveArray<'T> | ||
interface System.Collections.Generic.IEnumerable<'T> | ||
interface System.Collections.Generic.ICollection<'T> | ||
interface System.Collections.Generic.IList<'T> | ||
|
||
/// is the array currently empty? | ||
member IsEmpty : bool | ||
|
||
/// the number of elements currently in the array. | ||
member Length : int | ||
|
||
/// Gets or sets the value for the array. | ||
member Value : arr<'T> with get, set | ||
|
||
member Clear : unit -> unit | ||
member Add : 'T -> unit | ||
member Insert : index: int * value: 'T -> unit | ||
member Item : int -> 'T with get, set | ||
new : unit -> ChangeableArray<'T> | ||
new : arr<'T> -> ChangeableArray<'T> | ||
new : seq<'T> -> ChangeableArray<'T> | ||
/// Changeable adaptive array that allows mutation by user-code and implements aarr. | ||
type carr<'T> = ChangeableArray<'T> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.