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 2
jest to Obj2d
, Cuboid 1 1 1
jest 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!)
Odpowiedzi:
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:
Wierzę, że oni (deweloperzy GHC) pracują nad możliwymi rozwiązaniami tego problemu polegającymi na wprowadzeniu nowego
type class
dla 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ę)źródło
type class
konstrukcji, które proponujesz . - Powodem jest to: Nie mam problemu, mogę to zrobićTranslate2
iTranslate3d
, ale wolałbym nie zanieczyszczają nazw.