使用 scalaz Tag 代替 case 有什么好处 class

Whats the benefit of using scalaz Tag instead of a case class

case class KiloGram[A] (value:A)  

val mass= KiloGram(20.0)

使用 scalaz 标签,我们可以做这样的事情:

import scalaz._

sealed trait KiloGram


def KiloGram[A](a: A): A @@ KiloGram = Tag[A,KiloGram](a)

val mass = KiloGram(20.0)

现在,如果我们真的想使用 Tagged 对象的值,我们必须解包它

val twoTimesMass=2*Tag.unwrap(mass)

所以我没有真正看到使用保护套的好处 class

case class KiloGram[A] (value:A)  

val mass= KiloGram(20.0)

val twoTimesMass=2*mass.value

实际上我发现第二种方法更简洁

  1. 您可以轻松编写适用于任何 Tagged 的通用代码,例如 map[A, B, Tag](x: A @@ Tag)(f: A => B): B @@ Tag.

  2. 根据the documentation

    one has to be very careful when using value classes, because there are a lot of instances in which using a value class will incur a runtime boxing/unboxing of your value, which incurs a runtime cost. The scalaz tagged types will never cause boxing of a value.

    尽管从 Scalaz 7.1 开始最后一句话似乎是错误的:https://github.com/scalaz/scalaz/issues/676, https://github.com/scalaz/scalaz/issues/837.

请注意,在大多数情况下

,您可以避免为案例 类 调用 value
object KiloGram {
  implicit def unwrap[A](x: KiloGram[A]) = x.value
}