代数类型的传统方法推荐类似的方法:
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 方法来构建和匹配代数类型的实例。
是否有任何项目试图为此类类型构建框架?
这可能对演员隐喻有用。目前,actor 接收与已知类型匹配的无类型消息(Any
意味着没有类型限制)并为其他人提供安全默认值。它打破了 scala 的所有类型严格设计,并且使用更合适的类型限制演员会非常好。
更新:
阐明我的意图的示例:
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
但是对象层次结构可能只在一个方向上产生。
因此需要以其他方式定义代数类型。它有空间,因为原始特征的无限扩展并不是真正需要的,并且大多数此类特征都与sealed关键字一起使用。因此,可以使用其他一些比扩展功能更弱的机制来表示数据类型。