1
最初由3个类型类型设计的软件已经发展到使用大量的类型类。让我们以这个例子:存在越来越多的类型分类时的分层软件
- 你有
Service[A,B]
- 你有
TypeClass1[A]
- 你有
TypeClass2[B]
- 你有
TypeClass3[A,B,C]
- 你有一个
TypeClass4[A]
- 你有
TypeClass5[B]
- 您有
TypeClass6[C]
- 你有
TypeClass7[C]
- 你有
TypeClass8[B]
我们有这是完全不相交的A,B,C的6个已知组合(即每种组合都包含仅在该组合中使用的A,B,C类型)。所以,现在我们有两个选择:
- 写这将需要8种不同类型类
- 创建中间类型类,我们可以推导出如
TypeClass14[A]
,Typeclass67[C]
等顶级方法,所以最后你 能最终得到一个UberTypeClass[A,B,C]
,它提供了所有的 所需的行为。
作为一种通用的编程方法,第二种解决方案显然更合理:引入中间层和抽象提高了代码质量的多种方式。我们面临的挑战是:
如果我们没有在中间层通过提供堆叠起来的隐式转换,在现实中我们只是提高了语法召唤较低级别的类型类(但不管怎么说,这些都是implicits!),但如果我们不召唤下级类型类我们没有解决的代码缺乏层次感
问题,我们最终写了很多中间样板(
TypeClass1Instances
,TypeClass2Instances
的,Typeclass3Instances
)
当使用与软件分层相关的类型类时,什么是最佳实践?
这样做的方向是将所有类型暴露给顶层而不构建中间抽象。这不违反模块化吗? – Edmondo1984
这取决于你如何看待它。让我们考虑一下我有一个需要'TC1 [_]'和'TC2 [_]'的函数。在没有这种复合类型类服从的规律的情况下,我真的只想对类型系统说,这个函数需要这两个类型类遵循类型类的自身定律。这经常发生在应用程序代码中。在另一种情况下,如果有法律要遵守,单纯的存在是不够的,所以我会引入另一个'TC'。 – yw3410
后者的一个很好的例子是一个'编码器[A]'和一个'解码器[A]'。把它们放在一起,你会得到一个需要遵循法律的'Codec [A]'a.encode.decode === a'。另一方面,我不能在示例中的'Show'和'Eq'之间陈述任何新的东西。 – yw3410