This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Parametrized vs Abstract type

5 replies
Piotr Gabryanczyk
Joined: 2011-12-14,
User offline. Last seen 30 weeks 3 days ago.

I've got 2 class groups, which implement similar functionality:
object CurrencyWithAbstractType{

trait AbstractCurrency{
type Currency <: AbstractCurrency
def value : Double

def make(d:Double) : Currency
def +(x: AbstractCurrency/*doesnt compile if I change it to Currency*/) = make(x.value + value)
}

class USD(val value: Double) extends AbstractCurrency {
type Currency = USD
def make(d: Double) = new USD(d)
}
class EUR(val value: Double) extends AbstractCurrency {
type Currency = EUR
def make(d: Double) = new EUR(d)
}

def plus[T <: AbstractCurrency](c1: T, c2:T) : T#Currency = c1 + c2
val x : USD = plus(new USD(100),new USD(200))

new EUR(100) + new USD(50) //compiles which is wrong
}

object CurrencyWithParametrizedType{

trait AbstractCurrency[Currency <: AbstractCurrency[Currency]]{
val value : Double

def make(d:Double) : Currency
def +(x: Currency) = make(x.value + value)
}

class USD(val value: Double) extends AbstractCurrency[USD] {
def make(d: Double) = new USD(d)
}

class EUR(val value: Double) extends AbstractCurrency[EUR] {
def make(d: Double) = new EUR(d)
}

def plus[T <: AbstractCurrency[T]](c1: T, c2:T) : T = c1 + c2
val x : USD = plus(new USD(100),new USD(200))
new EUR(100) + new USD(50) // doesnt compile whis is expected

}

First question is how do I make Abstract Type version to detect that:
new EUR(100) + new USD(50)
shouldn't compile?

Second: how do I get rid of this funny T#Currency type in line:
def plus[T <: AbstractCurrency](c1: T, c2:T) : T#Currency = c1 + c2

I would guess that T is equivalent to T#Currency so this should be enough:
def plus[T <: AbstractCurrency](c1: T, c2:T) : T = c1 + c2

Piotr Gabryanczyk

Piotr Gabryanczyk
Joined: 2011-12-14,
User offline. Last seen 30 weeks 3 days ago.
Re: Parametrized vs Abstract type

Is my question so silly, or nobody really understand the
difference? :)

On Dec 14, 12:44 am, Piotr Gabryanczyk wrote:
> I've got 2 class groups, which implement similar functionality:
> object CurrencyWithAbstractType{
>
>   trait AbstractCurrency{
>     type Currency <: AbstractCurrency
>     def value : Double
>
>     def make(d:Double) : Currency
>     def +(x: AbstractCurrency/*doesnt compile if I change it to Currency*/) = make(x.value + value)
>   }
>
>   class USD(val value: Double) extends AbstractCurrency {
>     type Currency = USD
>     def make(d: Double) = new USD(d)
>   }
>   class EUR(val value: Double) extends AbstractCurrency {
>     type Currency = EUR
>     def make(d: Double) = new EUR(d)
>   }
>
>   def plus[T <: AbstractCurrency](c1: T,  c2:T) : T#Currency = c1 + c2
>   val x : USD = plus(new USD(100),new USD(200))
>
>   new EUR(100) + new USD(50) //compiles which is wrong
>
> }
>
> object CurrencyWithParametrizedType{
>
>   trait AbstractCurrency[Currency <: AbstractCurrency[Currency]]{
>     val value : Double
>
>     def make(d:Double) : Currency
>     def +(x: Currency) = make(x.value + value)
>   }
>
>   class USD(val value: Double) extends AbstractCurrency[USD] {
>     def make(d: Double) = new USD(d)
>   }
>
>   class EUR(val value: Double) extends AbstractCurrency[EUR] {
>     def make(d: Double) = new EUR(d)
>   }
>
>   def plus[T <: AbstractCurrency[T]](c1: T,  c2:T) : T = c1 + c2
>   val x : USD = plus(new USD(100),new USD(200))
>   new EUR(100) + new USD(50) // doesnt compile whis is expected
>
> }
>
> First question is how do I make Abstract Type version to detect that:
>   new EUR(100) + new USD(50)
> shouldn't compile?
>
> Second: how do I get rid of this funny T#Currency type in line:
> def plus[T <: AbstractCurrency](c1: T,  c2:T) : T#Currency = c1 + c2
>
> I would guess that T is equivalent to T#Currency so this should be enough:
>   def plus[T <: AbstractCurrency](c1: T,  c2:T) : T = c1 + c2
>
> Piotr Gabryanczyk

Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: Parametrized vs Abstract type
On Thu, Dec 15, 2011 at 9:38 AM, Piotr Gabryanczyk <piotrga@gmail.com> wrote:
Is my question so silly, or nobody really understand the
difference? :)

You can get there with dependent method types.
https://gist.github.com/1479149
-jason 
Lex
Joined: 2010-02-28,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Parametrized vs Abstract type
You have to drill all the way down and specify the type: T <: AbstractCurrency { type Currency = T }

object CurrencyWithAbstractType{

 trait AbstractCurrency{
   type Currency <: AbstractCurrency
   def value : Double

   def make(d:Double) : Currency
   def +(x: Currency/*must be Currency*/) = make(x.value + value)
 }

 class USD(val value: Double) extends AbstractCurrency {
   type Currency = USD
   def make(d: Double) = new USD(d)
 }
 class EUR(val value: Double) extends AbstractCurrency {
   type Currency = EUR
   def make(d: Double) = new EUR(d)
 }

 def plus[T <: AbstractCurrency { type Currency = T } ](c1: T,  c2:T) : T#Currency = c1 + c2
 val x : USD = plus(new USD(100),new USD(200))

 new EUR(100) + new USD(50) //compiles which is wrong
}


On Wed, Dec 14, 2011 at 5:47 PM, Jason Zaugg <jzaugg@gmail.com> wrote:
On Thu, Dec 15, 2011 at 9:38 AM, Piotr Gabryanczyk <piotrga@gmail.com> wrote:
Is my question so silly, or nobody really understand the
difference? :)

You can get there with dependent method types.
https://gist.github.com/1479149
-jason 

Piotr Gabryanczyk
Joined: 2011-12-14,
User offline. Last seen 30 weeks 3 days ago.
Re: Parametrized vs Abstract type
1. I noticed  -Ydependent-method-types flag, but I was puzzled that it doesn't work by default...
2. def plus[T <: AbstractCurrency](c1: T)(c2: c1.Currency) : c1.Currency = c1 + c2 I forgot about compiler deficiency which requires currying, so it understands the types better. I tried c1.Currency but without currying... (silly me... or the compiler...). I honestly think this is one of the reasons why people tend to think that scala is complicated...
Thanks for a quick answer! :)
Piotr Gabryanczyk
On 14 Dec 2011, at 23:47, Jason Zaugg wrote:
On Thu, Dec 15, 2011 at 9:38 AM, Piotr Gabryanczyk <piotrga@gmail.com> wrote:
Is my question so silly, or nobody really understand the
difference? :)

You can get there with dependent method types.
https://gist.github.com/1479149
-jason 

moors
Joined: 2010-10-06,
User offline. Last seen 36 weeks 4 days ago.
Re: Parametrized vs Abstract type
dependent method types will be on by default in the upcoming 2.10 (already the case in the nightly build)
cheersadriaan

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland