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

Use SubSet type as constructor #1577

Closed
seebees opened this issue Nov 9, 2021 · 5 comments
Closed

Use SubSet type as constructor #1577

seebees opened this issue Nov 9, 2021 · 5 comments
Labels
kind: enhancement Enhancements, feature requests, etc. These are NOT bugs, but ways we can improve Dafny part: resolver Resolution and typechecking

Comments

@seebees
Copy link

seebees commented Nov 9, 2021

It would be nice to be able to just use a SubSet type in the same way as the underlying datatype.

datatype Foo = Foo(bar: string)

type ShortFoo = f: Foo | |f.bar| < 20

// What I want
var good := ShortFoo("This is longer than 20 so just do it!");
var bad := ShortFoo("Too Short, error");
@MikaelMayer MikaelMayer added kind: enhancement Enhancements, feature requests, etc. These are NOT bugs, but ways we can improve Dafny part: resolver Resolution and typechecking labels Nov 9, 2021
@MikaelMayer
Copy link
Member

MikaelMayer commented Nov 9, 2021

Thanks for suggesting improvements. I see the value when the datatype has only one constructor and that constructor has the same name, but this is a narrow case.
This suggestions needs refinement. I will close it for now until there is a consensus.
For example, What if you have multiple constructors?

datatype Foo = Foo(bar: string) | Foo2(bar: string)

type ShortFoo = f: Foo | |f.bar| < 20 witness Foo("")

var good := ShortFoo("This is longer than 20 so error"); // What does it mean? Foo or Foo2?
var bad := ShortFoo("It's working");

@seebees
Copy link
Author

seebees commented Nov 9, 2021

Leaving this here: we can make the requirement regarding ShortFoo into a predicate. This makes it more portable, but there is still only an implicit binding between these two things.

Another way I might think about it would be to be able to extract the requirements about the SubSet type
directly from said SubSet type.

Perhaps we could use is? Like good is ShortFoo == true?

@MikaelMayer
Copy link
Member

To extract the requirements about the subset type, you can already do this:

var bad: ShortFoo := Foo("This is longer than 20 and will raise an error");

Were you thinking of something else?

@seebees
Copy link
Author

seebees commented Nov 9, 2021

Yes. The above is a static check. What if I am making (or given) a Foo from arbitrary data that I can not reason about statically?

var maybeBad: ShortFoo := Foo(myStringThatMayOrMayNotBeGood);

It is obviously possible to do because I can investigate what the condition is that makes something a ShortFoo,
but this... "brakes encapsulation".

@MikaelMayer
Copy link
Member

Oh, I see. Actually, it looks like you are defining a use case that would go along this PR:

#1522

In this PR, we explicitly allow the use of subset types in comprehensions, and we compile the condition in the loop. We can do this because if the subset constraint is not satisfied, we can just skip the element.

The problem of doing it on one single element is the failure handling. If you say it cannot be checked statically and you want a dynamic check, since Dafny is meant to be sound, it has to handle failure gracefully.

In this case, you would use the elephant operator :- and the following code:

function method CreateShortFoo(x: string): Outcome<ShortFoo> { if |x| < 20 then Success(ShortFoo(x)) else Failure("Length exceeded 20"); }

method f() returns (r: Outcome<....>) {
  var maybeBad: ShortFoo :- CreateshortFoo("My long string that will generate an error");
}

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: resolver Resolution and typechecking
Projects
None yet
Development

No branches or pull requests

2 participants