gotchaMinor
Difference between row-polymorpism and bounded polymorpishm?
Viewed 0 times
polymorpishmpolymorpismdifferencebetweenandrowbounded
Problem
I recently came across this blog post by Brian McKenna explaining row polymorphism. This seemed like a wonderful idea to me, but then I realized it smells an awful lot like bounded parametric polymorphism:
With row-polymorphism:
With bounded parametric polymorphism:
Can someone clarify the differences to polymorphism between these two approaches?
With row-polymorphism:
sum: {x: int, y: int | rho} -> int
function sum r = r.x + r.yWith bounded parametric polymorphism:
sum: forall a int
function sum r = r.x + r.yCan someone clarify the differences to polymorphism between these two approaches?
Solution
So, there are a few differences:
-
In row polymorphism, you've bound $\rho$ to a name, so you can use it elsewhere. For example,
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
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.
-
In row polymorphism, you've bound $\rho$ to a name, so you can use it elsewhere. For example,
forall rho . rho -> {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} -> 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} ->int. But most systems with bounded subtyping would have non-polymorphic subtyping too, that would allow this, since most systems have `{x : 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.
Context
StackExchange Computer Science Q#71282, answer score: 3
Revisions (0)
No revisions yet.