#scala #functional-programming #scala-cats
Вопрос:
Я хочу написать функцию showAll
, которая принимает a List
значений и выдает a String
, полученное путем объединения String
представлений каждого из значений, используя Show
экземпляры, доступные в неявной области.
Не должно быть никаких ограничений на тип элементов списка, кроме наличия Show
экземпляра.
Например:
case class Person(name: String)
implicit val showPerson: Show[Person] = Show.by(_.name)
showAll(List(1, Person("Martin")))
следует выводить:
1 Martin
В этом случае функция использует Show[Int]
Show[Person]
экземпляры и.
Какова была бы правильная подпись для функции?
Спасибо.
Комментарии:
1. Проблема в том, что список относится к типу
List[Any]
, для которого нетShow
простого способа получитьShow
каждый элемент. Существует множество трюков, чтобы получить то, что вы хотите, от шаблона магнита до создания пользовательского класса, который заархивирует каждый элемент с его экземпляром show, до использования Shapeless для автоматического заархивирования.2. Действительно, в этом-то и проблема. Моей первой мыслью было добавить какой-нибудь общий супертип T, а затем написать экземпляр show для T, но мне было интересно, смогу ли я решить эту проблему, просто каким-то образом улучшив подпись. Бесформенное выглядит интересно.
3. Проверьте это (найдите раздел «Бонусный раунд: как мы работаем с коллекциями?») — Если вам удастся заставить его работать, пожалуйста, напишите ответ! 🙂
4. Вы настаиваете на
List
этом, или варарги тоже будут работать на вас? НравитсяshowAll(1, person)
?
Ответ №1:
Вот мой пример кода , который, вероятно, решит вашу проблему. Я создал универсальный метод показать все, как вам нужно, чтобы отобразить элементы списка. также неявный метод для определенных значений полей. След микласса — это идентификатор. если Myclass не будет расширен ни на один случай, конкретное поле класса не будет напечатано.
trait Myclass
case class Person(name: String) extends Myclass
case class Admin(name: String,age:Long) extends Myclass
def main(args: Array[String]): Unit = {
showAll[Myclass](List(1, 2, Person("Martin"),Admin("Bob",30)))
}
implicit def showField: String = "name"
def showAll[T <: Myclass : ClassTag](listOfValues: List[Any]): Unit = {
listOfValues.foreach { data =>
if (data.isInstanceOf[T]) {
val myInstance= data.asInstanceOf[T]
val fld = myInstance.getClass.getDeclaredField(showField)
fld.setAccessible(true)
val value = fld.get(myInstance).asInstanceOf[String]
print(value " ")
}
else
print(data " ")
}
}