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!)

  • 6
    Regarding the type being inferred by the argument: Are you aware that sometimes the type of the argument is inferred from the type of the function?
    – user7043
    Jun 23, 2014 at 16:38
  • @delnan I wasn't aware of that... sounds like an answer to me. I had always figured the inference was bottom up, though I could see ambiguity resolution using type information from the other side of the type graph as you describe as a deciding factor... my mental image for this is return types at the bottom of the graph and function calls at the top, the resolution is an aggregate formed by folding up from the bottom, but that's not quite the whole picture, is what you're saying? Not surprisingly, in a dependently typed language with perfect inferrence this is probably more accurate.. Jun 23, 2014 at 16:56

1 Answer 1


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:

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)

  • I'm definitely looking forward to these type class constructs you are stipulating. -- The reason is: I don't have a problem, I can do Translate2 and Translate3d, but I'd rather not pollute the namespace.
    – A Sz
    Jun 24, 2014 at 6:57
  • I'm not a GHC dev, so it's just hear-say. I hope it happens too.
    – bstamour
    Jun 24, 2014 at 12:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.