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.

Articles by others on the same topic (0)

There are currently no matching articles.