2013-02-21 15 views
4

在論文«Type Classes as Objects and Implicits»中有一些使用Scala特徵的例子,例如C++概念和Haskell類型類。我試着寫類似InputIterator概念和find功能斯卡拉:使用Scala特徵對C++概念進行建模

concept InputIterator<typename Iter> { 
    typename value_type; 
    value_type operator*(Iter); 
    ... 
}; 

template<typename Iter, typename V> 
requires InputIterator<Iter> && EqualityComparable<Iter::value_type, V> 
Iter find(Iter first, Iter last, V v) { 
    while (first < last && *first != v) 
     ++first; 
    return first; 
} 

我不知道我理解正確的特徵。但仍...有InputIterator特質Scala編寫的(或者更確切地說 - 這是簡單的模擬與方法find功能使用):

trait InputIterator[Iter] { 
    type value_type 

    def <(a: Iter, b: Iter): Boolean 
    def ++(it: Iter): Unit 
    def *(it: Iter): value_type 
} 

EqualityComparable是明確的:

trait EqualityComparable[S, T] { 
    def ==(s: S, t: T): Boolean 
    def !=(s: S, t: T): Boolean = !(s == t) 
} 

但是我們應該用find做什麼?我想編寫這樣的事:

def find[Iter, V](first: Iter, last: Iter, x: V)(implicit iterator: InputIterator[Iter], 
    cmp: EqualityComparable[iterator.value_type, V]): Iter = 
{ 
    while (iterator.<(first, last) && cmp.!=(iterator.*(first), x)) 
     iterator.++(first) 
    first 
} 

但它會導致錯誤«非法方法依賴型»。而我不知道如何「抽取」其他方式抽象類型value_type。因此,作爲一個結果,我有這樣的代碼:

trait EqualityComparable[S, T] { 
    def ==(s: S, t: T): Boolean 
    def !=(s: S, t: T): Boolean = !(s == t) 
} 

trait InputIterator[Iter] { 
    type value_type 

    def <(a: Iter, b: Iter): Boolean 
    def ++(it: Iter): Unit 
    def *(it: Iter): value_type 
} 

trait VTInputIterator[Iter, VT] extends InputIterator[Iter] { 
    type value_type = VT 
} 

class ArrayListIterator[T](a: ArrayList[T], i: Int) { 
    val arr: ArrayList[T] = a 
    var ind: Int = i 

    def curr(): T = arr.get(ind) 
    def ++(): Unit = { ind += 1 } 

    override def toString() = "[" + ind.toString() + "]" 
} 

class InputIterArrList[T] extends VTInputIterator[ArrayListIterator[T], T]{ 
    def <(a: ArrayListIterator[T], b: ArrayListIterator[T]) = { 
     if (a.arr == b.arr) a.ind < b.ind 
     else throw new IllegalArgumentException() 
    } 

    def ++(it: ArrayListIterator[T]): Unit = it.++() 
    def *(it: ArrayListIterator[T]) = it.curr() 
} 

object TestInputIterator extends Application{ 

    def find[Iter, VT, V](first: Iter, last: Iter, x: V)(implicit iterator: VTInputIterator[Iter, VT], 
     cmp: EqualityComparable[VT, V]): Iter = 
    { 
     while (iterator.<(first, last) && cmp.!=(iterator.*(first), x)) 
     iterator.++(first) 
     first 
    } 

    implicit object EqIntInt extends EqualityComparable[Int, Int] { 
     def ==(a: Int, b: Int): Boolean = { a == b } 
    } 

    implicit object inputIterArrListInt extends InputIterArrList[Int]{} 

    val len = 10; 
    var arr: ArrayList[Int] = new ArrayList(len); 
    for (i: Int <- 1 to len) 
     arr.add(i) 
    var arrFirst = new ArrayListIterator(arr, 0) 
    var arrLast = new ArrayListIterator(arr, len) 
    var r = find(arrFirst, arrLast, 7) 
    println(r) 
} 

而不是抽象類型,我們用類型參數VTdef find[Iter, VT, V]

所以問題是:如何做得更好?是否可以使用抽象類型value_type而無需附加類型參數VT

+0

不太瞭解C++,所以,爲什麼InputIterator不僅僅是一個Iterator? – pedrofurla 2013-02-21 11:35:03

+0

在C++中'Iterator'是迭代器的基類,它沒有任何方法。 'InputIterator'允許你遍歷集合(僅用於讀取)。 – juliet 2013-02-21 11:46:47

回答

4

變化的簽名找到:

def find[Iter, V, II <: InputIterator[Iter]](first: Iter, last: Iter, x: V)(
    implicit iterator: II, cmp: EqualityComparable[II#value_type, V]): Iter 

這可能是你想表達什麼。

請注意,您的Scala代碼實際上與C++代碼不一樣。在C++ find中使用Iter::value_type,但在Scala中使用InputIterator[Iter]#value_type

+0

哦,謝謝!這實際上是我需要的。 – juliet 2013-02-21 12:22:51

+0

可能還有其他方法來定義'InputIterator'和'find'?或者只有上面的方法可以使用? – juliet 2013-02-21 12:29:15

+0

您的'InputIterator'特性沒有多大意義,只是讓迭代器擴展迭代器特性更簡單。然後找到看起來像'find [Iter <:Iterator,V](first:Iter,last:Iter,x:V)(implicit cmp:EqualityComparable [Iter#value_type,V]):Iter' – 2013-02-21 12:51:13