修改 Haskell 的格式化库中的格式化程序

Modifying formatters in Haskell's formatting library

我正在使用 Chris Done 的 formatting 库(特别是 formatting-6.0.0)。我发现很难构建一个将格式化程序映射到列表格式化程序的“高阶”函数,对生成的生成器列表执行自定义操作:

list :: ([Builder] -> Builder) -> Format r (a -> r) -> Format r ([a] -> r)

这是可取的,因为它允许我在格式字符串中嵌入构建器格式化逻辑。

举个例子,假设构建函数只是 mconcat。然后 format (list mconcat int) [1,2,3] 会产生 "123"。在实践中,我可能会使用将列表格式化为英文列表的构建器函数,这样上述输入的输出将是 "1, 2 and 3".

感谢您的帮助!

让我们从 list :: ([Builder] -> Builder) -> Format r (a -> r) -> Format r ([a] -> r)

扩展 Format 类型
 Format            r     (a -> r) -> Format            r     ([a] -> r)
 Holey  Builder    r     (a -> r) -> Holey  Builder    r     ([a] -> r)
(      (Builder -> r) -> (a -> r))->(      (Builder -> r) -> ([a] -> r))

我们可以尝试构建list的定义。

list append m = Holey $ \k -> ...

我们需要 return 一个 [a] -> r,其中 ... 是。我们没有很多可能的着法,因为我们对 r 类型一无所知。我们可以将 k :: Builder -> r 传递给 runHM m 以获得 a -> r。如果我们 map[a] 之上我们有一个 [r],但是我们对 r 一无所知,所以我们不能用它做任何事情。

如果像 list 这样的函数存在,它的类型与 ([Builder] -> Builder) -> Format r (a -> r) -> Format r ([a] -> r) 不同。


我们可以用不同的类型list :: ([Builder] -> Builder) -> Format Builder (a -> Builder) -> Format r ([a] -> r)定义list。这应该适用于大多数第一个参数,因为大多数格式化组件在所有 r.

上都是通用的。
list append m = Holey $ \k -> k . append . map (runHM m id)

这可以更简洁地写成

list append m = later (append . map (bprint m))