Nested Eithers with different error types - haskell

I have a nested either with different error types, that looks like:
Either e1 (Either e2 a)
And I'd like a function that does something like:
Either e1 (Either e2 a) -> Either e2 a
More generally, is there a typeclass that matches this pattern?

Your function is impossible!
What you’re asking for doesn’t really make sense as it stands. Let’s look at the type of your function:
f :: Either e1 (Either e2 a) -> Either e2 a
Assuming this function is total (as the vast majority of functions in Haskell really ought to be), we need to produce a value of type Either e2 a for any input of type Either e1 (Either e2 a). To try and implement this, let’s consider all of the “shapes” the input can come in.
It turns out that values of the type Either e1 (Either e2 a) can come in three possible shapes:
Left _
Right (Left _)
Right (Right _)
The bottom two shapes are easy to handle. In fact, we can just map any Right value to itself:
f (Right x) = x
However, this doesn’t handle the outer Left case. We can start by writing the pattern:
f (Left x) = ???
In the above pattern, we get a single value, x, with type e1. We need to produce a value of type Either e2 a. This means we essentially need a function with the following type:
g :: e1 -> Either e2 a
But wait! That type is clearly impossible to satisfy, since we need either an e2 or an a, but all we have is an e1. Therefore, we can’t implement that case (assuming we don’t infinitely loop or use error or undefined). We’re stuck.
Solution 1: provide more information
Without knowing what you’re actually trying to do, it’s hard to offer a good solution to this problem. I can at least offer a few possibilities, and maybe one of them will be relevant to your use case.
One easy solution is to provide a way to map e1 values to e2. That way, we can normalize all errors to e2. Implementing this is very easy with the help of the either function:
f :: (e1 -> e2) -> Either e1 (Either e2 a) -> Either e2 a
f g = either (Left . g) id
You could also do this by applying the mapping function to the left hand side of the outer Either, then using the monadic join function to merge the two layers:
import Data.Bifunctor
f :: (e1 -> e2) -> Either e1 (Either e2 a) -> Either e2 a
f g = join . first g
Solution 2: change the result type
Another way we could handle this would be to tweak the result to encode both possibilities. We could produce a value of type Either (Either e1 e2) a to hold either possible error. This is also fairly easy to write with the either function:
f :: Either e1 (Either e2 a) -> Either (Either e1 e2) a
f = either (Left . Left) (either (Left . Right) Right)
However, that’s probably clearer written with pattern-matching instead of either:
f :: Either e1 (Either e2 a) -> Either (Either e1 e2) a
f (Left x) = Left (Left x)
f (Right (Left x)) = Left (Right x)
f (Right (Right x)) = Right x

Related

Accessing a common field in sum type variants

Suppose I have a sum type (or several, in fact), that I know by design all have a common field:
data T1 a
= C1 String a
| C2 Int a
| C3 Bool a
data T2 a
= C4 Int Int a
| C5 [String] a
Is there a way to access the a field without having to pattern match on all variants across all types?
(I ask in the context of defining ASTs & having a neat way of accessing node-specific information)
A Minor Technical Detail
At the boring super-technical level, no. There is no way to access the fields of a constructor without pattern matching. Pattern matching is the primitive operation that causes the constructor to be evaluated. Before that, the fields don't even necessarily exist (thanks to non-strict evaluation).
Some Options That Might Be Useful
But you probably didn't mean that low-level question. You probably want a way to work with these data types without constantly writing pattern matches. And that can be done. It's just a matter of writing some functions. Which functions, though? ...that can be interesting.
You can write simple accessor functions:
t1ToA :: T1 a -> a
t1ToA (C1 _ x) = x
t1ToA (C2 _ x) = x
t1ToA (C3 _ x) = x
t2ToA :: T2 a -> a
t2ToA (C4 _ _ x) = x
t2ToA (C5 _ x) = x
Don't automatically reject this approach. Sure, it's a bit hungry on namespace because you need a different function name for each type. On the other hand, it's really good for readability and type inference. There's nothing magical anywhere. You might write some matching setter and modifier functions as well.
If you find that's getting to be too namespace hungry when you have various set and modify functions added in, you could use the van Laarhoven trick:
t1A :: Functor f => (a -> f a) -> T1 a -> f (T1 a)
t1A g (C1 x y) = C1 x <$> g y
t1A g (C2 x y) = C2 x <$> g y
t1A g (C3 x y) = C3 x <$> g y
t2A :: Functor f => (a -> f a) -> T2 a -> f (T2 a)
t2A g (C4 x y z) = C4 x y <$> g z
t2A g (C5 x y) = C5 x <$> g y
This representation lets you do reading and updating from the same type, though it is awkward without some helper functions. This is the representation used by libraries like lens, which provide you a huge number of those helper functions. But maybe you don't want to worry about learning how to work with this representation. I'm going to assume this isn't really what you're looking for and not even go into the details of how those helper functions work. But at a high level, they make clever use of specific types for f like Identity and Const a.
An option if you are willing to give up some type inference in order to reduce namespace use is to go for some sort of ad-hoc class:
class ToA f where
toA :: f a -> a
instance ToA T1 where
toA (C1 _ x) = x
toA (C2 _ x) = x
toA (C3 _ x) = x
instance ToA T2 where
toA :: T2 a -> a
toA (C4 _ _ x) = x
toA (C5 _ x) = x
You could choose to combine this with the van Laarhoven encoding, for what it's worth. This would minimize the amount of namespace you grab, but requiring some additional helpers for the sake of using them easily.
There are a few other options that you might be able to work with, like using less ad-hoc tools GHC provides. Data and Generic are different classes you could work with where GHC gives you a lot of the tools already. But these tend to be very complex to pick up the first time around.
But Maybe There's a Better Solution
There's one last option that is actually the one I would recommend in most cases. Refactor your data types so the shared values aren't duplicated.
data WithA t a = WithA t a
data T1
= C1 String
| C2 Int
| C3 Bool
And so on. Or however you might choose to refactor it. The important part is that the shared field is lifted out of the sum type, and is just always present. I think that this often ends up working the best. It often communicates what you mean better. When you have 3 constructors which each have a field of the same type it's not immediately obvious that that field should be seen as interchangeable between the constructors, even when the datatype is polymorphic over that field's type. But if it's a single field outside of the multiple constructors it is immediately obvious that it's always the same thing. Don't underestimate the communication value that provides for all future maintainers of the code.
Carl already mentioned a few alternatives. For completeness, let me add that using records allows one to use a common field name for all constructors, and that in turn allows to get/set the common field.
data T a
= K1 { foo :: a, oth1 :: Int }
| K2 { foo :: a, oth2 :: String }
get :: T a -> a
get = foo
set :: T a -> a -> T a
set t x = t{foo = x}
I am not a huge fan of this approach since other fields like oth1, oth2 become partial functions. I would rather refactor the type as Carl showed (the WithA example).

Using Just and Nothing Haskell

I am implementing a lambda calculus interpreter and one of the functions I have to write is specified as follows. I have written all of the other functions but this one is really giving me trouble because it needs to return either Just Expr or Nothing and I'm not sure how to propogate this through the recursion:
A single step. Now write a function to do a single step of reduction:
appNF_OneStep :: Expr -> Maybe Expr
where the built-in Maybe type is defined as follows:
data Maybe a =
Nothing
| Just a
appNF_OneStep takes an expression e. If there is a redex available in e, it picks the correct applicative
order redex and reduces e. (Note that in applicative order we are pursuing the leftmost, innermost strategy
as follows. Pick the leftmost redex R; if there are nested (inner) redexes within R, pick the leftmost one,
and so on, until we reach a redex without nested ones.) If a reduction was carried out, resulting in a
new expression expr', appNF_OneStep returns Just expr', otherwise it returns Nothing.
As example inputs/outputs:
Input: App (Lambda "x" (Lambda "y" (Var "x"))) (Lambda "x" (Var "x"))
Correct Output: Just (Lambda "1_" (Lambda "x" (Var "x")))
Another example:
Input: Lambda "y" (Lambda "x" (Var "x"))
Correct Output: Nothing
As can be seen, the entire expression with only the one reduction performed is wrapped inside of the Just.
I will provide a few hints.
You need to perform the recursive calls, and check whether their result is Nothing or Just something. This part of your code looks OK:
appNF_OneStep (App e1 e2) =
let f = appNF_OneStep e1
a = appNF_OneStep e2
in
Let's continue from there. There are four possible cases:
appNF_OneStep (App e1 e2) =
let f = appNF_OneStep e1
a = appNF_OneStep e2
in case (f, a) of
(Nothing, Nothing) -> ??? -- case 1
(Nothing, Just a') -> ??? -- case 2
(Just f', Nothing) -> ??? -- case 3
(Just f', Just a') -> ??? -- case 4
In case 1, both e1 and e2 can not be reduced. Can we reduce their application? How?
In case 2, e1 can not be reduced, but e2 can (to a'). Can we reduce their application? How?
And so on. You might not need to consider all four cases if you discover some of them are similar and can be grouped. Still, I'd recommend you start by examining all four cases, to understand what's going on.
The rest of the code has some issues:
appNF_OneStep::Expr -> Maybe Expr
appNF_OneStep (Var x) = (Var x)
Here the result (Var x) is an Expr, not a Maybe Expr, so it has the wrong type. We might fix that to Just (Var x). Is that really the right result, though? Do we really have that a variable can make one reduction step resulting in itself?
Similarly,
appNF_OneStep (Lambda x ex) = (Lambda x (appNFOneStep ex))
returns the wrong type, Expr instead of Maybe Expr. On top of that, Lambda expects an Expr as second argument, but the recursive call is Maybe Expr, so that won't do. You need to proceed by cases, as for application:
appNF_OneStep (Lambda x ex) = case appNFOneStep ex of
Nothing -> ???
Just a -> ???
Once you get fluent with Haskell, you could replace some of this boring code with helpers like fmap, but there is no need to hurry. Try to learn the basics of pattern matching and algebraic types, first.

Haskell - Applicative upon Either's Left

I'm trying to understand Applicative and Either's Left. Here is the source:
instance Applicative (Either e) where
pure = Right
Left e <*> _ = Left e
Right f <*> r = fmap f r
I'm unable to understand the Left e <*> _ = Left e part. It makes no sense because this:
Left (+3) <*> Right 5
Would return Left (+3), while this:
Right (+1) <*> Left 3
would return Left 3. The problem is inconsistency. Why would the do this? I apologize if my question isn't clean enough. Thanks!
TL;DR, It's an intentional design decision.
You should think of Right as the "default" state, and Left as the "fallback" state. I do want to make a small correction to your statements above. Left (+3) <*> Right 5 does not produce (+3) as you say, but rather Left (+3). That's an important distinction. The second correction is that Right (+1) <*> Left 3 procues not Left 4, but Left 3. Again, this is important to understand what's going on.
The reason why the <*> operator cannot be symmetric over Either is because the Left and Right constructors don't take the same type. Let's look at the type of <*> specialized to the Either functor:
(<*>) :: Either a (b -> c) -> Either a b -> Either a c
Notice how only the Right side of the first argument is required to be a function. This is so that you can use (<*>) to chain together arguments like this:
Right (+) <$> Right 3 <*> Right 2
> Right 5
But if the first argument were Left 3:
Right (+) <$> Left 3 <*> Right 2
> (Right (+) <$> Left 3) <*> Right 2
> Left 3 <*> Right 2
> Left 3
It also means that you can use (<*>) in general when Left and Right don't have the same type. If Left (+3) <*> Right 5 should produce Left 8, then what should Left (++ "world") <*> Right 5 produce, given that they can both be coerced to the same type, namely Num a => Either (String -> String) a? It's impossible to come up with a satisfactory answer that treats Left and Right equally when they aren't the same type, and a version of Either that was restricted to carrying one type would have severely hampered utility.
This also allows you to treat Left values as exceptional in some way. If at any stage, you end up with a Left value, Haskell will stop performing calculations and just cascade the Left value all the way up. This also happens to match up well with the way a lot of people think about programming. You could imagine creating alternate sets of computations for Left and Right values, but in many cases, you'd just end up filling the Left computations with id anyways, so this isn't too big a limitation in practice. If you want to execute one of a pair of branching computations, you should use regular branching syntax, such as guards, patterns, or case and if statements and then wrap the values up in Either at the end.
If you’re wondering how Right … <*> Left … can still return a Left, it’s because of the fmap call in this definition:
instance Applicative (Either e) where
pure = Right
Left e <*> _ = Left e
Right f <*> r = fmap f r
If we expand the definition of fmap for Either, then the definition of <*> looks like this:
Left e <*> _ = Left e
Right f <*> r = case r of
Left e -> Left e
Right x -> Right (f x)
Or, written more symmetrically with all the cases spelled out explicitly:
Left e1 <*> Left _e2 = Left e1 -- 1
Left e <*> Right _x = Left e -- 2
Right _f <*> Left e = Left e -- 3
Right f <*> Right x = Right (f x) -- 4
I’ve marked with an underscore _ the values that are discarded.
Notice that the only case that returns Right is when both inputs are Right. In fact, that’s the only time it’s possible to return Right.
In case (4) we only have a Right (f :: a -> b) and a Right (x :: a); we don’t have an e, so we can’t return a Left, and the only way we have to obtain a b is by applying f to x.
In cases (1), (2), and (3), we must return a Left, because at least one of the inputs is Left, so we are missing the a -> b or the a that we would need to produce a b.
When both inputs are Left in case (1), Either is biased toward the first argument.
There is a type similar to Either called Validation which combines its “failure” cases, instead of choosing one or the other, but it’s more constrained: it’s only an Applicative, while Either is both an Applicative and a Monad.
Consider this equivalent definition of the instance:
instance Applicative (Either e) where
pure = Right
lhs <*> rhs = case lhs of
Right f -> fmap f rhs
otherwise -> lhs
If lhs isn't a Right, it must be a Left, and so we return it as-is. We don't actually have to match against the wrapped value at all. If it is a Right, we defer to the Functor instance to find out what gets returned.
instance Functor (Either a) where
fmap f (Right x) = Right (f x)
fmap _ l = l
Again, I've given a definition that emphasizes that the content of the Left value doesn't matter. If the second argument isn't a Right, we don't have to explicitly match on it; it must be a Left, and we can just return it as-is.

Having trouble understanding Haskell's type system

I am currently trying to do 20 Intermediate Haskell Exercises. I was able to get done with the 1st 3 exercises (but this is because furry == fmap and Learn You a Haskell has those implementations already). I am currently stuck on the instance that says:
instance Fluffy (EitherLeft t) where
furry = error "todo"
I am not really understanding what to do. In Learn You Haskell they have a newtype variable called Pair which takes in a tuple. They then can do pattern matching as such:
fmap f (Pair (x,y)) = Pair (f x, y)
I was thinking maybe you could do something similar in my situation:
furry f (EitherLeft (Either a b)) = EitherLeft (Either (f a) b)
But, that doesn't work:
Not in scope: data constructor `Either'
I was thinking maybe I would import Data.Either because there might be some import things he has I don't have. But that didn't matter.
I also tried to get just this to work:
furry f (EitherLeft a b) = error "todo"
But that doesn't work either:
Constructor `EitherLeft' should have 1 argument, but has been given 2
I couldn't get this to work either:
furry f (Right x) = (Right f x)
furry f (Left x) = Left x
Which gave the error:
Couldn't match expected type `EitherLeft t a'
with actual type `Either t0 t1'
I have only been able to get:
furry f (EitherLeft t) = error "todo"
to work. But I have no idea what to do with t.
I don't necessarily want an answer. I just need a hint as to what to do because I'm reading and I can sort of, understand the examples but I can't really get my head around to coding this stuff right on my own.
Thanks Dan, this is what I came up with for my solution:
instance Fluffy (EitherLeft t) where
furry f (EitherLeft (Left x)) = EitherLeft $ Left (f x)
furry f (EitherLeft (Right x)) = EitherLeft $ Right x
The problem you are having is that the Either datatype does not have a data constructor called Either, basically the Either type looks like this
data Either a b = Left a
| Right b
So a value can have the type Either a b , but there is no value like Either "one" 1 or something like that, but instead Left "one", or Right 1.
So in the case of EitherLeft, similarly its values will look like EitherLeft (Left a) or EitherLeft (Right b), and need to be pattern matched against as such.

Pattern matching in a let expression

How do you extract a value from a variable of an unknown constructor?
For instance, I would like to negate the value in an Either if was constructed as a Right:
let Right x = getValue
in Right (negate x)
This code successfully binds Right's value (an Int in this case) to x.
This works, but what if getValue returns a Left instead? Is there a way to determine the type of a variable in a let expression? Or is there a better way to approach this problem?
In general, what you can do is this:
case getValue of
Right x -> Right $ negate x
e -> e
What this does should be clear: it's just like pattern matching in a function argument, but against a value. To do what you need, you have a default case which catches anything not matched, and then return that.
In your particular case, however, you can do something slightly nicer:
negate `fmap` getValue
Or, with import Control.Applicative, you can use <$> as a synonym for fmap (negate <$> getValue). The fmap function has type fmap :: Functor f => (a -> b) -> f a -> f b. For any functor1, fmap converts a function on ordinary values to a function within the functor. For instance, lists are a functor, and for lists, fmap = map. Here, Either e represents a functor which is either an exception Left e or a value Right a; applying a function to a Left does nothing, but applying a function to a Right applies it within the Right. In other words,
instance Functor (Either e) where
fmap _ (Left l) = Left l
fmap f (Right r) = Right $ f r
Thus the case version is the direct answer to your question, but your particular example is more nicely approximated by fmap.
1: To a first approximation, functors are "containers". If you're not comfortable with the various type classes, I recommed the Typeclassopedia for a comprehensive reference; there are many more tutorials out there, and the best way to get a feel for them is to just play with them. However, the fmap for specific types is often readily usable (especially, in my opinion, when written <$>).
Answer to the title of this question:
I don't see big difference between "... where" and "let ... in ...". Both allows you do declare several cases of function argument bindings:
f val = let negR (Right x) = Right (negate x)
negR y = y
in negR val
or
let { negR (Right x) = Right (negate x); negR y = y; } in negR val

Resources