17

Scrap Your BoilerplateやHaskellでのジェネリック プログラミングについて話している人を見かけます。これらの用語はどういう意味ですか? Scrap Your Boilerplate を使用するのはいつで、どのように使用すればよいですか?

4

1 に答える 1

20

多くの場合、複雑なデータ型を変換するときは、構造の小さな部分に影響を与えるだけで済みます。つまり、特定の簡約可能な式 (redex) のみを対象としています。

古典的な例は、整数式の型に対する二重否定の除去です。

data Exp = Plus Exp Exp | Mult Exp Exp | Negate Exp | Pure Int

doubleNegSimpl :: Exp -> Exp
doubleNegSimpl (Negate (Negate e)) = e
...

...この例を説明する場合でも、パーツ全体を書き出すことは避けたいと思います。これは完全に機械的ですExp。.

この「エンジン」は、私たちが廃棄しようとしているボイラープレートです。


これを実現するために、Scrap Your Boilerplate は、データ型に対して「一般的なトラバーサル」を構築できるメカニズムを提案しています。これらのトラバーサルは、問題の特定のデータ型について何も知らなくても正確に動作します。これを行うために、非常に大まかに言えば、一般的な注釈付きツリーの概念があります。これらは、すべての ADT を注釈付きツリーのタイプに投影できるように、ADT よりも大きくなります。

section :: Generic a => a -> AnnotatedTree

「有効な」注釈付きツリーは、ADT のブランドに投影することができます。

retract :: Generic a => AnnotatedTree -> Maybe a

特に、型クラスを導入して、定義済みのGeneric型を示します。sectionretract

すべてのデータ型のこの一般的な注釈付きツリー表現を使用して、トラバーサルを一度だけ定義できます。特に、エンドユーザーが型にさらされることがないように、(戦略的に使用して)sectionインターフェースを提供します。代わりに、次のようになります。retractAnnotatedTree

everywhere' :: Generic a => (a -> a) -> (AnnotatedTree -> AnnotatedTree)

final と initialsectionおよびretracts と、注釈付きツリーが常に「有効」であるという不変条件と組み合わせて、

everywhere :: Generic a => (a -> a) -> (a -> a)
everywhere f a0 = fromJust . retract . everywhere' f . section

何をしeverywhere f aますか?fADT の「どこでも」関数を適用しようとしますa。言い換えれば、二重否定の単純化を次のように書きます。

doubleNegSimpl :: Exp -> Exp
doubleNegSimpl (Negate (Negate e)) = e
doubleNegSimpl e                   = e

つまり、idredex(Negate (Negate _))が一致しない場合は常に として機能します。これに当てはめeverywhereてみると

simplify :: Exp -> Exp
simplify = everywhere doubleNegSimpl

次に、一般的なトラバーサルを介して「どこでも」二重否定が排除されます。...ボイラープレートはなくなりました。

于 2015-01-31T02:24:10.257 に答える