2014-05-22 51 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