问题
Reading http://eed3si9n.com/learning-scalaz/Tagged+type.html and trying out the sample code:
import scalaz._; import Scalaz._
sealed trait KiloGram
def KiloGram[A](a: A): A @@ KiloGram = Tag[A, KiloGram](a)
val mass = KiloGram(20.0)
2 * mass
according to the guide, should yield 40.0
, however, on Scala 2.11.2 I get:
scala> 2 * mass
<console>:17: error: overloaded method value * with alternatives:
(x: Double)Double <and>
(x: Float)Float <and>
(x: Long)Long <and>
(x: Int)Int <and>
(x: Char)Int <and>
(x: Short)Int <and>
(x: Byte)Int
cannot be applied to (scalaz.@@[Double,KiloGram])
2 * mass
^
whereas
2 * mass.asInstanceOf[Double]
works just fine.
Is that a 2.10 vs 2.11 thing or I'm missing something? What is the point of unboxed tagged types if I can't use them like this (anymore) and have to resort to explicit casts?
回答1:
OK, turns out this was changed in Scalaz 7.1 by https://github.com/scalaz/scalaz/pull/693.
Basically the old implementation of tagged types turned out as not safe enough, so it was made so that an explicit unwrap of the tagged type would be necessary before the contents of the "tag" could be used:
scala> trait Kg
scala> val Kg = Tag.of[Kg]
scala> val mass = Kg(15.0)
scala> 3 * Kg.unwrap(mass)
res0: Double = 45.0
Thanks to S11001001, ceedubs, tpolecat and adelbertC on #scalaz for pointing this out.
来源:https://stackoverflow.com/questions/26131145/scalaz-unboxed-tagged-type-not-automatically-unboxed