Law testing + Traits update + RWST #1379
louthy
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Laws testing
Functors, applicatives, and monads all have laws that make them what they are. Some think that
Mapjust means the same asMapin mathematics, when in fact functors are more constrained and are structure-preserving.The full set of laws are:
Functors
Applicatives
Monads
When you write your own functors/applicatives/monads you are expected to honour these laws. In reality it's pretty hard to go wrong if you just follow the type-signatures and implement the traits in the most obvious way, but still, it is possible to make a mistake and some of the guarantees of the traits start to fail.
assertThe type-system isn't able to enforce many of the laws above, so we need to do it ourselves. I have now made that process much easier. If you implement a monadic type (using the new traits system) then can simply call:
Where
Mis your monad trait implementation type.For example, this tests that
Optioncomplies with all of the laws listed above.If your type isn't a monad, but is an applicative, then you can call:
And if your type isn't an applicative, but is a functor, then you can call:
Note that, if your type is a monad and you call
MonadLaw<M>.assert, you do not need to callApplicativeLaw<M>.assertorFunctorLaw<M>.assert. Those will be tested automatically.validateThe
assertfunctions listed above are perfect for unit-tests, but you can callvalidateinstead. It will return aValidation<Error, Unit>which will collect a set of failures for any failing laws.Equality
The functions that test that the laws hold need to be able to test equality of functor/monad/applicative values. Unfortunately, not all functors/applicatives/monads support equality. Types like
Reader, for example, are computations (not values), and so must be evaluated to extract a concrete value. The generic traits don't know how to evaluate them to extract the values.And so, for types that have no valid
Equalsimplementation, you must provide an equality function toassertandvalidate.Here's an example for
Eff<int>:It's pretty simple, it just runs the effect and compares the result.
Examples
You can look at the unit-tests for all of the functor/applicative/monad types in language-ext:
Future
Removal of
AlternativeandSemiAlternativeI have removed
AlternativeandSemiAlternativetraits. I really disliked the nameSemiAlternative(which was a combination ofSemigroupKandApplicative. I was OK withAlternative(MonoidKandApplicative) but it doesn't make sense without its semigroup partner. So, for now, we will only haveSemigroupKandMonoidK(semigroup and monoid that work forK<F, A>rather thanA).I'm still refining the types and am not 100% happy with this, but am short of ideas for better names or approaches. Feel free to let me know what you think.
PuretopureThe computation types:
Reader,ReaderT,State,StateT,Writer, andWriterThave all had their modulePurefunction renamed topure-- as it's not strictly a constructor, it simply lifts a pure value into those computations.RWST
Reader/Write/State monad-transformer. This is still WIP but it should be usable. It just doesn't have all the bells and whistles yet.
This discussion was created from the release Law testing + Traits update + RWST.
Beta Was this translation helpful? Give feedback.
All reactions