2013-07-11 49 views
0

我試圖撰寫與複合類型的一些功能在他們的類型參數:防止scala函數組合推斷?類型

trait Contains[T] 
trait Sentence 
trait Token 
def sentenceSegmenter[T] = (c: Contains[T]) => null: Contains[T with Sentence] 
def tokenizer[T <: Sentence] = (c: Contains[T]) => null: Contains[T with Token] 

我的主要目標是能夠以簡單的東西來撰寫他們:

val pipeline = sentenceSegmenter andThen tokenizer 

然而中,產生一個編譯錯誤,因爲Scala推斷的tokenizer需要類型爲Contains[? with Sentence] => ?

scala> val pipeline = sentenceSegmenter andThen tokenizer 
<console>:12: error: polymorphic expression cannot be instantiated to expected type; 
found : [T <: Sentence]Contains[T] => Contains[T with Token] 
required: Contains[? with Sentence] => ? 

     val pipeline = sentenceSegmenter andThen tokenizer 
               ^

我試過的tokenizer由斯卡拉推斷類型更匹配一個稍微不同的定義,但我得到一個類似的錯誤:

scala> def tokenizer[T] = (c: Contains[T with Sentence]) => null: Contains[T with Sentence with Token] 
tokenizer: [T]=> Contains[T with Sentence] => Contains[T with Sentence with Token] 

scala> val pipeline = sentenceSegmenter andThen tokenizer 
<console>:12: error: polymorphic expression cannot be instantiated to expected type; 
found : [T]Contains[T with Sentence] => Contains[T with Sentence with Token] 
required: Contains[? with Sentence] => ? 

     val pipeline = sentenceSegmenter andThen tokenizer 
               ^

我可以,如果我指定幾乎與sentenceSegmenter沿任意類型的東西來編譯,或者,如果我創建一個沒有類型參數虛假初始功能:

scala> val pipeline = sentenceSegmenter[Nothing] andThen tokenizer 
pipeline: Contains[Nothing] => Contains[Nothing with Sentence with Sentence with Token] = <function1> 

scala> val pipeline = sentenceSegmenter[Any] andThen tokenizer 
pipeline: Contains[Any] => Contains[Any with Sentence with Sentence with Token] = <function1> 

scala> val begin = identity[Contains[Any]] _ 
begin: Contains[Any] => Contains[Any] = <function1> 

scala> val pipeline = begin andThen sentenceSegmenter andThen tokenizer 
pipeline: Contains[Any] => Contains[Any with Sentence with Sentence with Token] = <function1> 

我不會介意AnyNothing被推斷的類型,因爲我真的不關心什麼T是。 (我主要關心with XXX部分。)但是我希望推斷它,而不是必須明確指定它,或者通過僞造的初始函數提供它。

回答

1

您不能綁定(val)類型參數。你必須使用一個def代替它可以綁定類型時,它的使用:

def pipeline[T] = sentenceSegmenter[T] andThen tokenizer 

注意,您可以調用與推斷類型的管道:

scala> new Contains[Sentence] {} 
res1: Contains[Sentence] = [email protected] 

scala> pipeline(res1) 
res2: Contains[Sentence with Sentence with Token] = null 
+0

但是''begin''變通方法我的代碼使用''val'',一切正常,所以它不能只是一個''val''和''def''的問題。另外,在你的代碼中,你仍然必須顯式地指定一個類型參數給''''''''''''''''''''這就是我想要擺脫的... – Steve

+0

您的'begin'綁定的類型爲'Contains [Any]'並且與'val pipeline = sentenceSegmenter [Any]和Then tokenizer'沒有區別。請注意,您可以調用管道而不使用類型參數。 – Noah

+0

雖然我不想在調用管道時擺脫類型參數,但我的任何解決方法都不需要它。我在構建管道時試圖擺脫類型參數,例如在''sentenceSegmenter和Then tokenizer'行中。也許我應該澄清,我真的不在乎什麼「T」可以解決。只要它允許使用'sentenceSegmenter和Then tokenizer'',那對我來說就沒問題。我編輯了一下這個問題,希望能夠澄清這一點。 – Steve