我有一个函数tabulate
,它接受一个对象列表,以及一个将这些对象的字段转换为Builders
的函数列表。它返回一个表示格式良好的表格的 Builder。例如:
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
为此,我需要确定每列的最大长度。目前我在每个元素上使用 toLazyByteString
(这太慢了)。
是否可以在不先将 Builder
转换为 ByteString
的情况下获取其长度?
或者,是否有另一种方法(有效地)实现制表
(使用或不使用Builder
)?
最佳答案
调查 Builder
的来源,其定义为
newtype Builder = Builder (forall r. BuildStep r -> BuildStep r)
所以排序Builder
只是组合函数,并且无法在不评估函数堆栈的情况下获取输出的长度。但是您可以使用将 Builder
与长度计算结合起来的数据类型创建自己的帮助器模块:
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)
然后创建用于构造 BuilderL
的辅助函数,例如
byteString :: ByteString -> BuilderL
byteString t = BuilderL (length t) (byteString t)
等等。然后将此模块和 BuilderL
用于您的表格,您将始终掌握所需的长度。
关于haskell - 获取 Data.ByteString.Builder 的长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26492205/