import Control.Applicative
import Control.Arrow
filter ((&&) <$> (>2) <*> (<7)) [1..10]
filter ((>2) &&& (<7) >>> uncurry (&&)) [1..10]
Both get the same result! However, it is VERY difficult for me to understand. Could someone here explain it in detail?
Let's start with the second, which is simpler. We have two mysterious operators here, with the following types:
(&&&) :: Arrow a => a b c -> a b c' -> a b (c, c')
(>>>) :: Category cat => cat a b -> cat b c -> cat a c
The Arrow and Category type classes are mostly about things that behave like functions, which of course includes functions themselves, and both instances here are just plain (->). So, rewriting the types to use that:
(&&&) :: (b -> c) -> (b -> c') -> (b -> (c, c'))
(>>>) :: (a -> b) -> (b -> c) -> (a -> c)
The second has a very similar type to (.), the familiar function composition operator; in fact, they're the same, just with arguments swapped. The first is more unfamiliar, but the types again tell you all you need to know--it takes two functions, both taking an argument of a common type, and produces a single function that gives the results from both combined into a tuple.
So, the expression (>2) &&& (<7) takes a single number and produces a pair of Bool values based on the comparisons. The result of this is then fed into uncurry (&&), which just takes a pair of Bools and ANDs them together. The resulting predicate is used to filter the list in the usual manner.
The first one is more cryptic. We have two mysterious operators, again, with the following types:
(<$>) :: Functor f => (a -> b) -> f a -> f b
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Observe that the second argument of (<$>) in this case is (>2), which has type (Ord a, Num a) => a -> Bool, while the type of (<$>)'s argument has type f a. How are these compatible?
The answer is that, just as we could substitute (->) for a and cat in the earlier type signatures, we can think of a -> Bool as (->) a Bool, and substitute ((->) a) for the f. So, rewriting the types, using ((->) t) instead to avoid clashing with the other type variable a:
(<$>) :: (a -> b) -> ((->) t) a -> ((->) t) b
(<*>) :: ((->) t) (a -> b) -> ((->) t) a -> ((->) t) b
Now, putting things back in normal infix form:
(<$>) :: (a -> b) -> (t -> a) -> (t -> b)
(<*>) :: (t -> (a -> b)) -> (t -> a) -> (t -> b)
The first turns out to be function composition, as you can observe from the types. The second is more complicated, but once more the types tell you what you need--it takes two functions with an argument of a common type, one producing a function, the other producing an argument to pass to the function. In other words, something like \f g x -> f x (g x). (This function also happens to be known as the S combinator in combinatory logic, a subject explored extensively by the logician Haskell Curry, whose name no doubt seems strangely familiar!)
The combination of (<$>) and (<*>) sort of "extends" what (<$>) alone does, which in this case means taking a function with two arguments, two functions with a common argument type, applying a single value to the latter two, then applying the first function to the two results. So ((&&) <$> (>2) <*> (<7)) x simplifies to (&&) ((>2) x) ((<7) x), or using normal infix style, x > 2 && x < 7. As before, the compound expression is used to filter the list in the usual manner.
Also, note that while both functions are obfuscated to some degree, once you get used to the operators used, they're actually quite readable. The first abstracts over a compound expression doing multiple things to a single argument, while the second is a generalized form of the standard "pipeline" style of stringing things together with function composition.
Personally I actually find the first one perfectly readable. But I don't expect most people to agree!
Related
I'm reading the second edition of Programming in Haskell and I've came across this sentence:
... there is only one way to make any given parameterised type into a functor, and hence any function with the same polymorphic type as fmap must be equal to fmap.
This doesn't seem right to me, though. I can see that there is only one valid definition of fmap for each Functor type, but surely I could define any number of functions with the type (a -> b) -> f a -> f b which aren't equivalent to each other?
Why is this the case? Or, is it just a mistake by the author?
You've misread what the author was saying.
...any function with the same polymorphic type as fmap...
This means, any function with the signature
Functor f => (a -> b) -> f a -> f b
must be equivalant to fmap. (Unless you permit bottom values, of course.)
That statement is true; it can be seen quite easily if you try to define such a function: because you know nothing about f except that it's a functor, the only way to obtain a non-⊥ f b value is by fmapping over the f a one.
What's a bit less clear cut is the logical implication in the quote:
there is only one way to make any given parameterised type into a functor, and hence any function with the same polymorphic type as fmap must be equal to fmap.
I think what the author means there is, because a Functor f => (a -> b) -> f a -> f b function must necessarily invoke fmap, and because fmap is always the only valid functor-mapping for a parameterised type, any Functor f => (a -> b) -> f a -> f b will indeed also in practice obey the functor laws, i.e. it will be the fmap.
I agree that the “hence” is a bit badly phrased, but in principle the quote is correct.
I think that the quote refers to this scenario. Assume we define a parameterized type:
data F a = .... -- whatever
for which we can write not only one, but two fmap implementations
fmap1 :: (a -> b) -> F a -> F b
fmap2 :: (a -> b) -> F a -> F b
satisfying the functor laws
fmap1 id = id
fmap1 (f . g) = fmap1 f . fmap1 g
fmap2 id = id
fmap2 (f . g) = fmap2 f . fmap2 g
Under these assumptions, we have that fmap1 = fmap2.
This is a theoretical consequence of the "free theorem" associated to fmap's polymorphic type (see the comment under Lemma 1).
Pragmatically, this ensures that the instance we obtain from deriving Functor is the only possible one.
It is a mistake. Here's some examples of functions with the same type as fmap for lists that are not fmap:
\f -> const []
\f -> concatMap (replicate 2 . f)
\f -> map (f . head) . chunksOf 2
\f -> map f . reverse
There are many more. In general, given a function ixf from list lengths to lists of numbers no bigger than that length (that is, valid indices into the list), we can build
maybeIt'sFmapLol :: (Int -> [Int]) -> (a -> b) -> [a] -> [b]
maybeIt'sFmapLol ixf elemf xs = [map elemf xs !! ix | ix <- ixf (length xs)]
Use suitably lazy variants of Int to handle infinite lists. A similar function schema can be cooked up for other container-like functors.
I looked at past discussion but could not see why any of the answers are actually correct.
Applicative
<*> :: f (a -> b) -> f a -> f b
Monad
(>>=) :: m a -> (a -> m b) -> m b
So if I get it right, the claim is that >>= cannot be written by only assuming the existence of <*>
Well, let's assume I have <*>.
And I want to create >>=.
So I have f a.
I have f (a -> b).
Now when you look at it, f (a -> b) can be written as (a -> b) (if something is a function of x, y , z - then it's also a function of x, y).
So from the existence of <*> we get (a -> b) -> f a -> f b which again can be written as ((a -> b) -> f a) -> f b, which can be written as (a -> f b).
So we have f a, we have (a -> f b), and we know that <*> results in f b, so we get:
f a -> (a -> f b) -> f b
which is a monad.
Actually, in a more intuitive language: when implementing <*>, I extract (a -> b) out of f(a -> b), I extract a out of f a, and then I apply (a -> b) on a and get b which I wrap with f to finally get f b.
So I do almost the same to create >>=. After applying (a -> b) on a and getting b, do one more step and wrap it with f, so I return f b, hence I know I have a function (a -> f b).
Now when you look at it, f(a -> b) can be written as (a -> b)
No. It can't. Your intuition is (dangerously) far off at this point. That's like saying a hammer is perfect for driving screws in, since it already works for a nail*. You can't simply drop f here, it's part of the type**.
Instead, let's get the facts straight. An Applicative has three associated functions, counting Functor's fmap:
fmap :: Functor f => (a -> b) -> f a -> f b
pure :: Applicative f => a -> f a
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Here's another fact: you can define bind ((>>=)) in terms of join and vice versa:
join :: Monad m => m (m a) -> m a
join k = k >>= id
(>>=) :: Monad m => m a -> (a -> m b) -> m b
k >>= f = join (fmap f k)
are the implementations of join and bind you provided here part of the Monad definition, or are only join and bind signatures part of the Monad definition? [...] So now I ask myself why would they bother.
Those aren't the official definitions of course, since they would never terminate. You have to define (>>=) for your type if you want to make it a a monad:
instance Monad YourType where
k >>= f = ...
Also, your join definition uses id which is not in the Monad interface, why is it mathematically legitimate?
First of all, id :: a -> a is defined for any type. Second, the mathematical definition of a monad is actually via join. So it's "more"*** legitimate. But most important of all, we can define the monad laws in terms of join (exercise).
If we created join via Applicative, we could also create bind. If we cannot create join via Applicative methods, neither can we derive bind. And join's type actually makes it obvious that we cannot derive it from Applicative:
join :: Monad m => m (m a) -> m a
-- ^ ^ ^
Join is able to drop one of the m layers. Let's check whether it's possible to do the same in the other methods:
fmap :: Functor f => (a -> b) -> f a -> f b
^ ^
0 here 1 here
pure :: Applicative f => a -> f a
^ | ^
0 here | 1 here
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
^ ^
1 here 1 here
The answer is no: none of the tools we're given by Applicative enables us collapse multiple m's into a single one. And that's also what is written in the Typeclassopedia right after the cited paragraph in the other question:
To see the increased power of Monad from a different point of view, let’s see what happens if we try to implement (>>=) in terms of fmap, pure, and (<*>). We are given a value x of type m a, and a function k of type a -> m b, so the only thing we can do is apply k to x. We can’t apply it directly, of course; we have to use fmap to lift it over the m. But what is the type of fmap k? Well, it’s m a -> m (m b). So after we apply it to x, we are left with something of type m (m b)—but now we are stuck; what we really want is an m b, but there’s no way to get there from here. We can add m’s using pure, but we have no way to collapse multiple m’s into one.
Note that join doesn't make it possible to get rid of m completely, that would be a total extraction, and—depending on some other functions—a feature of a comonad. Either way, make sure that you don't let your intuition go astray; trust and use the types.
* That comparison is a little bit bad, because you could actually try to dive a screw in with a hammer into a piece of wood. So think of a plastic screw, a rubber hammer and a carbon steel plate you want to drive the nail in. Good luck.
** Well, you can drop it, but then the type changes drastically.
*** Given that (>>=) and join are equivalent of power and any (>>=) using formula can be transformed to one only using join, they are of course both mathematical sound.
Now when you look at it, f (a -> b) can be written as (a -> b)
Everyone has already contributed explaining that this is not a fact. Let me prove it to you.
If we genuinely had what you state then we should be able to write a function
expose :: f (a -> b) -> (a -> b)
Moreover, for any concrete data type we like, call it F, we ought to be able to write
expose_F :: F (a -> b) -> (a -> b)
expose_F = expose
Let's worry only about writing expose_F since if we can show that expose_F cannot be written for some F then we have surely shown that expose cannot be written.
Let me provide us a test F. It will certainly be non-intuitive feeling as I'm intending to use it to break intuition, but I'm happy to confirm all day long that there is nothing funny at all about
data F a = F
Indeed, it is a Functor
instance Functor F where
fmap _ F = F
and an Applicative for that matter
instance Applicative F where
pure _ = F
F <*> F = F
even a Monad
instance Monad F where
return _ = F
F >>= _ = F
You can verify yourself that all of these typecheck. There's nothing wrong at all about F.
So what's just right about, F? Why did I choose it? Well F is interesting in that values of F a fail to contain anything related at all to a within them. Often people like to talk about data types (or Functors) as "containers" or "boxes". F forces us to remember that in a certain sense a box that's 0 inches deep is still a box. [0]
So surely we cannot write
expose_F :: F (a -> b) -> (a -> b)
There are a number of ways of proving this. The easiest is to appeal to my supposition that you, for instance, believe that there is no coerce function. But, if we had expose_F there would be!
coerce :: a -> b
coerce = expose_F F
More specifically, let me introduce another pathological type (which I again assure you is totally fine)
data Void
There are zero constructors of Void and we like to say therefore that Void has no members. It cannot be made to exist. But we can make one with expose_F.
void :: Void
void = expose_F F ()
In Haskell we're not technically sound enough to execute the above proofs. If you dislike the way I talk about impossibility then you can conjure up whatever types you like with a convenient infinite loop, casual call to
error "Madness rides the star-wind... claws and teeth sharpened on centuries of corpses... dripping death astride a bacchanale of bats from nigh-black ruins of buried temples of Belial..."
or perhaps an unassuming undefined. But these are all on the path of madness.
There is no expose_F and therefore there is no expose.
[0] And to be completely clear, thinking of data types as boxes at all is often flawed. Instances of Functor tend to be "box-like", but here's another interesting data type which is difficult to think of as a box
data Unbox a = Unbox (a -> Bool)
unless perhaps you consider Unbox a to be a box containing a Bool and a negative a or something like that. Perhaps an IOU a.
I have been reading this article and in one of their section it is stated:
Lenses compose backwards. Can't we make (.) behave like functions?
You're right, we could. We don't for various reasons, but the
intuition is right. Lenses should combine just like functions. One
thing that's important about that is id can either pre- or post-
compose with any lens without affecting it.
What does that mean by Lenses compose backwards ?
Also, what does this mean: Can't we make (.) behave like functions ?
(.) is a function and by using it with Lens does it make (.) to behave like something else ?
The Lens type:
type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t
For our illustrative purposes, we can stick to the less general simple lens type, Lens'. The right side then becomes:
forall f. Functor f => (a -> f a) -> s -> f s
Intuitively, (a -> f a) is an operation on a part of a structure of type s, which is promoted to an operation on the whole structure, (s -> f s). (The functor type constructor f is part of the trickery which allows lenses to generalize getters, setters and lots of other things. We do not need to worry about it for now.) In other words:
From the user point of view, a lens allows to, given a whole, focus on a part of it.
Implementation-wise, a lens is a function which takes a function of the part and results in a function of the whole.
(Note how, in the descriptions I just made, "part" and "whole" appear in different orders.)
Now, a lens is a function, and functions can be composed. As we know, (.) has type:
(.) :: (y -> z) -> (x -> y) -> (x -> z)
Let us make the involved types simple lenses (For the sake of clarity, I will drop the constraint and the forall). x becomes a -> f a, y becomes s -> f s and z becomes t -> f t. The specialized type of (.) would then be:
((s -> f s) -> t -> f t) -> ((a -> f a) -> s -> f s) -> ((a -> f a) -> t -> f t)
The lens we get as result has type (a -> f a) -> (t -> f t). So, a composed lens firstLens . secondLens takes an operation on the part focused by secondLens and makes it an operation on the whole structure firstLens aims at. That just happens to match the order in which OO-style field references are composed, which is opposite to the order in which vanilla Haskell record accessors are composed.
You could think of the Getter part of a lens as a function, which you can extract using view. For example, the lens way of writing the fst function is:
view _1 :: (a,b) -> a
Now observe:
view _1 . view _2 :: (c, (a,b)) -> a -- First take the second pair element, then the first
view (_1 . _2) :: ((b,a) ,c) -> a -- This is "backwards" (exactly the opposite order of the above)
For lenses, (.) doesn't behave like it would for functions. For functions, f . g means "first apply g, then f", but for lenses, it means first use the lens f, then use the lens g. Actually, the (.) function is the same for both types, but lens' types make it seem like it's backwards.
I've written code with the following pattern several times recently, and was wondering if there was a shorter way to write it.
foo :: IO String
foo = do
x <- getLine
putStrLn x >> return x
To make things a little cleaner, I wrote this function (though I'm not sure it's an appropriate name):
constM :: (Monad m) => (a -> m b) -> a -> m a
constM f a = f a >> return a
I can then make foo like this:
foo = getLine >>= constM putStrLn
Does a function/idiom like this already exist? And if not, what's a better name for my constM?
Well, let's consider the ways that something like this could be simplified. A non-monadic version would I guess look something like const' f a = const a (f a), which is clearly equivalent to flip const with a more specific type. With the monadic version, however, the result of f a can do arbitrary things to the non-parametric structure of the functor (i.e., what are often called "side effects"), including things that depend on the value of a. What this tells us is that, despite pretending like we're discarding the result of f a, we're actually doing nothing of the sort. Returning a unchanged as the parametric part of the functor is far less essential, and we could replace return with something else and still have a conceptually similar function.
So the first thing we can conclude is that it can be seen as a special case of a function like the following:
doBoth :: (Monad m) => (a -> m b) -> (a -> m c) -> a -> m c
doBoth f g a = f a >> g a
From here, there are two different ways to look for an underlying structure of some sort.
One perspective is to recognize the pattern of splitting a single argument among multiple functions, then recombining the results. This is the concept embodied by the Applicative/Monad instances for functions, like so:
doBoth :: (Monad m) => (a -> m b) -> (a -> m c) -> a -> m c
doBoth f g = (>>) <$> f <*> g
...or, if you prefer:
doBoth :: (Monad m) => (a -> m b) -> (a -> m c) -> a -> m c
doBoth = liftA2 (>>)
Of course, liftA2 is equivalent to liftM2 so you might wonder if lifting an operation on monads into another monad has something to do with monad transformers; in general the relationship there is awkward, but in this case it works easily, giving something like this:
doBoth :: (Monad m) => ReaderT a m b -> ReaderT a m c -> ReaderT a m c
doBoth = (>>)
...modulo appropriate wrapping and such, of course. To specialize back to your original version, the original use of return now needs to be something with type ReaderT a m a, which shouldn't be too hard to recognize as the ask function for reader monads.
The other perspective is to recognize that functions with types like (Monad m) => a -> m b can be composed directly, much like pure functions. The function (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c) gives a direct equivalent to function composition (.) :: (b -> c) -> (a -> b) -> (a -> c), or you can instead make use of Control.Category and the newtype wrapper Kleisli to work with the same thing in a generic way.
We still need to split the argument, however, so what we really need here is a "branching" composition, which Category alone doesn't have; by using Control.Arrow as well we get (&&&), letting us rewrite the function as follows:
doBoth :: (Monad m) => Kleisli m a b -> Kleisli m a c -> Kleisli m a (b, c)
doBoth f g = f &&& g
Since we don't care about the result of the first Kleisli arrow, only its side effects, we can discard that half of the tuple in the obvious way:
doBoth :: (Monad m) => Kleisli m a b -> Kleisli m a c -> Kleisli m a c
doBoth f g = f &&& g >>> arr snd
Which gets us back to the generic form. Specializing to your original, the return now becomes simply id:
constKleisli :: (Monad m) => Kleisli m a b -> Kleisli m a a
constKleisli f = f &&& id >>> arr snd
Since regular functions are also Arrows, the definition above works there as well if you generalize the type signature. However, it may be enlightening to expand the definition that results for pure functions and simplify as follows:
\f x -> (f &&& id >>> arr snd) x
\f x -> (snd . (\y -> (f y, id y))) x
\f x -> (\y -> snd (f y, y)) x
\f x -> (\y -> y) x
\f x -> x.
So we're back to flip const, as expected!
In short, your function is some variation on either (>>) or flip const, but in a way that relies on the differences--the former using both a ReaderT environment and the (>>) of the underlying monad, the latter using the implicit side-effects of the specific Arrow and the expectation that Arrow side effects happen in a particular order. Because of these details, there's not likely to be any generalization or simplification available. In some sense, the definition you're using is exactly as simple as it needs to be, which is why the alternate definitions I gave are longer and/or involve some amount of wrapping and unwrapping.
A function like this would be a natural addition to a "monad utility library" of some sort. While Control.Monad provides some combinators along those lines, it's far from exhaustive, and I could neither find nor recall any variation on this function in the standard libraries. I would not be at all surprised to find it in one or more utility libraries on hackage, however.
Having mostly dispensed with the question of existence, I can't really offer much guidance on naming beyond what you can take from the discussion above about related concepts.
As a final aside, note also that your function has no control flow choices based on the result of a monadic expression, since executing the expressions no matter what is the main goal. Having a computational structure independent of the parametric content (i.e., the stuff of type a in Monad m => m a) is usually a sign that you don't actually need a full Monad, and could get by with the more general notion of Applicative.
Hmm, I don't think constM is appropriate here.
map :: (a -> b) -> [a] -> [b]
mapM :: (Monad m) => (a -> m b) -> [a] -> m b
const :: b -> a -> b
So perhaps:
constM :: (Monad m) => b -> m a -> m b
constM b m = m >> return b
The function you are M-ing seems to be:
f :: (a -> b) -> a -> a
Which has no choice but to ignore its first argument. So this function does not have much to say purely.
I see it as a way to, hmm, observe a value with a side effect. observe, effect, sideEffect may be decent names. observe is my favorite, but maybe just because it is catchy, not because it is clear.
I don't really have a clue this exactly allready exists, but you see this a lot in parser-generators only with different names (for example to get the thing inside brackets) - there it's normaly some kind of operator (>>. and .>> in fparsec for example) for this. To really give a name I would maybe call it ignore?
There's interact:
http://hackage.haskell.org/packages/archive/haskell98/latest/doc/html/Prelude.html#v:interact
It's not quite what you're asking for, but it's similar.
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.