Я экспериментировал с 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) Как правильно спланировать Type
s, полученный имплицитами в выражение результата?
Мне кажется, что макросы и импликации должны позволять мне использовать неявный код WeakTypeTag
и использовать его член tpe
для сращивания, поскольку они оба происходят во время компиляции.
Это нормально для утверждения равенства только двух типов, но свидетельство типа =: = не может использоваться в теле из-за стирания. Вызов foo [Int] и foo [String] идентичны во время выполнения, вам нужен механизм для восстановления стертой информации (т. Е. TypeTags). Я заинтересован в краткой формулировке равенства типов между этими двумя типами, независимо от стирания. Если вы замените 'typeEq [ty1, ty2]' на 'ty1 =: = ty2', приведенный выше пример не будет компилироваться. Также стоит отметить, что =: = на самом деле метод на 'scala.runtime.reflect.Type', а не class =: =, который используется для неявного свидетеля. – jroesch
обновил мое сообщение – drexin
Спасибо, это действительно решает мой пример (хотя и надуманный). Меня больше интересует макрокоманда. У меня все еще была проблема с правильной сортировкой типов. Это более важно для случая, когда 'A' может не совпадать с типом' xs.head' или с другими структурами. – jroesch