3

自然言語テキストを処理する関数をいくつか定義したいと思います。これらの関数はそれぞれ、テキストにいくつかの「注釈」を追加します。

class Annotation(val begin: Int, val end: Int)
class Sentence(begin: Int, end: Int) extends Annotation(begin, end)
class Token(begin: Int, end: Int) extends Annotation(begin, end)

したがって、Token アノテーションを追加する Tokenizer 関数、Sentence アノテーションを追加する SentenceSegmenter 関数などを使用する場合があります。これらの関数には、実行できる順序にいくつかの制約があります。たとえば、Tokenizer には Sentence アノテーションが必要な場合があるため、SentenceSegmenter の後に実行する必要があります。この場合、誤ってこれらの関数を間違った順序で作成した場合にコンパイル エラーが発生するようにしたいと考えています。したがってsentenceSegmenter andThen tokenizer、コンパイルする必要がありますが、コンパイルしtokenizer andThen sentenceSegmenterないでください。

以下は私の試みです。テキスト用に特別なコンテナー タイプを定義しました。このタイプ パラメーターは、テキストに追加された注釈を (複合型を介して) 指定し、関数は型パラメーターを適切に指定して、前提条件が満たされるまで実行できないようにします。複合タイプの一部です。

trait AnalyzedText[T] {
  def text: String
  def ++[U](annotations: Iterator[U]): AnalyzedText[T with U] 
}

val begin: (AnalyzedText[Any] => AnalyzedText[Any]) = identity
def sentenceSegmenter[T]: (AnalyzedText[T] => AnalyzedText[T with Sentence]) = ???
def tokenizer[T <: Sentence]: (AnalyzedText[T] => AnalyzedText[T with Token]) = ???

// compiles
val pipeline = begin andThen sentenceSegmenter andThen tokenizer
// fails to compile -- good!
//val brokenPipeline = begin andThen tokenizer andThen sentenceSegmenter

ここまでは順調ですね。関数の 1 つを実際に定義しようとすると、問題が発生します。たとえば、次のように定義したいと思いますtokenizer

def tokenizer[T <: Sentence]: (AnalyzedText[T] => AnalyzedText[T with Token]) =
  text => text ++ "\\S+".r.findAllMatchIn(text.text).map(m => new Token(m.start, m.end))

しかし、Scala コンパイラーはメソッドの型引数を推測する方法を理解できず、++手動で型パラメーターを指定しない限りtext.++[Token](...)、次のエラーが発生します。

type mismatch;  found: Iterator[Token]  required: Iterator[Nothing]

この型パラメーターを推論する方法はありますか? あるいは、私は問題について間違って考えていますか? Scala でこれらの種類の関数構成の制約をキャプチャするより良い方法はありますか?

4

1 に答える 1

2

これは非常にバグに似ています。それまでの間、非常に簡単な回避策があります。プロセッサをメソッドとして定義し、戻り値の型を省略してください。

def tokenizer[T <: Sentence](text: AnalyzedText[T]) =
  text ++ "\\S+".r.findAllMatchIn(text.text).map(m => new Token(m.start, m.end))

これで、まったく同じ方法でyour を定義できpipeline、eta-expansion (§6.26.5) によってメソッドが関数に変換されます。


脚注として:奇妙な部分は、上記の定義を考えると、以下が問題ないことですtokenizer:

def tokFunc[T <: Sentence]: (AnalyzedText[T] => AnalyzedText[T with Token]) =
  tokenizer _

問題トラッカーを一瞥しましたが、明らかに関連するものは見つかりませんでした。時間があれば、もう少し掘り下げて問題を報告したり、リストの 1 つに電子メールを送信したりする価値があるかもしれません。

于 2013-07-10T00:47:55.503 に答える