In my free time I'm learning Haskell, so this is a beginner question.
In my readings I came across an example illustrating how Either a is made an instance of Functor:
instance Functor (Either a) where
fmap f (Right x) = Right (f x)
fmap f (Left x) = Left x
Now, I'm trying to understand why the implementation maps in the case of a Right value constructor, but doesn't in the case of a Left?
Here is my understanding:
First let me rewrite the above instance as
instance Functor (Either a) where
fmap g (Right x) = Right (g x)
fmap g (Left x) = Left x
Now:
I know that fmap :: (c -> d) -> f c -> f d
if we substitute f with Either a we get fmap :: (c -> d) -> Either a c -> Either a d
the type of Right (g x) is Either a (g x), and the type of g x is d, so we have that the type of Right (g x) is Either a d, which is what we expect from fmap (see 2. above)
now, if we look at Left (g x) we can use the same reasoning to say that its type is Either (g x) b, that is Either d b, which is not what we expect from fmap (see 2. above): the d should be the second parameter, not the first! So we can't map over Left.
Is my reasoning correct?
This is right. There is also another quite important reason for this behavior: You can think of Either a b as a computation, that may succeed and return b or fail with an error message a. (This is also, how the monad instance works). So it's only natural, that the functor instance won't touch the Left values, since you want to map over the computation, if it fails, there's nothing to manipulate.
Your account is right of course. Maybe the reason why we have a difficulty with instances like this is that we are really defining infinitely many functor instances at once -- one for each possible Left type. But a Functor instance is a systematic way of operating on the infinitely many types in the system. So we are defining infinitely many ways of systematically operating on the infinitely many types in the system. The instance involves generality in two ways.
If you take it by stages, though, maybe it's not so strange. The first of these types is a longwinded version of Maybe using the unit type () and its only legitimate value ():
data MightBe b = Nope () | Yep b
data UnlessError b = Bad String | Good b
data ElseInt b = Else Int | Value b
Here we might get tired and make an abstraction:
data Unless a b = Mere a | Genuine b
Now we make our Functor instances, unproblematically, the first looking a lot like the instance for Maybe:
instance Functor MightBe where
fmap f (Nope ()) = Nope () -- compare with Nothing
fmap f (Yep x) = Yep (f x) -- compare with Just (f x)
instance Functor UnlessError where
fmap f (Bad str) = Bad str -- a more informative Nothing
fmap f (Good x) = Good (f x)
instance Functor ElseInt where
fmap f (Else n) = Else n
fmap f (Value b) = Value (f b)
But, again, why bother, let's make the abstraction:
instance Functor (Unless a) where
fmap f (Mere a) = Mere a
fmap f (Genuine x) = Genuine (f x)
The Mere a terms aren't touched, as the (), String and Int values weren't touched.
As others mentioned, Either type is a functor in its both arguments. But in Haskell we are able to (directly) define only functors in a type's last arguments. In cases like this, we can get around the limitation by using newtypes:
newtype FlipEither b a = FlipEither { unFlipEither :: Either a b }
So we have constructor FlipEither :: Either a b -> FlipEither b a that wraps an Either into our newtype with swapped type arguments. And we have dectructor unFlipEither :: FlipEither b a -> Either a b that unwraps it back. Now we can define a functor instance in FlipEither's last argument, which is actually Either's first argument:
instance Functor (FlipEither b) where
fmap f (FlipEither (Left x)) = FlipEither (Left (f x))
fmap f (FlipEither (Right x)) = FlipEither (Right x)
Notice that if we forget FlipEither for a while we get just the definition of Functor for Either, just with Left/Right swapped. And now, whenever we need a Functor instance in Either's first type argument, we can wrap the value into FlipEither and unwrap it afterward. For example:
fmapE2 :: (a -> b) -> Either a c -> Either b c
fmapE2 f = unFlipEither . fmap f . FlipEither
Update: Have a look at Data.Bifunctor, of which Either and (,) are instances of. Each bifunctor has two arguments and is a functor in each of them. This is reflected in Bifunctor's methods first and second.
The definition of Bifunctor of Either is very symetric:
instance Bifunctor Either where
bimap f _ (Left a) = Left (f a)
bimap _ g (Right b) = Right (g b)
first f = bimap f id
second f = bimap id f
Now, I'm trying to understand why the
implementation maps in the case of a
Right value constructor, but doesn't
in the case of a Left?
Plug in here and it might make sense.
Assume a = String (an error message)
You apply Either a to an Float.
So you have an f: Float -> Integer say for example roundoff.
(Either String) (Float) = Either String Float.
now (fmap f):: Either String Float -> Either String Int
So what are you going to do with f? f doesn't have a clue what to do with strings so you can't do anything there. That is obviously the only thing you can act on are the right values while leaving the left values unchanged.
In other words Either a is a functor because there is such an obvious fmap given by:
for Right values apply f
for Left values do nothing
Related
I admit, that my question may stem from a lack of knowledge and be rather vague.
But I try to understand, have some doubts and can't resolve them.
So GHC.Base have such definition, and what is the sense in it:
instance Functor ((->) r) where
fmap = (.)
From the viewpoint of programming language:
We have really base construction (->), I think more base than anything, but maybe terms, and you describe it as a part of very derivative construction (instance Functor). What is the sense? (->) is (->). Functor have any sense as far as (->) described under Haskell hood meaningfully. But not vice versa: (->) have sense while Functor described in Haskell libraries correctly.
From the viewpoint of lambda calculus:
2.1 If from "common sense" definition "(->) r" is a container around r (let's call it "Any_f"), then how function fmap shoul work?
fmap should change value into container, but do not change container-structure, try to write it.
fmap f (Any_f x) <=> Any_f (f x)
(yes, this is non-typed lambda calculus)
2.2. But let's look how Functor ((->) r) defined in Haskell:
instance Functor ((->) r) where
fmap = (.)
-- Or in other words (quotation marks intentionaly):
-- fmap f (Any_f x) = f (Any_f x)
-- fmap :: forall a, b, c => (b -> c) -> (a -> b) -> (a -> c)
So:
"common sense" (not change container structure) tells us to write:
fmap f (Any_f_as_container x) = Any_f_as_container (f x)
types requirements tell us to write:
fmap f (any_f_as_container x) = f (Any_f_as_container x)
Doesn't this means that "instance Functor ((->) r)" is meaningless? And if not - what sense does it has when it changes outermost function (container itself, not container value)?
I will try to convince you that fmap = (.) really is a thing that leaves a container's shape the same, but applies a function to all the elements in the container. But before we do that for (->), let's do it for some simpler types. Specifically, let's do it for types that are containers with a specific number of elements -- i.e., a container with exactly two elements will be TwoF, while one with no elements will be ZeroF. Like this:
data ZeroF a = ZeroF
data OneF a = OneF a
data TwoF a = TwoF a a
data ThreeF a = ThreeF a a a
What should the Functor instances for these look like? Well, the one for OneF looks exactly like in your question:
instance Functor OneF where
fmap f (OneF x) = OneF (f x)
The other ones look pretty similar -- just applying f more (or fewer) times to account for the fact that there are more (or fewer) elements. Here they all are, with some creative whitespace to highlight the similarities/pattern:
instance Functor ZeroF where fmap f (ZeroF ) = ZeroF
instance Functor OneF where fmap f (OneF x0 ) = OneF (f x0)
instance Functor TwoF where fmap f (TwoF x0 x1 ) = TwoF (f x0) (f x1)
instance Functor ThreeF where fmap f (ThreeF x0 x1 x2) = ThreeF (f x0) (f x1) (f x2)
Hopefully for now you agree that this definitely has the flavor of Functor instance that you described in your question: keep the shape of the container the same, and apply the given function f to each element contained within.
So those are containers with a given number of elements. Now, let's write accessors for these containers -- i.e. we want the equivalent of (!!) for lists, where given a number, we pull out that field from the container. Since there's zero elements in a ZeroF, we'll need an indexing type with zero values; while for ThreeF we need an indexing type with three values.
data Zero
data One = One0
data Two = Two0 | Two1
data Three = Three0 | Three1 | Three2
The indexing functions have types that look like this:
indexZero :: ZeroF a -> Zero -> a
indexOne :: OneF a -> One -> a
indexTwo :: TwoF a -> Two -> a
indexThree :: ThreeF a -> Three -> a
I won't implement them all -- they're pretty straightforward -- but here's one to give you the idea in case it's not immediately obvious.
indexTwo (TwoF x0 x1) Two0 = x0
indexTwo (TwoF x0 x1) Two1 = x1
It turns out that the indexing functions have an inverse -- if you give me a function which, when given an index, produces a value, then I can give you a container with those values in it. The types look like this:
tabulateZero :: (Zero -> a) -> ZeroF a
tabulateOne :: (One -> a) -> OneF a
tabulateTwo :: (Two -> a) -> TwoF a
tabulateThree :: (Three -> a) -> ThreeF a
(Do you see why this is the right type for an inverse? Note that, say, TwoF a -> Two -> a is the same type as TwoF a -> (Two -> a)!) Just to give you an idea of how these are implemented, in case it's not immediately obvious, we simply apply the indexing function to each index:
tabulateZero ix = ZeroF
tabulateOne ix = OneF (ix One0 )
tabulateTwo ix = TwoF (ix Two0 ) (ix Two1 )
tabulateThree ix = ThreeF (ix Three0) (ix Three1) (ix Three2)
It's not too hard to prove that tabulateX . indexX = id and indexX . tabulateX = id for each X, i.e. that tabulation really is the inverse of indexing.
Okay, but hold up now and take a look at what we've just done: we have turned a function (like Two -> a) into a container (like TwoF a), and vice versa. The types Two -> a and TwoF a are, morally speaking, exactly the same thing. So it seems reasonable to think we could implement fmap for Two -> a -- for example, just by converting to TwoF a and back as appropriate!
twomap :: (a -> b) -> (Two -> a) -> (Two -> b)
twomap f = indexTwo . fmap f . tabulateTwo
Let's visualize what that's doing. We'll start with an arbitrary indexing function:
\case Two0 -> x0; Two1 -> x1
Now we go through the process:
\case Two0 -> x0; Two1 -> x1
tabulateTwo
TwoF x0 x1
fmap f
TwoF (f x0) (f x1)
indexTwo
\case Two0 -> f x0; Two1 -> f x1
Since f gets applied in both branches, we could pull that out of the case:
f . (\case Two0 -> x0; Two1 -> x1)
That second term is exactly the indexing function we started out with. In other words, we have just determined another, simpler implementation for twomap:
twomap f ix = f . ix
If you work through similar reasoning for zeromap, onemap, and threemap, you'll discover they actually all have that same implementation! We can do this uniformly for all the various sizes of container just by going polymorphic; instead of having onemap for changing One -> a's, etc., let's have an xmap for changing x -> a's:
xmap :: (a -> b) -> (x -> a) -> (x -> b)
xmap f ix = f . ix
Of course, we don't have to name f and ix:
xmap = (.)
...and this is the Functor instance for (x -> _).
(->) isn't just syntax. It's an operator like any other, but at the type level instead of the term level. It has a kind Type -> Type -> Type, which means if you apply it to a single type, you get back not a type, but another "function" of kind Type -> Type.
Type -> Type is the kind of all functors, so it's reasonable to think the partially applied (->) operator might be a functor as well, which is what
instance Functor ((->) r) where
fmap = (.)
defines. That is, mapping a function over another function means to compose the two functions.
As a "container", think of a function (something of type r -> a) as containing all possible values of type a that you can get by applying the function to an argument of type r. fmap will apply a function to whatever the other function returns. (Or in theory, apply it to every value that the other could return.)
So the answer is: functions can be represent either as (a -> b) or as Map a b - for function with finite count of possible arguments these are literally two equivalent representations.
So instance Functor (Map r) is meaningful and it would be implemented just as instance Functor ((->) r) implemented already.
And the answer above is confirmed by the implementation of instance Functor ((,) r). Yes this is a bit different than Map r, but as close as possible.
P.S.
#chepner : I can't mark your answer as "best answer" because I don't understand (and almost don't agree) with one word in one sentense:
(->) isn't just syntax. It's an operator like any other
Function is not "like any other" operation (I used notion "construction") function is magical- or under-hood-compiler- construction, on which all other fuctions are based.
I need to write the Functor instances for the Flip datatype:
data K a b = K a
newtype Flip f a b = Flip (f b a) deriving (Eq, Show)
instance Functor (Flip K a) where
fmap=undefined
The solution I was given in class is:
instance Functor (Flip K a) where
fmap f (Flip (K b)) = Flip (K (f b))
I really don't understand what's going on here and I'm beginning to doubt my whole understanding of data types and functors. What I do understand is this (please correct me if any of this is wrong):
K is a data type that turns 2 parameters into a structure K a ( that only keeps the first parameter)
Flip is a datatype that turns 3 arguments into a structure with one
Because in fmap :: (a-> b) -> f a -> f b, f a has kind *, to write the Functor instance of Flip, we write it on the last type in Flip. Aka f and a are "constants" in a way, and we write the functor for the type b. I would write something like:
instance Functor (Flip f a) where
fmap f (Flip x y z) = fmap Flip x y (f z)
I know that that is completely wrong but I'm not sure why.
Also, why would we bring K into the Functor instance of Flip? Can someone explain thoroughly the process of coming up with this solution and why it is correct?
K is a data type that turns 2 parameters into a structure K a ( that only keeps the first parameter)
This isn't quite right. K a b is a data type formed using two parameters, but it's not really right to say that it "turns them into" anything. Instead, it's simply just stating to the world that there now exists a new type: K a b. "So what?" you might ask. Well, the second half of the data type defines how to make new values of this type. That part says, "You can make a new value of type K a b with this function I'll call K which has type a -> K a b." It's really important to recognize that there is a distinction between the type K and the constructor K.
So, it's not that K "only keeps the first parameter"—it's that the constructor K (which is a function) happens to not take any arguments of type b.
Flip is a datatype that turns 3 arguments into a structure with one
Just as above, this is not quite right. The Flip declaration states that there can be values of type Flip f a b, and the only way to make them is by using the constructor Flip that has type f b a -> Flip f a b.
In case you're wondering how I'm coming up with the type signatures for the constructors K and Flip, it's not actually mysterious, and you can double check by typing :t K or :t Flip into GHCi. These types are assigned based entirely on the right hand side of the data type declaration. Also, note that the type name and constructor don't have to be the same. For instance, consider this data type:
data Foo a = Bar Int a | Foo String | Baz a a
This declares a type Foo a with three constructors:
Bar :: Int -> a -> Foo a
Foo :: String -> Foo a
Baz :: a -> a -> Foo a
Basically, each of the types after the constructor name are the arguments, in order, to the constructor.
Because in fmap :: (a-> b) -> f a -> f b, f a has kind *, to write the Functor instance of Flip, we write it on the last type in Flip. Aka f and a are "constants" in a way, and we write the functor for the type b.
This is basically right! You could also say that f has kind * -> *. Since Flip has kind (* -> *) -> * -> * -> *, you need to provide it two type arguments (the first of kind * -> * and the second of kind *) to get it to the right kind. Those first two arguments become fixed ("constants" in a way) in the instance.
I would write something like: ... I know that that is completely wrong but I'm not sure why.
The reason your instance is completely wrong is that you've mixed up the type with the constructor. It doesn't make sense to put (Flip x y z) in the pattern position where you did because the constructor Flip only takes one argument—remember, it's type is Flip :: f b a -> Flip f a b! So you'd want to write something like:
instance Functor (Flip f a) where
fmap f (Flip fxa) = ...
Now, what do you fill in for the ...? You have a value fxa :: f x a, and you have a function f :: x -> y, and you need to produce a value of type f y a. Honestly, I don't know how to do that. After all, what is a value of typ f x a? We don't know what f is?!
Also, why would we bring K into the Functor instance of Flip? Can someone explain thoroughly the process of coming up with this solution and why it is correct?
We saw just above that we can't write the Functor instance for an arbitrary f, but what we can do is write it for a particular f. It turns out that K is just such a particular f that works. Let's try to make it work:
instance Functor (Flip K a) where
fmap f (Flip kxa) = ...
When f was arbitrary, we got stuck here, but now we know that kxa :: K x a. Remember that the only way to make a value of type K x a is using the constructor K. Therefore, this value kxa must have been made using that constructor, so we can break it apart as in: kxa ⩳ K x' where x' :: x. Let's go ahead and put that into our pattern:
fmap f (Flip (K x')) = ...
Now we can make progress! We need to produce a value of type Flip K a y. Hmm. The only way to produce a value of type Flip is using the Flip constructor, so let's start with that:
fmap f (Flip (K x')) = Flip ...
The Flip constructor at type Flip K a y takes a value of type K y a. The only way to produce one of those is with the K constructor, so let's add that:
fmap f (Flip (K x')) = Flip (K ...)
The K constructor at type K y a takes a value of type y, so we need to provide a value of type y here. We have a value x' :: x and a function f :: x -> y. Plugging the first into the second gives us the value we need:
fmap f (Flip (K x')) = Flip (K (f x'))
Just rename x' to b, and you have exactly the code your teacher provided.
DDub wrote in their answer:
You have a value fxa :: f x a, and you have a function f :: x -> y, and you need to produce a value of type f y a. Honestly, I don't know how to do that. After all, what is a value of type f x a? We don't know what f is?!
And I agree, but I woulld like to add a bit. Your teacher's idea as to how to deal with this is pretty cool (things like this K come in quite handy when you are trying to write down some counterexample, like here), and yet, I reckon we can make this code way broader. I use Data.Bifunctor.
So, what are Bifunctors? They are just what their name says: a * -> * -> * type (which we call bifunctors as well sometimes, yet they are not the same thing) which allows mapping over its both arguments (snippet from the source):
class Bifunctor p where
-- | Map over both arguments at the same time.
--
-- #'bimap' f g ≡ 'first' f '.' 'second' g#
bimap :: (a -> b) -> (c -> d) -> p a c -> p b d
bimap f g = first f . second g
{-# INLINE bimap #-}
-- | Map covariantly over the first argument.
--
-- #'first' f ≡ 'bimap' f 'id'#
first :: (a -> b) -> p a c -> p b c
first f = bimap f id
{-# INLINE first #-}
-- | Map covariantly over the second argument.
--
-- #'second' ≡ 'bimap' 'id'#
second :: (b -> c) -> p a b -> p a c
second = bimap id
{-# INLINE second #-}
So, here is how I would go about that:
instance Bifunctor f => Functor (Flip f a) where
fmap x2y (Flip fxa) = Flip (first x2y fxa)
Speaking of your teacher's code, it's a very nice idea, yet a more narrow one as K is a Bifunctor:
instance Bifunctor K where
bimap f _g (K a) = K (f a)
A lawful one:
bimap id id (K a) = K (id a) = id (K a)
As it says in the link above, having bimap only written down, that's the only law we need to worry about.
We just need to use sane and helpful naming, and suddenly it all becomes simple and clear (as opposed to torturous and contorted):
data K b a = MkK b -- the type (K b a) "is" just (b)
newtype Flip f a b = MkFlip (f b a) -- the type (Flip f a b) "is" (f b a)
deriving (Eq, Show)
instance Functor (Flip K a) where
-- fmap :: (b -> c) -> Flip K a b -> Flip K a c
fmap g (MkFlip (MkK b)) = MkFlip (MkK (g b))
-- MkK b :: K b a
-- MkFlip (_ :: K b a) :: Flip K a b
There's not even one question arising in our minds now looking at this, not one doubt we aren't able to immediately resolve.
Using same names for types and for data constructors while teaching, as well as using f both for "f"unction and "f"unctor, is pure abuse of the students.
Only when you've become fed up with all the Mks and don't feel they are helpful to you in any way, you can safely and easily throw them away, as experts usually do.
import Control.Applicative
main = print $ fmap (*2) (1,2)
produces (1,4). I would expect it it to produce (2,4) but instead the function is applied only to the second element of the tuple.
Update I've basically figured this out almost straight away. I'll post my own answer in a minute..
Let me answer this with a question: Which output do you expect for:
main = print $ fmap (*2) ("funny",2)
You can have something as you want (using data Pair a = Pair a a or so), but as (,) may have different types in their first and second argument, you are out of luck.
Pairs are, essentially, defined like this:
data (,) a b = (,) a b
The Functor class looks like this:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Since the types of function arguments and results must have kind * (i.e. they represent values rather than type functions that can be applied further or more exotic things), we must have a :: *, b :: *, and, most importantly for our purposes, f :: * -> *. Since (,) has kind * -> * -> *, it must be applied to a type of kind * to obtain a type suitable to be a Functor. Thus
instance Functor ((,) x) where
-- fmap :: (a -> b) -> (x,a) -> (x,b)
So there's actually no way to write a Functor instance doing anything else.
One useful class that offers more ways to work with pairs is Bifunctor, from Data.Bifunctor.
class Bifunctor f where
bimap :: (a -> b) -> (c -> d) -> f a c -> f b d
bimap f g = first f . second g
first :: (a -> b) -> f a y -> f b y
first f = bimap f id
second :: (c -> d) -> f x c -> f x d
second g = bimap id g
This lets you write things like the following (from Data.Bifunctor.Join):
newtype Join p a =
Join { runJoin :: p a a }
instance Bifunctor p => Functor (Join p) where
fmap f = Join . bimap f f . runJoin
Join (,) is then essentially the same as Pair, where
data Pair a = Pair a a
Of course, you can also just use the Bifunctor instance to work with pairs directly.
The Functor instance is actually from the GHC.Base module which is imported by Control.Applicative.
Trying to write the instance I want, I can see that it won't work, given the definition of tuples; the instance requires just one type parameter, while the 2-tuple has two.
A valid Functor instance would at least have to be on tuples, (a,a) that have the same type for each element, but you cannot do anything sneaky, like define the instance on:
type T2 a = (a,a)
because instance types aren't permitted to be synonyms.
The above restricted 2-tuple synonym is logically the same as the type:
data T2 a = T2 a a
which can have a Functor instance:
instance Functor T2 where
fmap f (T2 x y) = T2 (f x) (f y)
As Gabriel remarked in the comments, this can be useful for branching structures or concurrency.
Learn You a Haskell has an example about functors. I can read LYAH, and text, and figure out what is supposed to happen -- but I don't know enough to write something like this. I'm finding this problem often in Haskell.
instance Functor (Either a) where
fmap f (Right x) = Right (f x)
fmap f (Left x) = Left x
However, I'm confused.. Why doesn't this comple
instance Functor (Either a) where
fmap f (Right x) = Right (x)
fmap f (Left x) = Left (f x)
If f isn't being used in the top definition, then what else constrains x such that it can't satisfy Left
Here's the functor class:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Note that "f" by itself is a type constructor because it's applied to a type variable in the fmap line. Here are some examples to make this clear:
Type constructors:
IO
Maybe
Either String
Types:
IO Char
Maybe a
Either String String
"Maybe a" is a type with one type constructor (the "Maybe") and one type variable (the "a"). It's not something concrete yet, but it is usable in type signatures for polymorphic functions.
"Either" is a type constructor that takes two type arguments, so even after you apply one (e.g. Either String it's still a type constructor because it can take another type argument.
The point of this is: when you define a Functor instance, the type constructor f cannot change. This is because it's represented by the same variable, f, as both the argument and result of fmap. The only type that's allowed to change is the type that's applied to the f constructor.
When you write instance Functor (Either c), Either c is filled in for f everywhere in the declaration of fmap. This gives fmap the following type for this instance:
fmap :: (a -> b) -> (Either c) a -> (Either c) b
With the definition of Either, the only useful way to get this type is by applying the Right value to the function. Remember that "Either" has two possible values with possibly different types. Here the Left value has type 'c', so you can't apply it to the function (which expects an 'a')[1], and the result also wouldn't be correct because you'd be left with Either b a, which doesn't match the class definition.
After replacing "f" with "Either c" to get the above type signature for fmap with the "Either c" instance, writing the implementation is next. There are two cases to consider, the Left and the Right. The type signature tells us that the type of the Left side, "c", can't change. We also don't have any way to change the value because we don't know what type it actually is. All we can do is leave it alone:
fmap f (Left rval) = Left rval
For the Right side, the type signature says that we have to change from a value with type "a" to a value with type "b". The first argument is a function to do exactly that, so we use the function with the input value to get the new output. Putting the two together gives the full definition
instance Functor (Either c) where
fmap f (Right rval) = Right (f rval)
fmap f (Left lval) = Left lval
There's a more general principle at work here which is why writing a Functor instance that adjusts the Left side is impossible, at least with the Prelude definitions. Copying some code from above:
class Functor f where
fmap :: (a -> b) -> f a -> f b
instance Functor (Either c) where ...
Even though we have a type variable 'c' in the instance definition, we can't use it in any of the class methods because it's not mentioned in the class definition. So you can't write
leftMap :: (c -> d) -> Either c a -> Either d a
leftMap mapfunc (Left x) = Left (mapfunc x)
leftMap mapfunc (Right x) = Right x
instance Functor (Either c) where
--fmap :: (c -> d) -> Either c a -> Either d a
fmap = leftMap
The result of leftMap, and thus fmap, is now (Either d) a. The (Either c) has changed to an (Either d), but this isn't allowed because there's no way to express it in the Functor class. To express this, you'd need a class with two type variables, e.g.
class BiFunctor f where
lMap :: (a -> b) -> f a c -> f b c
rMap :: (c -> d) -> f a c -> f a d
biMap :: (a -> b) -> (c -> d) -> f a c -> f b d
In this class, since both the left and right type variables are in scope, it's possible to write methods that operate on either (or both) sides.
instance BiFunctor Either where
lMap = leftMap
rMap = rightMap --the same as the standard fmap definition
biMap fl fr e = rMap fr (lMap fl e)
Although in practice people usually just write "biMap" for the BiFunctor class and use "id" for the other function if a left or right mapping is necessary.
[1] More accurately, the Left value has type 'c', the function expects an 'a', but the type checker can't unify those types because the 'c' type isn't in scope in the class definition.
Left and Right aren't types, and Left x and Right y are of the same type. They are just constructors of Either. You may consider
Left :: c -> Either c d
Right :: d -> Either c d
You can have 2 fmap declarations because we know the Left's and the Right's are different values. It's just like
g :: Int -> Int
g 1 = 2
g 2 = 4
g n = n
Here we can't say 1 and 2 and n are different "types" just because pattern matching works.
The Functor class is defined such that
class Functor f where
fmap :: (a -> b) -> f a -> f b
Note that a and b are arbitrary types. For clarity, let's rename the a in your instance to c, and the function f to func.
instance Functor (Either c) where
fmap func (Right x) = Right (x)
fmap func (Left x) = Left (func x)
Assume your Either follows the default definition
data Either c d = Left c | Right d
then by your definition,
fmap func (Right x) = Right x
-- # (a -> b) -> f a f b
-- # f = Either c
this forces a = b, and
fmap func (Left x) = Left (func x)
-- # (a -> b) -> f a f b
-- # f = Either c
forces c = a = b. Both are not valid considering a, b and c are independent arbitrary types.
Ok so here's another very simple try at this.
You ask why this doesn't compile:
instance Functor (Either a) where
fmap f (Right x) = Right (x)
fmap f (Left x) = Left (f x)
So let's try to simplify the problem by trying to define the same function without putting it as part of a class instance declaration:
That gives us
foo f (Right x) = Right (x)
foo f (Left x) = Left (f x)
Which indeed does compile. ghci tells us the type signature:
*Main> :t foo
foo :: (t1 -> a) -> Either t1 t -> Either a t
We'll rename some of the variables to get something more uniform looking:
foo :: (a -> b) -> Either a c -> Either b c
That makes perfect sense. It takes a function and applies it to the Left of an Either.
But what's the signature for fmap?
*Main> :t fmap
fmap :: (Functor f) => (a -> b) -> f a -> f b
So let's substitute Either c for f in the fmap signature (I renamed Either a to Either c to keep our two different as from getting mixed up):
fmap :: (a -> b) -> Either c a -> Either c b
Do you see the problem? Your function is perfectly valid -- it just has a different type than what fmap for Either a must necessarily have.
This is a sort of beautiful thing about types. Given the signature for fmap, there is really only one meaningful implementation for fmap on Either a.
Sometimes, when we're lucky and careful, we can end up in similar situations -- given a type signature, the function almost writes itself.
Edit: trying to answer the questions below.
1) There's no "composition of two functions" going on. To get the type signature for fmap over Either a just go through the fmap function signature, and every place you see f, replace it with Either a. We would call that a "specialization" of the type signature of fmap. Which is to say, it is strictly less general than the normal type of fmap -- anyplace that requires a function of the more specialized type, you can pass in something of the general type with no problems.
2) Your function for mapping over the left side (which I named "foo" in the above examples) is just fine. It works fine, it does what you want. You just can't name it fmap and use it in a Functor instance. Personally, I'd name it something like onLeft or mapLeft.
All the following can be ignored/is for information, but not a suggestion for future reading in the near future/actual use:
If one wants to get very technical, because you can map over both the left and the right side (although you can only declare Functor for the latter), Either is not only a Functor, but a Bifunctor. This is provided in, e.g., ekmett's Category-Extras library ( see http://hackage.haskell.org/packages/archive/category-extras/0.44.4/doc/html/Control-Bifunctor.html).
There's lots of cool stuff involving calculating with programs, and "origami programming" that uses bifunctors more rigorously. You can read about it here: http://lambda-the-ultimate.org/node/1360. But, you probably don't want to, at least until you're much more familiar with Haskell. It is computer-sciency, mathy, researchy, and very cool, but not necessary at all to understand idiomatic Haskell programming.
While I will eventually cleave to your format, I'm going to start with something in a slightly different format, as I think it will make my explanation clearer.
Let's consider a different datatype
data Choice a = Default Integer | Chosen a
-- This corresponds to your top, working, instance.
instance Functor Choice where
fmap f (Default i) = Default i
fmap f (Chosen a) = Chosen (f a)
It should be clear why this instance works. However, what about the following:
-- Broken!
instance Functor Choice where
fmap f (Default i) = Default (f i)
fmap f (Chosen a) = Chosen a
You should be able to see why this doesn't work. The type of fmap is Functor f => (a -> b) -> f a -> f b; in this context, it's (a -> b) -> Choice a -> Choice b. Thus, the f argument has the type a -> b. However, in the second (failed) instance declaration, you write f i. We know, because of the datatype declaration, that i must be an Integer, so we can't apply f to it. Similarly, since a has type a, Chosen a will have type Chosen a, not type Chosen b. Thus, the Functor instance on the bottom can't work.
Well, your top instance for Either works because, like in the Choice example, it obeys the types. Let's look at it, with a few renamings:
instance Functor (Either c) where
fmap f (Left c) = Left c
fmap f (Right a) = Right (f a)
This instance declaration doesn't declare an instance of Functor for Either—it can't. Something which is an instance of Functor must take one type parameter. Thus, Int can't be a functor, since Int takes no type parameters, but [] and Maybe can be, since [a] and Maybe a are complete types. Either, however, takes two type parameters: Either a b. Thus, what this instance does is declare that Either c is a functor for any possible c. That c is fixed for the duration of the instance declaration. So let's go through and add types (this is not legal syntax!):
instance Functor (Either c) where
fmap :: forall a b. (a -> b) -> (Either c) a -> (Either c) b
fmap f (Left (c :: c)) = Left c
fmap f (Right (a :: a)) = Right (f a :: b)
Since f has type a -> b, but c's type is fixed at c, we can't possibly write Left (f c); and even if we could, we want the c to be left alone, so that we can return an (Either c) b. Similarly, we must apply f to a in order to get something of type b.
This is also why your bottom instance doesn't work: you have a function which needs to work for any type being applied only to the fixed type c, and you leave the type you need to transform alone. Let's look at it, again with type signatures added:
instance Functor (Either c) where
fmap :: forall a b. (a -> b) -> (Either c) a -> (Either c) b
fmap f (Left (c :: c)) = Left (f c)
fmap f (Right (a :: a)) = Right a
Here, your first part of the function definition attempts to apply a function f :: a -> b to something of the fixed type c, which cannot work, so this already fails. But let's look at what type this generates. In this case, we'd expect that (somehow) f c would have the type b, and a would have the type a. In that case, we're returning a value of type Either b a, which is still not allowed.
Basically, the problem stems from this. First, note that f is the same in between the two function definition clauses, so it can't change between lines. Second, note that we are fixing c, and declaring an instance for that c. This is true for any c, but we only look at one at a time. Finally, because of this, Left's argument is not parametrized by the type that f expects; it's guaranteed to have some fixed type c. This means that (a) you can't apply f to it, and (b) you must apply it to Right's argument, since otherwise you won't change the type you're expected to change.
(Edit to try to answer the question better)
The definition of Either is:
data Either a b = Left a | Right b
So "Either" takes two type arguments. By the way, technically "Either" is not actually a type but a type constructor; it takes type arguments to create a type.
The definition of Functor is:
class Functor f where
fmap :: (p -> q) -> f p -> f q
So in this class definition any type "f" that is an instance of Functor must take a type argument. This isn't declared; it is inferred from the "f p" and "f q"; since "f" is being given a type parameter here it must be a type that takes one.
(Note: the original definition used "a" and "b" instead of "p" and "q". I'm using different letters to keep things distinct from "Either a b" when I get to that later)
In most cases "f" is a container type like a list or a tree. So for instance you have
data Tree a = ...
instance Functor Tree where
fmap func_a2b tree_of_a = ... -- tree of b.
However "Either" takes two type parameters, so how can we fit it into this scheme? The answer is that types can have partial application just like functions. In the same way as
I can declare a function
foo x y = ...
and then say "foo 2" in order to get a new function that expects the second argument, so I can say "Either a" to get a new type that expects the second type argument.
Now look at the original instance:
instance Functor (Either a) where ....
So here "Either a" is a type constructor that expects one more argument, just like Functor expects of its instances. So the type of "fmap" for "Either a" will be
fmap :: (p -> q) -> Either a p -> Either a q
So now in the "where" clause you have to give a definition of "fmap" that has this type. The first one you quote has this type because the second type parameter is used for the "Right" constructor, and that is the one that the function is applied to. The second one won't work, because it would have the type
fmap :: (p -> q) -> Either p a -> Either q a
And that is not what the Functor class says its going to be.
Belive it or not, this isn't magic. It all has to do with the type Either a b not being the same type as Either b a. Here is the definition of Either from Prelude
data Either a b = Left a | Right b
... Notice How the type variable a comes first, then b, and also notice that we only include a in the declaration of the Either Functor:
instance Functor (Either a) where
fmap f (Right x) = Right (f x)
fmap f (Left x) = Left x
Now lets look at the definition of the Maybe Functor
instance Functor Maybe where
fmap = map
Here there is no type variable, Although Maybe takes one type parameter (like Maybe Int). What I am trying to get to is that types aren't functors, type constructors are functors (functors have kind *->*).
So let f :: b -> c, in the version of the Either Functor that works, the x from (Left x) is of type a, which is fine since it's (Either a) that is a functor, the x in (Right x) is of Type b so (Right x) is of type ((Either a) b), and (Right (f x)) is of type ((Either a) c), therefore fmap is of type (b->c) -> ((Either a) b) -> ((Either a) c), as required.
In your version that failed, we have that x in (Right (x)) is not of type a, but of type b, So (Right (x)) is not of type ((Either a) c) which doesn't fit with the type of fmap.
so to sum it up: the fmap that works comes out : (b -> c) -> (Either a) b -> (Either a) c,
but the one that doesn't work comes out: (b -> c) -> (Either b) a -> (Either c) a and thats not the right type for fmap.
Hopefully, this will help...
First, though, some background:
1) Functor needs a "type constructor", a (well, not a type per se,...) type that "needs" another regular type given to it to form a "full type", just like a generic in Java/C++.
So, for example, List is a Functor (it is, by the way), or Array, because (among other things) the full type isn't just List, but List<A>. So, :
A Functor takes a "type constructor", an incomplete type.
2) Either is a constructor type that Haskell folks (read: Edward Kmett, and other well-math-endowed all-stars) call a bifunctor. It needs two types given to it to be complete. For example, a full use of Either is: Either Integer String which means (yeah, yeah, "duh!") it's either a (Left) Integer, or a (Right) String. So, this means Either Integer is an incomplete type that is either a Left Integer or a Right...b when you
decide what that "b" is supposed to be.
Now, for the fun part!
The top stuff works because, fmap uses some type constructor, and uses it with an a -> b function to make a similar function from f a to f b - the hands-down favorite example for this in Haskell is the one for lists, AKA map :: (a -> b) -> ([a] -> [b]), where the Functor is the [ ] part. Now, using something like Either a (let's go ahead and use Either Integer from earlier), fmap's type signature looks like this:
fmap :: (a -> b) -> (Either Integer a -> Either Integer b)
and the two examples (from the Top part) show what fmap does with representative values of that Either Integer a type, in order to get an Either Integer b-typed value.
Now, yours -bottom- doesn't work, because:
You have a function, f, that takes
as to bs.
Your Left type has to be type
Integer, and stay an Integer (or
type Float, and stay a Float, what
ever type is the left one of the
two types of the Either type
you're using).
Your Right type has to be of
whatever type that the function
takes ("a"), and go to the type
that the function makes ("b").
It has to do this (but your stuff doesn't - that's why it doesn't work), because that's the type that fmap needs to have. Specifically, you have these equations:
fmap f (Right x) = Right (x)
fmap f (Left x) = Left (f x)
Your equations give fmap the types:
fmap :: (a -> b) -> Either c d -> Either c d
fmap :: (a -> b) -> Either a d -> Either b d
which not only doesn't fit what fmap wants, but it isn't even consistent with each other!
I'm sorry I wrote half a book to wade through, but I hope that gives some insight to you.
Top works because fmap::(b -> c) -> Either a b -> Either a c and yours -bottom- doesn't work because that would require fmap::(a -> c) -> Either a b -> Either a c. But, it would work if you changed Either to
data Either' a b = Left' b | Right' a deriving (Eq, Show)
instance Functor (Either' a) where
fmap f (Right' x) = Right' (x)
fmap f (Left' x) = Left' (f x)
The instance you're trying to write, let's call it fmap2 for now, has the following type:
fmap2 :: (a -> b) -> Either a c -> Either b c
If you set the LANGUAGE pragma TypeOperators, GHC also accepts the type
fmap2 :: (a -> b) -> (a `Either` c) -> (b `Either` c)
In an ideal world this also would work:
fmap2 :: (a -> b) -> (`Either` c) a -> (`Either` c) b
which would give a Functor instance for (`Either` c) but the similarity between normal operators (and their sections) and type operators breaks down at this point (unless there's a GHC option I'm missing!)
In short: your understanding of functors is okay, but you're bitten by the lack of type-level lambdas.
Ehm... How about a few words about "kinds" ?..
That may simplify understanding, I guess.
Remember what is currying. I.e. in ghci:
Prelude> let f x y z = x + y * z
f :: (Num a) => a -> a -> a -> a
Prelude> :t f 1
f 1 :: (Num t) => t -> t -> t
Prelude> :t f 1 2
f 1 2 :: (Num t) => t -> t
Prelude> :t f 1 2 3
f 1 2 3 :: (Num t) => t
The same things you have with types. When you say Either kind of that type is * -> * -> * (i.e. it takes two types and produces type) and when you say Either a kind is * -> * and for Either a b it's * (btw Monad a and Functor a requires a to be of kind * -> *, as I remember).
So when you say type Either a that means type that is still incomplete (requires some "argument" to be bound), so fmap :: (a -> b) -> f a -> f b becomes fmap :: (a -> b) -> (Either c) a -> (Either c) b when f substituted by Either c.
I wrote something like this:
instance Functor (Either e) where
fmap _ (Left a) = Left a
fmap f (Right b) = Right (f b)
How do I do the same if I want fmap to change the value only if it's Left?
I mean, what syntax do I use to indicate that I use type Either _ b instead of Either a _?
I don't think there's a way to do that directly, unfortunately. With a function you can use flip to partially apply the second argument, but that doesn't work with type constructors like Either.
The simplest thing is probably wrapping it in a newtype:
newtype Mirror b a = Mirrored (Either a b)
instance Functor (Mirror e) where
fmap _ (Mirrored (Right a)) = Mirrored $ Right a
fmap f (Mirrored (Left b)) = Mirrored $ Left (f b)
Wrapping with newtype is also the standard way to create multiple instances for a single type, such as Sum and Product being instances of Monoid for numeric types. Otherwise, you can only have one instance per type.
Additionally, depending on what it is you want to do, another option is to ignore Functor and define your own type class like this:
class Bifunctor f where
bimap :: (a -> c) -> (b -> d) -> f a b -> f c d
instance Bifunctor Either where
bimap f _ (Left a) = Left $ f a
bimap _ g (Right b) = Right $ g b
instance Bifunctor (,) where
bimap f g (a, b) = (f a, g b)
Obviously, that class is twice as much fun as a regular Functor. Of course, you can't make a Monad instance out of that very easily.
You can't make the instance you are looking for directly.
In order for type inference and type classes to work, there is a certain positional bias to the ordering of arguments in the types. It has been shown that if we allowed arbitrary reordering of the arguments when instantiating type classes, that type inference becomes intractable.
You could use a Bifunctor class that can map over both arguments separately.
class Bifunctor f where
bimap :: (a -> b) -> (c -> d) -> f a c -> f b d
first :: (a -> b) -> f a c -> f b c
second :: (c -> d) -> f a c -> f a d
first f = bimap f id
second = bimap id
instance Bifunctor Either where
bimap f _ (Left a) = Left (f a)
bimap _ g (Right b) = Right (g b)
instance Bifunctor (,) where
bimap f g (a,b) = (f a, g b)
Or you could use a Flip combinator like:
newtype Flip f a b = Flip { unFlip :: f b a }
Generalized versions of both of these are available in category-extras on hackage. The latter even includes an instance for Functor (Flip Either a) because Either is a Bifunctor. (I should probably fix that to only require a PFunctor)
Ultimately, the order of arguments in a type constructor is important in determining what classes you can instantiate. You may need to use newtype wrappers (like Flip above) to put the arguments where they need to be to qualify to construct an instance of another typeclass. This is the price we pay for the inference of type class constraints.
You essentially need a 'flip' combinator on types. A newtype wrapper that inverts the order should work, as camccann says. Note that you can't use a 'type' synonym, as they may not be partially applied.