= Solution
The expression parses as `g . (g x)`. Initially write `g :: a -> r` and `x :: a`. In the <function composition>, `g x` must itself be a function whose result can be passed to `g`. Hence `r = b -> a` for a fresh type `b`, so
``
g :: a -> b -> a
g x :: b -> a
g . g x :: b -> b -> a
``
Consequently the <principal type> is
``
f :: (a -> b -> a) -> a -> b -> b -> a
``
One can check the constraints by expanding the composition:
``
f g x y z = g (g x y) z
``
Here `g x y` has type `a`, and the second application accepts it and the final `b`-typed argument `z`. The two type variables remain independent; no <Haskell type class> constraints are required.
Back to article page