我正在读这本书:Haskell表达学派和第56页,在第5章的开头,我读到了术语“多态数据类型”和“多态类型”。
这两个术语是指同一个概念吗?
他们是同义词吗?
两者之间有什么区别吗?如果有,那是什么?
答案 0 :(得分:21)
类型(在Haskell中)是一段语法,可以有意义地放在::
的右边,以对::
左边的表达式进行分类。类型的每个句法组件本身都按种类进行分类,其中类型(对表达式进行分类)的类型为*
。 有些人乐于使用“#34; type"引用类型语法的任何组件,无论它是否允许它对表达式进行分类。
类型的语法可以通过各种声明形式进行扩展。
type Foo x y z = [x] -> IO (y, z)
,添加完全应用的表单的类型组件Foo
x y z ,根据其定义的等式扩展宏观时尚。data Goo x y z = ThisGoo x | ThatGoo (Goo y z x)
为类型的语法引入了一个全新的类型构造函数符号Goo
,用于构建对数据构造函数生成的值进行分类的类型,此处为ThisGoo
和ThatGoo
。newtype Noo x y z = MkNoo (x, [y], z)
制作现有类型的副本,该类型与类型语法中的原始类型不同。如果类型包含类型变量,则可以用其他类型组件替换多态:按多态类型分类的值可以专用到类型变量的任何替换实例。例如。 append (++) :: [a] -> [a] -> [a]
适用于其元素具有相同类型但任何类型都可以执行的列表。具有多态类型的值通常被称为"多态值"。
有时,"数据类型"用来简单地表示由data
声明引入的类型。从这个意义上讲,所有数据类型都是类型,但并非所有类型都是数据类型。非数据类型的类型示例包括IO ()
和Int -> Int
。此外,Int
不是此意义上的数据类型:它是硬连线的原始类型。为避免疑问,有些人将这些类型称为代数数据类型,因为构造函数给出了代数,意思是"通过组合其他值来构建值的一堆操作"。 A"多态数据类型"是一种包含类型变量的数据类型,例如[(a, Bool)]
,而不是[Int]
。有时人们谈论"声明多态数据类型"或者说" Maybe
之类的东西是多态数据类型"当他们真正只是意味着类型构造函数具有参数(并因此可以用于形成多态类型)时:迂腐地,人们确实声明了多态数据类型,但没有任何旧的多态数据类型,而是应用于形式参数的类型构造函数)。
当然,按类型分类的所有第一类值在某种意义上都是"数据",而在Haskell中,类型不用于分类任何不是一等值的东西,所以在那里更宽松的感觉,每个"类型"是一种"数据类型"。在除了具有类型的数据之外的东西(例如,Java中的方法)的语言中,区别变得更有意义。
非正式使用通常位于中间,而且定义不明确。人们经常在功能或过程与他们操作的东西("数据")之间进行某种区分。或者他们可能会认为数据是按照他们制作的方式理解的。 (并且例如通过模式匹配暴露他们的表示)而不是根据他们使用的方式理解#34;。最后一次使用"数据"对于抽象数据类型的概念有点不舒服,这是一种隐藏底层东西表示的类型。因此,表示隐藏的抽象数据类型与表示 - 暴露代数数据类型相当强烈地对比,这就是为什么它是相当不幸的" ADT"随便用作两者的缩写。
我担心的结果很模糊。
答案 1 :(得分:3)
在这种情况下,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时不再对它们感到困惑
答案 2 :(得分:0)
type
和data type
指的是相同的概念,polymorphic type
和polymorphic data type
也是如此。
为了说明两个短语可以完全使用的情况(没有任何意义上的差异),请考虑这个表达式
data Maybe a = Just a | Nothing
我可以说我刚刚定义了一个多态数据类型Maybe
,其中包含多态类型参数a
。