Data Constructors with Same Name in Different Type Constructors – Why Disallowed?

haskell

The following declaration gives an error:

type Vec2d = (Float, Float)
type Vec3d = (Float, Float, Float)
-- Rect x y defines a rectangle spanning from (0,0) to (x,y)
data Obj2d = Rect Float Float
           | Translate Vec2d Obj2d
-- Cuboid x y z defines a cuboid spanning from (0,0,0) to (x,y,z)
data Obj3d = Cuboid Float Float Float
           | Translate Vec3d Obj3d

namely Multiple declarations of 'Translate'.

Now, I wonder why this limitation was introduced?

If the limitation were not there, one could write

Translate (1, 1) Rect 2 2
and
Translate (1, 2, 3) Cuboid 1 1 1, which sounds natural.

I don't (immediately) see how this could result in a parsing problem bidding to disallow using the same name, the type could be inferred by the argument (Rect 2 2 is an Obj2d, Cuboid 1 1 1 is an Obj3d).

I'm sure there is a good reason the language designers chose to disallow using the same name for data constructors of different types, but I'd like to learn: why, when it's not obviously necessary?

(And type disambiguation is the bread-and-butter business of Haskell!)

Best Answer

That's because data constructors are just functions, and function overloading is not allowed in Haskell. It might be more clear if you use GADT syntax to define your types:

{-# LANGUAGE GADTs #-}
data Obj2d where
    Rect :: Float -> Float -> Obj2d   -- a function from floats to obj2d's
    Translate :: Vec2d -> Obj2d       -- a function from vec2d's to Obj2d's

I believe they (the GHC devs) are working on possible solutions to this problem involving introducing a new type class for all types that share the same data constructor, or something similar. So stay tuned, a solution to your problem may be coming soon! (I hope)

Related Topic