-
Notifications
You must be signed in to change notification settings - Fork 30
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
Problem with using Zero as discard in computation expression #28
Comments
I think we shouldn't use |
What I really want is to be able to write I agree that it's a bad style to use multiple asserts interspersed with more actions and generators, but two in a row is no differently logically to one with a |
True. |
Allowing for custom operations can even end up to having some property-based testing DSL, so this looks appealing, although technically this might not be trivial, as it seems. |
Yeah! I think we could do some cool stuff with this, the classification functions you mentioned here #25 and the |
Indeed! |
It looks like multiple yields don't work anyway unless you implement |
Also I managed to get So these seem to work: Property.check <| forAll {
let! n = Gen.int
where (n <> 0)
return 1 / n = 2 / n
}
Property.check <| forAll {
let! x = Gen.int
let! y = Gen.int
where (x > 0 && y > 0)
return x * y > 0
} |
using
As opposed to using
This could be problematic with a large number of arguments, needs more investigation to see if we can un-tuple the counterexamples. It turned out I was wrong by the way:
^ this is not true, it works just fine. So maybe we should stick with what's in master given the tupling issue. Hmm.. |
Nice analysis! Since |
Ok I think I made some progress, I can avoid capturing the tuple by only storing the values when something is bound using I actually tried this approach initially as it makes the most sense, show counterexample for the visible binding, but not for the magic that happens under the hood. But unfortunately I got no output at all when I added the I discovered that this is because of the encoding of type Result<'a> =
| Failure of List<string>
| Discard
| Success of 'a
type Property<'a> =
| Property of Gen<Result<'a>> I guess at some point we were getting a type Report =
| Report of List<string>
type Result<'a> =
| Failure
| Discard
| Success of 'a
type Property<'a> =
| Property of Gen<Report * Result<'a>> And was sure to append reports together when binding a property, this seemed to fix the issue. I now get this output:
from this: Property.check <| forAll {
let! x = Gen.int
let! y = Gen.int
where (x > 0 && y > 0)
return x * y > 0
} and also from this: Property.check <| forAll {
let! x = Gen.int
let! y = Gen.int
if x > 0 && y > 0 then
return x * y > 0
} So I guess we can choose, or have both, the most important thing is that we can make the DSL stuff work 😄 |
This seems useful 👍 |
|
Resolved by #29 |
If we write something like this:
It will discard every expression, as the printfn line will turn in toZero
.edit: turns out this is not the case at all
It seems like the solution is to turn it in to the "other" type of computation expression which uses
for
instead oflet!
. I prefer the let one personally, but I don't think it matters too much. Thefor
style of computation expression is a lot more flexible, allowing for custom operations likewhere
which we can use instead of theZero
hack.I'm going to start work on this now and see how I go.
The plan (if I can make it work) is to allow something like this:
The text was updated successfully, but these errors were encountered: