Re: [Haskell-cafe] Contravariant applicatives, monads and arrows (was ANN: rematch, an library for composable assertions with human readable failure messages)
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 [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 : > > 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
Re: [Haskell-cafe] Contravariant applicatives, monads and arrows (was ANN: rematch, an library for composable assertions with human readable failure messages)
* Stephen Tetley [2013-04-16 19:48:47+0100] > On 16 April 2013 16:12, Alejandro Serrano Mena wrote: > > 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: > > > > > Have you seen Ralf Hinze, Johan Jeuring and Andreas Loeh's paper on > Contracts? > > The found their Contract datatype formed a comonad - at the time this > seemed to be one of the few (non-synthetic) uses of comonads. Their Contract datatype is contravariant, just like Tom's Matcher. So it cannot be a comonad. It's their "contracted function" type which is a (very simple) comonad — but I'm not sure how it can be useful here. (I only skipped very quickly through the paper, so I may be missing something.) Roman ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Contravariant applicatives, monads and arrows (was ANN: rematch, an library for composable assertions with human readable failure messages)
The type looks similar to the denotation for sets, but implementing a covariant interface for it would not be straightforward and may also be inefficient. On Apr 16, 2013 11:17 AM, "Alejandro Serrano Mena" wrote: > 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 : > > 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 > ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Contravariant applicatives, monads and arrows (was ANN: rematch, an library for composable assertions with human readable failure messages)
On 16 April 2013 16:12, Alejandro Serrano Mena wrote: > 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: > Have you seen Ralf Hinze, Johan Jeuring and Andreas Loeh's paper on Contracts? The found their Contract datatype formed a comonad - at the time this seemed to be one of the few (non-synthetic) uses of comonads. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Contravariant applicatives, monads and arrows (was ANN: rematch, an library for composable assertions with human readable failure messages)
My idea was to convert Matcher to be a covariant functor. It would be essentially a Matcher which has been applied to the tested value. And the type argument would denote the result of a computation. For example, consider hasRight :: (Show a, Show b) => Matcher b -> Matcher (Either a b) Instead it could have type hasRight :: F (Either a b) -> F b ... and you then could test 'b' further. F, of course, would handle errors. But also it could record the chain of functions, so that it could print it in case of failure, like it Tom's code. (I guess that means that F has to be a monad. Also it (intentionally) wouldn't satisfy any usual laws, because we need to record all the computational steps.) Or, indeed, you could both preserve the input and add an output, which would make it a profunctor (and probably a category/arrow). Roman * Alejandro Serrano Mena [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 : > > 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 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Contravariant applicatives, monads and arrows (was ANN: rematch, an library for composable assertions with human readable failure messages)
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 : > 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