Por que construtores de dados com o mesmo nome não são permitidos em construtores de tipos diferentes?

11

A seguinte declaração apresenta um erro:

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'.

Agora, eu me pergunto por que essa limitação foi introduzida?

Se a limitação não existisse, alguém poderia escrever

Translate (1, 1) Rect 2 2 e Translate (1, 2, 3) Cuboid 1 1 1, o que parece natural.

Não vejo (imediatamente) como isso pode resultar em um problema de análise ao tentar proibir o uso do mesmo nome; o tipo pode ser inferido pelo argumento ( Rect 2 2é um Obj2d, Cuboid 1 1 1é um Obj3d).

Tenho certeza de que há uma boa razão pela qual os designers de linguagem optaram por não permitir o uso do mesmo nome para construtores de dados de tipos diferentes, mas eu gostaria de aprender: por que, quando não é obviamente necessário?

(E a desambiguação de tipo é o negócio de pão com manteiga de Haskell!)

A Sz
fonte
3
Em relação ao tipo que está sendo deduzido pelo argumento: Você está ciente de que, às vezes, o tipo de argumento é inferido a partir do tipo da função ?
@ delnan Eu não estava ciente disso ... parece uma resposta para mim. Eu sempre achei que a inferência era de baixo para cima, embora eu pudesse ver a resolução de ambiguidade usando informações de tipo do outro lado do gráfico de tipos, como você descreve como um fator decisivo ... minha imagem mental para isso são tipos de retorno na parte inferior do chamadas de gráfico e função na parte superior, a resolução é um agregado formado pela dobra para baixo, mas essa não é a imagem toda , é o que você está dizendo? Não surpreendentemente, em uma linguagem dependente digitado com perfeita extrapolação esta é provavelmente mais precisa ..
Jimmy Hoffa

Respostas:

13

Isso ocorre porque os construtores de dados são apenas funções e a sobrecarga de funções não é permitida no Haskell. Pode ficar mais claro se você usar a sintaxe do GADT para definir seus 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

Eu acredito que eles (os desenvolvedores do GHC) estão trabalhando em possíveis soluções para esse problema, envolvendo a introdução de um novo type classpara todos os tipos que compartilham o mesmo construtor de dados ou algo semelhante. Portanto, fique atento, uma solução para o seu problema pode estar em breve! (Eu espero)

bstamour
fonte
Definitivamente, estou ansioso por essas type classconstruções que você está estipulando. - O motivo é: não tenho um problema, posso fazer Translate2e Translate3d, mas prefiro não poluir o espaço para nome.
Um Sz
Eu não sou um desenvolvedor do GHC, então é só ouvir dizer. Espero que isso aconteça também.
bstamour