2016-04-23 31 views
0

我想创建一个记录,其中一个字段有一个未导出的类型,因为它使用了一个智能构造函数。使用智能构造函数作为类型不起作用。只有智能构造函数的记录语法字段类型注释

Not in scope: type variable `domain' 

也许有一种语言扩展,可以让我做到这一点,或类似的东西?

将构造函数与智能构造函数一起导出将允许我解决此问题,但这反过来又会创建创建智能构造函数不允许的值的可能性。

(非工作)的代码,我现在所拥有的:

import Domain (domain) -- Domain is not exported, and domain is a smart constructor for Domain 

data Rec = Rec 
    { dint :: domain Int -- what do I do here? I want it to be `Domain Int` but `Domain` isn't exported. 
    ... 
    } 
+0

请包括您的代码。很难说出这里发生了什么。 – Kwarrtz

+0

这听起来像你可能会混淆类型和类型构造函数。但是,我无法从你发布的内容中知道。 – Kwarrtz

+0

@Kwarrtz增加了代码。 –

回答

5

这里的问题是类型构造的概念和数据构造之间的混淆。为了简洁起见,我将用一个例子来说明不同之处。

data Foo a = Bar [a] 

在上面的表达式,Foo是类型构造和Bar是数据构造。关键区别在于Foo是Haskell类型空间中的值,Bar是其数据空间中的值。类型空间中的值不能用于数据空间,反之亦然。例如,编译器会在以下表达式中出错。

someVariable :: Bar Int 
someVariable = Foo [15] 

但是,下一个表达式是完全有效的。

someVariable :: Foo Int 
someVariable = Bar [15] 

此外,所有类型构造必须以大写字母开始。任何以小写字母开头的类型都将被视为类型变量,而不是类型构造函数(我们上面的定义中的a就是这样的一个例子)。

智能构造函数的引入为这个问题增加了另一层,但要理解的关键是智能构造函数是数据构造函数,而不是类型构造函数。在您定义的Rec中,您试图在dint字段的类型声明中使用智能构造函数domain。但是,因为domain是一个数据构造函数而不是类型构造函数,并且它是小写字母,Haskell编译器试图将domain解释为类型变量的名称。由于您从未在Rec类型的定义中指定名为domain的变量,因此编译器会产生错误。

您实际上不需要导出Domain的数据构造函数来解决问题,只是类型本身。这可以通过以下来完成。

module Domain (
    Domain(), domain, 
    ... 
    ) where 

包括出口定义Domain()告诉哈斯克尔导出Domain类型构造,但没有任何数据的构造函数。这可以保证您使用安全构造函数的安全性,并且允许您正确定义类型。您现在可以在Rec的定义中使用新导出的类型。

import Domain (Domain(), domain) 

data Rec = Rec 
    { dint :: Domain Int 
    ... 
    } 

欲了解更多信息,我强烈建议你读constructorssmart constructors的HaskellWiki文章。

+0

如果我理解正确,而且我当然可能没有提出这个问题,我认为这种类型本身不会被导出。如果是这种情况,他肯定会遇到问题,应该向图书馆作者输出类型或文件问题。这不会是第一次。 –

相关问题