3

Haskellでこれらの同様の機能をどのように組み合わせることができますか?

getGroup [] acc = reverse acc
getGroup ((Letter x):letfs) acc = getGroup letfs ((Letter x):acc)
getGroup ((Group x):letfs) acc = getGroup letfs ((Group (makeList x)):acc)
getGroup ((Star x):letfs) acc = getGroup letfs ((Star (makeList x)):acc)
getGroup ((Plus x):letfs) acc = getGroup letfs ((Plus (makeList x)):acc)
getGroup ((Ques x):letfs) acc = getGroup letfs ((Ques (makeList x)):acc)

Letter、Group、Star、Plus、および Ques はすべて、データ型定義の一部です。

data MyData a 
        = Operand a 
        | Letter a
        | Star [RegEx a] 
        | Plus [RegEx a] 
        | Ques [RegEx a]
        | Pipe [RegEx a] [RegEx a]
        | Group [RegEx a]
        deriving Show

それらの類似性のために、これらの関数を記述するより良い方法があるのではないかと思います。たいていはグループ、スター、プラス、キューの機能が同じなのでまとめたいのですが、全部をまとめられる方法があればいいなと思います。

4

2 に答える 2

4

いくつかの異なるケースのばらばらな和集合として定義されたデータ型定義がある場合、必然的に、その型を処理する関数で大規模なケース分析が発生することになります。

ケース分析を削減する 1 つのアプローチは、共通性を除外して基本型を単純化することです。

data MyData a = Val String a 
              | UnOp String [Regex a]
              | BinOp String [Regex a] [Regex a]

この定式化では、各ケースには、各ケースのさまざまな種類を区別できる識別子フィールドがあります。ここでは、"Operand"、"Letter"、"Star" などの名前を付けると仮定して String を使用しましたがVal、種類 、種類UnOpなどの有効な識別子に対して個別の列挙型を定義することもできます。

この場合に失われる主なものは型の安全性です。String私が与えたフィールドを使用して、特に無意味なものを構築できます。この問題に取り組む最初のアプローチは、スマート コンストラクターと呼ばれるものを使用することです。これらは、より弱く型付けされたコア データをタイプ セーフな方法で構築する、具体的に型付けされたパラメーターを持つ関数です。モジュールから実際のコンストラクターをエクスポートしない限り、そのMyDataタイプの他のユーザーは、スマート コンストラクターを介してのみ適切なデータを構築できます。

型コンストラクター自体からの安全な構築の保証がさらに必要な場合は、一般化代数データ型 (GADT)ファントム型の概念に目を向ける必要があります。=これらの背後にある基本的な考え方は、データ型定義の左側の型変数と右側の型変数の間に、より柔軟な関係を持たせることです。ただし、これらは Haskell のやや新しく高度な機能であるため、標準の Haskell データ型をしっかりと把握するまで、それらに飛び込むのは控えたほうがよいでしょう。

于 2013-08-26T20:21:01.560 に答える