Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.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 无法分析data/newtype声明中的数据构造函数_Haskell - Fatal编程技术网

Haskell 无法分析data/newtype声明中的数据构造函数

Haskell 无法分析data/newtype声明中的数据构造函数,haskell,Haskell,我有类型卡,包括西装和等级 data Suit = A|B deriving (Show, Eq) data Rank = 1|2 deriving (Show, Eq) data Card = Card Suit Rank deriving (Show, Eq) data Rank函数似乎是错误的,因为Int不能是类型构造函数,如果我的卡是A1 | B1 | A2 | B2,如何创建正确的函数 谢谢你这句话看起来像是: data Suit = A | B 只是将类型Suit定义为任意对象的

我有类型卡,包括西装和等级

data Suit = A|B deriving (Show, Eq)
data Rank = 1|2 deriving (Show, Eq)
data Card = Card Suit Rank deriving (Show, Eq)
data Rank函数似乎是错误的,因为Int不能是类型构造函数,如果我的卡是A1 | B1 | A2 | B2,如何创建正确的函数


谢谢你

这句话看起来像是:

data Suit = A | B
只是将类型Suit定义为任意对象的集合/集合。但实际上,它定义了三件事:类型Suit和两个用于创建该类型值的构造函数A和B

如果定义:

data Rank = 1 | 2
实际上是有效的,它不会将Rank定义为数字1和2的集合,而是将数字1和2重新定义为新类型Rank的构造函数/值,并且您将不再能够将它们用作常规数字。例如,表达式n+1现在将是一个类型错误,因为+需要一个数字,而1将被重新定义为秩

幸运或不幸的是,Haskell不接受数字作为构造函数名称——它们必须是以大写字母开头的有效标识符或以冒号开头的运算符

所以,有两种常用的方法来定义一种类型,比如表示数字子集的秩。第一个,如注释中所述,是定义它,就像您已经定义的一样,但通过使用大写字母前缀将数字更改为有效标识符:

data Rank = R1 | R2
这样做的优点是,它保证只能表示有效的列组。在这里,只允许排名1和2。如果有人试图在某个地方编写R3,它将不会工作,因为该构造函数尚未定义。最大的缺点是,这很快就会变得难以控制。如果这些是扑克牌,那么定义是:

data Rank = R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 | R9 | R10 | R11 | R12 | R13
比如说,为rummy的卡片分配点值的函数如下所示:

points :: Rank -> Int
points R1 = 10   -- Ace worth 10
points R2 = 2
points R3 = 3
...
points R9 = 9
points R10 = 10  -- 10 and face cards all worth 10
points R11 = 10
points R12 = 10
points R13 = 10
在实际代码中,您将使用更高级的Haskell特性(如派生的枚举实例)来处理此问题

第二种方法是根据现有的数字类型定义排名:

data Rank = Rank Int   -- actually, `data` would probably be `newtype`
这定义了两个东西,一个名为Rank的类型和一个名为Rank的构造函数。这没关系,因为类型和构造函数位于不同的名称空间中

在这个定义中,Rank不是定义为一组离散的值,由显式构造函数给出,每个值有一个构造函数,这个定义本质上使Rank类型成为一个Int,并用构造函数Rank标记

这种方法的缺点是现在可以创建无效的列组,因为有人可以编写列组14。优点是它通常更容易使用。例如,可以从秩中提取整数,因此可以将点定义为:

points :: Rank -> Int
points (Rank 1)             = 10  -- Ace is worth 10
points (Rank r) | r >= 10   = 10  -- 10 and face are worth 10
                | otherwise = r   -- rest are worth their rank
请注意,对于这组定义:

data Suit = A | B deriving (Show, Eq)
newtype Rank = Rank Int deriving (Show, Eq)
data Card = Card Suit Rank deriving (Show, Eq)
对于A1卡,您可以使用类似Card A Rank 1的表达式构造卡值

实际上还有第三种方法。有些人可能会完全跳过定义秩类型,然后编写:

data Suit = A | B deriving (Show, Eq)
data Card = Card Suit Int deriving (Show, Eq)
或使用类型别名编写等效代码:

data Suit = A | B deriving (Show, Eq)
type Rank = Int
data Card = Card Suit Rank deriving (Show, Eq)
请注意,这里的类型别名实际上只是用于文档。在这里,Rank和Int是完全相同的类型,可以互换使用。使用秩只是让代码更容易理解,因为它明确了程序员希望Int代表秩,而不是用于其他目的的整数


这种方法的主要优点是,您可以避免在很多地方包含单词Rank,例如,卡片写为Card A 1而不是Card A Rank 1,并且点的定义不需要模式匹配Rank r上的参数,等等。主要缺点是它模糊了秩和其他整数之间的区别,并使编程更容易出错,例如在打算使用点的位置使用秩,反之亦然。

语句可能看起来:

data Suit = A | B
只是将类型Suit定义为任意对象的集合/集合。但实际上,它定义了三件事:类型Suit和两个用于创建该类型值的构造函数A和B

如果定义:

data Rank = 1 | 2
实际上是有效的,它不会将Rank定义为数字1和2的集合,而是将数字1和2重新定义为新类型Rank的构造函数/值,并且您将不再能够将它们用作常规数字。例如,表达式n+1现在将是一个类型错误,因为+需要一个数字,而1将被重新定义为秩

幸运或不幸的是,Haskell不接受数字作为构造函数名称——它们必须是以大写字母开头的有效标识符或以冒号开头的运算符

所以,有两种常用的方法来定义一种类型,比如表示数字子集的秩。第一个,如注释中所述,是定义它,就像您已经定义的一样,但通过使用大写字母前缀将数字更改为有效标识符:

data Rank = R1 | R2
这样做的好处是 它保证只能表示有效的列组。在这里,只允许排名1和2。如果有人试图在某个地方编写R3,它将不会工作,因为该构造函数尚未定义。最大的缺点是,这很快就会变得难以控制。如果这些是扑克牌,那么定义是:

data Rank = R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 | R9 | R10 | R11 | R12 | R13
比如说,为rummy的卡片分配点值的函数如下所示:

points :: Rank -> Int
points R1 = 10   -- Ace worth 10
points R2 = 2
points R3 = 3
...
points R9 = 9
points R10 = 10  -- 10 and face cards all worth 10
points R11 = 10
points R12 = 10
points R13 = 10
在实际代码中,您将使用更高级的Haskell特性(如派生的枚举实例)来处理此问题

第二种方法是根据现有的数字类型定义排名:

data Rank = Rank Int   -- actually, `data` would probably be `newtype`
这定义了两个东西,一个名为Rank的类型和一个名为Rank的构造函数。这没关系,因为类型和构造函数位于不同的名称空间中

在这个定义中,Rank不是定义为一组离散的值,由显式构造函数给出,每个值有一个构造函数,这个定义本质上使Rank类型成为一个Int,并用构造函数Rank标记

这种方法的缺点是现在可以创建无效的列组,因为有人可以编写列组14。优点是它通常更容易使用。例如,可以从秩中提取整数,因此可以将点定义为:

points :: Rank -> Int
points (Rank 1)             = 10  -- Ace is worth 10
points (Rank r) | r >= 10   = 10  -- 10 and face are worth 10
                | otherwise = r   -- rest are worth their rank
请注意,对于这组定义:

data Suit = A | B deriving (Show, Eq)
newtype Rank = Rank Int deriving (Show, Eq)
data Card = Card Suit Rank deriving (Show, Eq)
对于A1卡,您可以使用类似Card A Rank 1的表达式构造卡值

实际上还有第三种方法。有些人可能会完全跳过定义秩类型,然后编写:

data Suit = A | B deriving (Show, Eq)
data Card = Card Suit Int deriving (Show, Eq)
或使用类型别名编写等效代码:

data Suit = A | B deriving (Show, Eq)
type Rank = Int
data Card = Card Suit Rank deriving (Show, Eq)
请注意,这里的类型别名实际上只是用于文档。在这里,Rank和Int是完全相同的类型,可以互换使用。使用秩只是让代码更容易理解,因为它明确了程序员希望Int代表秩,而不是用于其他目的的整数


这种方法的主要优点是,您可以避免在很多地方包含单词Rank,例如,卡片写为Card A 1而不是Card A Rank 1,并且点的定义不需要模式匹配Rank r上的参数,等等。主要缺点是它模糊了秩和其他整数之间的区别,并且更容易出现编程错误,例如在打算使用点的位置使用秩,反之亦然。

不能将整数用作数据构造函数名称。尝试类似于datarank=A1 | A2或R1 | R2,其中R表示秩?不能将整数用作数据构造函数名称。试试类似于data Rank=A1 | A2,或者R1 | R2,其中R表示秩?