2013-04-25 57 views
0

我正在試驗存在類型。scala模板函數vs forSome

我正在玩一個函數,期望一個序列,該序列的元素都是相同的類型。我有..

def bar[X](as: Seq[A[X]]) = true 

哪裏..​​.

// parametised type to use in the question 
trait A[T] 

我再跨越「forSome」語法來了,發現我可以用它實現同樣的約束。

我寫的比較的目的如下...

// useful types 
trait A[T] 
class AI extends A[Int] 
class AS extends A[String] 

// define two functions that both have the same constraint. 
// ie the arg must be a Sequence with all elements of the same parameterised type 

def foo(as: Seq[A[X]] forSome { type X }) = true 

def bar[X](as: Seq[A[X]]) = true 

// these compile because all the elements are the same type (AI) 
foo(Seq(new AI, new AI)) 
bar(Seq(new AI, new AI)) 

// both these fail compilation as expected because 
// the X param of X[A] is different (AS vs AI) 
foo(Seq(new AI, new AS)) 
bar(Seq(new AI, new AS)) 

什麼我想明白的是 - 我這麼想嗎? 一個簽名相對於另一個簽名有什麼好處。

一個明顯的差異是編譯錯誤是不同的。

scala> foo(Seq(new AI, new AS)) 
<console>:12: error: type mismatch; 
found : Seq[A[_ >: String with Int]] 
required: Seq[A[X]] forSome { type X } 

       foo(Seq(new AI, new AS)) 
        ^

scala> bar(Seq(new AI, new AS)) 
<console>:12: error: no type parameters for method bar: (as: Seq[A[X]])Boolean e 
xist so that it can be applied to arguments (Seq[A[_ >: String with Int]]) 
--- because --- 
argument expression's type is not compatible with formal parameter type; 
found : Seq[A[_ >: String with Int]] 
required: Seq[A[?X]] 
       bar(Seq(new AI, new AS)) 
      ^
<console>:12: error: type mismatch; 
found : Seq[A[_ >: String with Int]] 
required: Seq[A[X]] 
       bar(Seq(new AI, new AS)) 
        ^

scala> 
+0

了'forSome'的範圍是很重要的。你是否嘗試過'Seq [A [X] forSome {type X}]'?考慮存在型和forSome型的一種可能有用的方法是將其視爲一種類型和這種類型的值。因此,sometype for some {type A}類型的值就是一對「A」類型以及一些類型可以取決於「A」的值。如果你想要一個異構列表,你需要這個對在Seq'中的每個元素上有所不同,而你的版本對整個'Seq'都有一個'A'。 – 2013-04-26 19:55:18

+0

更進一步,如果將存在與存在類型和普遍存在(你的'bar [X]'泛型)的對視爲與類型相關的函數,那麼'foo'和'bar'類型是同構的,通過currying/uncurrying。這種關係在像Agda這樣依賴類型的語言中更加清晰,但是如果你足夠眯眼,你可能會在Scala中看到它。 – 2013-04-26 19:58:52

回答

0

不同的是,在foo你可能指的不是鍵入X,而在bar您可以:

// fails 
def foo(as: Seq[A[X]] forSome { type X }) = Set.empty[X] 

// btw the same: 
def foo(as: Seq[A[_]]) = Set.empty[???] // <-- what would you put here? 

// OK 
def bar[X](as: Seq[A[X]]) = Set.empty[X]