在scala上模拟可扩展的代数类型

时间:2013-03-04 15:19:22

标签: oop scala algebraic-data-types

代数类型的传统方法推荐类似的东西:

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

但是对象层次结构可能只在一个方向上产生。

因此需要以其他方式来定义代数类型。 它有空间,因为原始特性的无限扩展不是真正需要的东西,大多数这样的特征与密封关键字一起使用。因此,可以使用除扩展之外的其他一些不那么强大的机制来表示数据类型。

1 个答案:

答案 0 :(得分:1)

如您所知,object s是派生子类型的行的结尾。在这种情况下,您可以创建另一级中间抽象类型,从中导出Trivial的子类型(单例或其他):

sealed trait Trivial extends CompositeType
object Trivia extends Trivial { ... }
class Triviality extends Trivia(...) { ... } \
...