You are right Alejandro, arrows are a perfect fit here. (Most of it is possible with monads as well, but arrows are useful to maintain static names of the properties.)
Here's what I've come up with: https://gist.github.com/feuerbach/5409326 Now everyItem and hasJust have types everyItem :: Matcher [a] a hasJust :: Matcher (Maybe a) a (similarly for all other functions) This allows us to write myProp = everyItem >>> hasJust >>> is 3 or even myProp = proc list -> do mbItem <- everyItem -< list item <- hasJust -< mbItem is 3 -< item Roman * Alejandro Serrano Mena <trup...@gmail.com> [2013-04-16 17:12:51+0200] > Hi, > 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 <tcrayf...@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 _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe