代数类型的传统方法推荐类似的东西:
sealed trait CompositeType
final case class LeftBranch(left : String) extends CompositeType
final case class RightBranch(right : Int) extends CompoisteType
object Trivial extends CompositeType
问题在于我无法进一步扩展CompositeType
以获得更多选项(就像Double
扩展Float
提供更高的准确性并提供从Double转换为Float的系统
Scala允许您自由定义自己的apply和unapply方法,用于构建和匹配代数类型的实例。
是否有任何项目试图为这些类型构建框架?
这可能对演员隐喻有用。目前,参与者接收非类型化消息(因为Any
意味着没有类型限制)匹配已知类型并为其他人提供安全默认值。它打破了scala的所有类型严格设计,并且限制具有更合适类型的actor会非常好。
更新
澄清我的意图的例子:
sealed trait CompositeType1
final case class OtherBranch(x : Int, y : Int) extends CompositeType1
object Simple extends CompositeType1
trait ComplexChoice extends CompositionType with CompositionType1
我想创建CompositionType
不是作为类型层次结构中的根,而是作为一个实体类。这可能会进一步扩展,与其他类混合。
让我们看一些正常的 OOP 用法:
trait ContractOne
trait ContractTwo
def method(arg : ContractOne with ContractTwo)
在此示例中,函数method
需要一个适合两个契约的参数。什么意味着代数类型的合约?一组可用的构造函数和匹配器。扩展代数类型的自然观点是什么?使用一些新值扩展构造函数集(就像Double使用更精确的浮点数扩展Float)
CompositeType
显然错过了这个概念。如果我混合这两个代数类型,我得到了交集而不是联合。这是所选方式的直接效果,用于将代数类型表示为一组分层子类型。它提供了更多的自由来跨越初始类型之外的选择,但它缺乏OOP功能,因为继承是为了元素构造而不能用于扩展代数类型本身。
Haskell只有一种方法可以为代数类型添加新的选择:
data CompositeType = LeftBranch String | RightBranch Int | Trivial
data CompositeType1 = OtherBranch Int Int | Simple
data ComplexChoice = CompositeType | CompositeType1
ComplexChoice
在haskell数据类型的概念中无缝定义。但处理它变得复杂,因为我需要重新路由所有方法和组合。这就是为什么组合是scala中的解决方案但是麻烦和样板(如果没有可以为组合模式生成代码的编译器插件)
我真正需要的是类似的东西:
ComplexChois condense CompositeType and CompositeType1
但是对象层次结构可能只在一个方向上产生。
因此需要以其他方式来定义代数类型。 它有空间,因为原始特性的无限扩展不是真正需要的东西,大多数这样的特征与密封关键字一起使用。因此,可以使用除扩展之外的其他一些不那么强大的机制来表示数据类型。
答案 0 :(得分:1)
如您所知,object
s是派生子类型的行的结尾。在这种情况下,您可以创建另一级中间抽象类型,从中导出Trivial
的子类型(单例或其他):
sealed trait Trivial extends CompositeType
object Trivia extends Trivial { ... }
class Triviality extends Trivia(...) { ... } \
...