Dlaczego konstruktory danych o tej samej nazwie są niedozwolone w konstruktorach różnych typów?

11

Następująca deklaracja zawiera błąd:

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

mianowicie Multiple declarations of 'Translate'.

Zastanawiam się teraz, dlaczego wprowadzono to ograniczenie?

Gdyby ograniczenia nie było, można by napisać

Translate (1, 1) Rect 2 2 i Translate (1, 2, 3) Cuboid 1 1 1, co brzmi naturalnie.

Nie widzę (od razu), w jaki sposób może to spowodować problem z analizą składni, który nie pozwala na użycie tej samej nazwy, typ można wywnioskować na podstawie argumentu ( Rect 2 2jest to Obj2d, Cuboid 1 1 1jest Obj3d).

Jestem pewien, że istnieje dobry powód, dla którego projektanci języków postanowili zabronić używania tej samej nazwy dla konstruktorów danych różnych typów, ale chciałbym się dowiedzieć: dlaczego, skoro nie jest to oczywiście konieczne?

(A ujednoznacznienie typu to sprawa firmy Haskell z chleba i masła!)

A Sz
źródło
3
Odnośnie do typu wywodzącego się z argumentu: Czy zdajesz sobie sprawę, że czasami typ argumentu wywodzi się z typu funkcji ?
@delnan Nie wiedziałem o tym ... brzmi dla mnie jak odpowiedź. Zawsze uważałem, że wnioskowanie było oddolne, chociaż mogłem zobaczyć dwuznaczność przy użyciu informacji o typie z drugiej strony wykresu typów, które opisujesz jako czynnik decydujący ... mój obraz mentalny tego typu to typy zwrotów na dole wykres i wywołania funkcji u góry, rozdzielczość jest agregatem utworzonym przez złożenie od dołu, ale to nie do końca cały obraz, tak mówisz? Nic dziwnego, że w języku pisanym w sposób zależny z doskonałym wnioskiem jest to prawdopodobnie bardziej dokładne.
Jimmy Hoffa

Odpowiedzi:

13

To dlatego, że konstruktory danych są tylko funkcjami, a przeciążanie funkcji nie jest dozwolone w Haskell. Może być bardziej jasne, jeśli używasz składni GADT do definiowania typów:

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

Wierzę, że oni (deweloperzy GHC) pracują nad możliwymi rozwiązaniami tego problemu polegającymi na wprowadzeniu nowego type classdla wszystkich typów, które mają ten sam konstruktor danych lub coś podobnego. Bądź na bieżąco, wkrótce możesz rozwiązać problem! (Mam nadzieję)

bstamour
źródło
Z pewnością nie mogę się doczekać tych type classkonstrukcji, które proponujesz . - Powodem jest to: Nie mam problemu, mogę to zrobić Translate2i Translate3d, ale wolałbym nie zanieczyszczają nazw.
A Sz
Nie jestem deweloperem GHC, więc to tylko powiedz. Mam nadzieję, że to się stanie.
bstamour