¿Por qué no se permiten constructores de datos con el mismo nombre en constructores de diferentes tipos?

11

La siguiente declaración da un 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

a saber Multiple declarations of 'Translate'.

Ahora, me pregunto por qué se introdujo esta limitación.

Si la limitación no estuviera allí, uno podría escribir

Translate (1, 1) Rect 2 2 y Translate (1, 2, 3) Cuboid 1 1 1, lo que suena natural.

No veo (de inmediato) cómo esto podría resultar en un problema de análisis al intentar no usar el mismo nombre, el argumento podría inferir el tipo ( Rect 2 2es un Obj2d, Cuboid 1 1 1es un Obj3d).

Estoy seguro de que hay una buena razón por la que los diseñadores de idiomas decidieron no usar el mismo nombre para constructores de datos de diferentes tipos, pero me gustaría aprender: ¿por qué, cuando obviamente no es necesario?

(¡Y la desambiguación de tipos es el negocio de pan y mantequilla de Haskell!)

A Sz
fuente
3
Con respecto al tipo inferido por el argumento: ¿Es consciente de que a veces el tipo del argumento se infiere del tipo de la función ?
@delnan No estaba al tanto de eso ... suena como una respuesta para mí. Siempre pensé que la inferencia era de abajo hacia arriba, aunque pude ver la resolución de la ambigüedad utilizando la información de tipo del otro lado del gráfico de tipo, como usted describe como un factor decisivo ... mi imagen mental para esto es tipos de retorno en la parte inferior del llamadas de gráficos y funciones en la parte superior, la resolución es un agregado formado al plegarse desde la parte inferior, pero eso no es todo el panorama, ¿es lo que estás diciendo? No es sorprendente que en un lenguaje mecanografiado de forma dependiente con una inferencia perfecta esto sea probablemente más preciso ..
Jimmy Hoffa

Respuestas:

13

Esto se debe a que los constructores de datos son solo funciones, y la sobrecarga de funciones no está permitida en Haskell. Puede ser más claro si usa la sintaxis GADT para definir sus tipos:

{-# 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

Creo que ellos (los desarrolladores de GHC) están trabajando en posibles soluciones a este problema que implican la introducción de una nueva type classpara todos los tipos que comparten el mismo constructor de datos, o algo similar. ¡Estén atentos, una solución a su problema puede llegar pronto! (Espero)

bstamour
fuente
Definitivamente estoy ansioso por estas type classconstrucciones que está estipulando. - La razón es: no tengo un problema, puedo hacerlo Translate2y Translate3dprefiero no contaminar el espacio de nombres.
Un Sz
No soy un desarrollador de GHC, así que solo escucho decir. Espero que también suceda.
bstamour