Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add built-in Map Keys to Seq function #424

Open
lavaleri opened this issue Nov 12, 2019 · 3 comments
Open

Add built-in Map Keys to Seq function #424

lavaleri opened this issue Nov 12, 2019 · 3 comments
Labels
kind: enhancement Enhancements, feature requests, etc. These are NOT bugs, but ways we can improve Dafny part: language definition Relating to the Dafny language definition itself priority: not yet Will reconsider working on this when we're looking for work

Comments

@lavaleri
Copy link
Contributor

Maps should have a built-in function that outputs its keys in a sequence, given a way to deterministically decide ordering on input.

@robin-aws
Copy link
Member

It would be much more natural to expose the keys as a set<T> though, and then convert to a list and sort if needed.

@robin-aws
Copy link
Member

Note this is possible within Dafny source, if you use a datatype for which Dafny understands that <= is a total ordering such as int (full credit to @RustanLeino for coming up with this version):

function method MapToSequence<B>(m: map<int,B>): seq<(int,B)>
  ensures var qq := MapToSequence(m);
    |m.Keys| == |qq| &&
    forall i :: 0 <= i < |qq| ==> qq[i].0 in m.Keys && m[qq[i].0] == qq[i].1
{
  var keys := SetToSequence(m.Keys);
  seq(|keys|, i requires 0 <= i < |keys| => (keys[i], m[keys[i]]))
}

function method SetToSequence(s: set<int>): seq<int>
  ensures var q := SetToSequence(s);
    |s| == |q| &&
    forall i :: 0 <= i < |q| ==> q[i] in s
{
  if s == {} then
    []
  else
    ThereIsAMinimum(s);
    var a :| a in s && forall z :: z in s ==> a <= z;
    [a] + SetToSequence(s - {a})
}

lemma ThereIsAMinimum(s: set<int>)
  requires s != {}
  ensures exists a :: a in s && forall z :: z in s ==> a <= z;
{
  var a := FindMinimum(s);
}
  
lemma FindMinimum(s: set<int>) returns (a: int)
  requires s != {}
  ensures a in s && forall z :: z in s ==> a <= z;
{
  a :| a in s;
  if s == {a} {
    // done
  } else {
    var s' := s - {a};
    assert forall x :: x in s <==> x == a || x in s';
    var a' := FindMinimum(s');
    a := if a' < a then a' else a;
  }
}

Although it may be useful to have a built-in function for performance reasons, I'd love it if this could be part of the standard library, assuming there was a way to generalize over a type T for which <= is total. It might make sense to support a (<) or (<=) type parameter suffix for this.

@robin-aws robin-aws added the kind: enhancement Enhancements, feature requests, etc. These are NOT bugs, but ways we can improve Dafny label Jun 23, 2020
@acioc
Copy link
Collaborator

acioc commented Aug 12, 2020

Note: If the syntax changes, we should also revisit the syntax for seq to multi-set.

@acioc acioc added this to the Dafny 3.0 milestone Aug 12, 2020
@davidcok davidcok modified the milestones: Dafny 3.0, Dafny 3.1 Dec 23, 2020
@robin-aws robin-aws added the part: language definition Relating to the Dafny language definition itself label Sep 22, 2021
@atomb atomb removed this from the Dafny 3.1 milestone Apr 21, 2022
@MikaelMayer MikaelMayer added the priority: not yet Will reconsider working on this when we're looking for work label Aug 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: enhancement Enhancements, feature requests, etc. These are NOT bugs, but ways we can improve Dafny part: language definition Relating to the Dafny language definition itself priority: not yet Will reconsider working on this when we're looking for work
Projects
None yet
Development

No branches or pull requests

6 participants