在Haskell中,您可以定义不带构造函数的代数数据类型:
data Henk
但是没有构造函数的类型(或类型?)的目的是什么?
答案 0 :(得分:13)
类型级机制通常需要存在类型,但从不构造此类类型的值。
,例如,幻像类型:
module Example (Unchecked, Checked, Stuff()) where
data Unchecked
data Checked
data Stuff c = S Int String Double
check :: Stuff Unchecked -> Maybe (Stuff Checked)
check (S i s d) = if i>43 && ...
then Just (S i s d)
else Nothing
readFile :: Filepath -> IO (Stuff Unchecked)
readFile f = ...
workWithChecked :: Stuff Checked -> Int -> String
workWithChecked stuff i = ...
workWithAny :: Stuff any -> Int -> Stuff any
workWithAny stuff i = ...
只要模块没有导出S
构造函数,该库的用户就不能伪造"已检查" Stuff
数据类型的状态。
在上面,workWithChecked
函数不必在每次调用时清理输入。用户必须已经完成它,因为它必须在"已检查"中提供值。 type - 这意味着用户必须事先调用check
函数。这是一种高效且稳健的设计:我们不会在每次调用时反复重复检查,但我们不允许用户传递未经检查的数据。
请注意Checked
,Unchecked
类型的值是不重要的 - 我们从不使用它们。
正如评论中提到的其他人一样,空类型还有许多其他用途,而不是幻像类型。例如,一些GADT涉及空类型。 E.g。
data Z
data S n
data Vec n a where
Nil :: Vec Z a
Cons :: a -> Vec n a -> Vec (S n) a
上面我们使用空类型来记录类型中的长度信息。
此外,需要没有构造函数的类型来实现一些理论属性:如果我们寻找a
使Either a T
与T
同构,我们需要a
是空的。在类型理论中,空类型通常用作逻辑上类似的类型" false"命题。