类型类或通过隐式添加方法?

Typeclass or add a method via implicit?

我正在设计某种 Service 并且遇到了设计问题。这是我目前拥有的:

trait Service {
  def isFailed(): Boolean
  def start(): Unit
  def stop(): Unit
}

并且为了将 Service 彼此相关的分组(为了 restart/recover 分组,而不是其他服务)我创建了以下包对象:

package object app {
  type FaultTolerantServiceGroup = Seq[Service]
  object FaultTolerantServiceGroup{
    def apply(svcs: Service*): FaultTolerantServiceGroup = Seq(svcs: _*)
  }

  class FaultTolerantServiceGroupOps(val F: FaultTolerantServiceGroup){
    def hasFailed: Boolean = F.forall(_.failed())
  }

  trait FaultTolerantServiceGroupSyntax{
    implicit def serviceGroup2Ops(F: FaultTolerantServiceGroup) = new FaultTolerantServiceGroupOps(F)
  }
}

所以我将方法hasFailed添加到FaultTolerantServiceGroup。但我不确定这个决定。

定义一个类型类会更好吗,比如说

trait Watchable[T]{
     def hasFailed(t: T): Boolean
}

并隐式提供 Watchable[FaultTolerantServiceGroup] 的实例?

以我的愚见,隐式函数之后变得更难阅读。即使在阅读我的旧代码时,当对象具有突然出现的方法时,有时也会感到困惑。

我还没有看到隐式函数比声明函数更容易推理的实例:

val failedGroup : FaultTolerantServiceGroup => Boolean = _.forall(_.failed())

生成的代码似乎并不比隐式更好或更糟,但至少很明显功能来自何处:

val group : FaultTolerantServiceGroup = ???

//no implicit
val failed = failedGroup(group)

//with implicits : how does a Seq have a hasFailed method?
val failed = group.hasFailed

显式函数也使 Iterable 函数更易于阅读:

val groups : Iterable[FaultTolerantServiceGroup] = ???

val failedGroups = groups filter failedGroup