繁体   English   中英

Haskell术语:类型与数据类型的含义,它们是同义词吗?

[英]Haskell terminology: meaning of type vs. data type, are they synonyms?

我正在读这本书:Haskell表达学派和第56页,在第5章的开头,我读了“多态数据类型”和“多态类型”这两个术语。

这两个术语是指同一个概念吗?

他们是同义词吗?

或者这两者有什么区别? 如果有,那是什么?

一个类型 (在Haskell中)是一段语法,它可以有意义地放在::以对::左边的表达式进行分类。 一个类型的每个语法成分本身分类由一种 ,其中该种类型(其分类表达式)是* 有些人乐于使用“type”这个词来引用类型语法的任何组件,无论它是否允许它对表达式进行分类。

类型的语法可以通过各种声明形式进行扩展。

  1. 类型同义词 ,例如, type Foo xyz = [x] -> IO (y, z) ,添加完全应用的形式Foo x y z的类型分量,其根据其定义的等式扩展宏观方式。
  2. 数据声明,例如, data Goo xyz = ThisGoo x | ThatGoo (Goo yzx) data Goo xyz = ThisGoo x | ThatGoo (Goo yzx)类型语法中引入了一个新的类型构造函数符号Goo ,用于构建对数据构造函数生成的类进行分类,这里是ThisGooThatGoo
  3. newtype声明,例如newtype Noo xyz = MkNoo (x, [y], z)生成现有类型的副本,该类型与类型语法中的原始类型不同。

如果类型包含可以用其他类型组件替换的类型变量 ,则该类型是多态的 :按多态类型分类的值可以专用于类型变量的任何替换实例。 例如append (++) :: [a] -> [a] -> [a]适用于其元素具有相同类型的列表,但任何类型都可以。 具有多态类型的值通常被称为“多态值”。

有时,“数据类型”用于简单地表示由data声明引入的类型。 从这个意义上讲,所有数据类型都是类型,但并非所有类型都是数据类型。 非数据类型的类型示例包括IO ()Int -> Int 此外, Int这个意义上不是数据类型:它是一种硬连线原始类型。 为避免疑问,有些人将这些类型称为代数数据类型,因为构造函数给出了代数,意思是“通过组合其他值来构建值的一堆操作”。 “多态数据类型”是其中包含类型变量的数据类型,例如[(a, Bool)] ,与[Int]形成对比。 有时人们谈论“声明多态数据类型”或者说“ Maybe是多态数据类型”之类的东西,当它们真正意味着类型构造函数具有参数(并因此可以用于形成多态类型)时:迂腐地,人们会这样做声明一个多态数据类型,但不是任何旧的多态数据类型,而是应用于形式参数的类型构造函数)。

当然,按类型分类的所有第一类值在某种意义上都是“数据”,而在Haskell中,类型不用于对任何不是一等值的任何事物进行分类,因此在较宽松的意义上,每个“类型”都是一个“数据类型”。 在除了具有类型的数据之外的东西(例如,Java中的方法)的语言中,区别变得更有意义。

非正式使用通常位于中间,而且定义不明确。 人们经常在功能或过程与它们运行的​​东西(“数据”)之间进行某种区分。 或者他们可能会认为数据是“根据他们制作的方式理解”(并通过模式匹配来揭示他们的表现形式),而不是“根据他们使用的方式理解”。 最后一次使用“数据”对于抽象数据类型的概念有点不舒服,这是一种隐藏底层东西表示的类型。 因此,表示隐藏抽象数据类型与表示暴露代数数据类型的对比相当强烈,这就是为什么“ADT”被随意地用作两者的缩写是相当不幸的。

我担心,结果是模糊的。

在这种情况下, data typetype是同义词。 但是,我承认可能会出现混淆,因为Haskell有两个关键字datatype ,它们执行两个非常不同的功能。 为了保持清晰的区分,重要的是要注意上下文。 无论何时谈论签名类型中的类型 ,术语“数据类型”和“类型”几乎总是指同一件事。 无论何时谈论在代码中声明类型 ,都会有所不同。

使用data声明的类型是一种新的用户定义类型,因此您可以执行类似的操作

data Status = Ready | NotReady | Exploded

ReadyNotReadyExploded是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时不再对它们感到困惑。

typedata type是指相同的概念, polymorphic typepolymorphic data type

为了说明两个短语可以完全使用的情况(没有任何意义上的差异),请考虑这个表达式

data Maybe a = Just a | Nothing

我可以说我刚刚定义了一个多态数据类型Maybe ,带有多态类型参数a

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM