Reputation: 1472
So i know that:
(.) = (f.g) x = f (g x)
And it's type is (B->C)->(A->B)->A->C But what about:
(.)(.) = _? = _?
How this is represented? I thought of:
(.)(.) = (f.g)(f.g)x = f(g(f(g x))) // this
(.)(.) = (f.g.h)x = f(g(h x)) // or this
But as far as i tried to get type of it, it's not correct to what GHCi tells me. So what are both "_?"
Also - what does function/operator $ do?
Upvotes: 3
Views: 2513
Reputation: 71065
As dave4420 mentions,
(.) :: (b -> c) -> (a -> b) -> a -> c
So what is the type of (.) (.)
? dave4420 skips that part, so here it is: (.)
accepts a value of type b -> c
as its first argument, so
(.) :: ( b -> c ) -> (a -> b) -> a -> c
(.) :: (d -> e) -> ((f -> d) -> f -> e)
so we have b ~ d->e
and c ~ (f -> d) -> f -> e
, and the resulting type of (.)(.)
is (a -> b) -> a -> c
. Substituting, we get
(a -> d -> e) -> a -> (f -> d) -> f -> e
Renaming, we get (a -> b -> c) -> a -> (d -> b) -> d -> c
. This is a function f
that expects a binary function g
, a value x
, a unary function h
and another value y
:
f g x h y = g x (h y)
That's the only way this type can be realized: g x :: b -> c
, h y :: b
and so g x (h y) :: c
, as needed.
Of course in Haskell, a "unary" function is such that expects one or more arguments; similarly a "binary" function is such that expects two or more arguments. But not less than two (so using e.g. succ
is out of the question).
We can also tackle this by writing equations, combinators-style1. Equational reasoning is easy:
(.) (.) x y z w q =
((.) . x) y z w q =
(.) (x y) z w q =
(x y . z) w q =
x y (z w) q
We just throw as much variables as needed into the mix and then apply the definition back and forth. q
here was an extra, so we can throw it away and get the final definition,
_BB x y z w = x y (z w)
(coincidentally, (.)
is known as B-combinator).
1 a b c = (\x -> ... body ...)
is equivalent to a b c x = ... body ...
, and vice versa, provided that x
does not appear among {a,b,c}
.
Upvotes: 7
Reputation: 47052
First off, you're being sloppy with your notation.
(.) = (f.g) x = f (g x) -- this isn't true
What is true:
(.) f g x = (f.g) x = f (g x)
(.) = \f g x -> f (g x)
And its type is given by
(.) :: (b -> c) -> (a -> b) -> a -> c
-- n.b. lower case, because they're type *variables*
Meanwhile
(.)(.) :: (a -> b -> d) -> a -> (c -> b) -> c -> d
-- I renamed the variables ghci gave me
Now let's work out
(.)(.) = (\f' g' x' -> f' (g' x')) (\f g x -> f (g x))
= \g' x' -> (\f g x -> f (g x)) (g' x')
= \g' x' -> \g x -> (g' x') (g x)
= \f y -> \g x -> (f y) (g x)
= \f y g x -> f y (g x)
= \f y g x -> (f y . g) x
= \f y g -> f y . g
And ($)
?
($) :: (a -> b) -> a -> b
f $ x = f x
($)
is just function application. But whereas function application via juxtaposition is high precedence, function application via ($)
is low precedence.
square $ 1 + 2 * 3 = square (1 + 2 * 3)
square 1 + 2 * 3 = (square 1) + 2 * 3 -- these lines are different
Upvotes: 14