2013-02-21 69 views
13

Typeclassopedia中的所有類型類都具有關聯的規則,如某些操作符的關聯性或交換性。 「法律」的定義似乎是一種無法在類型體系中表達的約束。我當然明白爲什麼你想擁有monad法則,但是爲什麼一個可以在類型系統中完全表達的類型類型是毫無意義的,這有一個根本原因嗎?爲什麼所有Haskell類型類都有規律?

+2

您可能會覺得[this](http://www.haskell.org/haskellwiki/Monad_Laws)的第2部分很有趣。另外[this](http://stackoverflow.com/questions/6399648/what-happens-to-you-if-you-break-the-monad-laws)關於打破單子法的討論。我認爲最簡單的答案就是這些法律定義了類型類的預期行爲,那麼如果它不是鴨子,爲什麼還要叫鴨子呢? – sabauma 2013-02-21 14:10:00

+3

並非所有的特定類都有法律。 Typeclassopedia僅列出了所有現存類型類的一小部分,即具有重要代數/分類屬性的那些類(法*是*這些屬性)。諸如Read和Show等......沒有。 – 2013-02-21 14:10:53

+0

@sabauma沒有冒犯,但那不是很有趣。我寫了「我當然明白爲什麼你想擁有單子法」來避免這種類型的答案。 – Gurgeh 2013-02-21 14:18:58

回答

15

你會注意到幾乎所有的法律都是代數法則。他們可以通過使用一些擴展的類型系統來表達,但是證明會很麻煩。所以你有不受限制的法律和潛在的實施可能會打破他們。爲什麼這很好?

原因是Haskell中使用的設計模式是通過數學結構(通常來自抽象代數)激發(並且在大多數情況下是鏡像的)。雖然大多數其他語言都具有安全性,性能和語義等特定功能的直觀概念,但我們Haskell程序員更喜歡建立正式的概念。這樣做的好處是:一旦你的類型和功能服從安全法則,它們在底層代數結構的意義上是安全的。他們是可以證明安全。

以仿函數爲例。哈斯克爾仿函數有以下兩個規律:

fmap f . fmap g = fmap (f . g) 
fmap id   = id 

首先,這是非常重要的:在Haskell功能是不透明的。你不能檢查,比較或不管他們。雖然這在Haskell中聽起來像是一件壞事,但它確實是一件非常好的事情。 fmap函數無法檢查您通過它的函數。特別是它不能檢查你是否通過了身份識別功能,或者你已經通過了作文。總之:它不能作弊!它遵守這兩項法律的唯一方法實際上不是引入任何自身的影響。這意味着,在一個適當的函子fmap從來沒有做任何意想不到的事情。事實上,除了映射給定的函數之外,它無能爲力。這是一個非常簡單的例子,我沒有解釋爲什麼fmap不能作弊,但它證明了這一點。

現在擴展到整個語言,基礎庫和最明智的第三方庫。這給你一種語言可以預測的語言。當你編寫代碼時,你知道它會做什麼。這就是爲什麼Haskell代碼經常可以開箱即用的主要原因之一。我經常在編譯之前編寫Haskell代碼頁面。一旦我的類型錯誤得到解決,我的程序通常會起作用。

爲什麼這是可取的另一個原因是它允許更多的組合風格的編程。作爲一個團隊工作時,這特別有用。首先,將您的應用程序映射到代數結構並建立必要的法律。例如:您表達某件事物成爲有效Web服務器的意義。特別是你建立了一個Web服務器組成的正式概念。如果您撰寫兩個有效的Web服務器,結果是一個有效的Web服務器。你看到這是怎麼回事?在制定這些法律之後,隊友們開始工作,他們孤立地工作。很少或沒有溝通是必要的,以完成他們的工作。當他們再次見面時,每個人都會展示他們的有效Web服務器,並將他們組合成最終產品 - 一個網站。由於各個組件都是有效的Web服務器,因此最終結果必須是有效的Web服務器。可證明。

+1

這是一篇有趣而且寫得很好的評論,但似乎是一個完全不同的問題的答案,而不是「爲什麼一個可以在類型系統中完全表達的類型類型是毫無意義的根本原因?」 :) – Gurgeh 2013-02-21 16:59:15

+1

@Gurgeh:那麼,沒有法律的類型班很有道理,爲什麼不呢?我在第一段中說過,不是嗎?如果不是,我可能完全誤解了你的問題。 =) – ertes 2013-02-22 15:18:09

+0

嗯,我想如果你發現自己定義了一個沒有規律的類型類,它可能會是一種反模式。也許它應該是..別的東西(例如,只是將實例函數與數據類型一起傳遞或將它們放入記錄或其他東西)? – Gurgeh 2013-02-22 17:00:13

1

類型類不需要有法律,但它通常會更有用,如果它有。預計許多類型特定的方式會以某種方式發揮作用,這些法律將用戶期望編碼。法律允許用戶對類型類實例的工作方式做出假設。如果你打破類型法,你不會被哈斯克爾警察逮捕,你最終只會遇到困惑的用戶。

6

是和否。例如,Show班級沒有任何與之相關的法律,這當然是有用的。

但是,類型類表示接口。接口需要滿足的不僅僅是一堆功能 - 您希望這些功能能夠滿足規範。該規範通常比Haskell的類型系統中可以表達的要複雜得多。例如,採取Eq類。它只需要提供給我們一個功能,其類型必須是a -> a -> Bool。這是Haskell的類型系統允許我們從Eq類型的實例中得到的最多。然而,我們通常會對這個函數有更多的期待 - 你可能希望它是一個等價關係(自反,對稱和傳遞)。那麼你將這些要求作爲單獨的「法律」來陳述。

+2

'Show'種類確實也有規律 - 'show x'應該是等效於'x'的Haskell代碼(假設它被解釋爲相同類型)。這不像其他標準類型法律那樣遵守。 – leftaroundabout 2013-02-21 14:35:57

+2

@leftaroundabout雖然'read(show x)'與'x'不同,但它不傾向於* break *代碼,因爲人們不會傾向於通過將數據轉換爲String來將數據序列化, show'。鑑於打破monad,函子或應用法則有很強的破壞代碼的可能性,因爲合理的重構不再有效。 – 2013-02-21 14:55:48

+1

@ChrisTaylor,大多數時候單子法被打破,他們仍然滿足於一個等價關係;我經常用非確定性monad經歷這種情況,應用關聯性會改變結果的順序。但我通常不太關心這樣一個monad中結果的順序,只是我最終得到了我想要的結果。無論如何,我會說打破monad等法律具有非常強的*改變行爲的可能性*,不一定破壞代碼。 – luqui 2013-02-21 17:11:35

相關問題