Scala:遍历 class 类型的对象
Scala : Iterate over type class objects
我在 Scala 程序中使用了几种外部数据类型。我的目标是使用类型 classes 在这些数据类型上定义多态函数。问题在于,在 Scala 程序本身中,这些数据类型必须在某些点按顺序迭代,这些点与我需要使用类型 class 的多态函数的点相同。例如,如果我们有
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...
我尝试使用来自 Shapeless 的 HLists,但不太清楚如何获得可重复的代码块来使用它。我想我需要在这里使用某种反射,但不知道从哪里开始。任何建议或帮助将不胜感激。
有关此问题的著名讨论,请参阅 http://tpolecat.github.io/2015/04/29/f-bounds.html。
底线(接近 post 的底部)是您想要类似于 Seq[(A,Show[A]) forSome {type A}]
的内容,因此您可以访问 A
及其 Show
.没有运行时反射就无法避免存储 Show[A]
s 的需要,但 Rob 展示了一个更优雅的技巧来包含这对:
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
解决方案更可取,因为虽然代码最初看起来有点不透明,但以后任何 reader 的混乱都可以通过 Ctrl- 快速清除右键单击 IDE。
我在 Scala 程序中使用了几种外部数据类型。我的目标是使用类型 classes 在这些数据类型上定义多态函数。问题在于,在 Scala 程序本身中,这些数据类型必须在某些点按顺序迭代,这些点与我需要使用类型 class 的多态函数的点相同。例如,如果我们有
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...
我尝试使用来自 Shapeless 的 HLists,但不太清楚如何获得可重复的代码块来使用它。我想我需要在这里使用某种反射,但不知道从哪里开始。任何建议或帮助将不胜感激。
有关此问题的著名讨论,请参阅 http://tpolecat.github.io/2015/04/29/f-bounds.html。
底线(接近 post 的底部)是您想要类似于 Seq[(A,Show[A]) forSome {type A}]
的内容,因此您可以访问 A
及其 Show
.没有运行时反射就无法避免存储 Show[A]
s 的需要,但 Rob 展示了一个更优雅的技巧来包含这对:
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
解决方案更可取,因为虽然代码最初看起来有点不透明,但以后任何 reader 的混乱都可以通过 Ctrl- 快速清除右键单击 IDE。