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

时间:2014-07-18 13:50:53

标签: haskell terminology

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

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

他们是同义词吗?

两者之间有什么区别吗?如果有,那是什么?

3 个答案:

答案 0 :(得分:21)

类型(在Haskell中)是一段语法,可以有意义地放在::的右边,以对::左边的表达式进行分类。类型的每个句法组件本身都按种类进行分类,其中类型(对表达式进行分类)的类型为*有些人乐于使用“#34; type"引用类型语法的任何组件,无论它是否允许它对表达式进行分类。

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

  1. 类型同义词,例如type Foo x y z = [x] -> IO (y, z),添加完全应用的表单的类型组件Foo x y z ,根据其定义的等式扩展宏观时尚。
  2. 数据声明,例如,data Goo x y z = ThisGoo x | ThatGoo (Goo y z x)为类型的语法引入了一个全新的类型构造函数符号Goo,用于构建对数据构造函数生成的值进行分类的类型,此处为ThisGooThatGoo
  3. newtype 声明,例如newtype Noo x y z = MkNoo (x, [y], z)制作现有类型的副本,该类型与类型语法中的原始类型不同。
  4. 如果类型包含类型变量,则可以用其他类型组件替换多态:按多态类型分类的值可以专用到类型变量的任何替换实例。例如。 append (++) :: [a] -> [a] -> [a]适用于其元素具有相同类型但任何类型都可以执行的列表。具有多态类型的值通常被称为"多态值"。

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

    当然,按类型分类的所有第一类值在某种意义上都是"数据",而在Haskell中,类型不用于分类任何不是一等值的东西,所以在那里更宽松的感觉,每个"类型"是一种"数据类型"。在除了具有类型的数据之外的东西(例如,Java中的方法)的语言中,区别变得更有意义。

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

    我担心的结果很模糊。

答案 1 :(得分:3)

在这种情况下,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时不再对它们感到困惑

答案 2 :(得分:0)

typedata type指的是相同的概念,polymorphic typepolymorphic data type也是如此。

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

data Maybe a = Just a | Nothing

我可以说我刚刚定义了一个多态数据类型Maybe,其中包含多态类型参数a