使用抽象类型定义类型约束

时间:2015-06-19 13:50:28

标签: scala type-systems

我尝试使用抽象类型定义类型约束。但不幸的是,它没有编译。

  sealed trait MatchableValue {
    type A
    def value: A

    def asSingleItemValue : ItemValue
  }

  sealed trait ItemValue {
    type A
    def value: A
  }

  case class StringValue(value: String) extends ItemValue {type A = String}
  case class StringMatchableValue(value: String) extends MatchableValue{
    type A = String
    override def asSingleItemValue =  StringValue(value)
  }

不幸的是,这个不起作用

def asSingleItemValue[B <: ItemValue](implicit ev: A =:= B#A) : B

类型约束的目的是在编译时警告这样的错误:

  case class IntValue(value: Int) extends ItemValue {type A = Int}
  case class IntMatchableValue(value: Int) extends MatchableValue{
    type A = Int
    def asSingleItemValue = StringValue("error")
  }

2 个答案:

答案 0 :(得分:5)

您可以使用类型细化来完成此操作(请注意方法的返回类型):

sealed trait MatchableValue { self =>
  type A
  def value: A

  def asSingleItemValue: ItemValue { type A = self.A }
}

sealed trait ItemValue {
  type A
  def value: A
}

case class StringValue(value: String) extends ItemValue { type A = String }
case class IntValue(value: Int) extends ItemValue { type A = Int }

现在编译:

case class StringMatchableValue(value: String) extends MatchableValue {
  type A = String
  def asSingleItemValue = StringValue(value)
}

但这不是:

case class StringMatchableValue(value: String) extends MatchableValue {
  type A = String
  def asSingleItemValue = IntValue(1)
}

我认为这就是你想要的。

值得注意的是,在处理类型细化时,以下是一种常见模式:

sealed trait MatchableValue { self =>
  type A
  def value: A

  def asSingleItemValue: ItemValue.Aux[A]
}

sealed trait ItemValue {
  type A
  def value: A
}

object ItemValue {
  type Aux[A0] = ItemValue { type A = A0 }
}

这完全相同,但如果你发现自己需要大量写出类型细化,那么语法是一个不错的选择。

答案 1 :(得分:0)

我认为您打算在代码中删除此行?

def asSingleItemValue = StringValue(value)

并且override定义缺少一些签名,应该是这样的:

override def asSingleItemValue[B <: ItemValue](implicit ev: =:=[String, B#A]): B = ev

最后,生成的ev类型必须为B