# Function to get value of a Left

This was a challenge from a book: filter out `Right`s from a list of `[Either String Integer]`.

This works just fine

``````lst1 :: [Either String Integer]
lst1 = [ Left "foo", Right 3, Left "bar", Right 7, Left "baz" ]

lefts' :: [Either a b] -> [a]
lefts' [] = []
lefts' (x:xs) = if isLeft x
then (\(Left z) -> z) x : lefts' xs
else lefts' xs
``````

But I wanted to write the lambda as a separate function and could not figure out how to do it. I tried:

``````getLeftVal :: Either a b -> a
getLeftVal (Left l) = l
``````

But no surprise it gives the pattern matches not exhaustive warning.

I could of course do:

``````getLeftVal :: Either a b -> a
getLeftVal x = (\(Left z) -> z) x
``````

But is redundant and extra code.

I tried a few other things but none worked.

The traditional solution is to use a pattern match and not a boolean isConstructor test.

3 Likes

Your original lambda based implementation also gives a warning on newer GHC versions. The warning is under a separate flag `-Wincomplete-uni-patterns` which is included in `-Wall` only on newer compiler versions (I believe from GHC 9 on).

The reason is that GHC is not smart enough to look into the definition of the `isLeft` function. That would be very costly to do everywhere.

Instead, as Tom suggests, you should use pattern matching in the `lefts'` function so that the compiler can give more accurate error messages.

That would look like this by the way:

``````lefts' (x:xs) = case x of
Left x' -> x' : lefts' xs
Right _ -> lefts' xs
``````

Or

``````lefts' (Left x:xs) = x : lefts' xs
lefts' (Right _:xs) = lefts' xs``````
4 Likes

Since lists are being used, use comprehensions instead of lambda-definitions:

``````lefts' :: [Either a b] -> [a]
lefts' l = [ x | Left x <- l ]
``````

Simplicity has its benefitsâ€¦

2 Likes

I always found list comprehension magical

2 Likes

I was trying to find a way to detect a `Left` without having to pattern match `Right`. Seems that was a wrong turn. I like your second more.

I thought about a list comprehension but would not have know to write it like that. Is the `Left x` to the left of `<- l` a pattern match that just ignores `Right x`?

Beginners have a way of making things complicated

1 Like

You can do it without matching on Right:

``````lefts' (Left x:xs) = x : lefts' xs
lefts' (_:xs) = lefts' xs
``````

The reason I didnâ€™t do that was because of what Graham Hutton said in one of his FP lectures on youtube. Namely that explicitly matching on Right makes the patterns independent in the sense that you can change the order of the lines without changing the meaning of the function. Also, when reading the function you can read and understand each line separately.

2 Likes

Correct. See section 3.11 (page 42 of 329) in the Haskell 2010 Report for more details.

1 Like

The book wanted a solution using `foldr` so I came up with

``````lst1 :: [Either String Integer]
lst1 = [ Left "foo", Right 3, Left "bar", Right 7, Left "baz" ]

isItLeft :: Either a b1 -> [Either a b2]
isItLeft (Left x) = [Left x]
isItLeft (Right x) = []

lefts' :: Foldable t => t (Either a b1) -> [Either a b2]
lefts' xs = foldr (\cur acc -> acc ++ isItLeft cur) [] xs

ghci> lefts' lst1
[Left "baz",Left "bar",Left "foo"]

``````

Hint:

``````keepLefts (Left x)  = (x:)
keepLefts (Right _) = ...
``````

Also look at the `either` functionâ€¦

Wouldnâ€™t `keepLefts (Left x) = (x:)` return the value from inside the `Left` instead of a `Either`/`Left`?

Yes, just as this would do:

Keeping the `Left` constructors only requires a small change:

``````keepLefts (Left x)  = (Left x :)
keepLefts (Right _) = ...
``````

or using an as-pattern:

``````keepLefts x@(Left _)  = (x:)
keepLefts (Right _) = ...
``````
1 Like

So I struggled with that a bit until I change `(Left x :)` to `([Left x] :)`. And now this works:

``````lst1 :: [Either String Integer]
lst1 = [ Left "foo", Right 3, Left "bar", Right 7, Left "baz" ]

keepLefts :: Either a b1 -> [[Either a b2]] -> [[Either a b2]]
keepLefts (Left x)  = ([Left x] :)
keepLefts (Right _) = ([] :)

lefts' :: Foldable t => t (Either String Integer) -> [[Either String Integer]]
lefts' xs = foldr (\cur acc -> keepLefts cur acc ) [] xs
``````

From you example I also realized I was reversing the order of the list so am using `:` instead of `++`.

And if I had to say what `keepLefts` is returning: "A partial function from `[[Either a b2]] -> [[Either a b2]]`". Is that right?

Youâ€™ve simplified the lambda-function here:

â€¦to the point where `cur` and `acc` are now redundant:

``````lefts' xs = foldr keepLefts [] xs  -- after eta-reduction!
``````

â€¦letâ€™s now rewrite my fragment of `keepLefts` in similar fashion - I was using a cunningly-disguised lambda-function called a section:

``````keepLefts (Left x)  = (\xs -> Left x : xs)
keepLefts (Right _) = ...
``````

After the rewrite:

``````keepLefts (Left x)  xs = Left x : xs
keepLefts (Right _) xs = ... xs
``````

As you can see, the lambda-parameter `xs` is now a parameter of `keepLefts` and is in its result no matter what:

``````= Left x : xs  -- for a (Left ...) value
= ... xs       -- for a (Right ...) value
``````

So (in this case!) `keepLefts` shouldnâ€™t be partial - in either case, it returns a useful result.

Bringing it `(`almost `;-)` altogether:

``````lst1 :: [Either String Integer]
lst1 = [ Left "foo", Right 3, Left "bar", Right 7, Left "baz" ]

keepLefts :: Either a b1 -> [Either a b2] -> [Either a b2]
keepLefts (Left x)  xs = Left x : xs
keepLefts (Right _) xs = ... xs

lefts' :: Foldable t => t (Either String Integer) -> [Either String Integer]
lefts' xs = foldr keepLefts [] xs
``````
1 Like

I donâ€™t understand why theyâ€™re so often shown to beginners, and this is the main reason why. You can sort of imagine whatâ€™s going on in terms of `map` and `filter` in simple cases, but to understand everything about how they work, you need to grok the `Monad` instance for `[]`.

3 Likes

Looks like â€śalmostâ€ť was 99.5%. Just remove `...` unless Iâ€™m missing something.

``````keepLefts :: Either a b1 -> [Either a b2] -> [Either a b2]
keepLefts (Left x)  xs = Left x : xs
keepLefts (Right _) xs = xs

lefts' :: Foldable t => t (Either String Integer) -> [Either String Integer]
lefts' = foldr keepLefts []
``````

Also, I havenâ€™t thought about this before, but it looks like in this case having `b`, `b1` & `b2` is unnecessary since we know `b` will always be an Integer. is

``````keepLefts :: Either a b1 -> [Either a b2] -> [Either a b2]
``````

more correct in some way than

``````keepLefts :: Either a b -> [Either a b] -> [Either a b]
``````

Which works equally well?

Yes - itâ€™s more generic:

```ghci> :t keepLefts
keepLefts :: Either a b1 -> [Either a b2] -> [Either a b2]
ghci>
```

When `keepLefts` is used, GHC will specialise the type as needed.

1 Like

To close out a dangling line of thought, you can also spell `keepLefts` as

``````keepLefts :: Either a b -> [a] -> [a]
keepLefts = either (:) (flip const) -- or ((:) . Left) if you want to preserve the Lefts, for some reason
``````