[Haskell-cafe] function composition
Daniel Fischer
daniel.is.fischer at googlemail.com
Sun Jan 15 16:55:36 CET 2012
On Sunday 15 January 2012, 16:17:24, TP wrote:
> Hi,
>
> I have a basic question concerning function composition. I have used
> http://www.haskell.org/tutorial/functions.html
> to write a composition function:
>
> Prelude> let f°g = f g
This does not what you probably expect. That definition means (°) = ($) is
just function application, or, in other words, (°) is the identity function
restricted to function types.
If I'm correct in suspecting you want function composition,
Prelude> let f°g = f . g
Prelude> let (°) = (.)
Prelude> let (f ° g) x = f (g x)
are possible ways to obtain that.
> Prelude> let p = (*2)
> Prelude> let q = (+3)
These two lead to the surprise below.
> Prelude> p°q 4
This is parsed as
p ° (q 4)
> 14
> Prelude> :t (°)
> (°) :: (t1 -> t) -> t1 -> t
(°) is the identity restricted to function types.
>
> If I understand well, this means that the infix operator "°" takes a
> function of type t1, i.e. g in f°g,
it may be a function, but need not, it could also be a non-function value
like [], True, ...
> and applies f on it, which takes a
> type t1 as input and returns f(g) which is of type t. The final result
> is of type t. So the first argument is represented above by "(t1->t)",
> and the second by "t1", the final result being of type t.
>
> However, I am not able to get the type of p°q
>
> Prelude> :t p°q
>
> <interactive>:1:3:
> Couldn't match expected type `Integer'
> with actual type `Integer -> Integer'
> In the second argument of `(°)', namely `q'
> In the expression: p ° q
> Prelude>
>
> What's the problem here?
1. The monomorphism restriction. You have bound p and q
Prelude> let p = (*2)
Prelude> let q = (+3)
with simple pattern bindings (plain variable name, no function arguments in
the binding) and without type signature. The inferred most general type for
both is
Num a => a -> a
which is a constrained polymorphic type.
The monomorphism restriction (language report, section 4.5.5) says such
bindings must have a monomorphic type.
By the defaulting rules (section 4.3.4), the type variable is defaulted to
Integer to obtain a monomorphic type. Hence in your session, you have
p, q :: Integer -> Integer
Now, (°) :: (a -> b) -> a -> b, and matching p's type with the type of
(°)'s first argument, a = b = Integer. But if we try to match q's type with
the type of (°)'s second argument, that type has already been determined to
be Integer here, so q's type (Integer -> Integer) doesn't match.
2. Even with the monomorhism eliminated, by one (or more) of
a) binding p and q with a function binding (let p x = x * 2)
b) giving a type signature for the binding
c) disabling the MR (Prelude> :set -XNoMonomorphismRestriction)
you still get something probably unexpected. now
p :: Num a => a -> a
q :: Num b => b -> b
unifying p's type with the type of (°)'s first argument,
(p °) :: Num a => a -> a
Now we must unify a with q's type, thus
(p ° q) :: (Num b, Num (b -> b)) => b -> b
> How can I obtain the type of p°q?
Eliminate the MR from the picture.
>
> Thanks in advance,
>
> TP
More information about the Haskell-Cafe
mailing list