
How about popping these in Data.Either? -- | Maybe get the left side of an Either. leftToMaybe :: Either a b -> Maybe a leftToMaybe = either Just (const Nothing) -- | Maybe get the right side of an Either. rightToMaybe :: Either a b -> Maybe b rightToMaybe = either (const Nothing) Just

Christopher Done wrote:
How about popping these in Data.Either?
-- | Maybe get the left side of an Either. leftToMaybe :: Either a b -> Maybe a leftToMaybe = either Just (const Nothing)
-- | Maybe get the right side of an Either. rightToMaybe :: Either a b -> Maybe b rightToMaybe = either (const Nothing) Just
+1 And while we're at it: isLeft :: Either a b -> Bool isLeft (Left _) = True isLeft (Right _) = False isRight :: Either a b -> Bool isRight (Left _) = False isRight (Right _) = True Erik -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/

On 7 August 2013 14:06, Erik de Castro Lopo
Christopher Done wrote:
How about popping these in Data.Either?
-- | Maybe get the left side of an Either. leftToMaybe :: Either a b -> Maybe a leftToMaybe = either Just (const Nothing)
-- | Maybe get the right side of an Either. rightToMaybe :: Either a b -> Maybe b rightToMaybe = either (const Nothing) Just
+1
And while we're at it:
isLeft :: Either a b -> Bool isLeft (Left _) = True isLeft (Right _) = False
isRight :: Either a b -> Bool isRight (Left _) = False isRight (Right _) = True
If we're starting to add functions to Data.Either, I've often used something like this: mapEither :: (l -> l') -> (r -> r') -> Either l r -> Either l' r' mapEither fl fr = either (Left . fl) (Right . fr)
Erik -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
-- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com http://IvanMiljenovic.wordpress.com

Ivan Lazar Miljenovic wrote:
On 7 August 2013 14:06, Erik de Castro Lopo
wrote: Christopher Done wrote:
How about popping these in Data.Either?
-- | Maybe get the left side of an Either. leftToMaybe :: Either a b -> Maybe a leftToMaybe = either Just (const Nothing)
-- | Maybe get the right side of an Either. rightToMaybe :: Either a b -> Maybe b rightToMaybe = either (const Nothing) Just
+1
And while we're at it:
isLeft :: Either a b -> Bool isLeft (Left _) = True isLeft (Right _) = False
isRight :: Either a b -> Bool isRight (Left _) = False isRight (Right _) = True
If we're starting to add functions to Data.Either, I've often used something like this:
mapEither :: (l -> l') -> (r -> r') -> Either l r -> Either l' r' mapEither fl fr = either (Left . fl) (Right . fr)
+1 Erik -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/

Yep, I also use isLeft/isRight often and actually defined mapEither a couple times in the past, too. =)

Ivan Lazar Miljenovic wrote:
If we're starting to add functions to Data.Either, I've often used something like this:
mapEither :: (l -> l') -> (r -> r') -> Either l r -> Either l' r' mapEither fl fr = either (Left . fl) (Right . fr)
This function is hidden in Control.Arrow as (+++). There are more useful functions in there, but it's sometimes hard to find them, especially now that we can no longer use type operators for type variables. Erik

On 2013-08-07 19:13, Erik Hesselink wrote:
mapEither :: (l -> l') -> (r -> r') -> Either l r -> Either l' r' mapEither fl fr = either (Left . fl) (Right . fr)
This function is hidden in Control.Arrow as (+++).
I didn't know about those functions, and it seems everything I wanted is in there somewhere. However, I'm not sure what to think of Control.Arrow, I've always (ab)used it as an extended Data.Tuple, and as of today probably for its Either API functions. The thing is of course that Arrows aren't meant to be *just* that. Maybe there should at least be a highlighted section in Data.Either/Data.Tuple telling the user about the functionality provided in Control.Arrow? Most of the functions proposed here seem redundant, apart from the fact that they're arguably not in the right place. (A specialized re-export might be worth considering too, although I'm not sure whether I'd personally want that.) David

On Thu, 8 Aug 2013, David Luposchainsky wrote:
On 2013-08-07 19:13, Erik Hesselink wrote:
mapEither :: (l -> l') -> (r -> r') -> Either l r -> Either l' r' mapEither fl fr = either (Left . fl) (Right . fr)
This function is hidden in Control.Arrow as (+++).
I didn't know about those functions, and it seems everything I wanted is in there somewhere. However, I'm not sure what to think of Control.Arrow, I've always (ab)used it as an extended Data.Tuple, and as of today probably for its Either API functions.
For me using the arrow functions as Data.Tuple and Data.Either utility functions is abuse. Control.Arrow is meant to generalize (->). If you call maybeLeft and MaybeRight this is certainly not your intention.

On 2013-08-08 13:09, Henning Thielemann wrote:
For me using the arrow functions as Data.Tuple and Data.Either utility functions is abuse. Control.Arrow is meant to generalize (->). If you call maybeLeft and MaybeRight this is certainly not your intention.
That is precisely my point. The functionality is there, it's accessible, but due to meta-concerns (i.e. the "meaning of using these functions") they should not be used in a certain context. The syntax is sort of nice though, so maybe we should adopt that for Either/Tuple where applicable. David

On 2013-08-08 at 13:22:41 +0200, David Luposchainsky wrote:
On 2013-08-08 13:09, Henning Thielemann wrote:
For me using the arrow functions as Data.Tuple and Data.Either utility functions is abuse. Control.Arrow is meant to generalize (->). If you call maybeLeft and MaybeRight this is certainly not your intention.
That is precisely my point. The functionality is there, it's accessible, but due to meta-concerns (i.e. the "meaning of using these functions") they should not be used in a certain context. The syntax is sort of nice though, so maybe we should adopt that for Either/Tuple where applicable.
Btw, I have been wondering ever since I read[1] why Data.Tuple and Data.Either doesn't provide all those useful combinators mentioned in that paper for product and sum types. [1] "Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire" http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125

On Thu, Aug 8, 2013 at 1:09 PM, Henning Thielemann
On Thu, 8 Aug 2013, David Luposchainsky wrote:
On 2013-08-07 19:13, Erik Hesselink wrote:
mapEither :: (l -> l') -> (r -> r') -> Either l r -> Either l' r' mapEither fl fr = either (Left . fl) (Right . fr)
This function is hidden in Control.Arrow as (+++).
I didn't know about those functions, and it seems everything I wanted is in there somewhere. However, I'm not sure what to think of Control.Arrow, I've always (ab)used it as an extended Data.Tuple, and as of today probably for its Either API functions.
For me using the arrow functions as Data.Tuple and Data.Either utility functions is abuse. Control.Arrow is meant to generalize (->). If you call maybeLeft and MaybeRight this is certainly not your intention.
But the point of generalized functions is to use them in a specialized context, right? You can generalize mapEither in multiple ways: you can generalize (->), or you can generalize Either (getting bimap from the bifunctors package). I don't get why it's wrong to specialize the Arrow to (->) and use the functions on Eithers or tuples. I do agree that they're hard to find. The same goes for the functions from Foldable and Traversable (forM_ is often asked for as fromJust). Perhaps adding a comment to the appropriate modules (Data.Tuple, Data.Either, Data.Maybe) pointing in the right direction is a good low-tech solution here. Erik

On Thu, 8 Aug 2013, Erik Hesselink wrote:
On Thu, Aug 8, 2013 at 1:09 PM, Henning Thielemann
wrote: On Thu, 8 Aug 2013, David Luposchainsky wrote:
On 2013-08-07 19:13, Erik Hesselink wrote:
mapEither :: (l -> l') -> (r -> r') -> Either l r -> Either l' r' mapEither fl fr = either (Left . fl) (Right . fr)
This function is hidden in Control.Arrow as (+++).
I didn't know about those functions, and it seems everything I wanted is in there somewhere. However, I'm not sure what to think of Control.Arrow, I've always (ab)used it as an extended Data.Tuple, and as of today probably for its Either API functions.
For me using the arrow functions as Data.Tuple and Data.Either utility functions is abuse. Control.Arrow is meant to generalize (->). If you call maybeLeft and MaybeRight this is certainly not your intention.
But the point of generalized functions is to use them in a specialized context, right?
I think the primary goal is to use them to write generic functions.
You can generalize mapEither in multiple ways: you can generalize (->), or you can generalize Either (getting bimap from the bifunctors package). I don't get why it's wrong to specialize the Arrow to (->) and use the functions on Eithers or tuples.
Why should someone care about Arrows if he only wants to process Either?
I do agree that they're hard to find.
For me this is a hint that there is something wrong. If I want to have a function mapEither and do not find it in Data.Either, I might have the idea that it is subsumed by a more general function somewhere else. In this case I would certainly think about a generalization of Either, but not of (->).

I think the primary goal is to use them to write generic functions.
Would you avoid using mapM_ to sequence a list of IO operations, since it is using a generalized function in a specialized context? I take the idea of the generalized functions as being abstraction, allowing use of a common nomenclature across applications., as having context-specific names for specializations adds to what the programmer must remember to very little end. Where a specific type is needed for clarity or performance, I would prefer a general function and a local type signature rather than forcing a reader to remember yet another function.
I might have the idea that it is subsumed by a more general function somewhere else. In this case I would certainly think about a generalization of Either, but not of (->).
A fair point, I think; when I first started in Haskell I spent a while rewriting utilities from Control.Arrow because I never thought to look there. But the problem, as I see it, is of documentation, not of use; these are perfectly valid functions for the purpose, just hard to find if you do not already know to look there. (Although that said, Bifunctor does seem the more intuitive generalization here, and the more likely to survive a type change.) ________________________________________ From: Libraries [libraries-bounces@haskell.org] on behalf of Henning Thielemann [lemming@henning-thielemann.de] Sent: Thursday, August 08, 2013 10:26 AM To: Erik Hesselink Cc: libraries Subject: Re: leftToMaybe/rightToMaybe On Thu, 8 Aug 2013, Erik Hesselink wrote:
On Thu, Aug 8, 2013 at 1:09 PM, Henning Thielemann
wrote: On Thu, 8 Aug 2013, David Luposchainsky wrote:
On 2013-08-07 19:13, Erik Hesselink wrote:
mapEither :: (l -> l') -> (r -> r') -> Either l r -> Either l' r' mapEither fl fr = either (Left . fl) (Right . fr)
This function is hidden in Control.Arrow as (+++).
I didn't know about those functions, and it seems everything I wanted is in there somewhere. However, I'm not sure what to think of Control.Arrow, I've always (ab)used it as an extended Data.Tuple, and as of today probably for its Either API functions.
For me using the arrow functions as Data.Tuple and Data.Either utility functions is abuse. Control.Arrow is meant to generalize (->). If you call maybeLeft and MaybeRight this is certainly not your intention.
But the point of generalized functions is to use them in a specialized context, right?
I think the primary goal is to use them to write generic functions.
You can generalize mapEither in multiple ways: you can generalize (->), or you can generalize Either (getting bimap from the bifunctors package). I don't get why it's wrong to specialize the Arrow to (->) and use the functions on Eithers or tuples.
Why should someone care about Arrows if he only wants to process Either?
I do agree that they're hard to find.
For me this is a hint that there is something wrong. If I want to have a function mapEither and do not find it in Data.Either, I might have the idea that it is subsumed by a more general function somewhere else. In this case I would certainly think about a generalization of Either, but not of (->). _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

It happens again and again on this list: Someone request an innocent function on tuples or Either and after some initial discussion someone else writes "it is in Control.Arrow". No offense intended, but to me "just use Control.Arrow.xxx" is a smart-ass comment in the line of "this is just a lax monoidal functor" I hear from category-theorists all the time. Arrows are on a level of abstraction that many Haskell programmers (including me) do not make use of and should *not* be forced to study just because they need an innocent function about tuples (or Either). I bet that most imports of Control.Arrow are to make up for an impoverished Data.Tuple, and proper arrow programming is the exception. Thus, I agree with Henning and David and many more that there is something wrong here. mapEither, mapPair, mapFst, mapSnd and the like should be added to Data.Tuple and Data.Either, at the risk of duplicating stuff from Control.Arrow. Otherwise, programmers will just roll their own version of these function again (which is duplication that comes at a cost) and additionally be alienated at the design of the Haskell libraries. On 08.08.13 4:26 PM, Henning Thielemann wrote:
On Thu, 8 Aug 2013, Erik Hesselink wrote:
On Thu, Aug 8, 2013 at 1:09 PM, Henning Thielemann
wrote: On Thu, 8 Aug 2013, David Luposchainsky wrote:
On 2013-08-07 19:13, Erik Hesselink wrote:
mapEither :: (l -> l') -> (r -> r') -> Either l r -> Either l' r' mapEither fl fr = either (Left . fl) (Right . fr)
This function is hidden in Control.Arrow as (+++).
I didn't know about those functions, and it seems everything I wanted is in there somewhere. However, I'm not sure what to think of Control.Arrow, I've always (ab)used it as an extended Data.Tuple, and as of today probably for its Either API functions.
For me using the arrow functions as Data.Tuple and Data.Either utility functions is abuse. Control.Arrow is meant to generalize (->). If you call maybeLeft and MaybeRight this is certainly not your intention.
But the point of generalized functions is to use them in a specialized context, right?
I think the primary goal is to use them to write generic functions.
You can generalize mapEither in multiple ways: you can generalize (->), or you can generalize Either (getting bimap from the bifunctors package). I don't get why it's wrong to specialize the Arrow to (->) and use the functions on Eithers or tuples.
Why should someone care about Arrows if he only wants to process Either?
I do agree that they're hard to find.
For me this is a hint that there is something wrong.
If I want to have a function mapEither and do not find it in Data.Either, I might have the idea that it is subsumed by a more general function somewhere else. In this case I would certainly think about a generalization of Either, but not of (->).
-- Andreas Abel <>< Du bist der geliebte Mensch. Theoretical Computer Science, University of Munich Oettingenstr. 67, D-80538 Munich, GERMANY andreas.abel@ifi.lmu.de http://www2.tcs.ifi.lmu.de/~abel/

On 2013-08-09 08:52, Andreas Abel wrote:
It happens again and again on this list: Someone request an innocent function on tuples or Either and after some initial discussion someone else writes "it is in Control.Arrow". No offense intended, but to me "just use Control.Arrow.xxx" is a smart-ass comment in the line of "this is just a lax monoidal functor" I hear from category-theorists all the time.
I wouldn't go so far as to calling it a "smart-ass" suggestion. I think using Arrow is fine for this purpose, the thing is just that Control.Arrow is not where you might be looking for such a function. In that sense, the comparison to a "just lax monoidal functor" is not very good - the suggestion is not "view X as an Y and you'll see how Z is just function F", it is "that very function is almost directly in there".
Arrows are on a level of abstraction that many Haskell programmers (including me) do not make use of and should *not* be forced to study just because they need an innocent function about tuples (or Either).
Again, the "Arrows" we're talking here is just the (->) instance, which is like not knowing Monads but using >>= on Maybe anyway. In other words, you don't need to know Arrow to use (+++) as soon as you know it's mapEither, similarly to how you only need to know that >>= pipes on Just values until it hits a Nothing.
Thus, I agree with Henning and David and many more that there is something wrong here. mapEither, mapPair, mapFst, mapSnd and the like should be added to Data.Tuple and Data.Either, at the risk of duplicating stuff from Control.Arrow.
In the light of the recent Foldable/Traversable discussion, we'd be doing a similar thing again: have monomorphic versions of more general (standard) functions in different libraries. If we add the monomorphic functions, we should at least define them in terms of the Arrow functions, i.e. `mapEither :: (monomorphic); mapEither = Arrow.(+++)` so that we minimize code duplication. David

Here's another smart-ass remark, then: use lens and bifunctors. They
have great abstractions for these.
mapEither and mapPair are just two specializations of bimap. It also
has first and second which generalize mapFst, etc. And by the way,
everyone here (I think) has missed that you can also traverse these
things, but bifunctors also has that covered, with bitraverse.
The individual parts are applications of lenses, too. over _1 and over
_2 are mapFst and mapSnd. _1 and _2 function as traverseFst and
traverseSnd. For Either, there are prisms, _Left and _Right. over
_Left is mapLeft, over _Right is mapRight. has _Left is isLeft, has
_Right is isRight (apparently `is` was deemed too good to take; but
there's also isn't _Left). leftToMaybe is preview _Left. rightToMaybe
is preview _Right. _Left is traverseLeft. Etc. (fromLeft/Right is the
only one I can't cover well, but my knowledge of lens isn't
encyclopedic; the best I can come up with off the top of my head is
foldrOf _Left const).
I'm not really opposed to adding all these specialized functions to
data type modules. But you have to add a lot (far more than is even
called for here) to get all the functionality that you _already_ have
from a few general abstractions. And the latter translates to many
other types.
On Fri, Aug 9, 2013 at 2:52 AM, Andreas Abel
It happens again and again on this list: Someone request an innocent function on tuples or Either and after some initial discussion someone else writes "it is in Control.Arrow". No offense intended, but to me "just use Control.Arrow.xxx" is a smart-ass comment in the line of "this is just a lax monoidal functor" I hear from category-theorists all the time.
Arrows are on a level of abstraction that many Haskell programmers (including me) do not make use of and should *not* be forced to study just because they need an innocent function about tuples (or Either).
I bet that most imports of Control.Arrow are to make up for an impoverished Data.Tuple, and proper arrow programming is the exception.
Thus, I agree with Henning and David and many more that there is something wrong here. mapEither, mapPair, mapFst, mapSnd and the like should be added to Data.Tuple and Data.Either, at the risk of duplicating stuff from Control.Arrow. Otherwise, programmers will just roll their own version of these function again (which is duplication that comes at a cost) and additionally be alienated at the design of the Haskell libraries.
On 08.08.13 4:26 PM, Henning Thielemann wrote:
On Thu, 8 Aug 2013, Erik Hesselink wrote:
On Thu, Aug 8, 2013 at 1:09 PM, Henning Thielemann
wrote: On Thu, 8 Aug 2013, David Luposchainsky wrote:
On 2013-08-07 19:13, Erik Hesselink wrote:
> > > mapEither :: (l -> l') -> (r -> r') -> Either l r -> Either l' r' > mapEither fl fr = either (Left . fl) (Right . fr)
This function is hidden in Control.Arrow as (+++).
I didn't know about those functions, and it seems everything I wanted is in there somewhere. However, I'm not sure what to think of Control.Arrow, I've always (ab)used it as an extended Data.Tuple, and as of today probably for its Either API functions.
For me using the arrow functions as Data.Tuple and Data.Either utility functions is abuse. Control.Arrow is meant to generalize (->). If you call maybeLeft and MaybeRight this is certainly not your intention.
But the point of generalized functions is to use them in a specialized context, right?
I think the primary goal is to use them to write generic functions.
You can generalize mapEither in multiple ways: you can generalize (->), or you can generalize Either (getting bimap from the bifunctors package). I don't get why it's wrong to specialize the Arrow to (->) and use the functions on Eithers or tuples.
Why should someone care about Arrows if he only wants to process Either?
I do agree that they're hard to find.
For me this is a hint that there is something wrong.
If I want to have a function mapEither and do not find it in Data.Either, I might have the idea that it is subsumed by a more general function somewhere else. In this case I would certainly think about a generalization of Either, but not of (->).
-- Andreas Abel <>< Du bist der geliebte Mensch.
Theoretical Computer Science, University of Munich Oettingenstr. 67, D-80538 Munich, GERMANY
andreas.abel@ifi.lmu.de http://www2.tcs.ifi.lmu.de/~abel/
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Am 09.08.2013 17:31, schrieb Dan Doel:
Here's another smart-ass remark, then: use lens and bifunctors. They have great abstractions for these.
mapEither and mapPair are just two specializations of bimap. It also has first and second which generalize mapFst, etc. And by the way, everyone here (I think) has missed that you can also traverse these things, but bifunctors also has that covered, with bitraverse.
The individual parts are applications of lenses, too. over _1 and over _2 are mapFst and mapSnd. _1 and _2 function as traverseFst and traverseSnd.
These generalizations seem to be more natural to me than Control.Arrow. (However, identifiers with leading underscore are a bad idea, since they suppress "unused identifier" warnings in GHC. But I think I complained about that before.)

The fact that they suppress unused identifier warnings is a more of burden on me the implementor of lens more than on users of lens as the only names we generate with _'s in them are for prisms. And we exploit the fact that unused names that start with _'s don't give warnings, so that users who don't export the non-lens-based field accessors from their functions don't get complained at by the compiler. The adoption of _Constructor for prisms though it can lead to unexported prisms has the benefit of being unobtrusive and taking up namespace that literally nobody was using in the entire ecosystem, letting us avoid qualified import hell. Not everyone is so sanguine about qualifying every import in their program. ;) The convention was very uncomfortable for me at first, too, for the same reason it makes you unhappy, but all of alternatives take up names other people are using, collide between lenses and prisms, and are more verbose. -Edward On Fri, Aug 9, 2013 at 12:00 PM, Henning Thielemann < schlepptop@henning-thielemann.de> wrote:
Am 09.08.2013 17:31, schrieb Dan Doel:
Here's another smart-ass remark, then: use lens and bifunctors. They
have great abstractions for these.
mapEither and mapPair are just two specializations of bimap. It also has first and second which generalize mapFst, etc. And by the way, everyone here (I think) has missed that you can also traverse these things, but bifunctors also has that covered, with bitraverse.
The individual parts are applications of lenses, too. over _1 and over _2 are mapFst and mapSnd. _1 and _2 function as traverseFst and traverseSnd.
These generalizations seem to be more natural to me than Control.Arrow.
(However, identifiers with leading underscore are a bad idea, since they suppress "unused identifier" warnings in GHC. But I think I complained about that before.)
______________________________**_________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/**mailman/listinfo/librarieshttp://www.haskell.org/mailman/listinfo/libraries

Erik de Castro Lopo
writes:
And while we're at it:
isLeft :: Either a b -> Bool isLeft (Left _) = True isLeft (Right _) = False
isRight :: Either a b -> Bool isRight (Left _) = False isRight (Right _) = True
And what about: fromLeft :: a -> Either a b -> a fromLeft _ (Left x) = x fromLeft x _ = x fromRight :: b -> Either a b -> b fromRight _ (Right x) = x fromRight x _ = x -- John Wiegley FP Complete Haskell tools, training and consulting http://fpcomplete.com johnw on #haskell/irc.freenode.net

On Wed, 7 Aug 2013, Erik de Castro Lopo wrote:
And while we're at it:
isLeft :: Either a b -> Bool isLeft (Left _) = True isLeft (Right _) = False
isRight :: Either a b -> Bool isRight (Left _) = False isRight (Right _) = True
http://www.haskell.org/pipermail/libraries/2012-November/018709.html http://www.haskell.org/pipermail/libraries/2012-December/018716.html

Henning Thielemann wrote:
http://www.haskell.org/pipermail/libraries/2012-November/018709.html http://www.haskell.org/pipermail/libraries/2012-December/018716.html
Henning, In the second link above you wrote:
It would be a good opportunity to check how these packages use isLeft and isRight. E.g. if they use them in connection with fromLeft and fromRight then this would be an argument for me to exclude isLeft and isRight as well.
My main usage of isLeft/isRight is in HSpec tests where I write: value1 `shouldSatisfy' isLeft value2 `shouldSatisfy' isRight I would also be opposed to a fromLeft defined anything like fromJust: Data.Maybe.fromJust :: Maybe a -> a but would not be opposed to a fromLeft defined as John Wiegley suggested: fromLeft :: a -> Either a b -> a fromLeft _ (Left x) = x fromLeft x _ = x Erik -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/

On Wednesday, August 7, 2013, Erik de Castro Lopo wrote:
Henning Thielemann wrote:
http://www.haskell.org/pipermail/libraries/2012-November/018709.html http://www.haskell.org/pipermail/libraries/2012-December/018716.html
Henning,
In the second link above you wrote:
It would be a good opportunity to check how these packages use isLeft and isRight. E.g. if they use them in connection with fromLeft and fromRight then this would be an argument for me to exclude isLeft and isRight as well.
My main usage of isLeft/isRight is in HSpec tests where I write:
value1 `shouldSatisfy' isLeft value2 `shouldSatisfy' isRight
I would also be opposed to a fromLeft defined anything like fromJust:
Data.Maybe.fromJust :: Maybe a -> a
but would not be opposed to a fromLeft defined as John Wiegley suggested:
fromLeft :: a -> Either a b -> a fromLeft _ (Left x) = x fromLeft x _ = x
+1. Let's avoid adding any new partial functions.
Erik -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/
_______________________________________________ Libraries mailing list Libraries@haskell.org javascript:; http://www.haskell.org/mailman/listinfo/libraries

On Wed, 7 Aug 2013, Erik de Castro Lopo wrote:
In the second link above you wrote:
I have included both links since the discussion in November continued in December.
It would be a good opportunity to check how these packages use isLeft and isRight. E.g. if they use them in connection with fromLeft and fromRight then this would be an argument for me to exclude isLeft and isRight as well.
My main usage of isLeft/isRight is in HSpec tests where I write:
value1 `shouldSatisfy' isLeft value2 `shouldSatisfy' isRight
Yes, from what I have seen in some packages, testing seems to be the most sensible usage of 'isLeft' and 'isRight'. In other contexts 'isLeft' is usually combined with a non-total 'fromLeft', which is certainly a bad idea.
I would also be opposed to a fromLeft defined anything like fromJust:
Data.Maybe.fromJust :: Maybe a -> a
but would not be opposed to a fromLeft defined as John Wiegley suggested:
fromLeft :: a -> Either a b -> a fromLeft _ (Left x) = x fromLeft x _ = x
It looks indeed better than the non-total fromLeft. On the other hand the name would be inconsistent with fromJust, and the total fromLeft could be written as: fromLeft x = either (const x) id or using the proposed maybeLeft as fromLeft x = fromMaybe x . maybeLeft I don't know how often you need fromLeft.

El Aug 7, 2013, a las 4:26, Henning Thielemann
On Wed, 7 Aug 2013, Erik de Castro Lopo wrote:
In the second link above you wrote:
I have included both links since the discussion in November continued in December.
It would be a good opportunity to check how these packages use isLeft and isRight. E.g. if they use them in connection with fromLeft and fromRight then this would be an argument for me to exclude isLeft and isRight as well.
My main usage of isLeft/isRight is in HSpec tests where I write:
value1 `shouldSatisfy' isLeft value2 `shouldSatisfy' isRight
Yes, from what I have seen in some packages, testing seems to be the most sensible usage of 'isLeft' and 'isRight'. In other contexts 'isLeft' is usually combined with a non-total 'fromLeft', which is certainly a bad idea.
Another use, where I've defined isLeft in the past, is checking that a set of computations was successful, e.g. "if all isRight foo" +1 to all of these (although I could take or leave mapEither) -Tom
I would also be opposed to a fromLeft defined anything like fromJust:
Data.Maybe.fromJust :: Maybe a -> a
but would not be opposed to a fromLeft defined as John Wiegley suggested:
fromLeft :: a -> Either a b -> a fromLeft _ (Left x) = x fromLeft x _ = x
It looks indeed better than the non-total fromLeft. On the other hand the name would be inconsistent with fromJust, and the total fromLeft could be written as:
fromLeft x = either (const x) id
or using the proposed maybeLeft as
fromLeft x = fromMaybe x . maybeLeft
I don't know how often you need fromLeft.
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On Wed, 7 Aug 2013, amindfv@gmail.com wrote:
Another use, where I've defined isLeft in the past, is checking that a set of computations was successful, e.g. "if all isRight foo"
And you are not interested in the results itself? I would certainly prefer 'sequence foo'. Then you can also access the results of the computations.

Erik de Castro Lopo
Henning Thielemann wrote:
http://www.haskell.org/pipermail/libraries/2012-November/018709.html http://www.haskell.org/pipermail/libraries/2012-December/018716.html
Henning,
In the second link above you wrote:
It would be a good opportunity to check how these packages use isLeft and isRight. E.g. if they use them in connection with fromLeft and fromRight then this would be an argument for me to exclude isLeft and isRight as well.
My main usage of isLeft/isRight is in HSpec tests where I write:
value1 `shouldSatisfy' isLeft value2 `shouldSatisfy' isRight
What I don’t like about this is that isLeft strikes me as having too little mnemonic information in it. While there’s an argument that if one uses “(const True ||| const False)” many times in a programme one might usefully name it, the most suitable name surely depends on the programme. What is the /intention/ of isLeft in the above tests, and can you not name it to reflect that? I’ll grant that for some programmes isLeft may be as good a name as can be found, but I doubt it in general. -- Jón Fairbairn Jon.Fairbairn@cl.cam.ac.uk

Usually I start out writing such functions into Bool, but then end up generalizing them to Maybe, in this case isLeft :: Either a b -> Maybe a isLeft (Left a) = Just a isLeft Right{} = Nothing etc. If I really need a Bool, I can compose them with isJust/isNothing. On 07.08.13 9:18 AM, Henning Thielemann wrote:
On Wed, 7 Aug 2013, Erik de Castro Lopo wrote:
And while we're at it:
isLeft :: Either a b -> Bool isLeft (Left _) = True isLeft (Right _) = False
isRight :: Either a b -> Bool isRight (Left _) = False isRight (Right _) = True
http://www.haskell.org/pipermail/libraries/2012-November/018709.html http://www.haskell.org/pipermail/libraries/2012-December/018716.html
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
-- Andreas Abel <>< Du bist der geliebte Mensch. Theoretical Computer Science, University of Munich Oettingenstr. 67, D-80538 Munich, GERMANY andreas.abel@ifi.lmu.de http://www2.tcs.ifi.lmu.de/~abel/

On 2013-08-06 at 12:21:14 +0200, Christopher Done wrote:
How about popping these in Data.Either?
-- | Maybe get the left side of an Either. leftToMaybe :: Either a b -> Maybe a leftToMaybe = either Just (const Nothing)
-- | Maybe get the right side of an Either. rightToMaybe :: Either a b -> Maybe b rightToMaybe = either (const Nothing) Just
+1 Some minor nitpicking: IMHO, the naming is inconsistent with respect to the existing functions: listToMaybe :: [a] -> Maybe a maybeToList :: Maybe a -> [a] In these two cases, '[lL]ist' and '[mM]aybe' both denote types, whereas in '{left,right}ToMaybe', 'left' is a constructor and 'Maybe' is a type. However, I have no better naming alternative to offer. -- hvr

Some minor nitpicking: IMHO, the naming is inconsistent with respect to the existing functions:
listToMaybe :: [a] -> Maybe a maybeToList :: Maybe a -> [a]
In these two cases, '[lL]ist' and '[mM]aybe' both denote types, whereas in '{left,right}ToMaybe', 'left' is a constructor and 'Maybe' is a type. However, I have no better naming alternative to offer.
The names 'leftToMaybe' and 'rightToMaybe' could also be slightly irritating, because reading the name 'leftToMaybe' might provoke the question: and what happens for the 'Right' case. I would prefer the names 'left' and 'right', but If the name clash with 'Control.Arrow' is an issue, than perhaps 'maybeLeft' and 'maybeRight'. Greetings, Daniel
participants (17)
-
amindfv@gmail.com
-
Andreas Abel
-
Christopher Done
-
Dan Doel
-
Daniel Trstenjak
-
David Luposchainsky
-
Edward Kmett
-
Erik de Castro Lopo
-
Erik Hesselink
-
Henning Thielemann
-
Henning Thielemann
-
Herbert Valerio Riedel
-
Ivan Lazar Miljenovic
-
John Wiegley
-
Jon Fairbairn
-
Michael Snoyman
-
Sturdy, Ian