redefine instance for Either with specific type - haskell

I have this type synonym :
type ParseResult a = Either [CompilerError] (a, [CompilerWarning])
Where CompilerError and CompilerWarning are data types.
Now I know that Either has instance for Functor and Applicative but the instance for Functor applies fmap on the tuple (a,[CompilerWarning]), I want to redefine the instance for this type synonym so that fmap applies on a not the whole tuple, the same goes for Applicative.
If I use newtype I will have to put ParseResult all over the place and I've written a lot of code already.
I'm aware I need TypeSynonymInstances but I faced the same problem in this question, from the question I think I need to define my type synonym like this :
type ParseResult = ...
I need to fill ..., I don't know how to make the right side of kind * -> * with Either and the tuple, I tried Either [CompilerError] ((,) [CompilerWarning]) but this has two problems : first CompilerWarning is the first element and I need it to be the second(so that I don't have to change a lot of code), second I get this message :
• Expecting one more argument to ‘(,) [CompilerWarning]’
Expected a type, but ‘(,) [CompilerWarning]’ has kind ‘* -> *’
• In the second argument of ‘Either’, namely
‘(,) [CompilerWarning]’
In the type ‘Either [CompilerError] ((,) [CompilerWarning])’
In the type declaration for ‘ParseResult’
What's the best, least expensive solution to this problem ?

You can't redefine existing instances (and it would be terrible if you could).
Your options are:
Make ParseResult a real type, either using newtype or something like
data ParseResult a = Failure [CompilerError] | Success a [CompilerWarning]
and define instances for it.
Don't bother with type classes at all, and just define functions like
mapParseResult :: (a -> b) -> ParseResult a -> ParseResult b

You can take advantage of both Either and (,) being bifunctors, not just functors. This means using second . first instead of fmap to apply a function to the value of type a.
> import Data.Bifunctor
> (second . first) (+1) (Right (1, []))
Right (2, [])
> (second . first) (+1) (Left ["oops"])
Left ["oops"]
first f (x, y) is equivalent to (f x, y).
second f (Right x) is equivalent to Right f x, while second f (Left y) is equivalent to Left y.
Putting them together, you can see that
(second . first) (+1) (Right (1, [])) == second (first (+1)) (Right (1, []))
== Right $ first (+1) (1, [])
== Right ((+1) 1, [])
== Right (2, [])
If you have a Left instead, nothing happens.
(second . first) (+1) (Left ["oops"]) == second (first (+1)) (Left ["oops"])
== Left ["oops"]
Since fmap is the same as second for Either, this means you can still use fmap. You just need to wrap the function with first before using it.
(second . first) f == second (first f)
== fmap (first f)
Thus
> import Data.Bifunctor
> fmap (first (+1)) (Right (1, []))
Right (2, [])
> fmap (first (+1)) (Left ["oops"])
Left ["oops"]

Related

cannot construct the infinite type

I want to use applicative function and tried as follow:
*ReaderExercise Control.Applicative> (+4) <*> (+3)
then got following error message:
<interactive>:51:11: error:
* Occurs check: cannot construct the infinite type: a ~ a -> b
Expected type: (a -> b) -> a
Actual type: a -> a
* In the second argument of `(<*>)', namely `(+ 3)'
In the expression: (+ 4) <*> (+ 3)
In an equation for `it': it = (+ 4) <*> (+ 3)
* Relevant bindings include
it :: (a -> b) -> b (bound at <interactive>:51:1)
What do I expect is a return function with one argument.
What does it mean an infinite type?
The error "Occurs check: cannot construct [an] infinite type" results when Haskell determines that a type variable (explicitly given by the programmer or implicitly introduced by Haskell) must satisfy a condition that implies it would need to be recursively defined in terms of itself in a way that would lead to an infinitely "deep" type (i.e., the type variable "occurs" in its own definition).
It normally results from either a typo or conceptual error on the part of the programmer related to confusing two different "levels of structure" in a program.
As a simple example, a list of ints (type [Int]) is a valid Haskell type, and so is a list of lists of ints ([[Int]]) or a list of lists of lists of lists of lists of ints ([[[[[Int]]]]]) but only a finite number of list levels are allowed. You can't have a list of lists of lists of lists of lists, etc. all the way down -- that would be an infinite type. If Haskell thinks you want it to construct such a type, it'll give you an "occurs check" error.
The following definition:
yuck (x:xs) = x == xs
gives this error for exactly this reason. Haskell knows from the left-hand side that yuck takes a list of some unknown element type a where variable x is the head of type a and variable xs is the tail of type [a]. From the RHS, the operator (==) forces x and xs to have the same type -- in other words, it implies the constraint a ~ [a] where the tilde indicates "type equality". No finite type (no type with a finite number of list levels) has this properties, only the invalid infinite type [[[[...forever...]]]] could allow you to remove the outer list level and still have the same type left over, so you get the error.
The issue here is that the programmer has confused two levels of structure: the list xs and an element x.
In your specific example, the reason for the error is similar, but harder to explain. The operator:
(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
takes two applicative actions with different underlying types: the left-hand side has type given by the applicative functor f applied to the underlying type a -> b; the right-hand side has type given by the same applicative functor f applied to the underlying type b.
You haven't told Haskell which applicative functor f you meant to use, so Haskell tries to infer it. Because the LHS has type:
(+4) :: (Num n) => n -> n
Haskell tries to match the type n -> n with f (a -> b). It may be clearer to write these types using the prefix form of the (->) type operator: Haskell is trying to match (->) n n with f ((->) a b) where f is an applicative functor.
Fortunately, there's an applicative functor instance for (->) t for any type t. So, Haskell reasons that the applicative functor you want is f = (->) n, and it successfully matches (->) n n = f n to f ((->) a b). This implies that n is equal to ((->) a b). Haskell then tries to match the types on the RHS, matching (->) n n = f n with (->) n a = f a. This works, and it implies that n is equal to a.
Now we have a problem. n is simultaneously equal to a -> b (from the LHS) and a (from the RHS). This implies creation of an infinite function type, something that looks like:
(((... forever ...)->b)->b)->b)->b
which is the only way you could remove an outer ...->b and be left with the same type. This is an impossible infinite type, so you get the error.
The underlying problem is that you've made a conceptual error. Given that you are working on a ReaderExample, I think you intended to use the (->) n applicative functor instance, so you and Haskell are in agreement on this point. In this context:
(+4) :: (Num n) -> n -> n
is a reader action that reads a number from the reader and adds four to it. Similarly (+3) is a reader action that reads a number from the reader and adds three to it.
However, (<*>) is an operator that takes a reader action on the LHS that reads from the reader to produce a function (not a number!) that is then applied to the result of using the RHS to read from the reader to produce a number. For example, if you defined:
multiplyByReader :: (Num n) -> n -> n -> n
multiplyByReader readerNum input = readerNum * input
then:
multiplyByReader <*> (+4)
or the simpler version:
(*) <*> (+4)
would make sense. The intended meaning would be: Construct a reader action that (1) uses the LHS to read a number from the reader to create a function that multiplies by the reader; and then (2) applies this function to the number that results from applying the RHS to the reader.
This would be equivalent to \r -> r * (r + 4), as you can see:
> ((*) <*> (+4)) 5 -- same a 5 * (5 + 4)
45
>
When you write (+3) <*> (+4), you're mixing up two different structural levels: the LHS reader yields a number but should instead yield a function that can be applied to a number.
My best guess is that you want to create a reader action that applies (+4) to the reader to get a number and then applies (+3) to that result. In this case, (+3) isn't a reader action; it's just a function you want to apply to the result of the reader action (+4), which is equivalent to fmapping over the reader action:
(+3) <$> (+4)
Of course, you could equivalently write it directly as:
(+3) . (+4)
Both are composite reader actions that add seven to the number read:
> ((+3) <$> (+4)) 5
12
> ((+3) . (+4)) 5
12
>

Why is toList (1, 2) == [2]

As the question says, why is toList (1, 2) == [2]?
I remember something similar happening when fmapping on tuples, but I do not remember why or if it is related.
(1,2) does not correspend to the list [1,2]. That wouldn't make sense: what would then (True, 3.14) correspend to? You can't have the list [True, 3.14], because a list can only contain elements of a single type. (Haskell is different from e.g. Python here.)
The only way to pick elements of guaranteed a single type from any tuple is, well, to take only a single element. Hence toList, as generated from the Foldable (a,) instance, takes tuples (a,b) and yields lists [b]. Obviously there's always exactly one b element in such a tuple†.
You could in principle consider (Int, Int) as a special case where the elements have the same type and hence you can pick two instead of one, but such a special handling would require some highly awkward type-equality checking. And generally, special-case handling is not a good idea.
Arguably, it would have been better not to define the Foldable (a,) instance at all, to avoid this confusing behaviour. Then again, sometimes it's handy to use fold to just get rid of the first tuple element (e.g. some index).
†Why use b and not a? Kind of arbitrary? Well, not completely. (a,b) is actually syntactic sugar for (,) a b, hence you can consider (,) a as a functor (whose elements have type b), but you can't have a functor (`(,)`b) whose elements would have type a.
If you are planning to use homogeneous pairs heavily, you may want to declare a new type which will precisely correspond to them. This way you'll be able to have access to the toList you were expecting.
newtype Pair a = Pair { pair :: (a, a) }
instance Functor Pair where
fmap f (Pair (x, y)) = Pair (f x, f y)
instance Foldable Pair where
foldr f z (Pair (x, y)) = f x $ f y z
(a, b) is fundamentally different from Pair a or Constant (a, a) b and it is important to clearly document which one you mean in your code if you want typeclass resolution to pick the right instance.
newtype Constant a b = Constant a
instance Functor (Constant a) where
fmap f (Constant a) = Constant a
instance Foldable (Constant a) where
foldr f z _ = z
Examples:
length (Constant (1, 2)) == 0
length (1, 2) == 1
length (Pair (1, 2)) == 2
The results do make more sense when you interpret the function names like this:
length - how many values will be touched by fmap, fold etc.
toList - what elements will be touched by fmap, fold etc.
As long as
length x == length (toList x)
the world is fine.

Difference between Left and Right

In the book "Learn You a Haskell for Great Good" in the section about functors there is an example involving Either which I don't understand:
ghci> fmap (replicate 3) (Right "blah")
Right ["blah","blah","blah"]
ghci> fmap (replicate 3) (Left "foo")
Left "foo"
Why is the latter not Left ["foo", "foo", "foo"]?
The Left constructor on Either is implemented as the "failure case". Like other functors, once this failure value enters the equation, it prevents any real computations from happening. So, when you apply fmap to Left "foo" it immediately returns the same "failure" value.
You can see this by looking at how Either implements fmap:
instance Functor (Either a) where
fmap f (Right x) = Right (f x)
fmap f (Left x) = Left x
The idea here is that Left "foo" would actually be something more descriptive, like Left "Value could not be computed". If you try to apply further functions to that value, you just want the "error" to get passed along intact.
If it helps, just imagine how fmap would work on some other type where the failure case is more obvious, e.g.:
-- Maybe: failure value is `Nothing`
fmap (replicate 3) (Nothing)
This produces Nothing, not [Nothing, Nothing, Nothing]

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