Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between Either a and Either Int? What is Either a ? A polymorphic type constructor? What is its purpose?

Introduction:

I understand the difference between Maybe a and Maybe Int, I also understand the difference between Either a b and Either Int Int. I also understand that Either Int is the same kind of animal as Maybe, they both take a type as an argument and produce a new type i.e. they are both type constructors that take a single type as parameter (either concrete like Int or not concrete like a) and produce either a concrete type or polymorphic type.

Now what I don't understand is what kind of construct is Either a ? It is not like Maybe because it can never produce a concrete (read not polymorphic) type if we feed a concrete type (like Int) to it. So in this case is it correct to call Either a a polymorphic type constructor and call Maybe a concrete type constructor ? ( This is just how I call them, what are their official name in the Haskell nomenclature?)

Furthermore, I don't know what is the official categorization within the Haskell type system of type constructors like Either a because it cannot be in the same kind of category as Maybe because - as mentioned in the previous paragraph - no matter to what type we apply Either a the resulting type never will be a concrete type, i.e. it will always be a polymorhic type, for example, Either a Int.

The reason why I am asking this is because Either a is a Functor. Which starts to get confusing. Nothing like anything I've seen before. I don't know how should I conceptually interpret the fact that Either a ( a polymorphic type constructor ) is an instance of Functor? Similarly, (->) r (which is also the same kind of animal as Either a) is a Functor too.

Questions:

What are Either a and (->) r ?

What are they called officially?

How do they conceptually fit into the type system of Haskell ?

Where are these polymorphic type constructors described / discussed in more detail?

What whould I read about so I get a better understanding of them?

Should I read about kinds? Are kinds the secret way towards understanding such polymorphic type constructors as Either a and (->) r?

Is Either a Int the same kind of animal as [a] ?

Is the only purpose of Either a Int to declare polymorphic input and output types for functions, just like in the case of [a] in fmap :: (a -> b) -> [a] -> [b]?

Most important question:

How should I interpret the following code in the light of the above described thoughts?

instance Functor (Either a) where 
  fmap f (Right x) = Right (f x) 
  fmap f (Left x) = Left x

class Functor f where 
  fmap :: (a -> b) -> f a -> f b

So the resulting fmap function (whose type is fmap :: (a -> b) -> Either c a -> Either c b) will be polymorphic in c ?

Is this the only effect of making Either a an instance of Functor? So that the resulting fmap function will be polymorphic in c ?

As compared to, for example, making Either Int an instance of Functor?

Then the resulting fmap would work only on Either Int a types but would not work generally/polymorphically on all Either a b types?

If I understand correctly is this the only point and purpose of having polymorphic type constructors like Either a ? So that fmap works on all Either a b types?

I am confused and I am not sure if I am interpreting Either a correctly. Could someone please comfirm that 1) either my interpretation is correct 2) if not then please enlighten me.

Thanks for reading.

like image 269
jhegedus Avatar asked Apr 23 '14 09:04

jhegedus


1 Answers

There's not really any such thing as Either a. Like polymorphic functions, polymorphic instances should be read system-F style with universal quantification:

forall a . instance Functor (Either a) where ...

The functor instance itself is a dictionary, i.e. type-level function

functor = Λf -> { Λa b -> (a->b) -> f a->f b }

So the either instance would be something like

eitherFunctor = Λa -> functor (Either a)

Alternatively you can think about it as if the compiler replaced instance Functor (Either a) with tons of discrete instances

instance Functor (Either ()) where ...
instance Functor (Either Int) where ...
...
instance Functor (Either (Either Int String)) where ...
...

Though it would obviously not be possible to do that, literally.

like image 174
leftaroundabout Avatar answered Sep 29 '22 07:09

leftaroundabout