2016-12-01 3 views
2

Учитывая следующий пример Phantom Тип в Haskell от phadej:Phantom Type w/AnyVal?

{-# 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 Тип действует в Scala будет это использование Distance привести к распределению, т. е. использовать кучу, а не стек?

Если это будет выделено, в чем причина?

ответ

4

Как ваш код не должен приводить к какому-либо выделению Distance класса, потому что он не делает any of the things that would cause it: класс

  1. значения трактуются как другой типа.
  2. класс значений присваивается массиву.
  3. выполнение проверки времени выполнения, такой как образец сопоставив.

Это не относиться к ним как другому типу, нет массивов, и никаких испытаний типа.

В этих примерах, экземпляр 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) 

То же самое верно, есть ли параметр типа или нет.