0

私はそのようなきれいなプリンターを持っています:

somefun = text "woo" $+$ nest 4 (text "nested text") $+$ text "text without indent"
fun = text "------" $+$ somefun

私がそれから欲しいのはこれを印刷することです:

------ woo
    nested text
text without indent

しかし、それは印刷します:

------
woo
    nested text
text without indent

なぜこんな風に印刷されるのかは理解できますが、やりたいことがうまくいきません。私が見つけた1つの解決策はこれでした:

somefun p = p <+> text "woo" $+$ nest 4 (text "nested text") $+$ text "text without indent"
fun = somefun (text "------")

つまり、次のDocのインデントの基になるDocを渡します。これは私の問題を解決しますが、私はこれを行うためのより良い方法を探しています。

4

1 に答える 1

2

引数としてのパス・ザ・ドクのソリューションは優れています。1つのドキュメントにまとめると、それを再び分割することはできません。そのため、代わりにリストを使用する2つの方法を次に示します。

代替案1

これを行う別の方法は、後続のテキスト[Doc]の代わりにを使用Docすることです。行を別の方法で処理する場合は、次のようなものを使用して再結合します。

(<+$) :: Doc -> [Doc] -> Doc
doc <+$ [] = doc 
doc <+$ (d:ds) = (doc <+> d) $+$ foldr ($+$) empty ds

somefun :: [Doc]
somefun = [text "woo",
    nest 4 (text "nested text"),
    text "text without indent"]

fun :: Doc
fun = text "------" <+$ somefun

これはあなたに

*Main> fun
------ woo
    nested text
text without indent

代替案2

トップラインをインデントし続けたい場合は、リストを保持する別の方法でこのソリューションを書き直すことができます。

(<+:) :: Doc -> [Doc] -> [Doc]
doc <+: [] = [doc] 
doc <+: (d:ds) = (doc <+> d) : ds -- pop doc in front.

Docある段階で、それらを1つにまとめる必要があります。

vsep = foldr ($+$) empty

これで、上に行を配置し、一番上の行の前に少しプッシュする:ために使用できます。<+:

start = [text "text without indent"]
next  = nest 4 (text "nested text") : start
more  = text "woo" : next
fun   = text "------" <+: more
extra = text "-- extra! --" <+: fun

これをテストする

*Main> vsep fun
------ woo
    nested text
text without indent

*Main> vsep extra
-- extra! -- ------ woo
    nested text
text without indent

主な問題は、[Doc]代わりに使用Docすると、きれいな印刷ライブラリを使用していないかのようになることです。ただし、それが必要なものであるかどうかは関係ありません。

于 2012-11-10T17:29:03.000 に答える