有什么方法可以使用 class 的名称作为常用数据类型的名称吗?
Is there any way of using name of class as a name of usual data type?
嗯,我有两个结构(两个 ADT)Cashier
和 Porter
,它们有共同的 属性 salary
。它是通过实现 class Worker
.
实现的
type Money = Int
type Kg = Int
class Worker a where
salary :: a -> Money
data Cashier = C { salaryC :: Money
, polite :: Bool
}
instance Worker Cashier where
salary = salaryC
data Porter = P { salaryP :: Money
, liftingForce :: Kg
}
instance Worker Porter where
salary = salaryP
共同的界面意味着共同的行动。这使我能够不编写使用给定 ADT 的公共 属性 的任何函数的两种不同变体。
例如:
hasSalary :: (Worker a) => a -> Bool
hasSalary x = (salary x) > 0
但是当我尝试声明另一种类型时,例如 data Stuff = S [Worker]
编译器不允许我这样做。
当然也行不通 type Stuff = [(Worker a) => a]
或 (Worker a) => type Stuff = [a]
是的,有数据类型构造函数:
data (Worker a) => Stuff a = S [a]
甚至 GADT 的版本:
data Stuff a where
S :: Worker a => [a] -> Stuff [a]
但这不是我真正想要的。因为每次我使用 Stuff
时,Stuff Cashier
和 Stuff Porter
之间都会有区别。
因此,是否有使用 class' 名称 Worker
作为结构中字段类型的任何变体,就像它是通常的数据类型(Int
对于例如)?
在阅读 this piece of mandatory reading 之前,请勿使用此答案中的任何内容。
如果我没看错(或者,猜到真的,不太清楚),你要的是异构集合:一个可以包含 Cashier
s 和 Porter
s 的任意组合的列表。毕竟 List<Worker>
在 Java.
这样的语言中就是这样
为此,
type Stuff = [(Worker a) => a]
是你尝试过的有意义的东西:a
必须只出现在列表条目中,而不是在整体数据类型中(因为那样它们就被限制为相同的类型)。
事实上,如果 Haskell 有一个 存在量词 :
,那么尝试 将 成功
type Stuff = [∃ a . Worker a => a]
Haskell 没有那个,但是可以将存在性包装在 GADT 中:
data AWorker where
AWorker :: Worker a => a -> AWorker
type Stuff = [AWorker]
嗯,我有两个结构(两个 ADT)Cashier
和 Porter
,它们有共同的 属性 salary
。它是通过实现 class Worker
.
type Money = Int
type Kg = Int
class Worker a where
salary :: a -> Money
data Cashier = C { salaryC :: Money
, polite :: Bool
}
instance Worker Cashier where
salary = salaryC
data Porter = P { salaryP :: Money
, liftingForce :: Kg
}
instance Worker Porter where
salary = salaryP
共同的界面意味着共同的行动。这使我能够不编写使用给定 ADT 的公共 属性 的任何函数的两种不同变体。
例如:
hasSalary :: (Worker a) => a -> Bool
hasSalary x = (salary x) > 0
但是当我尝试声明另一种类型时,例如 data Stuff = S [Worker]
编译器不允许我这样做。
当然也行不通 type Stuff = [(Worker a) => a]
或 (Worker a) => type Stuff = [a]
是的,有数据类型构造函数:
data (Worker a) => Stuff a = S [a]
甚至 GADT 的版本:
data Stuff a where
S :: Worker a => [a] -> Stuff [a]
但这不是我真正想要的。因为每次我使用 Stuff
时,Stuff Cashier
和 Stuff Porter
之间都会有区别。
因此,是否有使用 class' 名称 Worker
作为结构中字段类型的任何变体,就像它是通常的数据类型(Int
对于例如)?
在阅读 this piece of mandatory reading 之前,请勿使用此答案中的任何内容。
如果我没看错(或者,猜到真的,不太清楚),你要的是异构集合:一个可以包含 Cashier
s 和 Porter
s 的任意组合的列表。毕竟 List<Worker>
在 Java.
为此,
type Stuff = [(Worker a) => a]
是你尝试过的有意义的东西:a
必须只出现在列表条目中,而不是在整体数据类型中(因为那样它们就被限制为相同的类型)。
事实上,如果 Haskell 有一个 存在量词 :
,那么尝试 将 成功type Stuff = [∃ a . Worker a => a]
Haskell 没有那个,但是可以将存在性包装在 GADT 中:
data AWorker where
AWorker :: Worker a => a -> AWorker
type Stuff = [AWorker]