Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在不同的名称空间中放置haskell字段名?_Haskell - Fatal编程技术网

如何在不同的名称空间中放置haskell字段名?

如何在不同的名称空间中放置haskell字段名?,haskell,Haskell,考虑以下两种类型: data Point=Point{x::Float,y::Float} data Rectangle = {upperLeft::Point, bottomRight::Point} data Square = {upperLeft::Point, bottomRight::Point} ghc编译器抱怨矩形中左上角的字段名与正方形的字段名冲突。这似乎很奇怪,因为从表面上看,每个字段名都应该在类型的命名空间中,否则就不能重用字段名,我怀疑这是一个足够常见的期望 例如,要定义

考虑以下两种类型:

data Point=Point{x::Float,y::Float}
data Rectangle = {upperLeft::Point, bottomRight::Point}
data Square = {upperLeft::Point, bottomRight::Point}
ghc编译器抱怨矩形中左上角的字段名与正方形的字段名冲突。这似乎很奇怪,因为从表面上看,每个字段名都应该在类型的命名空间中,否则就不能重用字段名,我怀疑这是一个足够常见的期望

例如,要定义我们编写的变量:

let a=Rectangle{upperLeft=Point 2 3, bottomRight=Point 7 7}
let a=Square{upperLeft=Point 2 3, bottomRight=Point 7 7}
从这里我们可以看到,我们应该能够期望每个字段名都应该在它们各自的类型名称空间中


我的用法是正确的还是我的期望是错误的?有没有办法解决这个问题?

在Haskell中,创建记录类型也会创建访问器函数。 例如,您可以在上面定义的任一变量上运行:
x(左上角a)
,得到2。 这是一个例子


您可以选择在记录上使用不同的字段名,或者将它们放在单独的模块中。因为每个模块都有自己的名称空间,如果您将Square放在Square模块中,将Rectangle放在Rectangle模块中,您将能够重用字段名。

您可以将Square构造函数放在Rectangle类型中,因为它实际上是该类型的一种特殊化

通过在GHCI中键入内容,这似乎可以很好地工作:

data Point
    = Point{x::Float,y::Float}
    deriving (Eq, Show)

data Rectangle
    = Rectangle {upperLeft::Point, bottomRight::Point}
    | Square    {upperLeft::Point, bottomRight::Point}
    deriving (Eq, Show)

let r = Rectangle (Point 3.0 4.0) (Point 4.0 2.0)
let s = Square (Point 2.0 4.0) (Point 4.0 2.0)
然后您可以同时调用这两个:

upperLeft s
upperLeft r
尽管您可能希望更改正方形,因为它必须满足一些约束:

data Rectangle
    = Rectangle {upperLeft::Point, bottomRight::Point}
    | Square    {upperLeft::Point, size::Float}
    deriving (Eq, Show)

由于对象可以通过其字段名访问,因此编译器必须能够从其字段名推断对象的类型。例如,在

boundingBox x = bottomRight x - upperLeft x
访问器
bottomRight
upperLeft
用于推断
x
的类型。如果允许多个类型具有相同的访问器名称,则无法推断该类型

为了避免名称冲突,一个常见的约定是在所有字段名称上都加上前缀。GHC项目中使用了此约定

data Rectangle = {rc_upperLeft :: Point, rc_bottomRight :: Point}
data Square =    {sq_upperLeft :: Point, sq_bottomRight :: Point}

将每种类型放在自己的模块中似乎有些过分。我意识到已经创建了访问器函数,但我更希望类型推断能够选择正确的字段名来使用。是的,我同意在这种情况下,将其拆分为模块感觉有点过头了。我可能只是更改字段名。类似于
rect upperLeft
的东西并不比
upperLeft
长一吨。我同意重复使用字段名似乎是一件有用且合理的事情,但据我所知,Haskell的记录无法做到这一点。