Следующая декларация выдает ошибку:
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
а именно Multiple declarations of 'Translate'
.
Теперь мне интересно, почему это ограничение было введено?
Если бы ограничения не было, можно было бы написать
Translate (1, 1) Rect 2 2
и
Translate (1, 2, 3) Cuboid 1 1 1
, что звучит естественно.
Я (сразу) не вижу, как это может привести к проблеме синтаксического анализа, запрещающей использование одного и того же имени, тип может быть выведен по аргументу ( Rect 2 2
is Obj2d
, Cuboid 1 1 1
is a Obj3d
).
Я уверен, что есть веская причина, по которой разработчики языка решили запретить использование одного и того же имени для конструкторов данных разных типов, но я хотел бы узнать: почему, когда это явно не нужно?
(И устранение неоднозначности типа - дело Хаскелла, связанное с хлебом и маслом!)
Ответы:
Это потому, что конструкторы данных - это просто функции, а перегрузка функций в Haskell недопустима. Это может быть более понятно, если вы используете синтаксис GADT для определения ваших типов:
Я полагаю, что они (разработчики GHC) работают над возможными решениями этой проблемы, включая введение нового
type class
для всех типов, которые используют один и тот же конструктор данных, или что-то подобное. Так что следите за обновлениями, решение вашей проблемы может появиться в ближайшее время! (Я надеюсь)источник
type class
конструкций, которые вы предусмотрели. - Причина в том , у меня нет проблем, я могу сделатьTranslate2
иTranslate3d
, но я предпочел бы не загрязнять пространство имен.