带 AnyVal 的幻影类型?

Phantom Type w/ AnyVal?

鉴于 中 Haskell 中的以下 Phantom Type 示例:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

newtype Distance a = Distance Double
  deriving (Num, Show)

data Kilometer
data Mile

marathonDistance :: Distance Kilometer
marathonDistance = Distance 42.195

distanceKmToMiles :: Distance Kilometer -> Distance Mile
distanceKmToMiles (Distance km) = Distance (0.621371 * km)

marathonDistanceInMiles :: Distance Mile
marathonDistanceInMiles = distanceKmToMiles marathonDistance

我试图将其翻译成 Scala:

case class Distance[A](x: Double) extends AnyVal

case object Kilometer
case object Mile

def marathonDistance: Distance[Kilometer.type] = Distance[Kilometer.type](42.195)

def distanceKmToMiles(kilos: Distance[Kilometer.type]): Distance[Mile.type] = 
    Distance[Mile.type](kilos.x * 0.621371)

def marathonDistanceInMiles: Distance[Mile.type] = distanceKmToMiles( marathonDistance )

假设这个 Phantom Type 实现在 Scala 中有效,Distance 的这种用法是否会导致分配,即使用堆,而不是堆栈?

如果会分配,是什么原因?

照原样,您的代码不应导致 Distance class 的任何分配,因为它不会 any of the things that would cause it:

  1. a value class is treated as another type.
  2. a value class is assigned to an array.
  3. doing runtime type tests, such as pattern matching.

它不把它们当作另一种类型,没有数组,也没有类型测试。

在这些示例中,Distance 的一个实例将被分配、装箱和拆箱:

类型测试:

def d(dist: Distance[Mile.type]): Double = dist match {
    case Distance(x) if x > 0 => 1.0
    case Distance(x) => x
}

被视为另一种类型(通用 A):

def identity[A](t: A): A = t

数组:

val dist = Distance[Meter.type](1.0)
val arr = Array[Distance[Meter.type]](dist)

有没有type参数也是一样