2014-05-22 87 views
0

我知道在scala中已經有了一些遍歷泛型的方法,但我試圖定義一個簡單的trait封裝可遍歷的類型。但是,我無法獲取類型簽名。第一次嘗試將類似以下內容:在scala中遍歷通用

trait Traversable1[B] { 
    def head: Option[B] 
    def next: Traversable1[B] 
} 

除了我想next返回擁有相同類型與原始穿越,而不是更一般的穿越類型的對象這個效果很好。例如,如果List的特性爲Traversable1,那麼它的next方法應返回某種類型的List而不是Traversable1。因此,我的第二次嘗試以下操作:

trait Traversable2[A[B] <: Traversable2[A[B]] { 
    def head: Option[B] 
    def next: A[B] 
} 

這裏,A可以等於List,所以next將返回List[B]。不幸的是,這段代碼不能編譯:A[B] takes no type parameters, expected: one

我該如何實現我想要做的?

+0

叫它這不是Iterable的是什麼? – acjay

+1

是的,可能。我正在處理更復雜的示例,並試圖更深入地理解Scala的類型系統和語法,以便在更復雜的新情況下使用正確的解決方案。 – jonderry

+0

你可能會發現'scalaz.Traverse'的實現很有趣。如上所述,它基於http://www.cs.ox.ac.uk/jeremy.gibbons/publications/iterator.pdf – Hugh

回答

3

你可以創建這樣一個特點:

trait Traversable[T[_]] { 
    def head[A](t: T[A]): Option[A] 
    def next[A](t: T[A]): T[A] 
} 

然後實現它像列表:

implicit val listTraversable = new Traversable[List] { 
    def head[A](l: List[A]) = l match { 
     case Nil => None 
     case x::_ => Some(x) 
    } 

    def next[A](l: List[A]) = l.tail 
} 

然後,您可以通過採取隱式使用「類型類」模式使用它執行特質來完成工作,例如

def foreach[T[_], A](t: T[A], f: A => Unit)(implicit trav: Traversable[T]): Unit = { 
    trav.head(t) match { 
     case Some(v) => 
      f(v) 
      foreach(trav.next(t), f) 
     case None =>() 
    } 
} 

foreach(List(1,2,3), println) 
+0

這看起來不錯,但你能解釋一下這將如何在實踐中使用嗎?如果我有一個接受'Traversable'的函數,當我有'List'時,是否需要同時傳遞'List'和singleton'listTraversable'?或者有沒有辦法隱式給出一個'List'這個功能?我想我不明白這些特徵的語法,它們只是定義接受它們封裝的數據的函數。 – jonderry

+0

@jonderry - 是的,您可以使用implicits來提供執行特徵,請參閱更新。 – Lee