Say I define this function:
f = ($ 5)
Then I can apply it:
> f (\x -> x ^ 2)
25
Its type is:
:t f
f :: (Integer -> b) -> b
Which makes sense, it gets a function as an argument, and returns this function applied on the Integer 5.
Now I define this function:
g = flip f
I would expect this to not make sense, because f is a function of a single argument.
But, checking its type:
:t g
g :: b -> (Integer -> b -> c) -> c
So now g is a function of 2 arguments!
Applying it on some values:
> g [2, 4, 6] (\x y -> x:y)
[5,2,4,6]
What is going on here? What does flip ($ 5) really mean?
Follow the types:
($ 5) :: (Int -> a) -> a
flip :: (x -> y -> z) -> y -> x -> z
But since -> is right associative, the type x -> y -> z is equivalent to x -> (y -> z), so
flip :: (x -> (y -> z)) -> y -> x -> z
($ 5) :: (Int -> a) -> a
So x ~ (Int -> a) and (y -> z) ~ a, so substituting back in:
($ 5) :: (Int -> (y -> z)) -> (y -> z)
And simplified
($ 5) :: (Int -> y -> z) -> y -> z
So
flip ($ 5) :: y -> (Int -> y -> z) -> z
Which is equivalent to the type you're seeing (although I used Int instead of Integer to save typing).
What this is saying is that the type of ($ 5) gets specialized when passed to flip such that it takes a function of 2 arguments. It is perfectly valid to have something like ($ 5) const, where const :: a -> b -> a and ($ 5) const :: b -> Int. All ($ 5) is doing is applying 5 as an argument to a function, not necessarily the argument for a function. This is an example of partial application, where not all of the arguments are supplied to a function. That's why you can do things like map (subtract 1) [1, 2, 3].
An example of how to use flip ($ 5) is:
> flip ($ 5) 2 (**)
25.0
> flip ($ 5) 1 (-)
4.0
> let f x y = (x, y)
> flip ($ 5) 1 f
(5, 1)
The confusion arises from the loose concept of "number of arguments" for polymorphic functions. For instance, it is tempting to say that
f :: (Integer -> b) -> b
has one argument (a function). Yet, a more precise statement would be that f is a function with at least one argument. This is because the type variable b can be substituted with any type, thanks to polymorphism, giving rise to e.g.
f :: (Integer -> String) -> String
f :: (Integer -> Double) -> Double
...
which are indeed functions with one argument, but also to, e.g.
f :: (Integer -> (String -> Double)) -> (String -> Double)
where b has been replaced with a functional type String -> Double. This substitution makes a second argument "appear" in an apparently magic way: f can take a first argument (a binary function Integer -> String -> Double), and then a second one (a String), before returning a Double.
Note that this phenomenon always appears when a polymorphic type ends with ... -> b for some type variable b.
Let me conclude with a trivia: how "many" arguments has the identity function id? Well, intuitively I would say one, but let me check ...
> id (+) 3 4
7
> id id id id id (+) 3 4
7
... and perhaps many is a better answer.
the function flip flips the order of the arguments, so all of these are equal:
f (\x y -> x:y) [2, 4, 6]
[5,2,4,6]
flip f [2, 4, 6] (\x y -> x:y)
[5,2,4,6]
g [2, 4, 6] (\x y -> x:y)
[5,2,4,6]
Related
I'm currently doing a course in Haskell, and I have a lot of difficulty understanding the types of functions, particularly when there's function application or lambda expressions. Say for instance the following:
f = (\x -> \y -> \z -> [x (y z), y z])
or
g = \x -> \y -> \z -> x.y.z
I can sort of make some assumptions about the fact that x and y are functions, but I don't have a concrete method for figuring out the types of these functions.
Similarly for the following:
h = foldr (&&)
I try to guess and then check via :t in the interpreter, but I'm usually off by quite a bit.
Is there any particular method I can use to find the types of such functions?
You start by assigning type variables to the inputs and the result
f = (\x -> \y -> \z -> [x (y z), y z])
and conclude
f :: a -> b -> c -> d -- (A0)
-- or even (f is not needed)
\x -> \y -> \z -> [x (y z), y z] :: a -> b -> c -> d
that is
x :: a -- (1)
y :: b -- (2)
z :: c -- (3)
[x (y z), y z] :: d -- (4)
You can continue with (4) and conclude
that the type d is a list of d1s, i.e. d ~ [d1] (5)
f :: a -> b -> c -> [d1] -- (A1)
and that the values of the list are of type d1, i.e.
x (y z) :: d1 -- (6)
y z :: d1 -- (7)
From (6) you learn that
x :: e -> d1 -- (8)
y z :: e -- (9)
(1) and (8) unify, i.e. a ~ (e -> d1) and
f :: (e -> d1) -> b -> c -> [d1] -- (A2)
You play this game until you get bored and use GHCi to arrive at
f :: (d1 -> d1) -> (f -> d1) -> f -> [d1] -- (A3)
-- and renaming
f :: (a -> a) -> (b -> a) -> b -> [a] -- (A4)
If you want to learn more and read a paper you can start with Principal type-schemes for functional programs.
Prelude> :t h
h :: Foldable t => Bool -> t Bool -> Bool
Prelude> :t foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
Prelude> :t (&&)
(&&) :: Bool -> Bool -> Bool
Prelude>
By "plugging in" (&&) you have removed (a -> b -> b)
so you need to provide the rest to the function
b -> t a -> b
That is restricted by (&&) to be a bool as second param to it, and the second parameter is the t a which is also restricted to being a bool. since a and b needs to be the same type as in the (a->b->b) function.
Given
> foldr (+) 5 [1,2,3,4]
15
this second version
foldr (\x n -> x + n) 5 [1,2,3,4]
also returns 15. The first thing I don't understand about the second version is how foldr knows which variable is associated with the accumulator-seed 5 and which with the list variable's elements [1,2,3,4]. In the lambda calculus way, x would seem to be the dependent variable and n the independent variable. So if this
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr _ z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
is foldr and these
:type foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
:t +d foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
its type declarations, can I glean, deduce the answer to "which is dependent and which is independent" from the type declaration itself? It would seem both examples of foldr above must be doing this
(+) 1 ((+) 2 ((+) 3 ((+) 4 ((+) 5 0))))
I simply guessed the second, lambda function version above, but I don't really understand how it works, whereas the first version with (+) breaks down as shown directly above.
Another example would be this
length' = foldr (const (1+)) 0
where, again, const seems to know to "throw out" the incoming list elements and simply increment, starting with the initial accumulator value. This is the same as
length' = foldr (\_ acc -> 1 + acc) 0
where, again, Haskell knows which of foldr's second and third arguments -- accumulator and list -- to treat as the dependent and independent variable, seemingly by magic. But no, I'm sure the answer lies in the type declaration (which I can't decipher, hence, this post), as well as the lore of lambda calculus, of which I'm a beginner.
Update
I've found this
reverse = foldl (flip (:)) []
and then applying to a list
foldl (flip (:)) [] [1,2,3]
foldl (flip (:)) (1:[]) [2,3]
foldl (flip (:)) (2:1:[]) [3]
foldl (flip (:)) (3:2:1:[]) []
. . .
Here it's obvious that the order is "accumulator" and then list, and flip is flipping the first and second variables, then subjecting them to (:). Again, this
reverse = foldl (\acc x -> x : acc) []
foldl (\acc x -> x : acc) [] [1,2,3]
foldl (\acc x -> x : acc) (1:[]) [1,2,3]
. . .
seems also to rely on order, but in the example from further above
length' = foldr (\_ acc -> 1 + acc) 0
foldr (\_ acc -> 1 + acc) 0 [1,2,3]
how does it know 0 is the accumulator and is bound to acc and not the first (ghost) variable? So as I understand (the first five pages of) lambda calculus, any variable that is "lambda'd," e.g., \x is a dependent variable, and all other non-lambda'd variables are independent. Above, the \_ is associated with [1,2,3] and the acc, ostensibly the independent variable, is 0; hence, order is not dictating assignment. It's as if acc was some keyword that when used always binds to the accumulator, while x is always talking about the incoming list members.
Also, what is the "algebra" in the type definition where t a is transformed to [a]? Is this something from category theory? I see
Data.Foldable.toList :: t a -> [a]
in the Foldable definition. Is that all it is?
By "dependent" you most probably mean bound variable.
By "independent" you most probably mean free (i.e. not bound) variable.
There are no free variables in (\x n -> x + n). Both x and n appear to the left of the arrow, ->, so they are named parameters of this lambda function, bound inside its body, to the right of the arrow. Being bound means that each reference to n, say, in the function's body is replaced with the reference to the corresponding argument when this lambda function is indeed applied to its argument(s).
Similarly both _ and acc are bound in (\_ acc -> 1 + acc)'s body. The fact that the wildcard is used here, is immaterial. We could just have written _we_dont_care_ all the same.
The parameters in lambda function definition get "assigned" (also called "bound") the values of the arguments in an application, purely positionally. The first argument will be bound / assigned to the first parameter, the second argument - to the second parameter. Then the lambda function's body will be entered and further reduced according to the rules.
This can be seen a bit differently stating that actually in lambda calculus all functions have only one parameter, and multi-parameter functions are actually nested uni-parameter lambda functions; and that the application is left-associative i.e. nested to the left.
What this actually means is quite simply
(\ x n -> x + n) 5 0
=
(\ x -> (\ n -> x + n)) 5 0
=
((\ x -> (\ n -> x + n)) 5) 0
=
(\ n -> 5 + n) 0
=
5 + 0
As to how Haskell knows which is which from the type signatures, again, the type variables in the functional types are also positional, with first type variable corresponding to the type of the first expected argument, the second type variable to the second expected argument's type, and so on.
It is all purely positional.
Thus, as a matter of purely mechanical and careful substitution, since by the definition of foldr it holds that foldr g 0 [1,2,3] = g 1 (foldr g 0 [2,3]) = ... = g 1 (g 2 (g 3 0)), we have
foldr (\x n -> x + n) 0 [1,2,3]
=
(\x n -> x + n) 1 ( (\x n -> x + n) 2 ( (\x n -> x + n) 3 0 ))
=
(\x -> (\n -> x + n)) 1 ( (\x n -> x + n) 2 ( (\x n -> x + n) 3 0 ))
=
(\n -> 1 + n) ( (\x n -> x + n) 2 ( (\x n -> x + n) 3 0 ))
=
1 + ( (\x n -> x + n) 2 ( (\x n -> x + n) 3 0 ))
=
1 + ( (\x (\n -> x + n)) 2 ( (\x n -> x + n) 3 0 ))
=
1 + (\n -> 2 + n) ( (\x n -> x + n) 3 0 )
=
1 + (2 + (\x n -> x + n) 3 0 )
=
1 + (2 + (\x -> (\n -> x + n)) 3 0 )
=
1 + (2 + (\n -> 3 + n) 0 )
=
1 + (2 + ( 3 + 0))
In other words, there is absolutely no difference between (\x n -> x + n) and (+).
As for that t in foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b, what that means is that given a certain type T a, if instance Foldable T exists, then the type becomes foldr :: (a -> b -> b) -> b -> T a -> b, when it's used with a value of type T a.
One example is Maybe a and thus foldr (g :: a -> b -> b) (z :: b) :: Maybe a -> b.
Another example is [] a and thus foldr (g :: a -> b -> b) (z :: b) :: [a] -> b.
(edit:) So let's focus on lists. What does it mean for a function foo to have that type,
foo :: (a -> b -> b) -> b -> [a] -> b
? It means that it expects an argument of type a -> b -> b, i.e. a function, let's call it g, so that
foo :: (a -> b -> b) -> b -> [a] -> b
g :: a -> b -> b
-------------------------------------
foo g :: b -> [a] -> b
which is itself a function, expecting of some argument z of type b, so that
foo :: (a -> b -> b) -> b -> [a] -> b
g :: a -> b -> b
z :: b
-------------------------------------
foo g z :: [a] -> b
which is itself a function, expecting of some argument xs of type [a], so that
foo :: (a -> b -> b) -> b -> [a] -> b
g :: a -> b -> b
z :: b
xs :: [a]
-------------------------------------
foo g z xs :: b
And what could such function foo g z do, given a list, say, [x] (i.e. x :: a, [x] :: [a])?
foo g z [x] = b where
We need to produce a b value, but how? Well, g :: a -> b -> b produces a function b -> b given an value of type a. Wait, we have that!
f = g x -- f :: b -> b
and what does it help us? Well, we have z :: b, so
b = f z
And what if it's [] we're given? We don't have any as then at all, but we have a b type value, z -- so instead of the above we'd just define
b = z
And what if it's [x,y] we're given? We'll do the same f-building trick, twice:
f1 = g x -- f1 :: b -> b
f2 = g y -- f2 :: b -> b
and to produce b we have many options now: it's z! or maybe, it's f1 z!? or f2 z? But the most general thing we can do, making use of all the data we have access to, is
b = f1 (f2 z)
for a right-fold (...... or,
b = f2 (f1 z)
for a left).
And if we substitute and simplify, we get
foldr g z [] = z
foldr g z [x] = g x z -- = g x (foldr g z [])
foldr g z [x,y] = g x (g y z) -- = g x (foldr g z [y])
foldr g z [x,y,w] = g x (g y (g w z)) -- = g x (foldr g z [y,w])
A pattern emerges.
Etc., etc., etc.
A sidenote: b is a bad naming choice, as is usual in Haskell. r would be much much better -- a mnemonic for "recursive result".
Another mnemonic is the order of g's arguments: a -> r -> r suggests, nay dictates, that a list's element a comes as a first argument; r the recursive result comes second (the Result of Recursively processing the Rest of the input list -- recursively, thus in the same manner); and the overall result is then produced by this "step"-function, g.
And that's the essence of recursion: recursively process self-similar sub-part(s) of the input structure, and complete the processing by a simple single step:
a a
: `g`
[a] r
------------- -------------
[a] r
[a]
a [a]
--------
(x : xs) -> r
xs -> r
----------------------
( x , r ) -> r --- or, equivalently, x -> r -> r
Well, the foldr itself knows this by definition. It was defined in such way that its function argument accepts the accumulator as 2nd argument.
Just like when you write a div x y = ... function you are free to use y as dividend.
Maybe you got confused by the fact that foldr and foldl has swapped arguments in the accumulator funtions?
As Steven Leiva says here, a foldr (1) takes a list and replaces the cons operators (:) with the given function and (2) replaces the last empty list [] with the accumulator-seed, which is what the definition of foldr says it will do
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr _ z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
So de-sugared [1,2,3] is
(:) 1 ((:) 2 ((:) 3 []))
and the recursion is in effect replacing the (:) with f, and as we see in foldr f z (x:xs) = f x (foldr f z xs), the z seed value is going along for the ride until the base case where it is substituted for the [], fulfilling (1) and (2) above.
My first confusion was seeing this
foldr (\x n -> x + n) 0 [1,2,3]
and not understanding it would be expanded out, per definition above, to
(\x n -> x + n) 1 ((\x n -> x + n) 2 ((\x n -> x + n) 3 0 ))
Next, due to a weak understanding of how the actual beta reduction would progress, I didn't understand the second-to-third step below
(\x -> (\n -> x + n)) 1 ...
(\n -> 1 + n) ...
1 + ...
That second-to-third step is lambda calculus being bizarre all right, but is at the root of why (+) and (\x n -> x + n) are the same thing. I don't think it's pure lambda calculus addition, but it (verbosely) mimics addition in recursion. I probably need to jump back into lambda calculus to really grasp why (\n -> 1 + n) turns into 1 +
My worse mental block was thinking I was looking at some sort of eager evaluation inside the parentheses first
foldr ((\x n -> x + n) 0 [1,2,3,4])
where the three arguments to foldr would interact first, i.e., 0 would be bound to the x and the list member to the n
(\x n -> x + n) 0 [1,2,3,4]
0 + 1
. . . then I didn't know what to think. Totally wrong-headed, even though, as Will Ness points out above, beta reduction is positional in binding arguments to variables. But, of course, I left out the fact that Haskell currying means we follow the expansion of foldr first.
I still don't fully understand the type definition
foldr :: (a -> b -> b) -> b -> [a] -> b
other than to comment/guess that the first a and the [a] mean a is of the type of the members of the incoming list and that the (a -> b -> b) is a prelim-microcosm of what foldr will do, i.e., it will take an argument of the incoming list's type (in our case the elements of the list?) then another object of type b and produce an object b. So the seed argument is of type b and the whole process will finally produce something of type b, also the given function argument will take an a and ultimately give back an object b which actually might be of type a as well, and in fact is in the above example with integers... IOW, I don't really have a firm grasp of the type definition...
I ran into the following error in Haskell:
"Type signatures are only allowed in patterns with ScopedTypeVariables"
How should I re-use the defined variables. Thanks in advance
sum :: (Double -> Double) -> (Double -> Double) -> Int ->
(Double -> Double)
sum f g n = (\x -> helper f g n x)
where
helper :: (Double -> Double) -> (Double -> Double) -> Int -> Double ->
Double
|n == 0 = 0
|mod n 2 == 1 = f(x) + helper f g n-1 f(x)
|otherwise = g(x) + helper f g n-1 g(x)
This actually looks more like a syntactical error: you never defined a function body for helper, indeed you defined the signature of helper, followed by guards (the | ... part), but you should again state helper f g n x = ....
Furthermore I don't think it is useful to define helper here with a variable for f, an g, since these remain fixed throughout the recursion.
You can probably define the function as:
sumfg :: (Double -> Double) -> (Double -> Double) -> Int -> Double -> Double
sumfg f g = helperf
where helperf 0 _ = 0
helperf i x = let fx = f x in fx + helperg (i-1) fx
helperg 0 _ = 0
helperg i x = let gx = g x in gx + helperf (i-1) gx
We here defined two "helper" functions helperf and helperg, helperf will sum up f x with helperg (i-1) (f x), and helperg does the same, except that we use g instead of f. We here thus use mutual recursion to solve the problem.
We can however solve this problem more elegantly, by making use of scanl :: (b -> a -> b) -> b -> [a] -> [b], take :: Int -> [a] and sum :: Num a => [a] -> a:
sumfg :: Num a => (a -> a) -> (a -> a) -> Int -> a -> a
sumfg f g n x = sum (take n (scanl (flip ($)) (f x) (cycle [g, f])))
Here we thus make an infinite list of g and f, like [g, f, g, f, g, f, ...] with cycle [f, g]. We then use scanl (flip ($)) to each time apply the accumulator to one of the functions, and yield that element. We take the first n items of that list with take n, and finally we use sum to sum up these values.
For example:
Prelude> sumfg (2+) (3*) 5 1
91
Since (2+1) + (3*(2+1)) + (2+(3*(2+1))) + (3*(2+(3*(2+1)))) + (2+(3*(2+(3*(2+1))))) is 91.
We also generalized the signature: we can now work with any numerical type a, with the two functions f and g of type f, g :: a -> a.
At the moment I am learning Haskell, but I am struggling with the syntax of a few example. What do they exactly mean?
First: What is the difference between these two lambdas (-> \y and y)?
lambda1 = \x -> \y -> x + y
lambda2 = \x y -> x + y
Second: What does this mean? Is this a lambda that act as a "pseudo" list generator that generates a list with 3 elements. How can I create such a list?
lambda3 = [\x -> x+1, \x -> 2*x, \x -> x^2]
Third: What does the \_ exactly mean?
lambda4 = \_ -> (\x -> x+1, \() -> 'a')
lambda2 is syntactic sugar for lambda1. All of these are equivalent:
f = \x -> \y -> x + y
f = \x y -> x + y
f x = \y -> x + y
f x y = x + y
f x y = (+) x y
f x = (+) x
f = (+)
lambda3 is a list of unary functions on numbers. Each function has the type (Num a) => a -> a, so the list has type (Num a) => [a -> a]. You could produce a list of values from this with map or a list comprehension:
fs = [\x -> x+1, \x -> 2*x, \x -> x^2]
map (\f -> f 3) fs
map ($ 3) fs
[f 3 | f <- fs]
==
[4, 6, 9]
lambda4 uses pattern-matching syntax. For example, if you have a data type:
data Foo = Foo Int String
Then you can write a lambda that pattern-matches on it:
f = \ (Foo n s) -> concat (replicate n s)
f (Foo 3 "bar") == "barbarbar"
(But unlike case, there is no way to provide alternative patterns if Foo has multiple constructors.)
The _ pattern just says “accept a value and ignore it”, so lambda4 is a function that accepts an argument, ignores it, and returns a pair (2-tuple) of unary functions, the first of type (Num a) => a -> a and the second of type () -> Char, so its type is Num a => r -> (a -> a, () -> Char).
lambda4 = \_ -> (\x -> x+1, \() -> 'a')
lambda4 = \ignored -> (\x -> x+1, \() -> 'a')
(inc, getA) = lambda4 ()
inc 3 == 4
getA () == 'a'
Functions that ignore their arguments can be constructed with the const function, and operator sections ((+ 1)) are typically preferred over lambdas (\x -> x + 1), so you can also write the above as:
lambda4 = const ((+ 1), const 'a')
On your second question, lambda3 is just a bad variable name. this is a list of functions of type Num a => a -> a. You can verify that by typing the following in ghci:
:t [\x -> x+1, \x -> 2*x, \x -> x^2]
First: What is the difference between these two lambdas (-> \y and y)?
There is no difference. Both produce the same output for the same input, and since they're pure functions, you can be sure that they produce no external effects that you wouldn't see.
The difference lies in that the first lambda uses syntactic sugar for currying.
\x y -> x + y is equal to \x -> \y -> x + y. Now, don't you think it looks a lot like type signatures, such as foo :: Int -> Int -> Int ? ;)
It means that the function foo takes 2 Int and produces an Int.
Since I don't have a very precise answer for the 2nd…
Third: What does the \_ exactly mean?
It's a lambda function (\) to which is associated the _ variable. _ is used as a placeholder to say “I don't care about the content of this variable, I'm even going to give it a proper name”.
There is no -> y. The correct way to read this is
(\ x -> (\ y -> (x + y)))
As it happens, Haskell has "curried functions", which means that
\ x y -> (x + y)
just happens to be equivalent to the above.
lambda3 is a list which contains three elements. Each of those elements happens to be a function. Functions are data in Haskell; you can pass them as arguments, return them as results, stuff them into lists, etc.
lambda3 = [ (\x -> x+1) , (\x -> 2*x) , (\x -> x^2) ]
lambda4 = \_ -> (\x -> x+1, \() -> 'a')
The "_" character basically means "I don't care what this is; ignore it". You can use it anywhere you can use a pattern. For example,
foobar x _ z = x + y
is a 3-argument function that completely ignores argument #2. Read about pattern matching and this should become clear. (I.e., it's not to do with lambdas, it's to do with patterns.)
I'm trying to understand the result of
(*) . (+)
in Haskell. I know that the composition operator is just the standard composition of mathematical functions- so
(f . g) = f (g x)
But:
(*) . (+) :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a
I'm struggling to understand this type signature. I would have expected to be able to do things like:
((*) . (+)) 1 2 :: Num a => a -> a
= (* (+ 1 2))
What is the meaning of (*) . (+)'s type signature? I tried playing with it by something like (just matching up with its signature):
((*) . (+)) 1 (\x -> x + 1) 1
But that fails to compile. I'm trying to walk through the logical steps when composing these, but I'm not fully understanding how it's getting to this result (and what the result is).
I understand how you feel. I found function composition to be quite difficult to grasp at first too. What helped me grok the matter were type signatures. Consider:
(*) :: Num x => x -> x -> x
(+) :: Num y => y -> y -> y
(.) :: (b -> c) -> (a -> b) -> a -> c
Now when you write (*) . (+) it is actually the same as (.) (*) (+) (i.e. (*) is the first argument to (.) and (+) is the second argument to (.)):
(.) :: (b -> c) -> (a -> b) -> a -> c
|______| |______|
| |
(*) (+)
Hence the type signature of (*) (i.e. Num x => x -> x -> x) unifies with b -> c:
(*) :: Num x => x -> x -> x -- remember that `x -> x -> x`
| |____| -- is implicitly `x -> (x -> x)`
| |
b -> c
(.) (*) :: (a -> b) -> a -> c
| |
| |‾‾‾‾|
Num x => x x -> x
(.) (*) :: Num x => (a -> x) -> a -> x -> x
Hence the type signature of (+) (i.e. Num y => y -> y -> y) unifies with Num x => a -> x:
(+) :: Num y => y -> y -> y -- remember that `y -> y -> y`
| |____| -- is implicitly `y -> (y -> y)`
| |
Num x => a -> x
(.) (*) (+) :: Num x => a -> x -> x
| | |
| |‾‾‾‾| |‾‾‾‾|
Num y => y y -> y y -> y
(.) (*) (+) :: (Num (y -> y), Num y) => y -> (y -> y) -> y -> y
I hope that clarifies where the Num (y -> y) and Num y come from. You are left with a very weird function of the type (Num (y -> y), Num y) => y -> (y -> y) -> y -> y.
What makes it so weird is that it expects both y and y -> y to be instances of Num. It's understandable that y should be an instance of Num, but how y -> y? Making y -> y an instance of Num seems illogical. That can't be correct.
However, it makes sense when you look at what function composition actually does:
( f . g ) = \z -> f ( g z)
((*) . (+)) = \z -> (*) ((+) z)
So you have a function \z -> (*) ((+) z). Hence z must clearly be an instance of Num because (+) is applied to it. Thus the type of \z -> (*) ((+) z) is Num t => t -> ... where ... is the type of (*) ((+) z), which we will find out in a moment.
Therefore ((+) z) is of the type Num t => t -> t because it requires one more number. However, before it is applied to another number, (*) is applied to it.
Hence (*) expects ((+) z) to be an instance of Num, which is why t -> t is expected to be an instance of Num. Thus the ... is replaced by (t -> t) -> t -> t and the constraint Num (t -> t) is added, resulting in the type (Num (t -> t), Num t) => t -> (t -> t) -> t -> t.
The way you really want to combine (*) and (+) is using (.:):
(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
f .: g = \x y -> f (g x y)
Hence (*) .: (+) is the same as \x y -> (*) ((+) x y). Now two arguments are given to (+) ensuring that ((+) x y) is indeed just Num t => t and not Num t => t -> t.
Hence ((*) .: (+)) 2 3 5 is (*) ((+) 2 3) 5 which is (*) 5 5 which is 25, which I believe is what you want.
Note that f .: g can also be written as (f .) . g, and (.:) can also be defined as (.:) = (.) . (.). You can read more about it here:
What does (f .) . g mean in Haskell?
(*) and (+) both have the type signature Num a => a -> a -> a
Now, if you compose them, you get something funky.
(*) . (+) :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a
That's because (*) and (+) are expecting two 'arguments'.
(+) with one argument gets you a function. The . operator expects that function (the a -> a that you see).
Here's the meaning of (*) . (+)
x f y
(*) . (+) :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a
(*) . (+) maps x f y to ((x +) * f) y where f is a function from a to a that is ALSO a number.
The reason (*) expects a function is to make the types match while it expects two arguments, but that function has to be a number because (*) only works on numbers.
Really, this function makes no sense at all.
Some extensions first:
{-# LANGUAGE FlexibleContexts, FlexibleInstances, TypeSynonymInstances #-}
As the other answers show, your function is
weird :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a
weird x g = (x +) * g
But this function does have non-weird semantics.
There is a notion of difference lists. Accordingly, there is a notion of difference integers. I've seen them being used only in the dependently typed setting (e.g. here, but that's not the only case). The relevant part of the definition is
instance Enum DiffInt where
toEnum n = (n +)
fromEnum n = n 0
instance Num DiffInt where
n + m = n . m
n * m = foldr (+) id $ replicate (fromEnum n) m
This doesn't make much sense in Haskell, but can be useful with dependent types.
Now we can write
test :: DiffInt
test = toEnum 3 * toEnum 4
Or
test :: DiffInt
test = weird 3 (toEnum 4)
In both the cases fromEnum test == 12.
EDIT
It's possible to avoid the using of the TypeSynonymInstances extension:
{-# LANGUAGE FlexibleContexts, FlexibleInstances #-}
weird :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a
weird x g = (x +) * g
instance (Enum a, Num a) => Enum (a -> a) where
toEnum n = (toEnum n +)
fromEnum n = fromEnum $ n (toEnum 0)
instance (Enum a, Num a) => Num (a -> a) where
n + m = n . m
n * m = foldr (+) id $ replicate (fromEnum n) m
type DiffInt = Int -> Int
As before we can write
test' :: DiffInt
test' = weird 3 (toEnum 4)
But now we can also write
-- difference ints over difference ints
type DiffDiffInt = DiffInt -> DiffInt
test'' :: DiffDiffInt
test'' = weird (toEnum 3) (toEnum (toEnum 4))
And
main = print $ fromEnum $ fromEnum test'
prints 12.
EDIT2 Better links added.
Let:
m = (*)
a = (+)
then
(m.a) x = (m (a x)) = m (a x)
Now m expects a Num a as a parameter, on the other hand (a x) , i.e. (x +) is a unary function (a -> a) by definition of (+). I guess what happened is that GHC tries to unite these two types so that, if you have a type that is both a number and a unary function, m can take a number and a unary function and return a unary function, since they are considered the same type.
As #Syd pointed, this unification wouldn't make sense for any normal number types such as integers and floating point numbers.
There are good answers here, but let me quickly point out a few steps where you went wrong.
First, the correct definition of function composition is
(f . g) x = f (g x)
you omitted the x on the LHS. Next, you should remember that in Haskell h x y is the same as (h x) y. So, contrary to what you expected,
((*) . (+)) 1 2 = (((*) . (+)) 1) 2 = ((*) ((+) 1)) 2 = ((+) 1) * 2,
and now you see why that fails. Also,
((*) . (+)) 1 (\x -> x + 1) 1
does not work, because the constraint Num (Int -> Int) is not satisfied.