获取Data.ByteString.Builder的长度 [英] Getting the length of a Data.ByteString.Builder
问题描述
我有一个函数 tabulate
,它包含一个对象列表和一个将这些对象的字段转换为 Builders
。它返回一个 Builder
,表示格式良好的表格。例如:
tabulate :: [a - > Builder] - > [a] - > Builder
tabulate = ...
data Assc = Assc {key :: String,value :: String}
>让funcs = [string7。 key,const $ char7'=',string7。值]
> let objs = [short`Assc`a,longer`Assc`b,waylongername`Assc`c]
> hPutBuilder stdout $ tabulate funcs objs
short = a
longer = b
waylongername = c
为此,我需要确定每列的最大长度。目前,我在每个元素上使用 toLazyByteString
(这太慢了)。
是否有可能获得没有首先将 ByteString
?
$ b $作为
Builder
的长度b 或者,是否有另一种方式(有效)实现 tabulate
(使用或不使用 Builder
)?
寻找 Builder
,它被定义为
newtype Builder = Builder(Forall r。BuildStep r - > BuildStep r)
pre>
因此,排序
Builder
只是组合函数,并且没有办法如何获得输出的长度而无需评估功能堆栈。但是你可以用一个数据类型创建你自己的帮助模块,这个数据类型可以结合Builder
s和长度计算:
newtype BuilderL = BuilderL {blLenght ::!Int,blBuilder :: Builder}
实例Monoid BuilderL其中
mempty = BuilderL 0 mempty
mappend (BuilderL l1 t1)(BuilderL l2 t2)= BuilderL(l1 + l2)(t1≠t2)
然后创建帮助函数来构造
BuilderL
s,比如
byteString :: ByteString - > BuilderL
byteString t = BuilderL(length t)(byteString t)
等。然后使用这个模块和
BuilderL
作为你的表格,你将始终拥有这个长度。I have a function
tabulate
that takes a list of objects, and a list of functions that turn fields of these objects intoBuilders
. It returns aBuilder
representing a nicely formatted table. E.g.:tabulate :: [a -> Builder] -> [a] -> Builder tabulate = ... data Assc = Assc { key :: String, value :: String } > let funcs = [string7 . key, const $ char7 '=', string7 . value ] > let objs = ["short" `Assc` "a", "longer" `Assc` "b", "waylongername" `Assc` "c"] > hPutBuilder stdout $ tabulate funcs objs short = a longer = b waylongername = c
To do this I need to determine the maximum length for each column. At the moment I am using
toLazyByteString
on each element (which is too slow).Is it possible to get the length of a
Builder
without first turning it into aByteString
?Alternatively, is there another way to (efficiently) implement
tabulate
(with or without usingBuilder
)?解决方案Looking into the source of
Builder
, it's defined asnewtype Builder = Builder (forall r. BuildStep r -> BuildStep r)
So sequencing
Builder
is just composing functions, and there is no way how to get the length of the output without evaluating the stack of functions. But you could create your own helper module with a data type that would combineBuilder
s with length calculations:newtype BuilderL = BuilderL { blLenght :: !Int, blBuilder :: Builder } instance Monoid BuilderL where mempty = BuilderL 0 mempty mappend (BuilderL l1 t1) (BuilderL l2 t2) = BuilderL (l1 + l2) (t1 <> t2)
and then create helper functions for constructing
BuilderL
s, likebyteString :: ByteString -> BuilderL byteString t = BuilderL (length t) (byteString t)
etc. Then use this module and
BuilderL
for your tables and you'll always have the length at hand.这篇关于获取Data.ByteString.Builder的长度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!