Scala: перебирать объекты класса type - PullRequest
0 голосов
/ 09 декабря 2018

Я использую несколько внешних типов данных в программе Scala.Моя цель - определить полиморфные функции для этих типов данных, используя классы типов.Проблема в том, что в самой программе Scala эти типы данных должны быть последовательно повторены в определенных точках, которые являются теми же точками, где мне нужно использовать полиморфные функции из класса типов.Так, например, если бы у нас было

trait Show[A] {
  def show(a: A, b : String): String
}

object Show {

  def apply[A](implicit sh: Show[A]): Show[A] = sh

  def show[A: Show](a: A, b : String) = Show[A].show(a, b)

  implicit class ShowOps[A: Show](a: A) {
    def show(b : String) = Show[A].show(a, b)}


  implicit val blogCanShow: Show[Int] = new Show[Blog] {
    def show(blog: Blog, b : String): String = s"blog $blog" + b
}
  implicit val twitterCanShow: Show[String] = new Show[Twitter] {
    def show(twitter: Twitter, b : String): String = s"twitter $twitter" + b    }
}

Тогда мне нужно было бы использовать типы данных следующим образом:

for each data type:
  call show()
  business logic
  call another polymorphic function like show()
  more business logic
  etc... 

Я пытался использовать HLists из Shapeless, но не мог понять, какполучить повторяемый блок кода для работы с ним.Я думаю, что мне нужно использовать какое-то отражение здесь, но не знаю точно, с чего начать.Любые предложения или помощь будут очень признательны.

1 Ответ

0 голосов
/ 09 декабря 2018

См. http://tpolecat.github.io/2015/04/29/f-bounds.html для известного обсуждения этой проблемы.

Суть (в нижней части поста) в том, что вы хотите что-то аналогичное Seq[(A,Show[A]) forSome {type A}], так что у вас есть доступкак A, так и Show.Нет необходимости хранить Show[A] s без отражения во время выполнения, но Роб показывает более изящный трюк, содержащий пару:

trait ∃[F[_]] {
  type A
  val a: A
  val fa: F[A]
}
object ∃ {
  def apply[F[_], A0](a0: A0)(implicit ev: F[A0]): ∃[F] =
    new ∃[F] {
      type A = A0
      val a = a0
      val fa = ev
    }
}

, поэтому вы можете объявить

val shows: List[∃[Show]] = ∃(myBlog) :: ∃(myTweet) :: Nil

и перебираем его, обращаясь к a и fa по мере необходимости.

Для меня это предпочтительнее решения HList, поскольку, хотя код изначально будет выглядеть немного непрозрачным,путаница любого будущего читателя может быть быстро устранена с помощью щелчка правой кнопкой мыши в среде IDE.

...