2013-02-25 52 views
1

我是關於monad,'pipes'和'red pipe'的reading an interesting article。從看起來它是說功能參數或類是管道的類型,以確保一切正常。然後它變成一個紅色管道,並且必須始終是一個紅色管道和純淨。這部分我不明白Monads的'紅色管'不同於類型?

爲什麼'紅管'不能成爲'藍管'?紅色管道可以轉換爲普通管道嗎?這與純度有什麼關係?我能想到這就像class RedPipe: PlainPipe { /* same interface and implementation here*/ }

+4

不要浪費你的時間與可愛的寓言描述的數學概念,如monads。研究實際的數學。 – 2013-02-25 14:13:50

回答

5

在Haskell中,函數的類型告訴你它到底做了什麼,更重要的是,它沒有做什麼。這使得更容易推理Haskell代碼。

舉例來說,如果我有以下類型的函數:

f :: Int -> Int 

我知道,它需要一個Int作爲輸入,併產生一個Int作爲輸出,它也沒有別的。重要的是,我知道它沒有副作用。

如果我有類型的函數:

g :: Double -> State Int Double 

...該功能需要一個Double作爲參數,併產生辦法產生Double,但只有當我允許它協商或修改一些Int狀態。

如果我有類型的函數:

h :: Int -> Maybe String 

我知道,這個功能需要一個Int,並可能產生String,也可能會失敗,生產什麼。請注意,前兩個函數都沒有返回Maybe,這意味着它們不會失敗。 Haskell默認不允許失敗(即可爲空值)。

如果我有類型的函數:

i :: String -> IO() 

我知道,這個功能需要一個String並且可以運行產生副作用。請注意,以前的函數都沒有IO的類型,這意味着它們不會產生副作用。 Haskell默認不允許副作用。你必須明確地加入他們的類型。

這意味着我們可以查看函數或值的類型,並立即瞭解它們正在使用的功能。因此,例如,如果我看到類型爲Maybe,我知道可能會失敗,如果我不這樣做,那麼我知道沒有可能失敗。同樣,如果我在該類型中看到IO,則我知道存在潛在的副作用,但如果我在該類型中看不到IO,則不存在副作用的可能性。

在主流語言中,您不具備選擇性「選擇」功能的能力。所有功能默認情況下始終處於打開狀態,這意味着您必須始終檢查null,因爲您無法保證某些功能沒有失敗,並且您必須始終運行測試,因爲您無法保證某些功能並沒有暗示修改你係統的狀態。

Haskell允許您限制函數的行爲,使您可以更細緻地控制其「權限」,這樣可以更輕鬆地擴展到大型程序而無需使用錯誤,還可以更輕鬆地閱讀和理解Haskell代碼,因爲類型枚舉代碼行爲的全部範圍,所以你永遠不必理解類型允許的更多內容。

+0

很好的答案,但我還有幾個問題。 'State'和'IO()'具有特殊含義,還是用戶/庫定義類型?如果我不得不猜測'State'意味着它修改了全局變量(我不明白,因爲我認爲所有內容都是隻讀/純的),IO()表示即使相同的參數是數據也不會相同多次呼籲。但我不確定爲什麼在IO之後有'()'。 IO是一種類型而'()'有意義嗎? – BruteCode 2013-02-25 15:09:21

+0

'State'純粹是一個庫類型,沒有語言或編譯器支持。 '國家的''是's - >(a,s)'在引擎蓋下。換句話說,每個「狀態值」實際上都是一個純函數,它接受一個初始狀態並返回一個值加上最終狀態。 'IO'有一些編譯器的支持。 'IO'類型中的'()'確實有意義。 'IO'操作可以返回值,如'getLine :: IO String'。 '()'意味着它返回一個無用的空值,而且我們真的只是用它的副作用(類似於C/Java中的'void'函數)。 – 2013-02-25 15:15:15

+0

@BruteCode在我最後的評論中忘了@你,但我也想提一提,如果你想更好地理解'IO',我建議你閱讀[我的這篇文章](http://www.haskellforall.com/ 2013/01/introduction-to-haskell-io.html),它更仔細地解釋了評估IO操作和運行它之間的區別。 – 2013-02-25 15:18:21

3

作者使用術語「紅管」和「藍管」作爲隱喻。據我所知,這不是廣泛使用的術語。我認爲他的文章的關鍵點在於Java等語言提供的類型安全性有助於捕捉某些程序員錯誤,將不純函數可以捕捉更多。用他的例子之一:

square :: Double -> Double 

這種類型的簽名告訴我,

  1. 功能square沒有任何副作用。它不會偷偷摸摸地更新數據庫,或者在屏幕上打印某些內容,或者更改某些狀態數據,否則會讓我感到驚訝。 (例如,在Java或C中,我將不得不閱讀函數及其調用的任何函數,或依賴文檔來知道函數的功能。)

  2. 每次我用特定的價值,比如說,square 5,我會得到完全一樣的結果。這被稱爲參考透明度,它允許編譯器做一些優化,因爲它知道這個值永遠不會改變,所以只需要計算一次。