类型在隐含证据检查中被删除

问题描述 投票:0回答:1

我正在尝试创建一个穷人版本的 refined types 实现,对字符串内容进行简单验证,并通过另一个函数的

Implicit
证据检查返回类型。似乎类型在从
check
函数返回后被删除了。有人可以建议我一个 scala 技巧来有效地做到这一点吗?

sealed trait Validate
sealed trait Pass extends Validate
sealed trait Fail extends Validate
type SUCCESS = Pass
case class Validator[State <: Validate: TypeTag](s: String = "") {

  def check = {
    if (s == "awesome") {
      Validator[Pass](s)
    } else {
      Validator[Fail](s)
    }
  }

  def pass: Validator[Pass] = Validator[Pass](s)
  def fail: Validator[Fail] = Validator[Fail](s)

  def validate(implicit ev: State =:= SUCCESS): String = s
  def testResult = typeOf[State] =:= typeOf[SUCCESS]

}

Validator("awesome").check.testResult // true
Validator("awesome").check.validate // Cannot prove that _1 =:= MdocApp.this.SUCCESS.
scala generics type-erasure
1个回答
0
投票

如果我正确理解了您的目标,您希望将使用

scala-reflect
TypeTag
(
testResult
) 的实现替换为使用静态类型和隐式 (
validate
) 的实现。

check
的返回类型只是
Validator[Validate]
,而不是
Validator[Pass]
Validator[Fail]

类型在编译时解析,因此编译器必须在编译时知道字符串是否为

"awesome"
。例如,您可以举起
s
来打字。 类型为
String
的字符串太粗糙,您可以改用精确的单例子类型。您可以为编译时“模式匹配”引入一个类型类

// type class
trait Check[S <: String] {
  type State <: Validate
}
trait LowPriorityCheck {
  type Aux[S <: String, State0 <: Validate] = Check[S] {type State = State0 }
  implicit def default[S <: String]: Aux[S, Fail] = null
}
object Check extends LowPriorityCheck {
  implicit val pass: Aux["awesome", Pass] = null
}

case class Validator[S <: String with Singleton, State <: Validate](s: S) {
  def check(implicit check: Check[S]): Validator[S, check.State] =
    Validator[S, check.State](s)

  def validate(implicit ev: State =:= SUCCESS): String = s
}

Validator("awesome").check.validate // awesome

Validator("abc").check.validate //  Cannot prove that Fail =:= SUCCESS

如果你更愿意保留这两个实现,你可以恢复

TypeTag
上下文边界

trait Check[S <: String, State <: Validate]
trait LowPriorityCheck {
  implicit def default[S <: String]: Check[S, Fail] = null
}
object Check extends LowPriorityCheck {
  implicit val pass: Check["awesome", Pass] = null
}

case class Validator[S <: String with Singleton, State <: Validate: TypeTag](s: S) {
  def check[St <: Validate : TypeTag](implicit 
    check: Check[S, St]
  ): Validator[S, St] = Validator[S, St](s)

  def testResult = typeOf[State] =:= typeOf[SUCCESS]

  def validate(implicit ev: State =:= SUCCESS): String = s
}
© www.soinside.com 2019 - 2024. All rights reserved.