为什么使用数据类型时不能为这些数据属性提供相同的内部属性名称?
在这里,我无法在多个数据中重用变量名val
不编译
data Product = Product {val::String}deriving (Show, Eq)
data Price = Price {val::Double}deriving (Show, Eq)
data Discount = Discount { val::Double }deriving (Show, Eq)
编译
data Product = Product {productVal::String}deriving (Show, Eq)
data Price = Price {priceVal::Double}deriving (Show, Eq)
data Discount = Discount { discountVal::Double }deriving (Show, Eq)
答案 0 :(得分:4)
为什么使用数据类型时不能为这些数据属性提供相同的内部属性名称?
如果定义记录类型,则隐式构造了一个“ getter”。如果您定义记录数据类型,例如:
data Product = Product { val :: String } deriving (Show, Eq)
然后Haskell将构造一个函数:
val :: Product -> String
获得给定val
对象的Product
。
如果以后再定义新的记录数据类型:
data Price = Price { val :: Double } deriving (Show, Eq)
然后,您定义val
的两个版本,从而导致名称冲突。
DuplicateRecordFields
扩展名 格拉斯哥Haskell编译器(GHC)自8.0.1起具有扩展名DuplicateRecordFields
,该扩展名允许指定两个具有相同字段名称的记录数据类型。
使用相同的记录名称进行模式匹配或构造记录时没有问题,例如:
productToPrice :: Product -> Price
productToPrice (Product {val = x}) = Price { val = 3 }
不会造成任何问题,因为val
中的Product { val = x }
显然引用了val
数据构造函数中定义的Product
和{{1}中的val
}指的是Price { val = 3 }
数据构造函数的val
。
但是,如果我们使用Price
作为函数,则会产生歧义:
val
我们可以添加函数的签名以指定要使用的Prelude> val (Product "foo")
<interactive>:15:1: error:
Ambiguous occurrence ‘val’
It could refer to either the field ‘val’,
defined at <interactive>:1:25
or the field ‘val’, defined at <interactive>:2:21
:
val
或通过指定Prelude> (val :: Product -> String) (Product "foo")
"foo"
的类型,我们获得相同的效果:
Product "foo"
鉴于Prelude> val (Product "foo" :: Product)
"foo"
具有相同的类型或具有某种通用含义,最好引入类型类,然后在其中定义val
函数。