Can someone explain me, why do these functions
have different number of arguments and behavior, but
the same type signature, yet they are both correct?
comp1 :: (a -> b) -> (b -> c) -> a -> c
comp1 f g = g.f
comp2 :: (a -> b) -> (b -> c) -> a -> c
comp2 f g x = g (f x)
also, why does comp2 has
comp2 :: (a -> b) -> (b -> c) -> a -> c
instead of something like
comp2 :: a -> (a -> b) -> (b -> c) -> a -> c
?
Thank you.
comp2 f g x = g (f x)
is syntactic sugar for
comp2 = \f -> \g -> \x -> g (f x)
Similarly
comp1 f g = g.f
is sugar for
comp1 = \f -> \g -> g.f
The definition of . is:
f1 . f2 = \x -> f1 (f2 x) -- Names of arguments have been changed to avoid confusion
So if we insert the definition into the desugared form of comp1, we get:
comp1 = \f -> \g -> \x -> g (f x)
This is exactly the same as the desugared form of comp2, so clearly the definitions are equivalent.
comp1 f g = g.f is written in point-free style (not referring to points, but to values). When you call comp1, there is implicitly a third parameter being passed to g.f, which is the composition of the two functions g and f: (g.f) x equals g (f x), i.e. g is passed the result of f x. No parameter x exists in comp1 because it's implicitly passed to the function. (You could think of comp1 as a partially applied or curried function if it makes you feel better.)
comp2's type asks for two functions, one from (a->b) and another (b->c), as well as a parameter of type a. There is no need to put an a -> in its signature.
The two functions are really equivalent; one simply uses some Haskell tricks to be more concise.
Currying. A multi-argument function in ML and Haskell, is just syntactic sugar for a one-argument function that returns a function; the function that it returns takes the remaining arguments.
Related
I struggle to understand how type declarations work...
Like these ones for example:
t :: (a -> b) -> (b -> c) -> a -> c
s :: (a -> b -> c) -> (a -> b) -> a -> c
I know from just trying different things that the correct functions would look like this:
t :: (a -> b) -> (b -> c) -> a -> c
t f g x = g (f x)
s :: (a -> b -> c) -> (a -> b) -> a -> c
s f g x = f x (g x)
But how does this work? Why are the brackets at the end? Why is it not
t f g x = (f x) g
or
s f g x = (f x) g x
Im so lost
For the first example:
t :: (a -> b) -> (b -> c) -> a -> c
In a type declaration, the type1 -> type2 pattern indicates a function from type1 to type2. In type declarations, the -> operator is right-associative, so this is parsed as:
t :: (a -> b) -> ((b -> c) -> (a -> c))
This kind of construction is called "currying": providing the first argument (type a -> b) yields a function which accepts the second argument (type b -> c) which yields a function which accepts the third argument (type a).
The function declaration syntax is set up to do this automatically. The first two arguments are functions and the third is just a, so start with names that reflect that: f :: a -> b and g :: b -> c are functions, while x :: a is a fully generic type which could be anything.
t f g x = ...
Note that function application in Haskell is just concatenation: to apply function f to value x, just use f x. This syntax is left-associative, so t f g x is parsed as (((t f) g) x) to match the currying construction described above.
Anyway, given these types, you don't have much choice in how to put them together:
the only thing you know about the type a is that it's the type of x, and the argument type of f, so the only thing you can do with them is to apply the function to the value: f x.
the only thing you know about the type b is that it's the result type of f and the argument type of g, so the only thing you can do is apply g (f x).
the only thing you know about the type c is that it's the result type of g and of the overall function t, so the only thing t can return is g (f x).
The reason you can't do (f x) g is that the types don't match:
f :: a -> b
x :: a
(f x) :: b
g :: b -> c
So, you can apply g :: b -> c to (f x) :: b to get a result of type c. But not the other way around, because b might not even be a function type.
I am studying Haskell. Currently, I am studying function composition. I understand (at least on a basic level) how function (.) can be used, but there are two things to it that I understand not.
So the function looks as follows:
(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> f (g x)
First, the type declaration. (b -> c) -> (a -> b) essentially means that function f takes an argument from resulting value (b) of function g (which takes value a) and returns value of type c. I don't understand the following part -> a -> c, why should there be -> a there? Why is (b -> c) -> (a -> b) -> c wrong? From my point of view (which is obviously wrong), function g is already taking a as an argument.
Second, the body of the function f . g = \x -> f (g x). What does \x -> do here? Lambda is pretty straightforward. For example filter (\(a,b) -> a + b > 4) [(1,2),(3,4)], but a simple \x -> makes me stuck. I would probably write the body like this f . (g x) = f (g x) (which is obviously wrong again).
(b -> c) -> (a -> b) -> c would be a function that takes two functions f :: b -> c and g :: a -> b, and somehow call g without an initial argument of type a.
For the second question, consider how you would define (.) using prefix notation instead. (It might be easier to see if we use a "regular" name for the function; I'll include that as a comment after each snippet of code):
(.) f g x = f (g x) -- compose f g x = f (g x)
x is the "third argument" for (.), or more precisely the argument for the function returned by (.) f g. This is equivalent to defining (.) f g as a function directly, by putting a function on the right-hand side instead of the ultimate return value of that function:
(.) f g x = f (g x) -- Implicit function def: compose f g x = f (g x)
(.) f g = \x -> f (g x) -- Explicit function def: compose f g = \x -> f (g x)
You can also use parentheses to define the function implicitly:
(f . g) x = f (g x)
Can someone help me with writing my own version of a (.) function in Haskell?
From this post Haskell write your version of a ($) function I know how to determine a type of this function, but I still have the problem with its body.
I also do not know why ghci refuses to use the name (..).
($$$) :: (b -> c) -> (a -> b) -> a -> c
($$$) f (g x) = ((f g) $) x
infixr 9 $$$
Another idea of mine was for instance this one:
($$$) :: (b -> c) -> (a -> b) -> a -> c
($$$) f (g x) = map (f) (g x)
infixr 9 $$$
The error message says that "Parse error in pattern: g".
From the signature:
($$$) :: (b -> c) -> (a -> b) -> a -> c
your function needs 3 arguments. So I would start:
($$$) f g x = ...
| | \
| \ a
| \
| a->b
b->c
Update
This attempt at defining ($$$) does not work:
($$$) (f g) x = ...
It says that ($$$) takes two arguments. The way I've started to define ($$$) says that the function takes three arguments.
Are you coming from Lisp? You still seem to assume lists everywhere...
As I already said in the other thread, lists have nothing to do with this task, so neither of (:), foldr or map can possibly be useful here.
More to the point, the occurence of (g x) in the left-hand side of the definition doesn't make sense. (This is not a list, but apparently you think it should be a kind of “argument list”).
As a matter of fact, you could define ($$$) in un-curried form this way:
($$$) :: (b->c) -> (a->b, a) -> c
($$$) f (g, x) = ...
...which is exactly the same thing as the more elegant
f $$$ (g, x) = ...
In this case, you have an argument tuple (g, x), which is more or less equivalent to a Lisp list.
In Haskell, we like to write functions curried though. The signature
($$$) :: (b -> c) -> (a -> b) -> a -> c
is in fact parsed as
($$$) :: (b -> c) -> ( (a -> b) -> (a -> c) )
Hence the way to define such a function is, at the most fundamental level
($$$) = \f -> (\g -> (\x -> ... ))
Which can be written short as
($$$) f g x = ...
or
(f $$$ g) x = ...
In the actual definition part, you should similarly get the grasp of how things are actually parsed. As you have by now figured out, the composition operator can be defined as
($$$) f g x = f(g(x))
In fact, only the outer parentheses are necessary here: the preferred form is
($$$) f g x = f (g x)
or indeed
($$$) f g x = f $ g x
If something like g x or (f g) appears on its own in an expression, it always means that the left function is applied to the right argument. For f g this doesn't make sense, because though f is a function it can not take another function as its argument, only the result of such a function. Well, to get such a result you need to apply g to an argument!
Many thanks for your patience. I used brackets where I should not have. I still have problems with looking at everything (including mathematical operators) as a function. Now the idea of (.) is clear.
($$$) :: (b -> c) -> (a -> b) -> a -> c
($$$) f g x = f(g x)
infixr 9 $$$
Ordinary function composition is of the type
(.) :: (b -> c) -> (a -> b) -> a -> c
I figure this should generalize to types like:
(.) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
A concrete example: calculating difference-squared. We could write diffsq a b = (a - b) ^ 2, but it feels like I should be able to compose the (-) and (^2) to write something like diffsq = (^2) . (-).
I can't, of course. One thing I can do is use a tuple instead of two arguments to (-), by transforming it with uncurry, but this isn't the same.
Is it possible to do what I want? If not, what am I misunderstanding that makes me think it should be possible?
Note: This has effectively already been asked here, but the answer (that I suspect must exist) was not given.
My preferred implementation for this is
fmap . fmap :: (Functor f, Functor f1) => (a -> b) -> f (f1 a) -> f (f1 b)
If only because it is fairly easy to remember.
When instantiating f and f1 to (->) c and (->) d respectively you get the type
(a -> b) -> (c -> d -> a) -> c -> d -> b
which is the type of
(.) . (.) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c
but it is a bit easier to rattle off the fmap . fmap version and it generalizes to other functors.
Sometimes this is written fmap fmap fmap, but written as fmap . fmap it can be more readily expanded to allow more arguments.
fmap . fmap . fmap
:: (Functor f, Functor g, Functor h) => (a -> b) -> f (g (h a)) -> f (g (h b))
fmap . fmap . fmap . fmap
:: (Functor f, Functor g, Functor h, Functor i) => (a -> b) -> f (g (h (i a))) -> f (g (h (i b))
etc.
In general fmap composed with itself n times can be used to fmap n levels deep!
And since functions form a Functor, this provides plumbing for n arguments.
For more information, see Conal Elliott's Semantic Editor Combinators.
The misunderstanding is that you think of a function of type a -> b -> c as a function of two arguments with return type c, whereas it is in fact a function of one argument with return type b -> c because the function type associates to the right (i.e. it's the same as a -> (b -> c). This makes it impossible to use the standard function composition operator.
To see why, try applying the (.) operator which is of type (y -> z) -> (x -> y) -> (x -> z) operator to two functions, g :: c -> d and f :: a -> (b -> c). This means that we must unify y with c and also with b -> c. This doesn't make much sense. How can y be both c and a function returning c? That would have to be an infinite type. So this does not work.
Just because we can't use the standard composition operator, it doesn't stop us from defining our own.
compose2 :: (c -> d) -> (a -> b -> c) -> a -> b -> d
compose2 g f x y = g (f x y)
diffsq = (^2) `compose2` (-)
Usually it is better to avoid using point-free style in this case and just go with
diffsq a b = (a-b)^2
I don't know of a standard library function that does this, but the point-free pattern that accomplishes it is to compose the composition function:
(.) . (.) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c
I was going to write this in a comment, but it's a little long, and it draws from both mightybyte and hammar.
I suggest we standardize around operators such as .* for compose2 and .** for compose3. Using mightybyte's definition:
(.*) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
(.*) = (.) . (.)
(.**) :: (d -> e) -> (a -> b -> c -> d) -> (a -> b -> c -> e)
(.**) = (.) . (.*)
diffsq :: (Num a) => a -> a -> a
diffsq = (^2) .* (-)
modminus :: (Integral a) => a -> a -> a -> a
modminus n = (`mod` n) .* (-)
diffsqmod :: (Integral a) => a -> a -> a -> a
diffsqmod = (^2) .** modminus
Yes, modminus and diffsqmod are very random and worthless functions, but they were quick and show the point. Notice how eerily easy it is to define the next level by composing in another compose function (similar to the chaining fmaps mentioned by Edward).
(.***) = (.) . (.**)
On a practical note, from compose12 upwards it is shorter to write the function name rather than the operator
f .*********** g
f `compose12` g
Though counting asterisks is tiring so we may want to stop the convention at 4 or 5 .
[edit] Another random idea, we could use .: for compose2, .:. for compose3, .:: for compose4, .::. for compose5, .::: for compose6, letting the number of dots (after the initial one) visually mark how many arguments to drill down. I think I like the stars better though.
As Max pointed out in a comment:
diffsq = ((^ 2) .) . (-)
You can think of f . g as applying one argument to g, then passing the result to f. (f .) . g applies two arguments to g, then passes the result to f. ((f .) .) . g applies three arguments to g, and so on.
\f g -> (f .) . g :: (c -> d) -> (a -> b -> c) -> a -> b -> d
If we left-section the composition operator with some function f :: c -> d (partial application with f on the left), we get:
(f .) :: (b -> c) -> b -> d
So we have this new function which expects a function from b -> c, but our g is a -> b -> c, or equivalently, a -> (b -> c). We need to apply an a before we can get what we need. Well, let's iterate once more:
((f .) .) :: (a -> b -> c) -> a -> b -> d
Here's what I think is an elegant way to achieve what you want. The Functor type class gives a way to 'push' a function down into a container so you can apply it to each element using fmap. You can think of a function a -> b as a container of bs with each element indexed by an element of a. So it's natural to make this instance:
instance Functor ((->) a) where
fmap f g = f . g
(I think you can get that by importing a suitable library but I can't remember which.)
Now the usual composition of f with g is trivially an fmap:
o1 :: (c -> d) -> (b -> c) -> (b -> d)
f `o1` g = fmap f g
A function of type a -> b -> c is a container of containers of elements of type c. So we just need to push our function f down twice. Here you go:
o2 :: (c -> d) -> (a -> (b -> c)) -> a -> (b -> d)
f `o2` g = fmap (fmap f) g
In practice you might find you don't need o1 or o2, just fmap. And if you can find the library whose location I've forgotten, you may find you can just use fmap without writ
ing any additional code.
(.) takes two functions that take one value and return a value:
(.) :: (b -> c) -> (a -> b) -> a -> c
Since (.) takes two arguments, I feel like (.).(.) should be invalid, but it's perfectly fine:
(.).(.) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c
What is going on here? I realize this question is badly worded...all functions really just take one argument thanks to currying. Maybe a better way to say it is that the types don't match up.
Let's first play typechecker for the mechanical proof. I'll describe an intuitive way of thinking about it afterward.
I want to apply (.) to (.) and then I'll apply (.) to the result. The first application helps us to define some equivalences of variables.
((.) :: (b -> c) -> (a -> b) -> a -> c)
((.) :: (b' -> c') -> (a' -> b') -> a' -> c')
((.) :: (b'' -> c'') -> (a'' -> b'') -> a'' -> c'')
let b = (b' -> c')
c = (a' -> b') -> a' -> c'
((.) (.) :: (a -> b) -> a -> c)
((.) :: (b'' -> c'') -> (a'' -> b'') -> a'' -> c'')
Then we begin the second, but get stuck quickly...
let a = (b'' -> c'')
This is key: we want to let b = (a'' -> b'') -> a'' -> c'', but we already defined b, so instead we must try to unify --- to match up our two definitions as best we can. Fortunately, they do match
UNIFY b = (b' -> c') =:= (a'' -> b'') -> a'' -> c''
which implies
b' = a'' -> b''
c' = a'' -> c''
and with those definitions/unifications we can continue the application
((.) (.) (.) :: (b'' -> c'') -> (a' -> b') -> (a' -> c'))
then expand
((.) (.) (.) :: (b'' -> c'') -> (a' -> a'' -> b'') -> (a' -> a'' -> c''))
and clean it up
substitute b'' -> b
c'' -> c
a' -> a
a'' -> a1
(.).(.) :: (b -> c) -> (a -> a1 -> b) -> (a -> a1 -> c)
which, to be honest, is a bit of a counterintuitive result.
Here's the intuition. First take a look at fmap
fmap :: (a -> b) -> (f a -> f b)
it "lifts" a function up into a Functor. We can apply it repeatedly
fmap.fmap.fmap :: (Functor f, Functor g, Functor h)
=> (a -> b) -> (f (g (h a)) -> f (g (h b)))
allowing us to lift a function into deeper and deeper layers of Functors.
It turns out that the data type (r ->) is a Functor.
instance Functor ((->) r) where
fmap = (.)
which should look pretty familiar. This means that fmap.fmap translates to (.).(.). Thus, (.).(.) is just letting us transform the parametric type of deeper and deeper layers of the (r ->) Functor. The (r ->) Functor is actually the Reader Monad, so layered Readers is like having multiple independent kinds of global, immutable state.
Or like having multiple input arguments which aren't being affected by the fmaping. Sort of like composing a new continuation function on "just the result" of a (>1) arity function.
It's finally worth noting that if you think this stuff is interesting, it forms the core intuition behind deriving the Lenses in Control.Lens.
Let’s ignore types for a moment and just use lambda calculus.
Desugar infix notation:
(.) (.) (.)
Eta-expand:
(\ a b -> (.) a b) (\ c d -> (.) c d) (\ e f -> (.) e f)
Inline the definition of (.):
(\ a b x -> a (b x)) (\ c d y -> c (d y)) (\ e f z -> e (f z))
Substitute a:
(\ b x -> (\ c d y -> c (d y)) (b x)) (\ e f z -> e (f z))
Substitute b:
(\ x -> (\ c d y -> c (d y)) ((\ e f z -> e (f z)) x))
Substitute e:
(\ x -> (\ c d y -> c (d y)) (\ f z -> x (f z)))
Substitute c:
(\ x -> (\ d y -> (\ f z -> x (f z)) (d y)))
Substitute f:
(\ x -> (\ d y -> (\ z -> x (d y z))))
Resugar lambda notation:
\ x d y z -> x (d y z)
And if you ask GHCi, you’ll find that this has the expected type. Why? Because the function arrow is right-associative to support currying: the type (b -> c) -> (a -> b) -> a -> c really means (b -> c) -> ((a -> b) -> (a -> c)). At the same time, the type variable b can stand for any type, including a function type. See the connection?
Here is a simpler example of the same phenomenon:
id :: a -> a
id x = x
The type of id says that id should take one argument. And indeed, we can call it with one argument:
> id "hello"
"hello"
But it turns out what we can also call it with two arguments:
> id not True
False
Or even:
> id id "hello"
"hello"
What is going on? The key to understanding id not True is to first look at id not. Clearly, that's allowed, because it applies id to one argument. The type of not is Bool -> Bool, so we know that the a from id's type should be Bool -> Bool, so we know that this occurrence of id has type:
id :: (Bool -> Bool) -> (Bool -> Bool)
Or, with less parentheses:
id :: (Bool -> Bool) -> Bool -> Bool
So this occurrence of id actually takes two arguments.
The same reasoning also works for id id "hello" and (.) . (.).
This is one of those neat cases where I think it's simpler to grasp the more general case first, and then think about the specific case. So let's think about functors. We know that functors provide a way to map functions over a structure --
class Functor f where
fmap :: (a -> b) -> f a -> f b
But what if we have two layers of the functor? For example, a list of lists? In that case we can use two layers of fmap
>>> let xs = [[1,2,3], [4,5,6]]
>>> fmap (fmap (+10)) xs
[[11,12,13],[14,15,16]]
But the pattern f (g x) is exactly the same as (f . g) x so we could write
>>> (fmap . fmap) (+10) xs
[[11,12,13],[14,15,16]]
What is the type of fmap . fmap?
>>> :t fmap.fmap
:: (Functor g, Functor f) => (a -> b) -> f (g a) -> f (g b)
We see that it maps over two layers of functor, as we wanted. But now remember that (->) r is a functor (the type of functions from r, which you might prefer to read as (r ->)) and its functor instance is
instance Functor ((->) r) where
fmap f g = f . g
For a function, fmap is just function composition! When we compose two fmaps we map over two levels of the function functor. We initially have something of type (->) s ((->) r a), which is equivalent to s -> r -> a, and we end up with something of type s -> r -> b, so the type of (.).(.) must be
(.).(.) :: (a -> b) -> (s -> r -> a) -> (s -> r -> b)
which takes its first function, and uses it to transform the output of the second (two-argument) function. So for example, the function ((.).(.)) show (+) is a function of two arguments, that first adds its arguments together and then transforms the result to a String using show:
>>> ((.).(.)) show (+) 11 22
"33"
There is then a natural generalization to thinking about longer chains of fmap, for example
fmap.fmap.fmap ::
(Functor f, Functor g, Functor h) => (a -> b) -> f (g (h a)) -> f (g (h b))
which maps over three layers of functor, which is equivalent to composing with a function of three arguments:
(.).(.).(.) :: (a -> b) -> (r -> s -> t -> a) -> (r -> s -> t -> b)
for example
>>> import Data.Map
>>> ((.).(.).(.)) show insert 1 True empty
"fromList [(1,True)]"
which inserts the value True into an empty map with key 1, and then converts the output to a string with show.
These functions can be generally useful, so you sometimes see them defined as
(.:) :: (a -> b) -> (r -> s -> a) -> (r -> s -> b)
(.:) = (.).(.)
so that you can write
>>> let f = show .: (+)
>>> f 10 20
"30"
Of course, a simpler, pointful definition of (.:) can be given
(.:) :: (a -> b) -> (r -> s -> a) -> (r -> s -> b)
(f .: g) x y = f (g x y)
which may help to demystify (.).(.) somewhat.
You're right, (.) only takes two arguments. You just seem to be confused with the syntax of haskell. In the expression (.).(.), it's in fact the dot in the middle that takes the other two dots as argument, just like in the expression 100 + 200, which can be written as (+) 100 200.
(.).(.) === (number the dots)
(1.)2.(3.) === (rewrite using just syntax rules)
(2.)(1.)(3.) === (unnumber and put spaces)
(.) (.) (.) ===
And it should be even more clear from (.) (.) (.) that the first (.) is taking the second (.) and third (.) as it's arguments.
Yes this is due to currying. (.) as all functions in Haskell only takes one argument. What you are composing is the first partial call to each respective composed (.) which takes its first argument (the first function of the composition).
(Read my answer on function composition, $ operator and point-free style first.)
Imagine you have a simple function: it adds up 2 numbers and then negates the result. We'll call it foo:
foo a b = negate (a + b)
Now let's make it point-free step by step and see what we end up with:
foo a b = negate $ a + b
foo a b = negate $ (+) a b
foo a b = negate $ (+) a $ b
foo a b = negate . (+) a $ b
foo a = negate . (+) a -- f x = g x is equivalent to f = g
foo a = (.) negate ((+) a) -- any infix operator is just a function
foo a = (negate.) ((+) a) -- (2+) is the same as ((+) 2)
foo a = (negate.) $ (+) a
foo a = (negate.) . (+) $ a
foo = (negate.) . (+)
foo = ((.) negate) . (+)
foo = (.) ((.) negate) (+) -- move dot in the middle in prefix position
foo = ((.) ((.) negate)) (+) -- add extra parentheses
Now let's analyze expression (.) ((.) negate) more closely. It's a partial application of (.) function, whose first argument is ((.) negate). Can we transform it even further? Yes we can:
(.) ((.) negate)
(.) . (.) $ negate -- because f (f x) is the same as (f . f) x
(.)(.)(.) $ negate
((.)(.)(.)) negate
(.).(.) is equivalent to (.)(.)(.), because in the 1st expression, the dot in the middle can be moved in prefix position and surrounded with parentheses, which gives rise to the 2nd expression.
Now we can rewrite our foo function:
foo = ((.).(.)) negate (+)
foo = ((.)(.)(.)) negate (+) -- same as previous one
foo = negate .: (+)
where (.:) = (.).(.)
Now you know that (.).(.) is equivalent to (\f g x y -> f (g x y)):
(\f g x y -> f (g x y)) negate (+) 2 3 -- returns -5
((.).(.)) negate (+) 2 3 -- returns -5