Scala中的高级类型约束 - 逻辑运算符和隐式参数

时间:2018-03-27 17:16:57

标签: scala logical-operators typeclass type-constraints implicits

我有以下代码,效果很好。

self.services = listeServices

输出:

package com.andrew

object ExperimentWithTypeConstraints {

  def union[T](t: T)(implicit c: (T =:= String)) = t match {
    case s: String => println(s"Some nice string: $s")
  }

  def main(args: Array[String]): Unit = {
    union("Hello.")
  }
}

我想修改方法Some nice string: Hello. 的定义,如下所示:

union

def union[T](t: T)(implicit c: (T =:= String) Or (T =:= Int)) = t match { case s: String => println(s"Some nice string: $s") case i: Int => println(s"Some int: $i") } 的输出应为以下值:union(1)

不幸的是,Scala对于这种情况并不知道逻辑运算符Or(And,Not,..),因此无法编译它。我该怎么办?

我在以下地址(http://hacking-scala.org/post/73854628325/advanced-type-constraints-with-type-classes)找到了一个解决方案,但不幸的是我不太了解它。你能告诉我如何根据你的方法解决这个问题吗?或者你能从上面提到的网址解释解决方案吗?他们的解决方案有效,具体如下:

Some int: 1

我不理解@implicitNotFound("Argument does not satisfy constraints: ${A} Or ${B}") trait Or[A, B] object Or { private val evidence: Or[Any, Any] = new Object with Or[Any, Any] implicit def aExistsEv[A, B](implicit a: A) = evidence.asInstanceOf[Or[A, B]] implicit def bExistsEv[A, B](implicit b: B) = evidence.asInstanceOf[Or[A, B]] } 部分。 Or是一个对象。如何通过Or将此部分(T =:= String) Or (T =:= Int)合并在一起?

非常感谢,安德鲁

2 个答案:

答案 0 :(得分:1)

  

不幸的是,Scala对于这种情况并不知道逻辑运算符Or(And,Not,..),因此无法编译它。我该怎么办?

这是解决同一问题的另一种方法。无可否认,这很难缠绕,但效果很好。

trait Contra[-C]
type Union[A,B] = {
  type Check[Z] = Contra[Contra[Z]] <:< Contra[Contra[A] with Contra[B]]
}

用法:

def f[T: Union[String,Int]#Check](arg:T) = arg match {
  case s:String         => s"got string: ${s.toUpperCase}"
  case i:Int if i < 100 => s"got small Int: $i"
  case i:Int            => s"got bigger Int: $i"
}

概念证明:

f(119)            //res0: String = got bigger Int: 119
f("string time")  //res1: String = got string: STRING TIME
f(true)           //does not compile

答案 1 :(得分:0)

implicit def aExistsEv[A, B](implicit a: A) =
  evidence.asInstanceOf[Or[A, B]]

implicit def bExistsEv[A, B](implicit b: B) =
  evidence.asInstanceOf[Or[A, B]]

表示如果您隐式拥有A,那么您隐式拥有Or[A, B],如果您隐式拥有B,那么您隐式拥有Or[A, B]

这正是在逻辑中的工作原理:如果 A 为真,则 A或B 为真,如果 B,则类似为真,那么 A或B 为真。

最后,如果TString,则提供隐式T =:= String,如果TInt则提供隐式T =:= Int

A X BX[A, B]相同,因此A Or BOr[A, B]相同。