标记类型(@@)Scalaz中的比较

时间:2015-12-14 11:47:19

标签: scala tags scalaz

在玩Scalaz.Tag时,我发现了一个奇怪的比较结果。

import scalaz._, Scalaz._, Tags._, syntax.tag._

test("Creating Tagged type") {
  sealed trait USD
  sealed trait EUR
  def USD[A](amount: A): A @@ USD = Tag[A, USD](amount)
  def EUR[A](amount: A): A @@ EUR = Tag[A, EUR](amount)

  val oneUSD = USD(1)
  2 * oneUSD.unwrap shouldBe 2

  def convertUSDtoEUR[A](usd: A @@ USD, rate: A)
                        (implicit M: Monoid[A @@ Multiplication]): A @@ EUR =
    EUR((Multiplication(usd.unwrap) |+| Multiplication(rate)).unwrap)

  convertUSDtoEUR(USD(1), 2) === EUR(2) // true
  convertUSDtoEUR(USD(1), 2) === USD(2) // true

  convertUSDtoEUR(USD(1), 2) shouldBe EUR(2) // true
  convertUSDtoEUR(USD(1), 2) shouldBe USD(2) // true
}

我想区分不同的密封特性。这是scalaz.Tag的预期行为,还是我错过了什么?

更新

由于=:=

,因为我无法在===内使用 scalaz org.scalatest.FunSuite,因此我实施了org.scalactic.TripleEqualSupport
trait FunTestSuite
  extends FunSuite
  with Matchers
  with BeforeAndAfterEach
  with BeforeAndAfterAll
  with TestImplicits

trait TestImplicits {
  final case class StrictEqualOps[A](val a: A) {
    def =:=(aa: A) = assert(a == aa)
    def =/=(aa: A) = assert(!(a == aa))
  }

  implicit def toStrictEqualOps[A](a: A) = StrictEqualOps(a)
}

// spec
convertUSDtoEUR(USD(1), 2) =:= EUR(2)
convertUSDtoEUR(USD(1), 2) =:= EUR(3) // will fail
convertUSDtoEUR(USD(1), 2) =:= USD(3) // compile error

1 个答案:

答案 0 :(得分:2)

您正在使用scalatest中的===shouldBe。它们只检查运行时值,而不是类型(它们委托给==)。如果要区分类型,则必须使用scalaz中的===