Difference between row-polymorpism and bounded polymorpishm?
So, there are a few differences:


In row polymorphism, you've bound $\rho$ to a name, so you can use it elsewhere. For example, forall rho . rho -&gt; {x : int | rho} is expressible with row polymorphism, but not purely using bounded polymorphism. Likewise, you can even express field deletion this way: forall rho .{x : int | rho} -&gt; rho is a perfectly valid row-polymorphic type, but subtyping doesn't really have a way of expressing this.

Because row polymorphism lets you add and delete fields this way, usually it works with a "stack" semantics, so that old fields are shadowed when new fields of the same name are added.
Bounded subtyping uses, well, subtyping. So with row polymorphism, you can't give x : {x : int, y : int} as argument to a function of type {x : int} -&gt;int. But most systems with bounded subtyping would have non-polymorphic subtyping too, that would allow this, since most systems have {x : int} &lt;: {x : int, y : int}.


Bounded subtyping tends to be  bit more precise and flexible, and the "stack" semantics of row polymorphism don't arise that much. But inference is much easier for row polymorphism, and can work in the absence of any type annotations (for example, in Elm), which usually isn't the case in the presence of subtyping.