This is an interesting idea, but I am wondering does it work out well in practice?
Suppose I have this:
type alias Point2D = {x: Float, y: Float}
type alias PlusZ extends = {extends | z : Float}
type alias Point3D = PlusZ Point2D
{-| Distance projected onto the XY plane. -}
distanceXY : Point2D -> Float
distanceXY point = Math.sqrt (point.x * point.x + point.y * point.y)
2dpoint : Point2D
2dpoint = { x = 1, y = 1 }
3dpoint : Point3D
3dpoint = { x = 1, y = 1, z = 1 }
distanceXY 2dpoint -- type checks ok
distanceXY 3dpoint -- fails to type check as distance is not over an extensible type.
The distance function is not over an extensible record. Distance needs to be:
distanceXY : { a | x : Float, y : Float } -> Float
So that there is an ‘a’ free to match against the remaining fields or empty record {}.
Is this good enough reason to rule out making the extending type the extensible one?