[英]Haskell terminology: meaning of type vs. data type, are they synonyms?
我正在读这本书:Haskell表达学派和第56页,在第5章的开头,我读了“多态数据类型”和“多态类型”这两个术语。
这两个术语是指同一个概念吗?
他们是同义词吗?
或者这两者有什么区别? 如果有,那是什么?
一个类型 (在Haskell中)是一段语法,它可以有意义地放在::
以对::
左边的表达式进行分类。 一个类型的每个语法成分本身分类由一种 ,其中该种类型(其分类表达式)是*
。 有些人乐于使用“type”这个词来引用类型语法的任何组件,无论它是否允许它对表达式进行分类。
类型的语法可以通过各种声明形式进行扩展。
type Foo xyz = [x] -> IO (y, z)
,添加完全应用的形式Foo
x y z的类型分量,其根据其定义的等式扩展宏观方式。 data Goo xyz = ThisGoo x | ThatGoo (Goo yzx)
data Goo xyz = ThisGoo x | ThatGoo (Goo yzx)
在类型语法中引入了一个新的类型构造函数符号Goo
,用于构建对数据构造函数生成的类进行分类,这里是ThisGoo
和ThatGoo
。 newtype Noo xyz = MkNoo (x, [y], z)
生成现有类型的副本,该类型与类型语法中的原始类型不同。 如果类型包含可以用其他类型组件替换的类型变量 ,则该类型是多态的 :按多态类型分类的值可以专用于类型变量的任何替换实例。 例如append (++) :: [a] -> [a] -> [a]
适用于其元素具有相同类型的列表,但任何类型都可以。 具有多态类型的值通常被称为“多态值”。
有时,“数据类型”用于简单地表示由data
声明引入的类型。 从这个意义上讲,所有数据类型都是类型,但并非所有类型都是数据类型。 非数据类型的类型示例包括IO ()
和Int -> Int
。 此外, Int
在这个意义上不是数据类型:它是一种硬连线原始类型。 为避免疑问,有些人将这些类型称为代数数据类型,因为构造函数给出了代数,意思是“通过组合其他值来构建值的一堆操作”。 “多态数据类型”是其中包含类型变量的数据类型,例如[(a, Bool)]
,与[Int]
形成对比。 有时人们谈论“声明多态数据类型”或者说“ Maybe
是多态数据类型”之类的东西,当它们真正意味着类型构造函数具有参数(并因此可以用于形成多态类型)时:迂腐地,人们会这样做声明一个多态数据类型,但不是任何旧的多态数据类型,而是应用于形式参数的类型构造函数)。
当然,按类型分类的所有第一类值在某种意义上都是“数据”,而在Haskell中,类型不用于对任何不是一等值的任何事物进行分类,因此在较宽松的意义上,每个“类型”都是一个“数据类型”。 在除了具有类型的数据之外的东西(例如,Java中的方法)的语言中,区别变得更有意义。
非正式使用通常位于中间,而且定义不明确。 人们经常在功能或过程与它们运行的东西(“数据”)之间进行某种区分。 或者他们可能会认为数据是“根据他们制作的方式理解”(并通过模式匹配来揭示他们的表现形式),而不是“根据他们使用的方式理解”。 最后一次使用“数据”对于抽象数据类型的概念有点不舒服,这是一种隐藏底层东西表示的类型。 因此,表示隐藏抽象数据类型与表示暴露代数数据类型的对比相当强烈,这就是为什么“ADT”被随意地用作两者的缩写是相当不幸的。
我担心,结果是模糊的。
在这种情况下, data type
和type
是同义词。 但是,我承认可能会出现混淆,因为Haskell有两个关键字data
和type
,它们执行两个非常不同的功能。 为了保持清晰的区分,重要的是要注意上下文。 无论何时谈论签名或类型中的类型 ,术语“数据类型”和“类型”几乎总是指同一件事。 无论何时谈论在代码中声明类型 ,都会有所不同。
使用data
声明的类型是一种新的用户定义类型,因此您可以执行类似的操作
data Status = Ready | NotReady | Exploded
Ready
, NotReady
和Exploded
是Haskell中未包含的新构造函数。
另一方面, type
关键字只是为现有类型创建了一个别名 :
type Status = String
ready, notReady, exploded :: Status
ready = "Ready"
notReady = "NotReady"
exploded = "Exploded"
这里, Status
只是String
的别名,在任何使用String
地方都可以使用Status
,反之亦然。 没有任何构造函数,只需要使用预先构建的值。 这种方法远不那么安全,如果你使用这样的东西,你会在某些时候遇到错误。 type
声明通常用于使某些参数更清楚地表明它们的用途,例如
type FilePath = String
这是GHC中的内置别名,如果你看到一个函数
doSomething :: FilePath -> IO ()
然后你知道立即传递一个文件名,相比之下
doSomething :: String -> IO ()
你不知道这个功能是做什么的,除了“某事”。 它们也常用于减少打字,例如:
type Point = (Double, Double)
现在,您可以在类型签名中使用Point
而不是(Double, Double)
,这样写入更短,更易读。
总而言之, data
声明了一个全新的类型,完全是为您定制的, type
应该重命名为alias
以便人们在第一次接近Haskell时不再对它们感到困惑。
type
和data type
是指相同的概念, polymorphic type
和polymorphic data type
。
为了说明两个短语可以完全使用的情况(没有任何意义上的差异),请考虑这个表达式
data Maybe a = Just a | Nothing
我可以说我刚刚定义了一个多态数据类型Maybe
,带有多态类型参数a
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.