Ответ 1
Исторические причины. Там были многие конкурирующие проекты для лучших систем записи для Haskell - так много на самом деле, что нет консенсуса. Тем не менее.
Я новичок Haskell. Я заметил, что Haskell не поддерживает перегрузку имен:
-- Records.hs
data Employee = Employee
{ firstName :: String
, lastName :: String
, ssn :: String
} deriving (Show, Eq)
data Manager = Manager
{ firstName :: String
, lastName :: String
, ssn :: String
, subordinates :: [Employee]
} deriving (Show, Eq)
Когда я скомпилирую это, я получаю:
[1 of 1] Compiling Main ( Records.hs, Records.o )
Records.hs:10:5:
Multiple declarations of `firstName'
Declared at: Records.hs:4:5
Records.hs:10:5
Records.hs:11:5:
Multiple declarations of `lastName'
Declared at: Records.hs:5:5
Records.hs:11:5
Records.hs:12:5:
Multiple declarations of `ssn'
Declared at: Records.hs:6:5
Records.hs:12:5
Учитывая "силу" системы типа Haskell, кажется, что компилятору должно быть легко определить, какое поле для доступа в
emp = Employee "Joe" "Smith" "111-22-3333"
man = Manager "Mary" "Jones" "333-22-1111" [emp]
firstName man
firstName emp
Есть ли какая-то проблема, которую я не вижу. Я знаю, что отчет Haskell не позволяет этого, но почему бы и нет?
Исторические причины. Там были многие конкурирующие проекты для лучших систем записи для Haskell - так много на самом деле, что нет консенсуса. Тем не менее.
Текущая система записи не очень сложна. В основном это синтаксический сахар для вещей, которые вы могли бы сделать с шаблоном, если не было синтаксиса записей.
В частности, это:
data Employee = Employee
{ firstName :: String
, lastName :: String
, ssn :: String
} deriving (Show, Eq)
генерирует (помимо прочего) функцию firstName :: Employee -> String
.
Если вы также разрешите в том же модуле этого типа:
data Manager = Manager
{ firstName :: String
, lastName :: String
, ssn :: String
, subordinates :: [Employee]
} deriving (Show, Eq)
то каким будет тип функции firstName
?
Это должно быть две отдельные функции, перегружающие одно и то же имя, которое Haskell не позволяет. Если вы не предполагаете, что это неявно генерирует класс typeclass и создает экземпляры для всего с полем с именем firstName
(становится беспорядочным в общем случае, когда поля могут иметь разные типы), то текущая система записи Haskell не собирается чтобы иметь возможность поддерживать несколько полей с тем же именем в одном модуле. В настоящее время Хаскелл даже не пытается сделать такую вещь.
Конечно, это можно было бы сделать лучше. Но есть некоторые сложные проблемы для решения, и, по сути, никто не придумывает решений для них, которые убедили всех, что есть самое перспективное направление для продвижения.
Один из вариантов избежать этого - поместить ваши типы данных в разные модули и использовать квалифицированный импорт. Таким образом, вы можете использовать одни и те же устройства доступа к полю в разных записях данных и сохранять код чистым и читаемым.
Вы можете создать один модуль для сотрудника, например
module Model.Employee where
data Employee = Employee
{ firstName :: String
, lastName :: String
, ssn :: String
} deriving (Show, Eq)
И один модуль для Менеджера, например:
module Model.Manager where
import Model.Employee (Employee)
data Manager = Manager
{ firstName :: String
, lastName :: String
, ssn :: String
, subordinates :: [Employee]
} deriving (Show, Eq)
И затем, где бы вы ни захотели использовать эти два типа данных, вы можете импортировать их и получить доступ к ним следующим образом:
import Model.Employee (Employee)
import qualified Model.Employee as Employee
import Model.Manager (Manager)
import qualified Model.Manager as Manager
emp = Employee "Joe" "Smith" "111-22-3333"
man = Manager "Mary" "Jones" "333-22-1111" [emp]
name1 = Manager.firstName man
name2 = Employee.firstName emp
Имейте в виду, что в конце концов вы используете два разных типа данных, и, таким образом, Manger.firstName - это еще одна функция, чем Employee.firstName, даже если вы знаете, что оба типа данных представляют человека, и у каждого человека есть имя. Но вам решать, как далеко вы перейдете к абстрактным типам данных, например, для создания типа данных Person из этих "коллекций атрибутов".