2016-04-23 33 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

如果我理解正確,而且我當然可能沒有提出這個問題,我認爲這種類型本身不會被導出。如果是這種情況,他肯定會遇到問題,應該向圖書館作者輸出類型或文件問題。這不會是第一次。 –

相關問題