2014-04-01 46 views
6

GHC有一個類型系統擴展的整個動物園:多參數類型類,函數依賴關係,等級n多態性,存在類型,GADT,類型族,範圍類型變量等等,哪些可能是最容易學習的關於第一?另外,這些功能是否以某種方式組合在一起,還是它們都是完全不同的用途,而且都是獨立的想法?我應該先試着學習哪些GHC類型的系統擴展?

+3

這是一個很大的話題。秩2多態性絕對是最重要的,而秩N多態性自然地遵循。下一個是你的興趣。 GADTs和MPTCs/FDs都可以用來實現一些相同的結果,所以作爲一個練習,嘗試每個都做同樣的事情。存在類型是有用的,但作爲練習,嘗試從類型中去除存在性量化 - 我的直覺告訴我,80%的時間,你只使用存在性量化,因爲這就是你如何在Java/C++/Python中做到這一點,不是因爲它更清晰的代碼。 –

+0

作爲練習,解釋爲什麼需要Rank 2類型以確保ST monad的安全。 –

+0

以基於非意見的方式回答這個問題是不可能的,恕我直言。不過,我會遵循以下順序:範圍類型變量,等級n多態性,多參數類型類,GADT和其他任何順序。它通過使用利用它們的庫來幫助學習它們:例如正如@DietrichEpp所指出的那樣,「ST」monad非常適合學習rank-2多態。 – chi

回答

7

早期學習的好方法是ScopedTypeVariables,因爲它們對調試函數中的類型問題非常有用。當我有一個令人困惑的類型錯誤時,我臨時爲函數中的每個表達式添加類型聲明。 (通常你需要分解一些表達式來看看真正發生了什麼。)這通常可以幫助我確定哪種表達式具有與我預期不同的類型。

TypeFamiliesMultiParamTypeClasses更強大,所以你不需要後者。在使用類型系列時,通常還需要啓用FlexibleContextsFlexibleInstances,因此,您將爲其中一個的價格學習三個編譯指示。 FunctionalDependencies通常與MultiParamTypeClasses一起使用,所以這是您現在可以忽略的一個。

GHC非常擅長告訴你何時需要啓用Rank2TypesRankNTypes,因此您可以推遲了解更多關於這些內容的內容,直到稍後。

那些是我開始的。


編輯:刪除了關於避免StandaloneDeriving的評論。 (我正在考慮孤兒實例。)

+0

在GHCi中,我認爲'StandaloneDeriving'有其最佳用途。有很多次我定義了一個內聯的數據類型,只是搞亂了一些東西,然後意識到我忘了添加'deriving(Eq,Show)'。我可以改爲':set -XStandaloneDeriving'和'導出實例Show MyType'。 – bheklilr

+4

'StandaloneDeriving'有什麼不好?它可能能夠派生出你不能用'data XXX ...派生(...)'' – bennofs

+0

D'oh!我正在考慮孤兒實例,而不是獨立實例。 – mhwombat

2

請注意,我已經與Haskell進行了一些合作,我已經就此事制定了一些我自己的意見。 mhwombat的suggestionScopedTypeVariables是一個很好的。現在通常是我開始編寫Haskell模塊時輸入的第一個東西。每當代碼變得有點棘手時,我喜歡有很多類型簽名來幫助我看看我在做什麼,而這個擴展讓我可以寫出我不知道的東西。它也可以顯着改善類型錯誤。當使用其他類型的系統擴展時,它似乎也是非常重要的。

直到我瞭解了一些關於依賴類型的編程語言之前,我並沒有真正欣賞GADT。注意我認爲它們如何可以作爲證明對象,以及它們如何受到類型索引的約束,真是太棒了。

GADTa非常適合DataKinds,它可以生成有趣的類型索引,如列表和布爾值。我現在可以做一些事情,比如表示一個索引列表與樹高一樣長,而不會使用高階嵌套類型讓自己瘋狂。

我還沒有探索多參數類型類和函數依賴關係。但是,我已經開始欣賞Edward Kmett的reflection庫,它在它的接口中使用它們。

我已經學會了對重疊和不連貫實例的健康尊重,我的意思是我從不使用它們。重疊的感覺有點像宏編程,差錯錯誤信息,而不連貫的是瘋了。

RankNTypes確實很強大。這是很少需要的事情之一,但在需要時非常重要。

+0

我認爲不同人的風格很有趣。看起來'RankNTypes'在這兩個答案中都是事後考慮的,而我覺得沒有它們就不能編碼。 – luqui

+0

@luqui,我可能比我意識到的更多地使用它們。他們有一些不被忽視的傾向。你如何使用它們? – dfeuer