最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網 會員登陸 & 注冊

【Haskell】【翻譯】操作上下文中的類型(Working with type in a context)

2021-10-25 22:15 作者:友紀V-入OP  | 我要投稿

發(fā)現《Get Programming with Haskell》這本書中對Functor,applicative,Monad的概念的引入非常直觀有趣,在這里進行一波翻譯。我是Haskell初學者,且英語水平也不高,所以難免拉垮,望讀者海涵并給予意見。文章最后粘貼了英文原文的圖片。

在文章中,我將type翻譯作類型,type class翻譯作類型類,但作者有時會把Maybe,IO等稱作類型,令人感嘆迷惑,總之忠于原文。我一些我拿不準的地方則把英文原文也貼上了。

在這個單元里,你將關注Haskell的三個最具威力,但同時也最迷惑人的類型類:Functor,applicative和Monad。這些類型類名字有趣,但其目的卻相對的明確。它們中的每一個都建立在前一個之上,并提供你在諸如IO等上下文中進行操作的能力。在單元4里,你大量使用了Monad類型類以操作IO。在這個單元里,你將更深刻地理解其工作原理。為更好地感受這些抽象的類型類的行為,(在這里)你將把類型當作形狀來看待。

理解函數的一種方式是認為其將一種類型轉換成另一種類型。讓我們把兩個類型可視化為兩個形狀,一個圓和一個正方形,就如圖1所示。

這些形狀可以代表任意兩個類型,比如Int和Double,String和Text,Name和FirstName以及其他。當你試圖將一個圓轉換成一個正方形的時候,你就在使用函數。你可以把函數可視化為兩個形狀間的一種連接(connector),如圖2所示。

譯者:顯然,這兩個形狀也可以代表同一個類型。

這個連接可以代表任何從一個類型到另一個類型的函數。它可以代表(Int -> Double),(String -> Text),(Name -> FirstName),諸如此類。當你試圖應用一個轉換時,你可以可視化地將連接器置于初始值(在當前的情形下,是一個圓形)以及期望值(一個正方形)之間;見圖3。

當每個形狀都正確匹配,你就能完成你所期望的轉換。

在這個單元,你將關注如何操作處于上下文(context)中的類型。你已經見過的兩個關于上下文中的類型的最好的例子是Maybe類型和IO類型。Maybe類型代表這樣一種上下文,即其中的值可能不存在;IO類型代表著這樣一種上下文,即其中的值將同I/O交互(the value has interacted with I/O)。放到我們的可視化語言中,你可以想象上下文中的類型將像圖4這樣表述。

這些形狀可以代表諸如IO Int,IO Double,Maybe String,Maybe Text,Maybe Name,Maybe FirstName等的類型。因為這些類型是處于一定的上下文中的,你不能用你的原有的連接去進行轉換。當前,在本書中你曾依賴過那些輸入和輸出都處在同樣的上下文中的函數。而為對上下文中的類型進行轉換,你需要一個類似圖5的連接。

這個連接代表那些類型簽名形如(Maybe Int -> Maybe Double),(IO String -> IO Text)和(IO Name -> IO FirstName)的函數。通過該連接,你很容易對上下文中的類型進行轉換,就如圖6所示。

這看上去像是一個完美的解決方案,但是這里有個問題。讓我們看下面這個函數halve,它的類型是Int -> Double,其行為就如我們所期望的,對半分(halve)輸入參數Int

這個函數很直白,但假設你想對半分一個Maybe Int呢?僅用手頭的工具,你必須對這個函數編寫一個包裝器(wrapper)以使它能夠對Maybe類型起作用。

在這個例子里,寫一個簡單的包裝器并非難事。但若是對一大片的現存的a -> b函數,想要使用它們中的任意一個操作Maybe類型都需要編寫幾乎同樣的包裝器。更糟糕的是你無法編寫對IO類型的包裝器!

譯者:為什么無法編寫IO的包裝器?你需要對IO類型的實例進行解構并獲取它的值,再重新構造它,而解構這一步是無法做到的——這意味著Haskell將會提供諸如IO Int -> Int這樣簽名的函數,這是不安全的——你不能保證函數是純函數了!假設你又有一個函數Int -> IO Int(這是容易做到的,通過return之類),你就可以將兩個函數組合,使其具有Int -> Int的函數簽名,但是在內部做dirty work。當然,Haskell的確提供了這樣的unsafe函數就是了。

于是,我們的Functor,applicative和Monad來到了!你可以認為這些類型類是適配器(adapter),它們允許你在底層(underlying)類型(圓和正方形)相同的情況下使用不同的連接(You can think of these type classes as adapters that allow you to work with different connectors so long as the underlying types (circle and square) are the same)。比如在halve中,你關心轉換你的基本的Int到Double(的函數),使它能夠適配以工作在上下文的類型中。這是Functor類型類的工作,如圖7。

Functor類型類能夠解決上下文中的類型和連接不匹配的問題。

譯者:這也就是說Functor能夠使類型a -> b的函數將(Functor f) => f a類型轉化為(Functor f) => f b。換句話說,Functor能夠將a -> b轉化成(Functor f) => f a -> f b

如果你曾了解過Functor的方法(是這么叫嗎?)fmap,查看它的簽名fmap :: (Functor f) => (a -> b) -> f a -> f b,就容易發(fā)現上面的“換句話說”兩邊的描述其實就是對fmap的不同詮釋。

Functor能解決一種類型不匹配問題),但仍有其它三種類型不匹配問題。applicative能解決其中兩種。其中第一種情況是連接的第一部分在上下文中,而結果不在,如圖8。

另一種情形則是整個函數都在上下文中。比如函數Maybe (Int -> Double)意味著這個函數本身可能不存在。這(函數被包裹在上下文中)聽起來奇怪,但它很有可能發(fā)生在對Maybe和IO的偏調用中。圖9描述了這一有趣的情形。

然后還有最后一種可能的函數和上下文中類型不匹配的情形。這種情況是參數不在上下文中,而結果在上下文中。這種情形比你想象中的更加普遍。如Map.lookup和putStrLn的類型簽名都是這樣。這個問題被Monad類型類解決,見圖10。

當你結合使用這三個類型類,只要底層類型匹配,你能把所有函數應用到諸如Maybe,IO等上下文。這可是件了不起的事——你可以在上下文中應用任何你想做的計算,并能夠不同的上下文中重用大量的現存代碼。

下面是英文原文。


【Haskell】【翻譯】操作上下文中的類型(Working with type in a context)的評論 (共 條)

分享到微博請遵守國家法律
突泉县| 河东区| 中西区| 仁寿县| 汤原县| 隆昌县| 通州市| 拉孜县| 英山县| 抚宁县| 临夏市| 顺义区| 孟州市| 中山市| 密山市| 溧阳市| 榆社县| 浦江县| 古田县| 沧州市| 鄂尔多斯市| 淳安县| 报价| 松滋市| 松原市| 贵阳市| 濮阳市| 红原县| 屯留县| 涿鹿县| 武鸣县| 时尚| 鄯善县| 荥阳市| 潍坊市| 乃东县| 漳浦县| 彰化市| 东乌珠穆沁旗| 宜丰县| 鲜城|