为什么Haskell/GHC不支持记录名称重载

Ral*_*lph 15 haskell naming record

我是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)
Run Code Online (Sandbox Code Playgroud)

当我编译这个时,我得到:

[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
Run Code Online (Sandbox Code Playgroud)

鉴于Haskell类型系统的"强度",编译器似乎应该很容易确定要访问哪个字段

emp = Employee "Joe" "Smith" "111-22-3333"
man = Manager "Mary" "Jones" "333-22-1111" [emp]
firstName man
firstName emp
Run Code Online (Sandbox Code Playgroud)

是否有一些我没有看到的问题.我知道Haskell报告不允许这样做,但为什么不呢?

Don*_*art 16

历史原因.有 许多相互竞争的设计更好的记录系统哈斯克尔-其实这么多,那没有达成共识可以达成.然而.


Ben*_*Ben 9

目前的记录系统不是很复杂.如果没有记录语法,那么对于你可以使用样板文做的事情来说,它主要是一些语法糖.

特别是,这个:

data Employee = Employee
  { firstName :: String
  , lastName :: String
  , ssn :: String
  } deriving (Show, Eq)
Run Code Online (Sandbox Code Playgroud)

生成(除其他外)一个函数firstName :: Employee -> String.

如果您还允许在同一模块中使用此类型:

data Manager = Manager
  { firstName :: String
  , lastName :: String
  , ssn :: String
  , subordinates :: [Employee]
  } deriving (Show, Eq)
Run Code Online (Sandbox Code Playgroud)

那么firstName函数的类型是什么?

它必须是重载相同名称的两个独立函数,Haskell不允许这样做.除非你想象这会隐式生成一个类型类并为所有命名的字段创建它的实例firstName(在一般情况下变得混乱,当字段可能有不同的类型时),那么Haskell的当前记录系统将无法实现在同一模块中支持多个具有相同名称的字段.Haskell目前甚至都没有尝试过这样的事情.

当然,它可以做得更好.但是有一些棘手的问题需要解决,基本上没有人能够找到解决方案,让大家相信还有一个最有前途的方向.