2012-04-20 35 views
13

我是Haskell的新手,目前正在通过Real World Haskell。本书说类型构造函数仅用于类型签名,而值构造函数用于实际代码中。它也给出了一个声明的例子,表明两者的名称是相互独立的。为什么首先需要两个构造函数,如果其中只有一个用于实际代码?由于我们不会在实际代码中使用类型构造函数,因此类型构造函数的用途是什么?为什么除了Haskell中的类型构造函数外,还有一个值构造函数?

+11

短语“实际代码”是不幸的,因为它暗示你不会在程序中使用类型构造函数,而作者实际上是指类型构造函数仅用于类型注释。这相当于说你在C中不需要关键字“int”或“long”,因为你在实际代码中不使用它们(它们只用于声明中,它不被视为“实际代码“按此标准)。 – 2012-04-20 10:24:30

+0

...不接受? :) – 2012-11-27 14:26:32

回答

22

也许名字有​​点误导。 A 类型构造函数表示您声明的类型的名称。它们就是这样调用的,因为它们构建的是类型,而不是值:实际上,(可能)对类型变量进行参数化,它们定义了一系列类型。它们的行为类似于C++的模板和Java的泛型。在data MyType a b = Constr a b中,MyType是一个类型构造函数,它需要两种类型ab来构建一个新类型(MyType a b)

A 值构造函数是您在其他(面向对象)语言中称为“构造函数”的唯一部分,因为您需要它来构建该类型的值。因此,在前面的示例中,如果采用值构造函数Constr :: a -> b -> MyType a b,则可以创建值Constr "abc" 'd' :: MyType [Char] Char

+2

请问如何改进我的答案摆脱那-1?怎么了? – 2012-04-20 13:42:09

7

一种方便的方式来获取有关类型和值的直觉是,前者是编译时值,而后者则是运行时值。换句话说,Type构造函数是Haskell类型集合中值的构造方法,唯一目的是在编译时键入您的程序。这也意味着你不能在运行时构造一个类型,并且你不能在编译时构造一个值。所以,因为你不能在运行时根据类型值显式地分支(尽管你可以隐式地使用类型类型),所以类型构造函数作为运行时对象是完全没用的,并且在很多情况下完全没有最终的二进制。相反,因为值构造函数允许在运行时在它们的类型集合中构造值,所以它们作为编译时对象完全没有用处。

由于这个简单的属性,Type构造函数和Value构造函数可以毫不含糊地共享名称。

+0

这是对来自紧急背景的人的最简单理解! – 2013-06-17 13:36:52

16

这有点像说“为什么我们需要类对象,如果对象是唯一实际运行?”

这两种构造函数做不同的工作。类型构造函数进入类型签名。值构造函数进入可运行代码。

在最简单的情况下,类型“构造函数”只是一个类型名称。在最简单的情况下,一个类型只有一个值构造函数。所以,你的东西落得像

data Point = Point Int Int

你可以对自己说:“现在为什么赫克我需要写Point两次?”

但现在考虑不那么简单的例子:

data Tree x = Leaf x | Branch (Tree x) (Tree x)

这里Tree是一个类型构造。你给它一个类型参数,它“构造”一个​​类型。因此Tree Int是一种类型,Tree String是另一种类型,依此类推。 (类似于C++中的模板,或Java或Eiffel中的泛型)。

另一方面,Leaf是一个值构造函数。给定一个值后,它会生成一个单节点树。所以Leaf 5是一个Tree Int值,Leaf "banana"是一个Tree String值,依此类推。

类似地对于Branch。它需要两个树值并构建一个树状节点,并将这些树作为子节点。例如,Branch (Leaf 2) (Leaf 7)Tree Int的值。

+0

感谢您的详细解释! – 2012-04-23 06:28:13

相关问题