Skip to content

Support partial folds over Dict #1117

Open
@DavidDTA

Description

@DavidDTA

Currently, there is no performant way to query a subset (range) of keys in a dictionary. The best way currently involves converting the entire Dict to a list and then filtering, which runs in O(n). Theoretically, this should be able to be done in O(log(n) + size_of_results).

Concrete API proposal:

foldl : (k -> v -> b -> Maybe b) -> Maybe k -> b -> Dict k v -> b
foldl func startKeyInclusive initialAcc dict =
  -- func: If the returned value is `Nothing`, exclude this and all subsequent keys from the fold and return the passed in accumulation value.  Otherwise, pass the new accumulation value into func with the next key and value.
  -- startKeyInclusive: Skip all keys strictly less than this.  The first key passed into the func will be the first key greater than or equal to this.  `Nothing` is considered to be  less than all values.
  -- initialAcc: the initial accumulation value

foldr : (k -> v -> b -> Maybe b) -> Maybe k -> b -> Dict k v -> b
foldr func startKeyInclusive initialAcc dict =
  -- same as `foldl`, except that we fold from the right, we skip keys strictly greater than `startKeyInclusive`, and `Nothing` is considered greater than any value for `startKeyInclusive`.

The existing fold functions can be implemented using these new ones:

fold f initAcc dict = newFoldl (\k v acc -> Just (f k v acc)) Nothing initAcc dict

These functions also allow us to implement before and after as in IntDict, which is currently impossible with the existing API.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions