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)
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.
i am trying to understand why there is no type error for fmap (+) (1)
I do understand the following sequence:
Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
Prelude> :t (+)
(+) :: Num a => a -> a -> a # like a-> b with b = a -> a
Prelude> :t fmap (+)
fmap (+) :: (Functor f, Num a) => f a -> f (a -> a)
Prelude> :t fmap (+) (Just 1)
fmap (+) (Just 1) :: Num a => Maybe (a -> a) # f=Maybe is implied by the Just constructor
Prelude>
I expected a type error for fmap (+) (1) since there is no functor implied for (1), instead i get:
Prelude> :t (1)
(1) :: Num p => p
Prelude> :t (+)
(+) :: Num a => a -> a -> a
Prelude> :t fmap (+)
fmap (+) :: (Functor f, Num a) => f a -> f (a -> a)
Prelude> :t fmap (+) (1)
fmap (+) (1) :: (Functor f, Num a, Num (f a)) => f (a -> a) ## why ??
Prelude>
why is this ?
Similarly, i don't understand the type of fmap (+) id:
Prelude> :t fmap (+)
fmap (+) :: (Functor f, Num a) => f a -> f (a -> a)
Prelude> :t id
id :: a -> a
Prelude> :t fmap (+) id
fmap (+) id :: Num a => a -> a -> a ## why no error ?
Prelude>
Numerical literals can fit any type, provided it is a numeric type (in class Num).
GHC works under an open-world assumption, where even if a type does not belong to an instance right now, it might be in the future. This is because it is possible to write a new module and declare an instance there, and we want separate compilation.
For numeric types, this means that even if a type is not numeric right now, it might still be later on.
Suppose we write reverse 1. It looks wrong, since reverse expects a list, and 1 is not a list. Or is it? Even if [a] is not numeric now, it might be in the future, hence the type of reverse 1 is Num [a] => [a], and not a type error. Of course, under normal circumstances we won't have a Num [a] instance, but GHC can not assume that.
In your specific example, fmap wants an f a and you pass (1), which is the same as 1. Here, this numeric literal gets instantiated as Num (f a) => f a, so that type checking works.
fmap (+) (1) :: (Functor f, Num a, Num (f a)) => f (a -> a)
The above constraint Num (f a) is required to allow 1 to be interpreted in the type f a. Then f must be a functor because fmap requires it, and we must have Num a since (+) requires its argument to be numeric (the argument of (+) has type a and its result has type a -> a, where a must be numeric). We get f (a -> a) as a result again because of the return type of (+).
About fmap (+) id, this is simpler. Here id :: (->) a a, that is id :: f a where f = (->) a, which happens to be a functor. For this functor we have that fmap = (.), the functional composition operator. Hence, fmap (+) id means (.) (+) id, or (+) . id which is simply (+).
It's a simple consequence of the fact that number literals such as 1 are polymorphic - their type is (Num a) => a. In addition, there is no fixed list of numeric types, as Haskell allows you to make your own instances for any class - including Num - anywhere.
As a result, in applying this:
Prelude> :t fmap (+)
fmap (+) :: (Functor f, Num a) => f a -> f (a -> a)
to the literal 1, the type checker only needs to check if it's possible to unify the type of 1 with the input type f a. Given the polymorphic type of 1 as above, this is clearly possible provided there is an instance of Num available for f a - as then f a is a valid type for 1. And this explains the final type.
As for fmap (+) id, this is rather different. Here GHC needs to unify f a (for a functor f and numeric a) with a -> a, which results in the only possible choice for f, the "function functor" ((->) a) (where fmap is just composition). That is f b here means a -> b, and so f (a -> a) is a -> a -> a.
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
Currently reading through this article (which is pretty brilliant btw) and have a pretty simple question:
If I combine two functions like (+3) and (+2) with <$>, it seems to give me a new function that adds 5 to whatever is passed to it. If I do the same with the function composition operator, i.e. (+3) . (+2), would it not do the same thing? If that is true, is there a relationship here between these two operators such that they do the same thing in this simple case?
Is this even an intelligent question?
The functions fmap and <$> both have the same type:
> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
> :t (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
While the function . is
> :t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
So how is it possible that we can use fmap on a function and end up with .? I'm assuming you understand what a Functor is, so now you have to understand that "functions" are Functors. How so?
> :i (->)
data (->) a b -- Defined in `GHC.Prim'
instance Monad ((->) r) -- Defined in `GHC.Base'
instance Functor ((->) r) -- Defined in `GHC.Base'
instance Applicative ((->) a) -- Defined in `Control.Applicative'
Unlike Just, [] and Left, functions do not have a constructor that can be used. The Functor instance is applied to the syntax itself. We can see from :info in ghci that the syntactic arrow -> actually has an instance for functor.
What happens when we look at the type of +3?
> :t (+3)
(+3) :: Num a => a -> a
So the function (+3) is a Functor that accepts an a and returns an a. When we use fmap on a Functor and that also gives us back a Functor, we get nested Functors:
> :t fmap Just (Just 3)
fmap Just (Just 3) :: Num a => Maybe (Maybe a)
> :t fmap (replicate 5) [1,2,3]
fmap (replicate 5) [1,2,3] :: Num a => [[a]]
Likewise, when we apply fmap to two functions we get a function inside a function. The only difference is that they are fused together:
> :t (fmap (+3) (+2))
(fmap (+3) (+2)) :: Num a => a -> a
Why doesn't this result in the type (->) (->) a a? We have to remember that the first argument of fmap is a function (a -> b) and not necessarily a Functor. So when we do fmap g (Just 5) we can have any transformation. But whenever we perform fmap on a function we know that it will always result with a function inside of a function.
Thus fmap (+3) (+2) evaluates to something like this: \x -> (\x' -> x' + 3) (x + 2). That is a really roundabout way of writing (+3) . (+2).
> :t (fmap (+3) (+2))
(fmap (+3) (+2)) :: Num a => a -> a
> :t ((.) (+3) (+2))
((.) (+3) (+2)) :: Num a => a -> a
Normally to get around the concat problem (Maybe (Maybe a)) or [[a]] we actually need to rely on it being a Monad a, so that we can use a bind >>=. But functions (->) are a special case because we know that every single time we use fmap on a function, it will always give us a function in side of a function. This cannot be said for any other Functor except ->. As such we can be sure to always concatenate fmap on functions.
Therefore any f <$> g == f . g
Edit: A quick side note, if you do this fmap (+) (+0) you end up with a function inside a function. In this case the monadic bind (>>=) is actually needed to concatenate the functions:
> :t fmap (+) (+0)
fmap (+) (+0) :: Num a => a -> a -> a
> :t (+0) >>= (+)
(+0) >>= (+) :: Num b => b -> b
> let bindfunc = (+0) >>= (+)
> bindfunc 5
10
Which is not entirely unlike the behaviour we get when we do [1,2] >>= replicate 5:
> [1,2] >>= replicate 5
[1,1,1,1,1,2,2,2,2,2]
To find information about the Functor instance for functions, match up the types to find the relevant instance:
fmap :: (a -> b) -> f a -> f b
Then here a ~ Int, b ~ Int and f ~ (->) Int.
You can see all of the Functor instances that come with GHC here. (->) is just an infix type operator with two type parameters. We usually see it applied as Int -> Int, but this is equivalent to (->) Int Int.
There is a Functor instance for the (partially applied) type (->) r (for any type r::*).
Looking at the ((->) r) instance for Functor, we see that fmap = (.), so there is no practical difference between (+3) . (+2) and fmap (+3) (+2) (same as (+3) <$> (+2).
My question is very simple, as anyone beginning haskell I've been thinking about types, function composition and how to apply them. I started thinking about what the result of ((+) . (*)) might be.
Now obviously the solution to that question is open ghci and find out. So I did that and inspected the type:
λ> :t ((*) . (+))
((*) . (+)) :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a
Is this type possible? I'm struggling to understand what it might be or what it means?
apologies again for the simplistic question, everything I tried to put into the function failed. I'm simply trying to develop intuition for function composition with dyadic functions.
Unfortunately, GHC doesn't give a very good message for this. This is almost certainly not what you want. There is no instance for Num (a -> a) by default and implementing one, though it could be useful for some things, could lead to very unintuitive runtime errors. Even in this case, this function would not likely be very useful.
Let's look at type restricted (*) and (+) to simplify the situations and avoid the added complexity of the type class:
(*!) :: Int -> Int -> Int
(*!) = (*)
(+!) :: Int -> Int -> Int
(+!) = (+)
Now when we try
λ> :t (*!) . (+!)
<interactive>:1:8:
Couldn't match type ‘Int -> Int’ with ‘Int’
Expected type: Int -> Int
Actual type: Int -> Int -> Int
Probable cause: ‘(+!)’ is applied to too few arguments
In the second argument of ‘(.)’, namely ‘(+!)’
In the expression: (*!) . (+!)
which indicates that we aren't applying (+!) to enough arguments to be able to apply its result to (*!). If we expand the function composition we see this, which might make it more clear why it doesn't make sense:
(*!) . (+!) == \x -> (*!) ((+!) x) -- definition of (.)
== \x y -> (*!) ((+!) x) y -- eta-expansion
== \x y -> ((+!) x) *! y -- changed (*.) from prefix to infix
The left argument of (*!) is a function, which doesn't match the expected type of Int.
Composing with a function of two arguments
In order to do this, we need a function (b -> c) -> (a1 -> a2 -> b) -> a1 -> a2 -> c. Luckily, that's exactly what ((.) . (.)) is.
λ> :t ((.) . (.)) (*!) (+!)
((.) . (.)) (*!) (+!) :: Int -> Int -> Int -> Int
Some libraries provide this under the name (.:) (like this one). Sometimes people like to write it fmap . fmap (this generalizes to more than just normal function composition though).
It's a bit cryptic though and is usually avoided for that reason. It's almost always more clear to just explicitly write out the function.
that's a fun question....
First of all, I'll explain why you get the type you do.
Both (+) and (*) have type
Num a=>a->a->a
which basically means that they have two numbers as input, and output one number (as should be expected from add and multiply)
Function composition chains two functions of type (a->b) together (where, of course, the output of the first needs to be the same type as the input to the next).
(.)::(b->c)->(a->b)->a->c
So, at first glance, neither (+) or (*) seem to be of that type.... Except that in the world of Haskell, you can think of them as type
(+)::Num a=>a->(a->a)
which makes sense.... If you fill in one value of (+), you get a function that increments the value of a number by that amount, for instance
(+) 1 --evaluates to incrementByOne
where incrementByOne x = 1+x
So, you can chain the two together, but.....
Remember, the inputs of (*) need to be numbers! (because of the Num a=>)
Applying (.) to (+) and (*) yields your type
(Num (a -> a), Num a) => a -> (a -> a) -> a -> a
But, it has the strange constraint Num (a->a), which states that a function needs to be a number. This is basically not supposed to be done, but there is nothing in Haskell that would forbid it, so the compiler doesn't complain at this point. It is only when you try to use the function that it performs the check.
((+) . (*)) 1 (+ 1) 2
<interactive>:16:1:
No instance for (Num (a0 -> a0)) arising from a use of ‘it’
In a stmt of an interactive GHCi command: print it
The three inputs have the correct type, except for the constraint.... The interpreter is complaining here that the function (+ 1) is not a number.