2

単純な空白に敏感な言語用のきれいなプリンターを書いています。

私はWadlerライブラリよりもLeijenプリティプリンターライブラリが好きですが、Leijenライブラリには私のドメインに1つの問題があります。挿入する改行は、group構文によって上書きされる可能性があります。これにより、行が圧縮され、セマンティクスが変更される可能性があります。出力の。

wl-pprintにグループ化できない行を実装することはできないと思います(間違っていると思いますが)。

wl-pprint-extrasパッケージを少し見てみると、公開された内部インターフェイスでさえ、によって押しつぶされない行を作成できるとは思いませんgroup

私は決して使用しないという事実に頼る必要がありgroupますか、それとももっと良いオプションがありますか?

4

2 に答える 2

1

はい、避ける必要がありgroupます。ライブラリは、指定した出力の幅に基づいて、折り返しを容易にするか、折り返さないように設計されています。

実装している言語の構文によっては、それらを使用するandおよびand演算子にも注意する必要softlinesoftbreakあり</>ます<//><$>代わりに使用できないことがわかる理由はありません<$$>

sep、、およびすべてが直接または間接的に使用されます(またfillSep、回避したい不確定なセマンティクス/幅に依存する改行があります)。しかし、あなたの目的を考えると、私はあなたがそれらを必要としないと思います:catfillCatgroup

vsepまたはhsepの代わりにsepまたはを使用しfillSepます。またはの代わりにまたは
を使用します。hcatvcatcatfillCat

あなたは次のような行を使うことができます

import Text.PrettyPrint.Leijen hiding (group,softline,softbreak,
                                      (</>),(<//>),
                                      sep,fillSep,cat,fillCat)

これらの関数を呼び出さないようにします。

使用している関数がどこかでグループを呼び出さないようにする方法は考えられませんが、避けるべきものだと思います。

于 2012-10-09T08:00:07.870 に答える
1

グループ化できるようにし、一部の行が挿入されていないことを確認する必要がある場合、ライブラリ設計者がコードではなくデータ型でセマンティクスをエンコードしたという事実を使用してみませんか。この素晴らしい決定により、非常に再設計可能になります。

Docデータ型は、コンストラクターを使用して改行をエンコードしますLine :: Bool -> Doc。Boolは、行を削除するときにスペースを省略するかどうかを表します。(行はそこにあるときにインデントします。)Boolを置き換えましょう:

data LineBehaviour = OmitSpace | AddSpace | Keep

data Doc = ...
    ...
    Line !LineBehaviour   -- not Bool any more

データとしてのセマンティクスの設計のすばらしい点は、このBoolデータをLineBehaviourデータに置き換えた場合、それを使用せずに変更せずに渡した関数を編集する必要がないことです。Boolが何であるかを調べる関数は、変更によって壊れます。古いセマンティクスが存在していたデータ型を変更することにより、新しいセマンティクスをサポートするために変更が必要なコードの部分を正確に書き直します。プログラムは、必要なすべての変更を行うまでコンパイルされませんが、改行のセマンティクスに依存しないコード行に触れる必要はありません。やったー!

たとえばrenderPretty、コンストラクターを使用しますLineが、パターンLine _では、それをそのままにしておくことができます。

まず、、、に置き換える必要がLine TrueありLine OmitSpaceます。Line FalseLine AddSpace

line = Line AddSpace

linebreak = Line OmitSpace

しかし、おそらく私たちは自分自身を追加する必要があります

hardline :: Doc
hardline = Line Keep

そして、おそらくそれを使用する二項演算子で行うことができます

infixr 5 <->
(<->) :: Doc -> Doc -> Doc
x <-> y = x <> hardline <> y

そして、垂直セパレーターに相当します。これは、非常に垂直なセパレーターよりも優れた名前とは思えません。

vvsep,vvcat :: [Doc] -> Doc
vvsep = fold (<->)
vvcat = fold (<->)

実際の行の削除はgroup関数で行われます。以下を除いて、すべて同じままでかまいません。

flatten (Line break)    = if break then Empty else Text 1 " "

に変更する必要があります

flatten (Line OmitSpace)    = Empty
flatten (Line AddSpace)     = Text 1 " "
flatten (Line Keep)         = Line Keep

それだけです:私は他に変更するものを見つけることができません!

于 2012-10-09T23:45:26.070 に答える