Whether m
can be "any TreeLike" depends on your perspective.
From the perspective of implementing improve
, it's true--m
can be any TreeLike
, so it picks one that's convenient, and uses abs
.
From the perspective of the argument m
--which is to say, the perspective of whatever is applying improve
to some argument, something that's rather the opposite holds: m
in fact must be able to be any TreeLike
, not a single one that we choose.
Compare this to the type of numeric literals--something like (5 :: forall a. Num a => a)
means that it's any Num
instance we want it to be, but if a function expects an argument of type (forall a. Num a => a)
it wants something that can be any Num
instance it chooses. So we could give it a polymorphic 5
but not, say, the Integer
5.
You can, in many ways, think of polymorphic types as meaning that the function takes a type as an extra argument, which tells it what specific type we want to use for each type variable. So to see the difference between (forall m. TreeLike m => m a) -> Tree a
and forall m. TreeLike m => m a -> Tree a
you can read them as something like (M -> M a) -> Tree a
vs. M -> M a -> Tree a
.