如何扩展以下基于隐式的设计以涵盖Option案例?

时间:2016-12-19 17:44:12

标签: scala

此问题与this other question有关。在那里,我基本上可以将接口实现附加到一个简单的case类。核心是这一点:

case class UserRow(id: Long, username: String, firstName: String, 
                   lastName : String, ...)

trait PluggableUserService extends be.objectify.deadbolt.scala.models.Subject {
  override def roles: List[Role]
}

object PluggableUserService {
  implicit class toPluggable(user: UserRow)(implicit userService: UserService) 
    extends PluggableUserService {
    //------------------------------------------------------------------------
    override def roles: List[Role] = {
      userService.roles(user)
    }
}

然后我可以做:

val user : UserRow = UserRow(...)
user.roles

// or even nicer
val subject : Subject = UserRow(..)
subject.roles

但现在我需要能够做到这一点但不起作用:

val subject : Option[Subject] = Some(UserRow(...))

如何扩展上述设计以涵盖此选项协变分配?

2 个答案:

答案 0 :(得分:2)

怎么样

  implicit def toPluggableOpt(o: Option[UserRow])(implicit us: UserService) = o.map(new toPluggable(_))

答案 1 :(得分:1)

拥有implicit def封装implicit中的现有Option

implicit def toPluggableOpt[T](t: Option[T])(implicit ev: T => PluggableUserService): Option[PluggableUserService] = t.map(ev)

这适用于可以隐式转换为PluggableUserService的所有内容。它也可以很容易地推广到任何仿函数(List等)。给出你选择的库中的Functor[F[_]]类型类(scalaz / cats / whatever):

implicit def mapPluggable[T, F[_]: Functor](t: F[T])
    (implicit ev: T => PluggableUserService): F[PluggableUserService] = implicitly[Functor[F[_]]].map(t)(ev)