I am trying to define a function to find the absolute difference of two numbers, such that both
absoluteDifference 2 5
absoluteDifference 5 2
return 3.
Here is my best effort so far:
absoluteDifference :: Num a => a -> a -> a
absoluteDifference = abs . (-)
In my head, this applies abs to the result of subtracting two numbers. However, this gives me the error
* Could not deduce (Num (a -> a)) arising from a use of `abs'
(maybe you haven't applied a function to enough arguments?)
from the context: Num a
bound by the type signature for:
absoluteDifference :: Num a => a -> a -> a
at C:\Users\Adam\dev\daily-programmer\e311\e311.hs:3:1-42
* In the first argument of `(.)', namely `abs'
In the expression: abs . (-)
In an equation for `absoluteDifference':
absoluteDifference = abs . (-)
Which I don't understand. I could trivially implement the function as
absoluteDifference a b = abs $ a - b
but I want to know how to compose the functions.
The info for (.)
Prelude> :i (.)
(.) :: (b -> c) -> (a -> b) -> a -> c -- Defined in ‘GHC.Base’
shows that it accepts functions with types a -> b
but (-) has the type
Prelude> :i (-)
class Num a where
...
(-) :: a -> a -> a
...
-- Defined in ‘GHC.Num’
infixl 6 -
so, it is possible to define another composition operator that accepts functions having the above type, and then they can be composed.
of' :: (a -> a) -> (a -> a -> a) -> a -> a -> a
of' f g a b = f (g a b)
abdiff = abs `of'` (-)
abdiff 1 10
9
note: as user #david-young points out correctly, of' can be more general by specifying the type as below:
of' :: (a -> b) -> (c -> d -> a) -> c -> d -> b
of' f g x y = f (g x y)
Besides defining a custom operator, as suggested by Haleemur Ali's answer, one alternative is making the definition less point-free by having a single-argument function as the second argument of (.).
absoluteDifference a = abs . (-) a
Given how similar are the roles of the two arguments in your function, from a readability point of view it doesn't make much sense to write it in this way (though it might work better in other cases).
Another possibility is making it more point-free (by having a function-modifying function as the first argument of (-)):
absoluteDifference = (abs .) . (-)
While this is a nice parlour trick, this sort of code with (.) sections is rather cryptic, and it is generally a good idea to avoid it in "real" code.
Why not an owl operator?
(...) = (.) . (.)
absoluteDifference = abs ... (-)
Actually your answer is pretty close. All you need is to amend it as follows;
absDiff :: Num a => a -> a -> a
absDiff n = abs . (n-)
*Main> absDiff 3 9
6
*Main> absDiff 9 3
6
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.
For example, I can't do
f = ((*2).(+)) 3
which is alright since I can always do
f = (*2).(+3)
but this is slightly inconvenient when I want to create a list of functions, e.g.
map ((*2).(+)) [1, 2, 3]
whereas
map (+) [1, 2, 3]
would be alright.
Of course, I can always use lambda notation to implement currying:
map (\x y -> 2*(x + y)) [1, 2, 3]
As far as I can tell, GHC doesn't like composing partially applied functions because it doesn't know how to feed function types to operations like (*2).
(+) 2 :: Num a => a -> a
(*2) :: Num a => a -> a
But I've always thought it should be a rather natural thing: the type of the output of (+) is Num a => a, so (*2) should be able to 'eat' that.
My question is: is this implemented in some way? Or, does someone have any idea why such a straightforward thing isn't implemented in Haskell?
Haskell support composition of partial functions but you have type mismatch. Composition is function
(.) :: (b -> c) -> (a -> b) -> a -> c
In your case you have two function
(*2) :: Num a => a -> a
(+) :: Num a => a -> a -> a
and when you compose this functions type of result will be
((*2).(+)) :: (Num (a -> a), Num a) => a -> a -> a
that not what you want. You can rewrite your function f such as (.) (*2) . (+) but I think that lambda is more readable.
And you confuse partial function and partial application. Partial function is function that defined not for the entire domain and partial application is the process of fixing a number of arguments to a function, producing function of smaller arity.
When going to point-free it might get confusing. If we go through the type signatures;
(.) is (b -> c) -> (a -> b) -> a -> c
(+) is Num a => a -> a -> a
(2*) is Num a => a -> a
Now if we do (2*) . (+) being the second parameter of (.) which is (+), has to have a type (a -> b) which is in fact true when we rewrite (+)s type as Num a => a -> (a -> a). So our b type happens to be Num a => a -> a. Now remember that (.) takes (b -> c) as first parameter. We have a little problem here because in our expression (2*) . (+) (2*) waits for a b type like Num a => a while we have our b type like Num a => a -> a. You can't multiply a function by 2..! We must transform (2*) into such a function that would take a function of our type which is Num a => a -> a, run it and feed it's result to (2*). No need to look this is no more than (.). In this case if we write again like ((2*) . ) we can safely feed our Num a => a -> a type function (remember this is partially applied (+)). Let us wrap it up...
Our point free equivalent of \x y -> 2*(x + y) is ((2*) . ) . (+)
Prelude> (((2*) . ) . (+)) 3 5
16
We may use applicative functors of ((->) r) type to express ourselves more easily in these situations. I will try to add it once i have more time.
I have the applicative <$> operator more or less figured out, but I can't understand the signature I'm getting with the following example:
ghci> let f x y z = x + y + z -- f::Num a => a -> a -> a -> a
ghci> f <$> Just 2 <*> Just 3 <*> Just 4
Just 9
This result I understand, but when checking the following type:
ghci> :t (<$> f)
(<$> f) :: Num a => ((a -> a -> a) -> b) -> a -> b --This makes no sense to me
That signature I would understand as : a function that takes a (a -> a- > a) -> b function and an a as parameters and returns a b. According to this reasoning , I should call this like :
(<$>f) f 4
which would result in an Integer.
Obviously this is not true, so can you please help me understand how to read the type of (<$> f)?
a function that takes a (a -> a- > a) -> b function and an a as parameters and returns a b.
This is correct.
According to this reasoning , I should call this like :
(<$>f) f 4
which would result in an Integer.
No, because f does not have type (a -> a -> a) -> b or one compatible with it. Instead it has type Num a => a -> a -> a -> a. That is, f takes three numbers and produces a number, whereas we're looking for a function that takes a function (of type a -> a -> a) as its first argument.
<$> takes as a second argument something of type g b, where g is any applicative functor.
You are passing f :: Num a => a -> a -> a -> a as a second argument. Let's ignore the Num a context to keep things simple.
Hence, we look for g,b such that g b = a -> a -> a -> a.
Let's write the type of f in prefix form:
f :: (->) a ((->) a ((->) a a)) = g b
Hence, g = (->) a and b = ((->) a ((->) a a)). The latter is b = a -> a -> a in infix form.
It happens that (->) a is an applicative functor, so <$> f type checks. Note however that <$> is used on a completely different functor than the Maybe one you were using in your examples. Hence the confusion.
TL;DR: overloaded identifiers can shapeshift to many things adapting to their contexts, possibly in some unexpected way.
I struggle understanding function composition type results e.g
ghci> :t (id . const)
(id . const) :: a -> b -> a
ghci> :t ((:) . (+))
((:) . (+)) :: a -> [a -> a] -> [a -> a]
How do you guys generally derive function composition types?
That's simple, initially write down the types of both the functions:
> :t const
const :: a -> b -> a
> :t id
id :: a -> a
(id . const) gets translated to \x -> id (const x)
(const x) :: b -> a -- (Note that the type of `x` is `a` here)
id (const x) :: b -> a -- The output of id type will be the same as the input it takes
\x -> id (const x) :: a -> b -> a -- We aleady know the type of x
You can follow the same step for the next function.
Lets see that
> :t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
So in general:
Given two functions. Consider them as curried functions of one parameter, i.e. function of type
a -> b -> c -> ... -> z we'll consider as a function a -> ( b -> c -> ... -> z ) of one parameter that returns function with one parameter less.
Result type of second function should be same as parameter type of first. So consider parameter of first function as result parameter of second. Denote it as b.
Result type of whole composition should be equal a function from parameter type of second function (denote it as a) to result type of first function (denote it as c)
> :t (id . const)
> :t id
id :: a -> a
rename it to x -> x
> :t const
const :: a -> b -> a
Note that a here is not necessary the same that in previous type equation, some rename it to y -> z -> y
a = y
b = z -> y = x
c = x = z -> y
So result is a -> c = y -> ( z -> y) same as a -> b -> c
Overall semantics is equal to const
> :t ((:) . (+))
> :t (:)
(:) :: a -> [a] -> [a]
rename it to x -> [x] -> [x]
> :t (+)
(+) :: Num a => a -> a -> a
rename it to Num y => y -> y -> y
a = y
b = y -> y = x
c = [x] -> [x] = [y -> y] -> [y -> y]
Also we have restriction with type class Num y
So overall type well be Num y => a -> c = y -> [y -> y] -> [y -> y] same as Num a => a -> [a -> a] -> [a -> a]
Overall semantics is "make single parameter function that adds first parameter to numeric value and prepend that function to a given list of single parameter functions"
Exercises: Find the types of the function compositions below, by hand, not using GHCi. Do these exercises to build intuition for reasoning about function types. Remember that type a -> a, where a is a type variable, matches not only Int -> Int or [Bool] -> [Bool], but (a -> a) -> (a -> a) too. If you can't do the exercises, read below.
(*3) . (+2) (easy)
(*) . (+2)
(:) . (+2)
(:) . (*)
What is a function? It's something, that takes an input and returns an output. Not just random output, but output that depends on that input. For the same input the same function always returns the same output. A function transforms some stuff to another stuff. Input and output can be of different types. So imagine a function as a magical one-way tube: you put one thing in the hole labeled in and get something else from another hole named out, possibly of entirely different form. Like, you put a tomato in a tube and get a machine gun from the opposite end. But remember, functions are one-way, you can't put anything in the function's out hole.
a :: Int -> Int -- take a thing of type Int and return a thing of type Int
a n = n + 2
b :: Int -> Int
b n = n -- a function can even return the same value
c :: Int -> Bool -- an output can be of different type than input
c n = n `mod` 3 == 0
Haskell supports higher-order functions and is curried by default. This means that there are no multiple-argument functions in Haskell, every function accepts only 1 argument, but sometimes they can return functions. Haskell tubes always has one and only one hole in, but sometimes tubes pop tubes from the hole out! There are even tubes, in which you can put other tubes. Function types are right-associative, which means that a -> b -> c and a -> (b -> c) are the same thing.
:t (+) -- Num a => a -> a -> a
:t (:) -- a -> [a] -> [a]
So what's a function composition? It's when you compose functions into a new function, or when you fuse 2 tubes together, welding 1st's out to 2nd's in, so that whatever you put into the first tube's in hole, falls through and pops out of second tube's out hole.
A composed function then can be imagined as a long tube made out of two shorter tubes welded together. What would be the type of a composed function? Our new tube still has 2 holes in it, one labeled in, another labeled out. But remember, in of our new tube corresponded to in of a first part, and out of our new tube corresponded to out of the second part. So the type will be from whatever was input to 1st function to whatever was output of 2nd function.
:t (:[2,3]) . (+1) -- Num a => a -> [a]
-- why?
:t (+1) -- Num a => a -> a
:t (:[2,3]) -- Num a => a -> [a]
We joint 2 functions together, first's output to second's input, and get a new function that still has one input and one output. And that's exactly what function operator's type says:
:t (.) -- (b -> c) -> (a -> b) -> (a -> c)
Due to a historical accident, function composition goes from right to left, so (*3) . (+2) is a function that first adds 2 to a number, and then multiples by 3 the result. So how to deduce a type of a function composition? You joint the the input of 2nd function to an output of 1st function and throw away the types in between.
a -> b
b -> c becomes
a -> c
See also: [1], [2], [3], [4] for more ideas on how to use function composition and how to reason about function types.
In ghci,
:t ((+).(+))
> ((+).(+)) :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a
but what is this thing? Can any one give me an example of the use of this please?
How can one composite 2 functions that take 2 parameters each?
for example, how does (map.map) :: (a -> b) -> [[a]] -> [[b]] work?
(^.^)
(-.-)
(+.+) (can't help making funny faces out of it. PS: I thought it means to tell the compiler how you feel today)
Num (a -> a) (or e.g. Eq (a -> a)) is basically an indicator for code that doesn't make any sense1, but the compiler nevertheless deduces a (nonsensical) type signature. Usually it turns up when you've forgotten to apply a function to some argument. In this case, obviously (+) needs a "plain number" argument to become a "simple function" to which you can post-compose another such function.
However, (a -> a) is sure enough a valid type of functions that you can also pass on, just not as numbers. For instance, map . (+) is a perfectly good combination:
Prelude> :t map . (+)
map . (+) :: Num b => b -> [b] -> [b]
Prelude> zipWith (map . (+)) [10,20,30] [[1,2],[3,4]]
[[11,12],[23,24]]
because map actually expects a function as its first argument. Similarly,
Prelude> zipWith (map . map) [(+10),(+20),(+30)] [[[1,2],[3,4]],[[5,6]]]
[[[11,12],[13,14]],[[25,26]]]
Here, the right map takes a simple function (like numerical increment) and returns the corresponding list-map function. That function is then fed to the left map resulting in a function that maps nested lists.
1Actually, you can force it to make sense by defining
instance (Num a) => Num (b -> a) where
fromInteger x = const $ fromInteger x
f + g = \x -> f x + g x
Personally, I'm not a fan of this. It confusing, for instance let a = 3 in 4 a produces 4 when most people would expect multiplication to 12.
That won't work. As ghci tells you, you should have an instance of Num (a -> a) in order to use that function, but a -> a obviously isn't a number.
This is because (+) assumes to get two numerical parameters, but with the composition you wrote you gave it a partially applied function instead, the a -> a mentioned in the computed type signature.
Usually, when composing functions which take more than one parameter, you partially apply them first in order to reduce them to functions which take just one parameter, e.g. (+1) . (*2) applied to 3 will result in (3 * 2) + 1 = 7
f . f can make sense for a binary function f; it entirely depends on the signature of f. The key is that partial application of the inner f to its first argument has to give something that is a valid input to the outer f.
For example, with map :: (a -> b) -> [a] -> [b], we can hand-unify map . map:
map :: (a -> b) -> [a] -> [b]
map :: (c -> d) -> [c] -> [d]
. :: (e -> f) -> (f -> g) -> (e -> g)
e === a -> b
f === [a] -> [b]
=== c -> d
c === [a]
d === [b]
g === [c] -> [d] === [[a]] -> [[b]]
map . map :: e -> g
:: (a -> b) -> [[a]] -> [[b]]
So, as expected, map . map takes a transformation a -> b and gives us a transformation from list-of-list-of-a to list-of-list-of-b. We can check this by hand-applying (map . map) f ll:
(map . map) f ll
= map (map f) ll
= map (\l -> map f l) ll
But if we try the same with (+) :: Num a => a -> a -> a, it all goes horribly wrong:
(+) :: Num a => a -> a -> a
(+) :: Num b => b -> b -> b
. :: (c -> d) -> (d -> e) -> (c -> e)
c === a
d === a -> a
=== b
e === b -> b === (a -> a) -> (a -> a)
(+) . (+) :: c -> e
:: (Num a, Num (a -> a)) => a -> (a -> a) -> (a -> a)
So, partial application of the inner + is giving a transformation a -> a, the outer + is then trying to add that transformation to another function which we are expected to supply. Since it doesn't make sense to add transformations, the overall (+) . (+) doesn't make sense either.
g . f means applying f first, then applying g to the result of f, in
other words, it can be rewritten as
\x -> g (f x)
Therefore,
((+) . (+))
can be rewritten as
\x -> (\y -> (x +) + y)
According to the type of (+), in the above lambda abstraction, x needs
having type Num a => a, y having type Num a => Num (a -> a), as inferred
by ghci
(Num a, Num (a -> a)) => a -> (a -> a) -> a -> a
So if we have made a -> a an instance of type class Num a, for example,
here is one way to achieve that
{-# LANGUAGE FlexibleInstances #-}
instance (Num a) => Num ((->) a a) where
a + b = \x -> a x + b x
a * b = \x -> a x * b x
a - b = \x -> a x - b x
negate a = \x -> negate $ a x
abs a = \x -> abs $ a x
signum a = \x -> signum $ a x
fromInteger n = \_x -> fromInteger n
we can use ((+) . (+)) like this
*Main> ((+) . (+)) 1 (+2) 3
9
Because ((+) . (+)) equals
\x -> \y -> (x +) + y
which means ((+) . (+)) 1 (+2) 3 equals
((1 + ) + (+ 2)) 3
according to the definition of (+) in the instance of (a -> a), ((1+) +
(+2)) equals
\x -> (1+x) + (x+2)
So ((1+) + (+2)) 3 equals (1+3) + (3+2), which is 9, as given by ghci.
map . map is similar, as indicated by its type, given by ghci:
(a -> b) -> [[a]] -> [[b]]
the first argument of that function should be a function of type a->b, the
second argument should be a nested list of type [[a]], and that composed
function map . map will apply the first argument to each element of each
list in its second argument, return a nested list of type [[b]]. For
example
*Main> (map . map) (+1) [[1,2], [3,4,5]]
[[2,3],[4,5,6]]