[Haskell-cafe] Contravariant applicatives, monads and arrows (was ANN: rematch, an library for composable assertions with human readable failure messages)

Alejandro Serrano Mena trupill at gmail.com
Tue Apr 16 17:12:51 CEST 2013

First of all, let me say that this work on matchers is really useful :)

Following Roman advice, I'm trying to find a more principled approach
that could be useful for this library. It seems that "Match" could
easily be converted to Either and thus made into Functor, Applicative,
Alternative and Monad. That would allow to write things like:

User <$> runMatch (isNot isEmpty) name <*> runMatch (hasItem (is '@')) email

However, I'm also thinking about the correct way to "combine" matchers
to get bigger matchers. Basically, if I have matchers on every field
of a record, can I get a matcher for the entire one?

My first idea was to make Matcher a functor. However, what I come was
a contravariant functor: given (a -> b) and Matcher b, I can easily
construct a Matcher a by running the one in b over this function. So
we have:

contramap :: (a -> b) -> Matcher b -> Matcher a

My first question is: is there any structure similar to applicative
functors or monads which work on these kind of contravariant functors?
This also brought into my mind to see Matcher a just as functions a ->
Match and derive its properties from there. This may give better
results that the above mentioned idea of looking it as a -> Either
String a, because in this latter case we have a in covariant and
contravariant positions and it's difficult to get anything.

On the other hand, it seems very easy, from a Matcher a and a Matcher
b, to get a Matcher (a,b). This reminds me a bit about arrows, but
without output parameters. Does it make sense? I've always been
reluctant to arrows because I don't fully understand them, but maybe
this is a good moment to learn.

Do any of this make sense? I would really like to contribute to this
great library! :)

2013/4/16 Tom Crayford <tcrayford at gmail.com>:
> Roman,
> Thanks for the feedback! I'd originally left the QuickCheck and HUnit
> implementations in this library for convenience, thinking that there aren't
> going to be many people who care about the transitive dep. But you care, so
> I'm happy moving them out of core. I'll release a 0.2 with both the HUnit
> and the QuickCheck runners in separate libraries soonish.
> Thanks for the haddock tip and the implementation tips.
> Re the Control namespace, these matchers aren't exclusively a testing tool.
> I've been using the core api for other purposes as well (primarily for
> validating forms in user interfaces in conjunction with digestive-functors).
> I couldn't figure anything better to put it in apart from Control (I
> definitely don't want it in Test, even though that's going to be what most
> people use it for). I guess it could be in `Data`, but that doesn't sound
> much better to me.
> I'm not amazingly strong at building more principled interfaces right now,
> so I guess that's something I'll improve on. Are there any concrete
> suggestions you have there? I'd *like* these to have an `Alternative`
> instance, but making `Applicative`/`Functor` instances is beyond me right
> now (I guess I'd have to change the core API for that to work out).
> Tom
> ...

More information about the Haskell-Cafe mailing list