Is there any explanation for why a lifted function, when applied to 2-tuple, only applies to the 2nd entry:
f x = x + 1
f <$> (2,2)
// -> (2,3)
On the other hand, tuples of any other length than 2 return errors.
Also
:t f <$>
returns an error. Is it possible to see the type of f <$> when acting on tuples?
Is there any explanation for that behaviour?
The Data.Tuple documentation is extremely brief and has no mention of how functions are lifted to tuples. Is there any source explaining it?
Update. A part of question about 2-tuples is related to this answer, where, however, the above question about multiple length tuples is not addressed.
One could (and arguably, GHC should) define a Functor instance for triples and larger tuples. To wit:
instance Functor ((,,) a b) where
fmap f (a, b, c) = (a, b, f c)
If this instance truly doesn't exist anywhere in base, I suspect that's mostly oversight, though I don't know the history well enough to say for sure. You can include this in any code where it seems useful, with the caveat that you should then absolutely put a fairly strict upper bound on the version of base in your *.cabal file, as this instance might reasonably be included in future versions of base. The PVP allows only the third component of the version to change in such a case, so include at least that many components in your upper bound!
Is there any explanation for why a lifted function, when applied to 2-tuple, only applies to the 2nd entry
Because tuples are heterogeneous which means that, in general, it would not make sense to try to apply a function of type b -> c to each component of a tuple of type (a, b).
If you want pairs of values of the same type, you can declare your own type Pair and then have the functor instance apply the function to each component.
data Pair a = Pair { fst :: a
, snd :: a }
instance Functor Pair where
fmap f (Pair fst snd) = Pair (f fst) (f snd)
Is it possible to see the type of f <$> when acting on tuples?
f <$> is a section (a partially applied infix operator). To get its type, you need to wrap it with parentheses like so:
:t (f <$>)
The Data.Tuple documentation is extremely brief and has no mention of how functions are lifted to tuples. Is there any source explaining it?
The combinator (<$>) (and (<*>)) are more general than just for tuples, you can find them in the Control.Applicative module.
All the other answers here seem pretty good, but I don't think anyone precisely answered your question yet.
I believe the reason 2-tuples (and no other tuples) are treated this way by default is because this allows them to be used in the same way as a Writer in a monadic context. (That is, ((,) a) and Writer are isomorphic.)
For example, given a function running in a Writer monad:
import Control.Monad.Writer
foo :: Int -> Writer [String] Int
foo n = do tell ["Running foo " ++ show n]
if (n <= 0) then do
tell ["We are done!"]
return 1
else do
rest <- foo (n-1)
return (n * rest)
you can rewrite it using the Monad instance of ((,) a):
bar :: Int -> ([String], Int)
bar n = do tell' ["Running bar " ++ show n]
if (n <= 0) then do
tell' ["We are done!"]
return 1
else do
rest <- bar (n-1)
return (n * rest)
where tell' str = (str, ())
and you'll find that these do the same thing:
runWriter (foo 5)
bar 5
up to the ordering of the pair.
The definition of tell' is only needed because ((,) a) hasn't been made an instance of MonadWriter for some reason.
(Edited to add:) While you could extend the definition to larger tuples, this doesn't really provide any additional generality over the definition for the pair: one component of the pair is a monoid to which you can write, and the other component is the underlying "value" in the monad context -- if you need more components for one or the other, you can just make the component a tuple itself.
In this answer, I will just expand a bit on one of the suggestions I made in a comment.
Is it possible to see the type of f <$> when acting on tuples?
(<$>) is a polymorphic function:
GHCi> :t (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
With GHC 8, you can use the TypeApplications extension to specialise polymorphic functions by supplying instantiations of some or all of their type variables (in this case, f, a and b, in that order):
GHCi> :set -XTypeApplications
GHCi> :t (<$>) #Maybe
(<$>) #Maybe :: (a -> b) -> Maybe a -> Maybe b
GHCi> :t (<$>) #Maybe #Int
(<$>) #Maybe #Int :: (Int -> b) -> Maybe Int -> Maybe b
GHCi> :t (<$>) #Maybe #_ #Bool
(<$>) #Maybe #_ #Bool :: (t -> Bool) -> Maybe t -> Maybe Bool
GHCi> :t (<$>) #_ #Int #Bool
(<$>) #_ #Int #Bool
:: Functor t => (Int -> Bool) -> t Int -> t Bool
GHCi> :t (<$>) #Maybe #Int #Bool
(<$>) #Maybe #Int #Bool :: (Int -> Bool) -> Maybe Int -> Maybe Bool
To use that with pairs, use the prefix syntax for the pair type constructor:
GHCi> :t (<$>) #((,) _)
(<$>) #((,) _) :: (a -> b) -> (t, a) -> (t, b)
GHCi> -- You can use the specialised function normally.
GHCi> -- That includes passing arguments to it.
GHCi> f x = x + 1
GHCi> :t (<$>) #((,) _) f
(<$>) #((,) _) f :: Num b => (t, b) -> (t, b)
The _ in ((,) _) leaves it unspecified what the type of the first element of the pair (which is the first argument of the (,) type constructor) should be. Every choice of it gives rise to a different Functor. You can be more specific if you wish:
GHCi> :t (<$>) #((,) String) f
(<$>) #((,) String) f :: Num b => (String, b) -> (String, b)
Lastly, it is worth having a look at what happens if you try that with 3-tuples:
GHCi> :t (<$>) #((,,) _ _) f
(<$>) #((,,) _ _) f
:: (Num b, Functor ((,,) t t1)) => (t, t1, b) -> (t, t1, b)
As Daniel Wagner discusses in his answer, base doesn't define a Functor instance for 3-tuples. In spite of that, the type checker cannot exclude the possibility that someone somewhere might have defined an instance specific for some choice of the first two type parameters, however pointless that would be. For that reason, the speculative constraint Functor ((,,) t t1) shows up in the type (no such thing happens with pairs because there is a Functor ((,) a) instance in base). As expected, that blows up as soon as we try to instantiate the first two type parameters:
GHCi> :t (<$>) #((,,) Bool String) f
<interactive>:1:1: error:
• Could not deduce (Functor ((,,) Bool String))
arising from a use of ‘<$>’
from the context: Num b
bound by the inferred type of
it :: Num b => (Bool, String, b) -> (Bool, String, b)
at <interactive>:1:1
• In the expression: (<$>) #((,,) Bool String) f
Related
If I compose two fmaps
Prelude> :t (fmap.fmap)
(fmap.fmap)
:: (Functor f, Functor f1) => (a -> b) -> f1 (f a) -> f1 (f b)
I get a function which applies a function to a value inside 2 nested leves of structure, f1 and f.
And I can use it—this works as I expected:
Prelude> (fmap.fmap) (+1) [[1,2]]
[[2,3]]
With inferred type as I expected (2 leves of structure around result)
Prelude> :t (fmap.fmap) (+1) [[1,2]]
(fmap.fmap) (+1) [[1,2]] :: Num b => [[b]]
The following does not work. I also expect this (because we can't apply sum to a single number):
Prelude> (fmap.fmap) sum [[1,2]]
<interactive>:39:2: error:
• Could not deduce (Num (t0 b))
from the context: (Num (t b), Num b, Foldable t)
bound by the inferred type for ‘it’:
(Num (t b), Num b, Foldable t) => [[b]]
at <interactive>:39:2-24
The type variable ‘t0’ is ambiguous
• In the ambiguity check for the inferred type for ‘it’
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
When checking the inferred type
it :: forall (t :: * -> *) b.
(Num (t b), Num b, Foldable t) =>
[[b]]
Prelude> :t (fmap.fmap) sum [[1,2]]
(fmap.fmap) sum [[1,2]] :: (Num (t b), Num b, Foldable t) => [[b]]
BUT! If I change one level of structure to a Maybe type:
Prelude> (fmap.fmap) sum Just [1,2]
Just 3
then it begins to work, but in my opinion breaking the type signature
(fmap.fmap) :: (Functor f, Functor f1) => (a -> b) -> f1 (f a) -> f1 (f b)
(because it applies the sum function inside the first level of structure, not the second as I expected).
I think problem in my undersanding how function application order evaluates here, because I find that with parentheses this works as expected inside two levels of structure with foldable list values (vs numbers in first exapmles):
Prelude> (fmap.fmap) sum (Just [[1,2],[2,3]])
Just [3,5]
But what happens here:
Prelude> (fmap.fmap) sum Just [1,2]
Just 3
Why is the first level of stucture skipped?
What is the order of function applications here?
How does Haskell infer the final type?
Prelude> :t (fmap.fmap) sum Just [1,2]
(fmap.fmap) sum Just [1,2] :: Num t => Maybe t
Why Maybe t and not Maybe List t as I understand (fmap.fmap) must determine f1 (f b) two levels of structure not one?
Let's compute, pretending that numeric literals are Ints for the sake of simplicity.
(fmap.fmap) sum Just [1,2]
= fmap (fmap sum) Just [1,2]
| | \ -- an additional argument applied to the result of fmap
| \ -- the value with a type of the form f a with f Functor
\ -- the function to fmap
Here, Just is a function [Int] -> Maybe [Int], so the first fmap operates on the functor f = (->) [Int], we have fmap = (.) because that's how it's defined in Functor ((->) [Int]).
= (.) (fmap sum) Just [1,2]
= (fmap sum) (Just [1,2])
Now, fmap f (Just x) = Just (f x) since that's how Functor Maybe is defined.
= Just (sum [1,2])
= Just 3
why first level of structure skipped?
It isn't. The first level is (->) [Int].
what is the order of function applications here?
The usual one. fmap.fmap is applied to sum. The result is applied to Just. The final result is applied to [1,2].
how does Haskell infer the final type?
It sees that Just is a "value wrapped inside the (->) [Int] functor", and uses that to instantiate the first fmap. The second fmap is instead used on the Maybe level since Just returns that.
What you have just discovered is that functions are themselves functors. That statement may sound a bit confusing, so let’s explore this a bit further. Let’s have a look at the function composition operator (.):
Prelude> :t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
But now let’s rewrite the type signature slightly:
(.) :: (b -> c) -> ((->) a b) -> ((->) a c)
Here, I’ve behaved as if the function composition arrow were a normal infix operator, and could be placed in front of what look like its ‘type parameters’ (which in fact it can be). And now we notice something interesting — (.) looks almost exactly like fmap! See:
(.) :: (b -> c) -> ((->) a b) -> ((->) a c)
fmap :: Functor f => (b -> c) -> f b -> f c
And in fact it’s possible to write a Functor instance for the partially applied function arrow (->) r (where ((->) r) a is the same as (r -> a)):
instance Functor ((->) r) where
fmap = (.)
-- type signature here would be:
-- fmap :: (a -> b) -> ((->) r) a -> ((->) r) b
-- that is:
-- fmap :: (a -> b) -> (r -> a) -> (r -> b)
So, if f and g are functions, then fmap f g = f . g.
Now, how does that relate to your question? Let’s have a look at the expression you’re confused about:
Prelude> (fmap.fmap) sum Just [1,2]
Just 3
Let’s go through this bit by bit. First, notice that this can be rewritten as: (fmap (fmap sum) Just) [1,2]. Now, fmap sum is a function — that means it’s a functor! So, using fmap = (.) for functions as I said above, this becomes: ((fmap sum) . Just) [1,2], that is fmap sum (Just [1,2]). And of course that simply evaluates to Just 3.
Thanx for answers, it cleans for me that Just not Just [1,2] goes as second argument to (fmap.fmap).
I want to write type inference as I understand in more details (correct me if I wrong)
We have expression:
(fmap.fmap) sum Just [1,2]
the type of (fmap.fmap) is
(a -> b) -> f1 (f a) -> f1 (f b)
this determine that it takes two next arguments - sum and Just and return function.
sum has type List int -> int (for simplicity int)
this implies that a = List int and b = int
Second argument Just has type a -> Maybe a or another words
(->) a (Maybe a) so f1 = (->) a and f = Maybe
this implies that f1 (f b) = (->) (List int) (Maybe int)
Or another words the result type of expression
(fmap.fmap) sum Just is List int -> Maybe int
So the result is function.
And finnaly we apply value [1,2] to this function and get value Just 3 as expected with infered types.
Reading Function application with $ in Learn You Haskell book I found example of applying $ to list of functions.
map ($ 3) [(4+), (10*), (^2), sqrt]
I wanted try similar thing and reduce example to applying to one function
fmap ($ 3) (4+)
But I am getting errors which I don't understand
• Non type-variable argument in the constraint: Num (a -> b)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a b. (Num (a -> b), Num a) => (a -> b) -> b
Could you help me understand why it works in the first case but it doesn't in the second? How can I achieve desired effect?
Thank you
You need map in the first example because you have a whole container full of functions, and each of them you want to apply to the number. In that example, you could indeed also replace map with fmap, which does work on any container (on any functor).
Prelude> fmap ($ 3) [(4+), (10*), (^2), sqrt] -- list functor
[7.0,30.0,9.0,1.7320508075688772]
Prelude> fmap ($ 3) (Just (4+)) -- `Maybe` functor
Just 7
Prelude> fmap ($ 3) (do y<-readLn; return (y+)) -- `IO` functor
> 100
103
However, (4+) by itself is not a function wrapped in any functor, it's just a function by itself. So, you don't really need any fmap:
Prelude> ($ 3) (4+)
7
Of course you could simplify that even further to 4+3...
If for some reason you do need to use fmap regardless†, you'd need it to operate in the identity functor:
Prelude> :m +Data.Functor.Identity
Prelude Data.Functor.Identity> fmap ($ 3) (Identity (4+))
Identity 7
The identity functor is a very boring container that just always contains exactly one element.
†That's not unrealistic BTW: in Haskell we like to keep code as generic as possible. You may have a function that is able to work with arbitrary functors (more typically, arbitrary monads, which are special functors) but may want to use it in the trivial context of just one element contained. Or, you may want to stack different monad functionalities as monad transformers; then you'll generally start with Identity as the “vanilla monad”.
I would say the main issue is that your (4 +) is not wrapped correctly inside a functor. If you inspect the type of fmap you'll get:
Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
In your first example, all the functions were wrapped in a list. Here if you change your (4 +) into [ (4 +) ], it will work.
As for the explanation about functor, you'll probably find more documentation online (or in the comment section :D Thanks for the feedback)
fmap applies a function to values found in some functorial value. In fmap ($ 3) [(4+), (10*), (^2), sqrt], the list is the functorial value, and the function ($ 3) is applied to its elements. As for fmap ($ 3) (4+), leftaroundabout correctly points out that:
However, (4+) by itself is not a function wrapped in any functor, it's just a function by itself.
In this case, there is a complementary way to look at it. (4+) is a functorial value; however, the functor isn't the one you need. Functions are functors, and, for the purposes of fmap, the values "found in them" are the results of the function:
GHCi> :set -XTypeApplications
GHCi> :t fmap #((->) _)
fmap #((->) _) :: (a -> b) -> (w -> a) -> w -> b
fmap for functions applies a function to the results of another function, which amounts to function composition. So this...
GHCi> fmap (4*) (2+) 1
12
... is the same as:
GHCi> ((4*) . (2+)) 1
12
In your case, we have:
GHCi> :t (4+)
(4+) :: Num a => a -> a
So fmap f (4+) will apply f to the Num a => a result of (4+). The type of ($ 3), though, is:
GHCi> :t ($ 3)
($ 3) :: Num a => (a -> b) -> b
And so fmap ($ 3) will expect a functorial value with functions to be possibly found in it:
GHCi> :t fmap ($ 3)
fmap ($ 3) :: (Num a, Functor f) => f (a -> b) -> f b
Putting it all together, we get:
GHCi> :t fmap ($ 3) (4+)
fmap ($ 3) (4+) :: (Num (a -> b), Num a) => (a -> b) -> b
The type error this will lead to has to do with the Num (a -> b) constraint. If there are functions to be found in (4+), then 4 itself must be a function. As 4 is a numeric literal, its type must be also an instance of Num. However, there is no Num instance for functions. Trying fmap ($ 3) (4+) leads to an error which mentions Num (a -> b). That should suggest something is off:
GHCi> fmap ($ 3) (4+)
<interactive>:33:1: error:
* Non type-variable argument in the constraint: Num (a -> b)
(Use FlexibleContexts to permit this)
* When checking the inferred type
it :: forall a b. (Num (a -> b), Num a) => (a -> b) -> b
The "Non-type variable argument" complaint, though, is a bit of a distraction, induced by numeric literals being polymorphic. We can get a more straightforward error either by enabling FlexibleContexts and then trying to use fmap ($ 3) (4+) (which will lead to Num a => a being specialised to Integer thanks to the defaulting rules)...
GHCi> :set -XFlexibleContexts
GHCi> fmap ($ 3) (4+) (2*)
<interactive>:39:1: error:
* No instance for (Num (Integer -> Integer))
arising from a use of `it'
(maybe you haven't applied a function to enough arguments?)
* In the first argument of `print', namely `it'
In a stmt of an interactive GHCi command: print it
... or by specialising the numeric type through a type annotation:
GHCi> fmap ($ 3) ((4 :: Integer)+)
<interactive>:42:13: error:
* Couldn't match type `Integer' with `Integer -> b'
Expected type: Integer -> Integer -> b
Actual type: Integer -> Integer
* In the second argument of `fmap', namely `((4 :: Integer) +)'
In the expression: fmap ($ 3) ((4 :: Integer) +)
In an equation for `it': it = fmap ($ 3) ((4 :: Integer) +)
* Relevant bindings include
it :: Integer -> b (bound at <interactive>:42:1)
I've just written a function (for Data.Sequence)
traverseWithIndex :: Applicative f => (Int -> a -> f b) -> Seq a -> f (Seq b)
which should obey
traverseWithIndex f = sequenceA . mapWithIndex f
Thankfully, this is a straightforward mechanical modification of the source of mapWithIndex, so I am quite confident it is correct. However, in more complex cases thorough testing would be required. I'm trying to write a QuickCheck property to test this simple one. Obviously, I can't try it out with every Applicative functor! When testing monoids, it makes good sense to test with the free monoid over (i.e., finite lists of) some type. So it seems sensible here to test with the free applicative functor over some functor. There are two difficulties:
How do I choose an appropriate base functor? I presumably want a nasty one that isn't applicative or traversable or anything, but such a thing seems likely hard to work with.
How do I compare the results? They'll have functions in them, so they have no Eq instance.
Here's a partial(?) solution. The main aspects we want to check are 1) obviously the same value is computed, and 2) the effects are performed in the same order. I think the following code is self-explanatory enough:
{-# LANGUAGE FlexibleInstances #-}
module Main where
import Control.Applicative
import Control.Applicative.Free
import Data.Foldable
import Data.Functor.Identity
import Test.QuickCheck
import Text.Show.Functions -- for Show instance for function types
data Fork a = F a | G a deriving (Eq, Show)
toIdentity :: Fork a -> Identity a
toIdentity (F a) = Identity a
toIdentity (G a) = Identity a
instance Functor Fork where
fmap f (F a) = F (f a)
fmap f (G a) = G (f a)
instance (Arbitrary a) => Arbitrary (Fork a) where
arbitrary = elements [F,G] <*> arbitrary
instance (Arbitrary a) => Arbitrary (Ap Fork a) where
arbitrary = oneof [Pure <$> arbitrary,
Ap <$> (arbitrary :: Gen (Fork Int)) <*> arbitrary]
effectOrder :: Ap Fork a -> [Fork ()]
effectOrder (Pure _) = []
effectOrder (Ap x f) = fmap (const ()) x : effectOrder f
value :: Ap Fork a -> a
value = runIdentity . runAp toIdentity
checkApplicative :: (Eq a) => Ap Fork a -> Ap Fork a -> Bool
checkApplicative x y = effectOrder x == effectOrder y && value x == value y
succeedingExample = quickCheck (\f x -> checkApplicative
(traverse (f :: Int -> Ap Fork Int) (x :: [Int]))
(sequenceA (fmap f x)))
-- note reverse
failingExample = quickCheck (\f x -> checkApplicative
(traverse (f :: Int -> Ap Fork Int) (reverse x :: [Int]))
(sequenceA (fmap f x)))
-- instance just for example, could make a more informative one
instance Show (Ap Fork Int) where show _ = "<Ap>"
-- values match ...
betterSucceedingExample = quickCheck (\x ->
value (sequenceA (x :: [Ap Fork Int]))
== value (fmap reverse (sequenceA (reverse x))))
-- but effects don't.
betterFailingExample = quickCheck (\x -> checkApplicative
(sequenceA (x :: [Ap Fork Int]))
(fmap reverse (sequenceA (reverse x))))
The output looks like:
*Main Text.Show.Functions> succeedingExample
+++ OK, passed 100 tests.
*Main Text.Show.Functions> failingExample
*** Failed! Falsifiable (after 3 tests and 2 shrinks):
<function>
[0,1]
*Main Text.Show.Functions> betterSucceedingExample
+++ OK, passed 100 tests.
*Main Text.Show.Functions> betterFailingExample
*** Failed! Falsifiable (after 10 tests and 1 shrink):
[<Ap>,<Ap>]
Obviously, I can't try it out with every Applicative functor!
I'm reminded of this blog post series, which I won't claim to fully understand:
http://comonad.com/reader/2012/abstracting-with-applicatives/
http://comonad.com/reader/2013/algebras-of-applicatives/
The lesson that I recall drawing from this is that nearly every applicative functor you see in the wild turns out to be the composition, product or (restricted) coproduct of simpler ones like these (not meant to be exhaustive):
Const
Identity
(->)
So while you can't try it out with every Applicative functor, there are inductive arguments that you might be able to exploit in QuickCheck properties to gain confidence that your function works for large inductively-defined families of functors. So for example you could test:
Your function works correctly for the "atomic" applicatives of your choice;
If your function works correctly for functors f and g, it works correctly for Compose f g, Product f g and Coproduct f g.
How do I compare the results? They'll have functions in them, so they have no Eq instance.
Well, I think you may have to look at QuickCheck testing of function equality. Last time I had to do something along those lines I went with Conal's checkers library, which has an EqProp class for "[t]ypes of values that can be tested for equality, perhaps through random sampling." This should give you an idea already—even if you don't have an Eq instance for functions, QuickCheck may be capable of proving that two functions are unequal. Critically, this instance exists:
instance (Show a, Arbitrary a, EqProp b) => EqProp (a -> b)
...and any type that has an Eq instance has a trivial EqProp instance where (=-=) = (==).
So that suggests, to my mind, using Coyoneda Something as the base functor, and figuring out how to plug together all the little functions.
I'm looking at the following function:
fmap :: (a -> b) -> f a -> f b
and I want to understand what the 'f' is, as in (f a or f b). The article I am reading describes it as a 'box' but what's the actual correct name for it? Is it just a type variable? I think I'm confusing it and thinking it's a function application - which is correct?
Your intuition that it is a kind of function application is correct, but they are not regular functions. Instead, this is application of type constructors on the type level.
Specifically, Functors must have kind (type-of-type) * -> * which means they take one type argument and produce a concrete type * such as, for example, [Int].
Examples of such type constructors include IO, Maybe, [], Either e and many others, and these specific examples all have valid Functor instances.
fmap (+1) [1,2,3] :: [] Int -- also known as [Int]
= [2,3,4]
fmap (+1) (Just 1) :: Maybe Int
= Just 2
fmap (+1) (Right 1) :: Either e Int
= Right 2
fmap (+1) (return 1) :: IO Int -- Uses Monad IO instance as well
"=" 2
It's a type variable, representing the particular functor you're working in. For example IO is a functor, so you can specialize fmap to
fmap :: (a -> b) -> IO a -> IO b
Similarly you could specialize it to lists:
fmap :: (a -> b) -> [a] -> [b]
Take a quick peek at the following interactive session in GHCi:
Prelude> import Control.Applicative
Prelude Control.Applicative> (+1) <$> [1,2]
[2,3]
Prelude Control.Applicative> (+1) <$> (1,2)
(1,3)
I guess there is a good reason for the behavior of <$> regarding pairs, but I wasn't able to find one so far, so:
Why is <$> (or fmap) defined to act only on the second member of a pair and not on both values?
<$> (aka fmap) is a member of the Functor class like so:
class Functor f where
fmap :: (a -> b) -> f a -> f b
So whatever f is must be a parameterised type with one type argument. Lists are one such type, when written in their prefix form [] ([] a is the same as [a]). So the instance for lists is:
instance Functor [] where
-- fmap :: (a -> b) -> [] a -> [] b
fmap = map
Pairs can also be written in prefix form: (,) a b is the same as (a, b). So let's consider what we do if we want a Functor instance involving pairs. We can't declare an instance Functor (,) because the pair constructor (,) takes two types -- and they can be different types! What we can do is declare an instance for (,) a -- that's a type that only needs one more type:
instance Functor ( (,) a ) where
-- fmap :: (b -> c) -> (,) a b -> (,) a c
fmap f (x, y) = (x, f y)
Hopefully you can see that the definition of fmap is the only sensible one we can give. The answer as to why the functor instance operates on the second item in a pair is that the type for the second item comes last in the list! We can't easily declare a functor instance that operates on the first item in a pair. Incidentally, this generalises to larger tuples, e.g. the quadruple (,,,) a b c d (aka (a, b, c, d)) can also have a Functor instance on the last item:
instance Functor ( (,,,) a b c) where
-- fmap :: (d -> e) -> (,,,) a b c d -> (,,,) a b c e
fmap f (p, q, r, s) = (p, q, r, f s)
Hope that helps explain it all!
Consider the definition of the Functor typeclass:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Obviously, f has kind * -> *. So you can only declare instances for a datatype, which has kind * -> *. What you can do, is doing some stuff like this:
instance Functor (,) where
fmap :: (a -> b) -> (,) a -> (,) b
This would work on partitial applicated tuples and is really unhandy. So one defined the instance like this:
instance Functor ((,) a) where
fmap :: (b -> c) -> (,) a b -> (,) a c
fmap f (x,y) = (x,f y)
In a nutshell: It is not possible in plain Haskell 98 (although I believe tht there's a syntax extension for this) to define an instance as
What you can do, is defining your own tuple:
data T a = T a a
instance Functor T where
fmap f (T a b) = T (f a) (f b)
Then you can do whatever you like. You see, because the kind is * -> * instead of * -> * -> *, anything's okay.
I guess, a tuple doesn't need to be homogeneous, I mean both types can be different. If you want a homogeneous tuple you can use a list and then fmap will work.
How would you expect (+1) ("Hello", 2) to work ?
Prelude> import Control.Applicative
Prelude Control.Applicative> (+1) <$> ("hello",2)
("hello",3)
That's just work, but there is not special behavior when both type are same.
By the way I don't know why the second value is not used rather than the first one, but anyway you can only use one value.