我一直在嘗試MacroParadise(here和here)以及一些其他更新的功能。今天,在使用TypeTags時,我意識到我現在可以做這樣的事情來強制執行類型相等。使用Scala的宏來強制執行類型相等
def typeEq[A: TypeTag, B: TypeTag]: Boolean = {
implicitly[TypeTag[A]].tpe =:= implicitly[TypeTag[B]].tpe
}
然後我想起TypeTag
implicits產生的編譯器,我有我或許可以寫一個宏實現更簡潔TypeTag使用這樣的想法:
def foo[A](xs: List[A]): String = xs match {
case y :: ys if typeEq[A, String] => y
case y :: ys if typeEq[A, Int] => y.toString
}
我只寫Lisp中的一些宏,以及試圖使用宏庫時磕磕絆絆。這導致我進行了幾次嘗試,但最終都擴大到了Int =:= Int
這種不起作用的東西,或者像typeA =:= typeB
這樣的東西都是免費的(這也不起作用)。
這導致我有兩個問題: 1)這可能沒有foo
上的背景界限(如上面寫的)? 2)如何將implicits獲得的Type
正確拼接到結果表達式中?
在我看來,宏和暗示應該允許我獲取隱含的WeakTypeTag
並使用其成員進行拼接,因爲它們都發生在編譯時。
這對於在兩種類型上聲明相等性很好,但由於擦除,=:=類型見證在主體中不可用。調用foo [Int]和foo [String]在運行時是相同的,您需要一種恢復擦除信息的機制(即TypeTags)。不管是否擦除,我都希望有一種簡潔的方式來說明兩種類型之間的類型相等。如果用'ty1 =:= ty2'替換'typeEq [ty1,ty2]',則上面的示例不會編譯。值得注意的是=:=實際上是'scala.runtime.reflect.Type'上的一個方法,而不是class =:=,它用於隱含的見證。 – jroesch 2013-02-21 09:32:11
更新了我的帖子 – drexin 2013-02-21 09:51:00
謝謝,這確實解決了我的例子(儘管是一個人爲的)。我對宏寫作部分更感興趣。我仍然無法正確拼接類型。這對於'A'可能與'xs.head'類型或其他結構不同的情況更爲重要。 – jroesch 2013-02-21 20:46:02