2017-05-18 13 views
2

我有DL <: HList,我試圖用mkStringdetailsIn: DL如何在無形中實現ToTraversable?

val detail: String = detailsIn.mkString("", "; ", "") 

mkString被定義爲無形如下:

def mkString(start: String, sep: String, end: String) 
    (implicit toTraversable: ToTraversable.Aux[L, List, Any]): String = this.toList.mkString(start, sep, end) 

我已經看到了很多的例子定義,需要一個功能一個ToTraversable的含義,但還沒有看到任何人真正創造了它的價值(我懷疑我在Shapeless中不夠精通,無法像我應該那樣容易地找到這些東西)。

我有我需要有???填寫,如果這是正確的,我覺得一個例子是極大的幫助下面的代碼片段:

implicit val dlToList: ToList[DL, Any] = new ToTraversable[DL, List] {???} 

不過,我懷疑有可能是工廠方法已經這樣做了,但如果是的話,我還沒有找到它。

回答

3

您不希望自己實例化此值。相反,你應該要求它作爲一個額外的隱含參數,讓編譯器做的工作:

def myMethod[DL <: HList](detailsIn: DL)(implicit ev: ToTraversable.Aux[DL, List, Any]) = { 
    val detail: String = detailsIn.mkString("", "; ", "") 
    println(detail) 
} 

編輯

  1. 不要如果myMethod的使用的IntelliJ
  2. 可以找到隱含的,爲什麼不能mkString找到它?

    因爲從一個myMethod點,你正在尋找ToTraversable[DL, List]任何DL <: HList!編譯器不可能知道對於每個可能的實例DL,都可能推導出ToTraversable(即使在這種特殊情況下,這可能通過結構歸納來實現)。

    相比之下,實際進行呼叫myMethod(1 :: "s" :: HNil)的地方應該具有所有靜態信息以隱含地解決ToTraversable.Aux[Int :: String :: HNil, List, Any]。但是你可能會問,如果我不想在通用環境中調用myMethod怎麼辦?然後你別無選擇,只能將該隱式約束傳播到調用鏈,直到所有泛型消失。

+0

如果myMethod可以找到隱式,爲什麼mkString找不到它呢? – bbarker

+0

我希望有一個原因是它不在範圍內,但爲什麼?是否允許在選擇隱含方面有更多靈活性的設計決策? – bbarker

+0

我試着編譯你的例子,但它在這個項目中仍然失敗了MWE:https://github.com/bbarker/ProjectGists/tree/master/Scala/ShapelessToTraversable;也許我錯過了一個適當的包括。 IntelliJ沒有解決這個問題,但我想這並不奇怪。 – bbarker