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

How to use / Proxy #68

Open
alt-romes opened this issue Mar 14, 2022 · 7 comments
Open

How to use / Proxy #68

alt-romes opened this issue Mar 14, 2022 · 7 comments

Comments

@alt-romes
Copy link

Hello,

I was trying to use but as someone unfamiliar with quick check it’s quite hard to understand how to use this library, so much that I’ve decided to open this issue.

I would love to see some examples of functor and monad

From the source I understand the first argument of those functions is just to correctly infer the type of monad to test m, but I don’t understand the triple (a, b, c) and their constraints (QuickCheck related). How am I supposed to call those functions?

A thought: if the argument is discarded and is only there for matters of inference, why not use Data.Proxy which is what I think to be the preferred way of passing an argument for its type?

@sjakobi
Copy link
Member

sjakobi commented Mar 14, 2022

I suggest you look at some code that uses checkers. You can find some examples here: https://packdeps.haskellers.com/reverse/checkers, e.g. https://github.com/twanvl/multiset/blob/3392f94ee25cac145c4a0270b470ca298e32943d/test/multiset-properties.hs.

From the source I understand the first argument of those functions is just to correctly infer the type of monad to test m, but I don’t understand the triple (a, b, c) and their constraints (QuickCheck related). How am I supposed to call those functions?

I think you can pick about any types for a, b and c as long as they satisfy the constraint. The tests will be more likely to catch a problem if you use types where the [Co]Arbitrary instances produce some reasonably good distribution. E.g. using () may cause some issues to go unnoticed.

A thought: if the argument is discarded and is only there for matters of inference, why not use Data.Proxy which is what I think to be the preferred way of passing an argument for its type?

Proxy would definitely be better. I suspect it's not being used here because much of the library was written before Proxy was well-known.

Note that there are similar packages with more "modern" APIs, e.g. https://hackage.haskell.org/package/quickcheck-classes-0.6.5.0/docs/Test-QuickCheck-Classes.html.

In case you're interested in improving the documentation or changing the API to use Proxy, you're welcome to send a PR BTW.

@alt-romes
Copy link
Author

alt-romes commented Mar 14, 2022

OK, thank you for the pointers, I'll get started.

I might send an example.

I have some new questions: Do you keep this API because of backwards compatibility? Don't you want to also provide a modern API? Is this package still valuable despite its less modern API because of featuring perhaps more laws?

But you say I could update the API to use Proxy?

I would have to know better about this library to do changes like that: for example how would monad look with Proxy?

Proxy m -> Proxy a -> Proxy b -> Proxy c? Proxy (m (a, b, c))?

@conal
Copy link
Collaborator

conal commented Mar 14, 2022

Hasn't Proxy been obsoleted by type application?

@alt-romes
Copy link
Author

alt-romes commented Mar 14, 2022

@conal Yes, mostly except for when using type families but needing the argument type still.

However, for a beginner, seeing monad :: forall m ........ => TestBatch it isn't clear at all how to say what kind of monad it is, while Proxy m -> TestBatch makes much more sense (and is better than making users call monad with an undefined :: Type...

I wouldn't pass a proxy to disambiguate a type, but when the library is about testing types it makes sense that the type is somehow "an argument" of the function

@conal
Copy link
Collaborator

conal commented Mar 14, 2022

when the library is about testing types it makes sense that the type is somehow "an argument" of the function

My 2¢: Type application is (GHC-)Haskell's modern, direct way of saying that the type (including higher-kinded) is an argument. The two older techniques you mention predated our ability to say so directly and so instead tried to fudge type applications with (ignored or vacuous) value applications.

@alt-romes
Copy link
Author

@conal You're right. I still think it would depend on who we would be showing the library to (forall m. TestBatch does not look like a function that takes arguments), but good documentation could make sure it would be understood

@sjakobi
Copy link
Member

sjakobi commented Mar 14, 2022

I have some new questions: Do you keep this API because of backwards compatibility? Don't you want to also provide a modern API? Is this package still valuable despite its less modern API because of featuring perhaps more laws?

You might be the first person to point out that the current API is bit weird with it's requirement for an arbitrary value to guide type inference. I'm not aware of any previous discussions about modernizing the API.

Backwards compatibility is a concern of course, but if we agree that a different API would be better, why stick with the old cruft?!

Regarding differences to other libraries: The main reason I went with checkers for the multiset-properties is andrewthad/quickcheck-classes#74.

I agree with @conal though, that it would be better to use TypeApplications than Proxy these days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants