F# Immutable variable sized window data structure

2019-02-19 00:44发布

I have below a description of a data structure I need and I want to implement it using immutable data structures. I'm trying to determine... is there an existing data structure out there that will support what I'm trying to do here or do I need to create one--and if I need to create it, what would be a good place to start (building blocks)?


I have a steady stream of incoming values of a certain type. I want to add them to a persistent/immutable data structure to hold a history of them, and on each add, it will review the history and determine if one or more oldest items will be removed (for example, if the history is > a certain length or a value has a certain property).

2条回答
The star\"
2楼-- · 2019-02-19 00:51

Thanks to Juliet's kind information, I have implemented what I need and I put it here in case anyone else might find it useful.

let rec removeLast (s : Set<'a>, num : int) : Set<'a> = 
    match num with
    | 0 -> s
    | _ -> removeLast(s.Remove(s.MinimumElement), num-1)


type History<'a when 'a : comparison>(underlying : Set<'a>, removal : History<'a> -> int) =
    member this.Add(x) =
        History(removeLast(underlying, removal(this)).Add x, removal)

    member this.Count = underlying.Count
    member this.Min = underlying.MinimumElement
    member this.Max = underlying.MaximumElement
    member this.Under = underlying

let maxHist = 2
let maxCountRemover (h : History<int>) =
    if h.Count >= maxHist
    then h.Count - maxHist + 1
    else 0


let testHistory =
    let s = History(Set.empty, r)
    let s = s.Add(1);
    printfn "%i: %i - %i" s.Count s.Min s.Max
    let s = s.Add(2);
    printfn "%i: %i - %i" s.Count s.Min s.Max
    let s = s.Add(3);
    printfn "%i: %i - %i" s.Count s.Min s.Max
    let s = s.Add(4);
    printfn "%i: %i - %i" s.Count s.Min s.Max
    let s = s.Add(5);
    printfn "%i: %i - %i" s.Count s.Min s.Max
    printfn "%A" s.Under
查看更多
兄弟一词,经得起流年.
3楼-- · 2019-02-19 01:13

Without knowing more about your requirements, I'd just say a vanilla Set<'a> does a more than adequate job. I'd prefer a 'Set' over a 'List' so you always have O(lg n) access to the largest and smallest items, allowing you to ordered your set by insert date/time for efficient access to the newest and oldest items.

Seems very easy to wrap up a set so that its Add/Remove methods invoke your callbacks:

type AwesomeSet(internalSet : Set<'a>, insertCallback : 'a -> unit, removeCallback : 'a -> unit) =
    member this.Add(x) =
        insertCallback(x)
        AwesomeSet(internalSet.Add x, insertCallback, removeCallback)

    member this.Remove(x) =
        removeCallback(x)
        AwesomeSet(internalSet.Remove x, insertCallback, removeCallback)

    member this.Count = internalSet.Count
    member this.Min = internalSet.MinimumElement
    member this.Max = internalSet.MaximumElement
查看更多
登录 后发表回答