2012-07-16 24 views
10

我很困惑,Put monad提供的優惠直接使用Builder,在Data.Binary。我讀了處理二進制數據的Binary Generation部分,它似乎假定你應該使用Put,但它很短並不能解釋爲什麼。Haskell中的ByteStrings:我應該使用Put還是Builder?

Data.Binary.Put

認沽單子。一個monad用於有效地構造懶惰的字節串。

type Put = PutM() 

把電梯Builder放入Writer monad中,應用於()。

Data.Binary.Builder

懶字節字符串的高效施工。


什麼是適用於()一個Writer單子的意義呢?

我可以看到Put是(A型同義詞)一個單子,而Builder是沒有,但我真的不知道爲什麼Put是必要的。在我的情況下,我渲染一個3D場景,並將每個像素寫爲3個字節,然後將PPM格式的標題添加到開頭(稍後將使用PNG)。

Binary看起來像它是爲了實例化的類型,可以序列化和從二進制數據反序列化。這不正是我在做什麼,但感覺自然實例Binary我的色彩類型

instance (Binary a) => Binary (Colour a) where 
    put (Colour r g b) = put r >> put g >> put b 
    get = Colour <$> get <*> get <*> get 

這可以很容易地put一個Colour Word8到24位。但是接下來我也必須加上頭,我不知道我該怎麼做。

Builder意味着隱藏在幕後,還是取決於? Binary類僅用於(反)序列化數據,還是用於所有二進制生成目的?

+0

不是一個答案,但你可能想看看使用blaze-builder(和朋友)而不是二進制。 – 2012-07-16 21:15:08

+0

@TiloWiklund:之前我曾見過。它有什麼不同?效率更高嗎? – mk12 2012-07-16 21:16:44

+0

等等。其中一位作者寫了一篇很好的文章:http://lambda-view.blogspot.se/2010/11/blaze-builder-library-faster.html – 2012-07-16 21:29:32

回答

10

首先注意概念上的差異。建設者是爲了有效地構建字節串流,而PutM monad是真正用於序列化的。所以你應該問自己的第一個問題是你是否實際上是序列化(回答問自己是否存在一個有意義的完全相反的操作 - 反序列化)。

一般來說,我會去Builder爲了方便它提供。但是,不是二進制包,而是其實來自的大建設者包。它是一個monoid,有許多預定義的字符串生成器。它也是非常可組合的。最後它非常快,實際上可以進行微調。

最後但並非最不重要,如果你真的想要的速度,方便你將要與不同的流處理器的圖書館之一週圍像管道枚舉管道這種結合優雅的代碼。

9

我可以看到Put是一個單子,而Builder是沒有,但我真的不知道爲什麼Put是必要的。

確切地說,PutMMonad。這是爲了方便而需要的,並且爲您提供更少的錯誤機會。以單向或可應用的方式編寫代碼通常比明確地攜帶所有臨時對象方便得多,並且通過在Monad實例中完成的管道工作,您不會意外地在函數的中間使用錯誤的Builder

您可以使用Builder來完成PutM的所有工作,但通常編寫代碼的工作量更大。

但是接下來我也必須加上頭,我不知道該怎麼做。

我不知道PPM格式,所以我不知道如何構造標題。但構建完成後,您可以簡單地使用putByteStringputLazyByteString來加以解決。

+0

您是否同意'Put'僅用於序列化和反序列化,並且(例如)單向渲染數據到二進制圖像(作爲ByteString)最好使用'Builder'(可能是blaze-builder)來完成, ,正如其他人所說的那樣? – mk12 2012-07-17 00:58:39

+0

我會說'put'和'get'是,但是'Put'和'Get'可以合理地用於更廣的範圍。然而,[binary](http://hackage.haskell.org/package/binary)的主要意圖確實是Haskell結構的(de)序列化,所以界面就是爲此而塑造的。因此,大火建設者可能是更好的選擇(我從來沒有使用過,所以我不知道使用它有多方便)。 – 2012-07-17 01:23:51

3

我不知道到什麼程度,這是準確的,但我的理解一直是的Put當你看到它的表現主要是DO-符號的濫用,這樣就可以像這樣寫代碼:

putThing :: Thing -> Put 
putThing (Thing thing1 thing2) = do 
    putThing1 thing1 
    putThing2 thing2 

我們沒有使用Monad的「本質」(特別是,我們從不綁定任何結果),但我們獲得了一種方便且乾淨的連接語法。然而,在純粹monoidal選擇的審美優勢:

putThing :: Thing -> Builder 
putThing (Thing thing1 thing2) = mconcat [ 
    putThing thing1, 
    putThing thing2] 

是相當最小,在我看來。

(注意,Get,相比之下,真正的 Monad和受益於如此明確的方式)。

相關問題