gpt4 book ai didi

haskell - Text.PrettyPrint : Starting indentation from left margin

转载 作者:行者123 更新时间:2023-12-04 08:28:06 26 4
gpt4 key购买 nike

我正在尝试使用 Text.PrettyPrint 生成 Javascript .问题是 nest当放在另一个 pretty-print 的元素旁边时会产生巨大的缩进。例如,在这段代码中:

import Text.PrettyPrint

fun :: Doc
fun = vcat [ text "function" <+> lbrace
, nest 4 $ vcat $ replicate 5 $ text "// foo"
, rbrace
]

var :: Doc
var = text "var" <+> text "x"

test :: Doc
test = var <+> equals <+> fun <> semi
funtest 的第 9 列开始(因为 var <+> equals <> empty 在它的左边),因此它的后续行缩进了 9+4=13 列:
var x = function {
// foo
// foo
// foo
// foo
// foo
};

有没有办法从左边距渲染缩进,以便将上面的内容渲染为
var x = function {
// foo
// foo
// foo
// foo
// foo
};

?

最佳答案

解决方案确实是使用 wl-pprint (并将 nest 替换为 indent )。然后,给出的代码产生

var x = function {
// foo
// foo
// foo
// foo
// foo
};

如预期的。对于任何仍然打算尝试破解 pretty 的人,请注意,尽管 Doc 的构造函数没有暴露,您仍然可以通过 Generic 获取它们与 -XPatternSynonyms :
-- | Means of exposing the data constructors of `Doc` from `pretty`
pattern GEmpty = M1 (L1 (L1 (L1 (M1 U1))))
pattern GNilAbove doc = M1 (L1 (L1 (R1 (M1 (M1 (K1 doc))))))
pattern GTextBeside d doc = M1 (L1 (R1 (L1 (M1 (M1 (K1 d) :*: M1 (K1 doc))))))
pattern GNest n doc = M1 (L1 (R1 (R1 (M1 (M1 (K1 n) :*: M1 (K1 doc))))))
pattern GUnion ldoc rdoc = M1 (R1 (L1 (L1 (M1 (M1 (K1 ldoc) :*: M1 (K1 rdoc))))))
pattern GNoDoc = M1 (R1 (L1 (R1 (M1 U1))))
pattern GBeside ldoc s rdoc = M1 (R1 (R1 (L1 (M1 (M1 (K1 ldoc) :*: M1 (K1 s) :*: M1 (K1 rdoc))))))
pattern GAbove ldoc b rdoc = M1 (R1 (R1 (R1 (M1 (M1 (K1 ldoc) :*: M1 (K1 b) :*: M1 (K1 rdoc))))))

问题主要是不违反库在引擎盖下的许多不变量中的任何一个。

作为旁注,我还发现了 wl-pprint-annotated ,对 wl-pprint 的现代重写,通过它可以访问底层数据构造函数(以需要记住所涉及的不变量为代价)。这实际上是我最终将使用的包。

特别是,它让我可以制作这种大括号 block ,这样如果它足够小,它将只在一行上:
-- | Asserts a 'Doc a' cannot render on multiple lines.
oneLine :: Doc a -> Bool
oneLine (WL.FlatAlt d _) = oneLine d
oneLine (WL.Cat a b) = oneLine a && oneLine b
oneLine (WL.Union a b) = oneLine a && oneLine b
oneLine (WL.Annotate _ d) = oneLine d
oneLine WL.Line = False
oneLine _ = True

-- | Make a curly-brace delimited block. When possible, permit fitting everything on one line
block :: Doc a -> Doc a
block b | oneLine b = hsep ["{", b, "}"] `WL.Union` vsep [ "{", indent 2 b, "}" ]
| otherwise = vsep [ "{", indent 2 b, "}" ]

然后我会得到很好的结果,这些结果会自动跨越或不跨越多行:
ghci> "function" <> parens "x" <+> block ("return" <+> "x" <> semi)
function(x) { return x; }
ghci> "function" <> parens "x" <+> block ("x" <> "++" <> semi <#> "return" <+> "x" <> semi)
function(x) {
x++;
return x;
}

关于haskell - Text.PrettyPrint : Starting indentation from left margin,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9713296/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com