Haskell 数据类型

发布于 2024-12-11 12:54:28 字数 454 浏览 1 评论 0原文

假设我有一个这样的类型(有效):

data WAE = Num Float
         | Id String
         | With [(String, WAE)] WAE -- This works, but I want to define it as below
         deriving(Eq, Read, Show)

我想要一个这样的类型(无效):

data WAE = Num Float
         | Id String
         | With [(Id, WAE)] WAE -- This doesn't work ("Id not in scope")
         deriving(Eq, Read, Show)

为什么我不能在 Haskell 中这样做?有什么想法可以达到类似的效果吗?

Let's say that I have a type like this (that works):

data WAE = Num Float
         | Id String
         | With [(String, WAE)] WAE -- This works, but I want to define it as below
         deriving(Eq, Read, Show)

I want a type like this (doesn't work):

data WAE = Num Float
         | Id String
         | With [(Id, WAE)] WAE -- This doesn't work ("Id not in scope")
         deriving(Eq, Read, Show)

Why can't I do that in Haskell? Any ideas in achieveing a similar effect?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

萌无敌 2024-12-18 12:54:28

在 Haskell 中,有两个不同的名称空间。一种用于值,一种用于类型。诸如Id之类的数据构造函数位于值命名空间中,而诸如String之类的类型构造函数以及类则位于类型命名空间中。这是可以的,因为没有上下文允许两者都被允许。

在数据类型的定义中,两个命名空间并存,因为您定义了一个新的类型构造函数和几个新的数据构造函数,同时引用了现有的类型构造函数。

data WAE = Num Float
         | Id String
         | With [(String, WAE)] WAE
         deriving(Eq, Read, Show)

这里,WAEFloatString(,)[]EqReadShow 都是类型世界中的名称,而 NumId< /code> 和 With 是值世界中的名称。混合它们没有任何意义,这就是为什么 Id 不在第二段代码的范围内,因为您处于类型上下文中,并且没有称为 ID 。

从你的问题来看,你想要做什么并不是100%清楚,但我怀疑它可能是这样的:

type Id = String   -- Or perhaps a newtype
data WAE = Num Float
         | Id Id
         | With [(Id, WAE)] WAE
         deriving(Eq, Read, Show)

请注意,因为命名空间是不同的,所以在两者中都有一个名为 Id 的东西是完全可以的。

In Haskell, there are two distinct namespaces. One for values, and one for types. Data constructors such as Id live in the value namespace, whereas type constructors such as String, as well as classes live in the type namespace. This is OK because there is no context where both would be allowed.

In the definition of a data type, the two namespaces live side by side, as you're defining a both a new type constructor and several new data constructors, while referring to existing type constructors.

data WAE = Num Float
         | Id String
         | With [(String, WAE)] WAE
         deriving(Eq, Read, Show)

Here, WAE, Float, String, (,), [], Eq, Read and Show are all names in the world of types, whereas Num, Id and With are names in the world of values. Mixing them does not make any sense, and this is why Id is not in scope in your second piece of code, as you are in a type context, and there is no type-level thing called Id.

It's not 100% clear from your question what you were trying to do, but I suspect it might be something like this:

type Id = String   -- Or perhaps a newtype
data WAE = Num Float
         | Id Id
         | With [(Id, WAE)] WAE
         deriving(Eq, Read, Show)

Note that because the namespaces are distinct, it's perfectly fine to have something called Id in both.

傲娇萝莉攻 2024-12-18 12:54:28

根据您的问题,我不完全确定您想要实现什么目标。 Haskell 的类型系统可以实现以下两种可能性。

data WAE = Num Float
         | Id String
         | With [(WAE, WAE)] WAE
         deriving (Eq, Read, Show)

然而,我不确定这是否是您想要的,因为它不仅仅允许在该对的第一部分中包含一个 id。

另一种可能性是为 id 创建一个新类型(或别名),如下所示:

data MyId = MyId String deriving (Eq, Read, Show)
data WAE = Num MyId Float
         | Id MyId
         | With [(MyId, WAE)] WAE 
         deriving (Eq, Read, Show)

请注意,MyId 也可以使用 newtypetype 创建,每个都给出一个稍微不同的含义。

但是,您不能使用 Id,因为它是需要类型的数据构造函数。

Based on your question, I'm not entirely sure what you are trying to accomplish. Here are two possibilities that are possible with Haskell's type-system.

data WAE = Num Float
         | Id String
         | With [(WAE, WAE)] WAE
         deriving (Eq, Read, Show)

I'm not sure this is what you want, however, because it allows for more than just an id in the first portion of the pair.

Another possibility is to create a new type (or alias) for the id, like so:

data MyId = MyId String deriving (Eq, Read, Show)
data WAE = Num MyId Float
         | Id MyId
         | With [(MyId, WAE)] WAE 
         deriving (Eq, Read, Show)

Note that MyId could also be created with either newtype or type, each giving a slightly different meaning.

You cannot, however use Id as it is a data-constructor, where a type is expected.

月依秋水 2024-12-18 12:54:28

此处:

     | With [(Id, WAE)] WAE

您在需要类型的上下文中使用数据构造函数 IdId 的类型是 WAE,因此如果将此行更改为:

     | With [(WAE, WAE)] WAE

它将编译,但结果可能不是您想要的。

如果您只是想表明所讨论的字符串在语义上是标识符,则可以使用类型别名:

type Id = String

data WAE = Num Float
         | Id Id
         | With [(Id, WAE)] WAE
         deriving(Eq, Read, Show)

Here:

     | With [(Id, WAE)] WAE

you are using a data constructor Id in a context where a type is expected. The type of Id is WAE, so if you change this line to:

     | With [(WAE, WAE)] WAE

it will compile, but the result is probably not what you want.

If you just want to show that the string in question is an identifier semantically, you can use a type alias:

type Id = String

data WAE = Num Float
         | Id Id
         | With [(Id, WAE)] WAE
         deriving(Eq, Read, Show)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文