2014-09-10 29 views
1

下最後語句行產生一個錯誤: 「類型不匹配;發現的:需要TestExpandableWithLibrary.this.library.type(與下面類型org.typeclass.Library):V」Scala的類型類和隱式的益智

這是我試圖做隱式轉換的地方。前面的行我簡單地使用typeclass函數確實工作正常。

關於如何解決它的任何想法?

package org.typeclass 

/////////////////////////////////////////////////////////////////////////////// 
// the domain objects 

case class Book(bookName: String) 

case class Library(libraryName: String, books: Set[Book]) 

object Library { 
    def apply(libraryName: String, bookNames: String*): Library = 
    Library(libraryName, bookNames.map(Book(_)).toSet) 
} 

case class TreeClass(nodeName: String, children: Seq[TreeClass]) 

/////////////////////////////////////////////////////////////////////////////// 
// the typeclass definition 

trait Expandable[T, V, R] { 
    def expandWith(template: T, values: V): R 
} 

object Expandable { 

    def expandWithF[T, V, R](template: T, values: V)(implicit ev: Expandable[T, V, R]): R = 
    ev.expandWith(template, values) 

    implicit class ExpandableItem[T, V, R](val template: T) extends AnyVal { 
    def expandWithM(values: V)(implicit ev: Expandable[T, V, R]): R = 
     ev.expandWith(template, values) 
    } 
} 

/////////////////////////////////////////////////////////////////////////////// 
// a typeclass implementation 

object ExpandableImpls { 

    implicit object ExpandableTreeClass extends Expandable[TreeClass, Library, TreeClass] { 
    def expandWith(template: TreeClass, library: Library): TreeClass = { 
     val parentName = s"${template.nodeName}.${library.libraryName}" 
     val children = library.books.map(book => TreeClass(s"${parentName}.${book.bookName}", Seq.empty)).toSeq 
     TreeClass(parentName, children) 
    } 
    } 

} 

//@RunWith(classOf[JUnitRunner]) 
class TestExpandableWithLibrary /*extends FlatSpec*/ { 

    import Expandable._ 
    import ExpandableImpls._ 

    val library = Library("test", "black", "white") 
    val root = TreeClass("parent", Seq.empty) 

    val useF = expandWithF(root, library) // this works 

    val useM = root.expandWithM(library) // this doesn't work! 

} 

回答

4

的問題就是,你需要把後兩個類型參數的隱含類的擴展方法,因爲這是他們會被推斷爲Nothing,因爲他們沒有提到的構造函數參數。

implicit class ExpandableItem[T](val template: T) extends AnyVal { 
    def expandWithM[V, R](values: V)(implicit ev: Expandable[T, V, R]): R = 
    ev.expandWith(template, values) 
} 

這應該工作得很好。

+0

完美,非常感謝! – satyagraha 2014-09-10 16:49:53

+0

不要粗暴,但也許在理想情況下,編譯器可能會給我一些關於我要去哪裏漂泊的線索。鍵入推論=龍在這裏! – satyagraha 2014-09-10 21:42:28

+0

@satyagraha:我同意這個錯誤可能會更好。但是,如果你想要推斷出一個類型參數,那麼它應該出現在參數的非通用位置,這是一個好主意。 – 2014-09-11 13:40:00