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.
Related
What I don't get is how it is possible to use foldl in this way in haskell. I do not understand how the argument ( in this case list) is carried over implicitly:
addAll :: [Int] -> Int
addAll = foldl (+) 0
-- This is how I could write foldl to simplify addAll where xs is clearly defined
addAll :: [Int] -> Int
addAll xs = foldl (+) 0 xs
or
addAll :: [Int] -> Int
addAll = \ xs -> foldl (+) 0 xs
But I don't really understand the first example. So basically I wonder how it is possible for something to be evaluated like that in haskell?
But I don't really understand the first example. So basically I wonder how it is possible for something to be evaluated like that in haskell?
The foldl (+) 0 produces a function. A function of type (Foldable f, Num a) => f a -> a, so why would you need an extra parameter? The addAll is a function as well.
In functional programming, functions are "first class citizens". This means that you can pass functions as parameters, and that the result can be a function. In Haskell every function takes exactly one parameter. Indeed:
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
is short for:
foldl :: Foldable t => (b -> a -> b) -> (b -> (t a -> b))
foldl is thus a function that takes as parameter a function of type (b -> a -> b), and produces a function of type b -> t a -> b. This thus means that foldl (+) has type:
foldl (+) :: (Foldable f, Num b) => b -> (f b -> b)
again a function that in this case takes a parameter the base case for foldl, and returns then a function that maps a (Foldable f, Num a) => f a -> f a. If you write foldl (+) 0, this is thus short for (fold (+)) 0.
Remember that all functions in Haskell are curried. foldl is no exception; it has type Foldable t => (b -> a -> b) -> b -> t a -> b, which means it takes an argument of type (b -> a -> b) and returns a function of type Foldable t => b -> t a -> b.
That function is also curried. foldl (+) takes an argument of type Int b => b and returns a function of type (Foldable t, Num b) => t b -> b.
Thus, foldl (+) 0 has type (Foldable t, Num b) => t b -> b, and your type annotation makes the restrictions t ~ [] and b ~ Int.
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 struggling with an exercise in R. Bird's functional programming book that asks for an example of a function with type (num -> num) -> num
The best I can come up with is a polymorphic type
func1 f = f 3
:t func1
func1 :: Num t1 => (t1 -> t2) -> t2
The problem I am having is that I can't specify the return type of f, so the type remains (num -> t2) -> t2.
My attempt to force the return type of f is as follows:
square x = x * x
:t func1 square
func1 square :: Num t2 => t2 -> t2
Because of course if I try to find the type of func1 ∘ square it will just be num -> num
If it is enough to give a function which can be assigned that type, then yours is already enough. That is, the following type-checks just fine:
func1 :: Num a => (a -> a) -> a
func1 f = f 3
If, on the other hand, you want a function which is inferred to have that type, then you need to do some trickery. What we want to do here is to specify that the result of f 3 and the 3 that we fed in have the same type. The standard way to force two terms to have the same type is to use asTypeOf, which is implemented this way:
asTypeOf :: a -> a -> a
asTypeOf x _ = x
So let's try:
> :t \f -> f 3 `asTypeOf` 3
(Num a, Num t) => (t -> a) -> a
Unfortunately for us, this doesn't work, because the 3 in f 3 and the standalone 3 are inferred to be using potentially different instances of Num. Still, it is a bit closer than \f -> f 3 was -- note the new Num a constraint on the output that we didn't have before. An obvious next idea is to let-bind a variable to 3 and reuse that variable as the argument to both f and asTypeOf; surely then GHC will get the picture that f's argument and result have the same type, right?
> :t \f -> let x = 3 in f x `asTypeOf` x
(Num a, Num t) => (t -> a) -> a
Drat. Turns out that lets do what's called "let generalization"; the x will be just as polymorphic as the 3 was, and can be specialized to different types at different use sites. Usually this is a nice feature, but because we're doing an unnatural exercise we need to do unnatural things...
Okay, next idea: some lambda calculi do not include a let, and when you need one, instead of writing let a = b in c, you write (\a -> c) b. This is especially interesting for us because Haskell uses a specially-restricted kind of polymorphism that means that inside c, the type of a is monomorphic. So:
> :t \f -> (\x -> f x `asTypeOf` x) 3
Num a => (a -> a) -> a
And now you complain that asTypeOf is cheating, because it uses a type declaration that doesn't match its inferred type, and the whole point of the exercise was to get the right type through inference alone. (If we were okay with using type declarations that don't match the inferred type, we could have stopped at func1 :: Num a => (a -> a) -> a; func1 f = f 3 from way back at the beginning!) Okay, no problem: there's another standardish way to force the types of two expressions to unify, namely, by putting them in a list together. So:
> :t \f -> (\x -> head [f x, x]) 3
Num a => (a -> a) -> a
Phew, now we're finally at a place where we could in principle build, from the ground up, all the tools needed to get a term of the right type without any type declarations.
func1 f = let x = f x in x This is a partial function, it technically has the type you want and you should be aware of what they are and how they work in haskell.
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
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.