私は次のことを達成したい:
- 処理する必要がある文字列のリストがあります。
- これらのプロセッサにはいくつかの異なる種類があり、それぞれが文字列のどの部分を読み取るかを認識しています。
- 2 つのフェーズで作業する必要があります。まず、プロセッサは各入力文字列を確認して、プロセッサ固有のデータを構築する必要があります。次に、各入力文字列が各プロセッサによって処理され、結果の文字列が 1 つに結合されます。
変更可能な方法でそれを行うのは簡単です。すべてのプロセッサに共通の基本クラスがあり、それらが集約するさまざまな種類のデータが具体的な実装にカプセル化されます。このインターフェースは、「入力文字列を見て内部データを作成する」と「内部データを使用して入力文字列を処理する」という 2 つの機能だけで構成されています。
Scala で書いているので、純粋な関数型アプローチが存在するかどうか疑問に思っています。問題は、現在、これらのプロセッサのベース トレイトが内部データのタイプによってパラメータ化されており、さまざまな種類のプロセッサのリストを持つ方法がないように思われることです。
この問題は、より単純なケースで示すことができます: 変更可能なアプローチに固執するとしますが、何らかの理由で、プロセッサが文字列から取得するものの型をパラメーター化したとします。
trait F[V] {
def get(line: String) : V
def aggregate(value: V)
def process(value: V) : String
}
class F1 extends F[Int] // ...
class F2 extends F[HashMap[Int, Int]] // ...
for (s <- List("string1", "string2");
f <- List(new F1(), new F2())
{
f.aggregate(f.get(s)); // Whoops --- doesn't work
}
f.get(s)
を返すため、機能しませんAny
。Scala の型システムで表現する必要があるように見えList(new F1(), new F2())
ますがF[?]
、それは異なりますが、そのリストの要素を取得すると、その型パラメーターの具体的な値があり、その型でありf.get(s)
、によって受け入れられる必要があるという点で一貫していますf.aggregate()
。
最後に、私はこのようなものを持ちたいと思います(方法がわからないため省略しています):
trait F[D] {
def initData : D
def aggregate(line: String, data: D) : D
def process(line: String, data: D) : String
}
class F1 extends F[Int] // ...
class F2 extends F[HashMap[Int, Int]] // ...
// Phase 1
// datas --- List of f.initData, how to?
for (s <- List("string1", "string2")) {
for (f <- List(new F1(), new F2()) {
// let fdata be f's data
// update fdata with f.aggregate(s, fdata)
}
}
// Phase 2
for (s <- List("string1", "string2")) {
for (f <- List(new F1(), new F2()) {
// let fdata be f's data
// for all fs, concatenate f.process(s, fdata) into an output string
}
}
質問:
- このタスクは、Scala で純粋に機能的な方法で解決できますか?
- このタスクは他の関数型言語で解決できますか?
- この状況は非常に一般的な状況のように見えます。検索できる名前はありますか?
- 型理論や関数型プログラミング言語の背景知識がほとんどまたはまったくないと仮定して、それについて読むのに最適な場所はどこですか?