没有数据构造函数的数据声明。可以实例化吗?为什么编译?

时间:2017-07-29 05:25:15

标签: haskell types

读了我的一本Haskell书,我看到了这句话:

  

数据声明总是创建一个新的类型构造函数,但可能或可能不会创建新的数据构造函数。

一个人应该能够声明一个没有数据构造函数的数据类型,这听起来很奇怪,因为它似乎永远无法实例化该类型。所以我试了一下。以下数据声明编译时没有错误。

@media only screen and (min-width : 768px) {
    .is-table-row {
        display: table;
    }
    .is-table-row [class*="col-"] {
        float: none;
        display: table-cell;
        vertical-align: top;
    }
}

如何创建此类型的实例?有可能吗?我似乎无法找到办法。

我认为可能会自动创建一个名称与类型构造函数匹配的数据构造函数,但似乎不是这种情况,如尝试使用data B = String 作为数据构造函数所导致的错误所示范围内的声明。

B

如果永远不能实例化类型,为什么允许编译此数据声明? 尽管没有已知的实际应用,它是否仅仅出于某种正式理由而被允许?

我也想知道我的书中关于没有构造函数的数据类型的陈述是否可能是指通过Prelude> data B = String deriving Show Prelude> B <interactive>:129:1: error: Data constructor not in scope: B type关键字而不是newtype声明的类型。

  • data案例中,类型同义词显然不使用数据 构造函数,如下所示。

    type

    这样的类型同义词可以由构造函数实例化 他们设置的类型。但我不相信这就是我的 本书所指的类型同义词似乎并没有像新的数据类型那样声明 只需为现有类型定义新别名。

  • Prelude> type B = String Prelude> 案例中,似乎没有数据的类型 无法创建构造函数,如以下错误所示。

    newtype

Prelude> newtype B = String <interactive>:132:13: error: • The constructor of a newtype must have exactly one field but ‘String’ has none • In the definition of data constructor ‘String’ In the newtype declaration for ‘B’ type似乎不是本书所指的内容,这让我回到原来的问题:为什么可以使用newtype声明类型没有数据构造函数?

1 个答案:

答案 0 :(得分:10)

  

如何创建此类型的实例?

你书中的陈述是正确的,但你的例子不是。 data B = String定义类型构造函数 B数据构造函数 String,两者都不带参数。请注意,您定义的String位于值命名空间中,因此与通常的String类型构造函数不同。

ghci> data B = String
ghci> x = String
ghci> :t x
x :: B

但是,这是一个没有数据构造函数的数据定义示例(因此无法实例化)。

ghci> data B

现在,我有一个新类型构造函数B,但没有数据构造函数可以生成类型B的值。实际上,这样的数据类型是在Haskell base中声明的:它被称为Void

ghci> import Data.Void
ghci> :i Void
data Void   -- Defined in ‘Data.Void’
  

如果永远不能实例化类型,为什么允许编译此数据声明?

能够拥有无人居住的类型在少数地方变得有用。我现在能想到的例子大多是将类型参数这样的类型传递给另一个类型的构造函数。另一个实际用例是像conduit这样的流媒体库。

有一个ConduitM i o m r类型的构造函数,其中:i是输入流元素的类型,o是输出流元素的类型,m是monad in执行哪些操作,r是最终产生的最终结果。

然后,它将Sink定义为

type Sink i m r = ConduitM i Void m r

因为Sink不应该输出任何值。 Void是编译时保证,Sink 无法输出任何(非底部)值。

Identity非常相似,Void主要与其他抽象结合使用。

  

...类型同义词显然不使用数据构造函数

是的,但他们也没有定义类型构造函数。同义词只是一些表面级别的便捷重命名。在引擎盖下,没有新的定义。

  

在newtype情况下,似乎无法创建没有数据构造函数的类型,如以下错误所示。

我建议您查看newtype的用途。 newtype的重点是围绕现有类型提供零成本包装。这意味着你有一个且只有一个构造函数只接受一个参数(包装的值)。在编译时,包装和解包操作变为NOP。