代码之家  ›  专栏  ›  技术社区  ›  paul

数据类型中的相同变量名

  •  3
  • paul  · 技术社区  · 6 年前

    为什么使用数据类型我不能为这些数据属性提供相同的内部属性名?

    这里我不能重用变量名 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)
    
    1 回复  |  直到 6 年前
        1
  •  4
  •   willeM_ Van Onsem    6 年前

    为什么使用数据类型我不能为这些数据属性提供相同的内部属性名?

    如果定义了记录类型,则隐式构造了一个“getter”。如果定义的记录数据类型如下:

    data Product = Product { val :: String } deriving (Show, Eq)
    

    然后Haskell将构造一个函数:

    val :: Product -> String
    

    获得 val 给定的 Product 对象。

    如果随后定义新的记录数据类型:

    data Price = Price { val :: Double } deriving (Show, Eq)
    

    然后定义两个版本 瓦尔 从而导致名称冲突。

    这个 DuplicateRecordFields 延伸

    这个 格拉斯哥Haskell编译器(GHC) 从8.0.1开始,有一个扩展 DuplicateRecordFields 允许指定两个字段名相同的记录数据类型。

    使用相同的记录名进行模式匹配或构造记录时没有问题,例如:

    productToPrice :: Product -> Price
    productToPrice (Product {val = x}) = Price { val = 3 }
    

    没有问题,因为 瓦尔 在里面 Product { val = x } 清楚地指 瓦尔 定义在 产品 数据建设者,以及 瓦尔 在里面 Price { val = 3 } 指的是 瓦尔 Price 数据构造函数。

    如果我们使用 瓦尔 作为函数,它将产生歧义:

    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
    

    我们可以添加函数的签名来指定 瓦尔 我们想使用:

    Prelude> (val :: Product -> String) (Product "foo")
    "foo"
    

    或者通过指定 Product "foo" 我们得到了同样的效果:

    Prelude> val (Product "foo" :: Product)
    "foo"
    

    鉴于 瓦尔 但是,具有相同的类型,或者具有某种通用含义,最好引入一个typeclass,从而定义 瓦尔 功能在那里。