Could m be "any TreeLike" depending on your perspective.
From the point of view of the improve implementation, true - m can be any TreeLike , so it chooses the convenient one and uses abs .
From the point of view of the argument m - that is, the perspective of what improve applies to a certain argument, something that is more likely to have the opposite: m should actually be able to be any TreeLike , not the one we choose.
Compare this to the type of numeric literals - something like (5 :: forall a. Num a => a) means that this is any Num instance that we want it to be, but if the function expects an argument of type (forall a. Num a => a) , he wants something that could be any instance of Num that he selects. Therefore, we could give it polymorphic 5 , but not, say, Integer 5.
In many ways, you can think of polymorphic types, which means that a function takes a type as an additional argument that tells it which specific type we want to use for each type variable. Therefore, to see the difference between (forall m. TreeLike m => ma) -> Tree a and forall m. TreeLike m => ma -> Tree a forall m. TreeLike m => ma -> Tree a , you can read them as something like (M -> M a) -> Tree a vs. M -> M a -> Tree a .
source share