在存在越来越多的类型的情况下分层软件

时间:2017-06-14 20:08:16

标签: scala typeclass

最初设计有3个类型类的软件已经发展成使用大量类型类。我们来看这个例子:

  • 您有Service[A,B]
  • 您有TypeClass1[A]
  • 您有TypeClass2[B]
  • 您有TypeClass3[A,B,C]
  • 您有TypeClass4[A]
  • 您有TypeClass5[B]
  • 您有TypeClass6[C]
  • 您有TypeClass7[C]
  • 您有TypeClass8[B]

我们有6种已知的完全不相交的A,B,C组合(即每种组合包含仅在该组合中使用的A,B,C类型)。所以现在我们有两个选择:

  1. 编写一个顶级方法,该方法需要8个不同的类型
  2. 创建我们可以派生的中间类型类,例如 TypeClass14[A]Typeclass67[C]等等,所以最终你 最终可能会有UberTypeClass[A,B,C]提供所有 期望的行为。
  3. 第二种解决方案作为通用编程方法显然更合理:引入中间层和抽象可以通过多种方式提高代码质量。我们面临的挑战如下:

    1. 如果我们不通过提供叠加它们的隐式转换来召唤中间层的低级类型类,实际上我们只是在改进语法(但无论如何,这些都是隐含的!)但我们没有'解决代码缺少分层的问题

    2. 如果我们召集较低级别的类型类,我们最终会编写大量的中间样板(TypeClass1InstancesTypeClass2InstancesTypeclass3Instances

      < / LI>

      使用与软件分层相关的类型类时的最佳做法是什么?

1 个答案:

答案 0 :(得分:1)

您可以使用以下内容来捆绑类型类。

您也可以使用无形的HLists将此代码推广到任意区域。

trait Lemma2[F1[_], F2[_], A] {
  val F1: F1[A]
  val F2: F2[A]
}

object Lemma2 {
  implicit def lemma[A, F1[_], F2[_]](implicit FA: F1[A], FB: F2[A]): 
    Lemma2[F1, F2, A] =
     new Lemma2[F1, F2, A] {
       val F1 = FA
       val F2 = FB
   }

}

trait LemmaSyntax {
  implicit def f1[F1[_], F2[_], A](implicit lemma: Lemma2[F1, F2, A]): F1[A] = {
    lemma.F1
  }

  implicit def f2[F1[_], F2[_], A](implicit lemma: Lemma2[F1, F2, A]): F2[A] = {
    lemma.F2
  }
}

import cats._
import cats.implicits._

object Test extends LemmaSyntax {
  type Proof[A] = Lemma2[Show, Eq, A]


   def foo[A : Proof](a: A): String = {
     a.show
   }
}

object Other {
  Test.foo("moo")
}