2016-09-16 14 views
0

警告:非常初學者的問題。如何理解Haskell類型構造函數的有效輸入集?

我目前深陷在Haskell的書我讀代數類型的部分,我已經遇到了下面的例子:

data Id a = 
    MkId a deriving (Eq, Show) 

idInt :: Id Integer 
idInt = MkId 10 

idIdentity :: Id (a -> a) 
idIdentity = MkId $ \x -> x 

OK,堅持住。我不完全瞭解idIdentity示例。書中的解釋是:

這有點奇怪。類型Id接受參數,數據 構造函數MkId接受相應多態的 類型的參數。因此,爲了獲得Id Integer類型的值,我們需要 將a -> Id a應用於Integer值。這將a類型變量綁定到 Integer,並在類型構造函數中使用(->),給我們 Id Integer。我們還可以通過將a綁定到 類型和術語級別中的多態函數來構建MkId值,該值是身份 函數。

但是等等。爲什麼只有完全多態的功能?我以前的理解是,a可以是任何類型。但很顯然,受限的多態類型不起作用:(Num a) => a -> a不會在這裏工作,並且GHC錯誤表明,只有完全態類型或「合格類型」(不知道那些是什麼)是有效的:

f :: (Num a) => a -> a 
f = undefined 

idConsPoly :: Id (Num a) => a -> a 
idConsPoly = MkId undefined 

Illegal polymorphic or qualified type: Num a => a -> a 
Perhaps you intended to use ImpredicativeTypes 
In the type signature for ‘idIdentity’: 
    idIdentity :: Id (Num a => a -> a) 

編輯:我是一個笨蛋。我在下面的答案中寫下了類型簽名,正如@chepner在他的回答中指出的那樣。這也解決了我在下面的下一句話中的困惑......

回想起來,這種行爲是有道理的,因爲我還沒有爲Id定義Num實例。但那麼什麼解釋我能​​夠在idInt :: Id Integer中應用Integer這種類型?

所以在一般情況下,我想我的問題是:什麼是特定的類型構造函數的有效輸入集合?只有完全多態類型?那麼什麼是「合格類型」呢?等...

+0

限定類型是指具有上下文的那些類型,即以'Constraint => ...'開始。約束是「資格」。 –

+0

進入限定類型和多態的一個好的開端是這篇關於排名n類型的博客文章https://ocharles.org.uk/blog/guest-posts/2014-12-18-rank-n-types.html – epsilonhalbe

回答

3

你只是在錯誤的地方的類型構造函數。以下是罰款:

idConsPoly :: Num a => Id (a -> a) 
idConsPoly = MkId undefined 

類型構造Id在這裏有一種* -> *,這意味着你可以給它具有一種*(包括所有「普通」的類型)的任何值,並返回一個新值種類*。一般來說,你更關心箭頭函數(?),其中的類型構造函數只是一個例子。

TypeProd是三元類型構造器,其頭兩個參數有樣* -> *

-- Based on :*: from Control.Compose 
newtype TypeProd f g a = Prod { unProd :: (f a, g a) } 

Either Int是其值具有一種* -> *但不是類型構造,作爲類型構造Either的局部應用的表達到無限型構造函數Int

+0

Ahhhhhhhh 。那是一個愚蠢的錯誤。我很抱歉。謝謝。所以基本上,類型構造函數的域是所有可能類型的集合,然後呢? – gogurt

+0

或多或少。有些類型的細微差別我確信我不完全理解,但是https://wiki.haskell.org/Kind將普通類型定義爲具有'*'種類,並將類型構造函數定義爲具有'P - > Q'類型其中'P'和'Q'是種類。 (這裏額外的一般性允許'( - >)'有'* - > * - > *',其中'P'和'Q'分別是'*'和'* - > *'。) – chepner

+2

@ chepner次要術語修正:「類型構造函數」是一個技術術語,與具有一種形式'P - > Q'的屬性正交。例如,'Int'是類型'*'的類型構造函數,'Either Int'具有箭頭類型,但不是類型構造函數。通過類比術語構造函數:'False'是沒有箭頭類型的構造函數,而'(+)0'在其類型中有一個箭頭,但不是構造函數。 –

0

類型簽名幾乎是正確

idConsPoly :: (Num a) => Id (a -> a) 

應該是正確的,但我有我的手機上沒有GHC來進行測試。 此外,我認爲你的問題是相當廣泛的,因此我故意只回答這裏的具體問題。

1

也有助於你的困惑是你誤解了來自GHC的錯誤信息。這意味着「Num a => a -> a是多態或限定類型,因此是非法的(在這種情況下)」。

你從書中引用的最後一句話措辭不是很好,也可能是導致誤解。意識到在Id (a -> a)中參數a -> a而不是是一個多態類型,但只是碰巧提到類型變量的普通類型很重要。多態的東西是idIdentity,對於任何類型a可以有Id (a -> a)類型。

在標準Haskell中,多態性和限定條件只能出現在類型簽名類型的最外層。

+0

謝謝你。我想,我開始明白了。你碰巧知道另一個來源,我可以看看在第二段中更好地理解你的解釋嗎?我真的很想處理這個問題。 – gogurt

相關問題