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

First steps into generic types

27 replies
Matthias Kluwe
Joined: 2011-05-18,
User offline. Last seen 42 years 45 weeks ago.

Hi!

I just made my first steps in Scala and tried to expand the simple OO
Expr class given in "Scala by Example" with a type parameter:

abstract class Expr[ T ] {
def eval: T
}

class Number[ T ]( n: T ) extends Expr[ T ] {
def eval: T = n
}

class Sum[ T <% Numeric[ T ] ]( e1: Expr[ T ], e2: Expr[ T ] )
extends Expr[ T ] {
def eval: T = e1.eval + e2.eval
}

This yields the (unexpected for me) compiler error:

error: type mismatch;
found : T
required: String
def eval: T = e1.eval + e2.eval
^
one error found

Please help me understand what's wrong here. Obviously, the concept of
type parameters is quite different from what I'm used to coding in C+
+, where the equivalent code would not give an error, as nothing is
generated (no instance of Sum) and only syntax is checked at this
level.

Regards,
Matthias

Peter 2
Joined: 2011-02-16,
User offline. Last seen 42 years 45 weeks ago.
Re: First steps into generic types

Hi Matthias,

"e1.eval" returns T <: Any because in "abstract class Expr[ T ]" T is
unconstrained, not Numeric or whatever you'd like.
Any has no "+" defined, so the compiler only sees the implicit
conversion to String.

Peter

Matthias Kluwe
Joined: 2011-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: First steps into generic types

Hi!

On May 18, 9:31 am, Sonnenschein wrote:

> "e1.eval" returns T <: Any because in "abstract class Expr[ T ]" T is
> unconstrained, not Numeric or whatever you'd like.
> Any has no "+" defined, so the compiler only sees the implicit
> conversion to String.

I changed the line

abstract class Expr[ T ] {

to

abstract class Expr[ T <% Numeric[ T ] ] {

Unfortunately, that does not help.

Regards,
Matthias

Kevin Wright 2
Joined: 2010-05-30,
User offline. Last seen 26 weeks 4 days ago.
Re: Re: First steps into generic types
Numeric doesn't work like that.  It's a type class, so you'll want a context bound:
    abstract class Expr[T : Numeric] {
      def eval: T
    }

    class Number[T : Numeric]( n: T ) extends Expr[T] {
      def eval: T = n
    }

    class Sum[T : Numeric](e1: Expr[T], e2: Expr[T] )extends Expr[T] {
      def eval: T = e1.eval + e2.eval
    }
(disclaimer, this was hastily written and is untested)

On 18 May 2011 10:41, Matthias Kluwe <mkluwe@gmail.com> wrote:
Hi!

On May 18, 9:31 am, Sonnenschein <peter.em...@arcor.de> wrote:

> "e1.eval" returns T <: Any because in "abstract class Expr[ T ]" T is
> unconstrained, not Numeric or whatever you'd like.
> Any has no "+" defined, so the compiler only sees the implicit
> conversion to String.

I changed the line

 abstract class Expr[ T ] {

to

 abstract class Expr[ T <% Numeric[ T ] ] {

Unfortunately, that does not help.

Regards,
Matthias



--
Kevin Wright

gtalk / msn : kev.lee.wright@gmail.comkev.lee.wright@gmail.commail: kevin.wright@scalatechnology.com
vibe / skype: kev.lee.wrightquora: http://www.quora.com/Kevin-Wright
twitter: @thecoda

"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra
Matthias Kluwe
Joined: 2011-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: First steps into generic types

Hi!

On 18 Mai, 05:47, Kevin Wright wrote:
> Numeric doesn't work like that.  It's a type class, so you'll want a context
> bound:
>
>     abstract class Expr[T : Numeric] {
>       def eval: T
>     }
>
>     class Number[T : Numeric]( n: T ) extends Expr[T] {
>       def eval: T = n
>     }
>
>     class Sum[T : Numeric](e1: Expr[T], e2: Expr[T] )extends Expr[T] {
>       def eval: T = e1.eval + e2.eval
>     }
>
> (disclaimer, this was hastily written and is untested)

Hmm, does not work here, same error: type mismatch;
found : T
required: String
def eval: T = e1.eval + e2.eval

Regards,
Matthias

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: First steps into generic types

Guys, "T" does not implement "+". Why do you expect it to?

To use Numeric implicit conversions you have to import it.

On Wed, May 18, 2011 at 14:32, Matthias Kluwe wrote:
> Hi!
>
> On 18 Mai, 05:47, Kevin Wright wrote:
>> Numeric doesn't work like that.  It's a type class, so you'll want a context
>> bound:
>>
>>     abstract class Expr[T : Numeric] {
>>       def eval: T
>>     }
>>
>>     class Number[T : Numeric]( n: T ) extends Expr[T] {
>>       def eval: T = n
>>     }
>>
>>     class Sum[T : Numeric](e1: Expr[T], e2: Expr[T] )extends Expr[T] {
>>       def eval: T = e1.eval + e2.eval
>>     }
>>
>> (disclaimer, this was hastily written and is untested)
>
> Hmm, does not work here, same error: type mismatch;
>  found   : T
>  required: String
>  def eval: T = e1.eval + e2.eval
>
> Regards,
> Matthias

Matthias Kluwe
Joined: 2011-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: First steps into generic types

Hi!

On 18 Mai, 20:22, Daniel Sobral wrote:

> Guys, "T" does not implement "+". Why do you expect it to?

I skipped through the mentiones text "Scala By Example" and read (p.
60 ) that I could use

Set[A <: Ordered[A]]

to "enforce the comparability of a type by demanding that the type is
a subtype of Ordered" (which defines "<" that is needed in the ordered
set example).

I have to admit: By looking at the scala.math docs I simply _guessed_
I'd have to use Numeric.

> To use Numeric implicit conversions you have to import it.

I do not know how to do that until now.

Regards,
Matthias

Peter 2
Joined: 2011-02-16,
User offline. Last seen 42 years 45 weeks ago.
Re: First steps into generic types

Hi Matthias,

imo playing with Numeric is nothing for the first steps. But maybe
this discussion helps:
http://groups.google.com/group/scala-user/browse_thread/thread/9303f68d2...

Cheers, Peter

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: First steps into generic types

On Thu, May 19, 2011 at 15:16, Matthias Kluwe wrote:
>
>> To use Numeric implicit conversions you have to import it.
>
> I do not know how to do that until now.

Ok, basic lessons.

Lesson 1: type classes. One of the patterns of code in Scala is the
type class pattern. If you know Java, it is very much like
Comparator, whose instances define a method that can compare two T.
The important point here is that a type class defines some object that
knows how to do something to other objects, as opposed to the other
objects themselves being able to do it (like in Comparable).

The type class pattern is defined in one of two ways:

def method[A : Numeric](x: A, y: A) = ...
def method[A](x: A, y: A)(implicit ev: Numeric[A]) = ...

These declarations are identical, except that the the implicit
parameter is anonymous in the first one, whereas the second one is
explicit.

Lesson 2: Implicits must be "carried". That is, if you call a method
that requires Numeric[A], then _your_ method must be able to provide
that as well. For example:

def addAll[A](list: List[A]): A = list.sum // doesn't work, because
sum requires implicit Numeric[A]

You can do this using the first syntax, which is shorter:

def addAll[A : Numeric](list: List[A]): A = list.sum // works, because
addAll received an implicit as parameter, even if anonymously

Lesson 3: Numeric type class

The Numeric type class defines some methods that do basic arithmetic.
For example:

def add[A](x: A, y: A)(implicit ev: Numeric[A]) = ev.plus(x, y)

See scaladoc for more methods, but it is generally agreed that this
looks ugly, so we don't want to do it that way.

Lesson 4: Numeric Ops

For that reason, there is an implicit conversion that add operators to
a type based on the Numeric for that type. It works like this:

def add[A](x: A, y: A)(implicit ev: Numeric[A]) = {
import ev._
x + y
}

If you used the first syntax, you then have to get the implicit first.
You can do that like this:

def add[A : Numeric](x: A, y: A) = {
val ev = implicitly[Numeric[A]] // cannot import directly
import ev._
x + y
}

What actually happens in the examples above is that ev contains an
implicit that converts from A to Ops[A], and Ops[A] has the method
"+".

Lesson 5: Ops for free

If you are going to do a lot of stuff with Numeric, all this importing
might get tedious. On Scala 2.9.0 you can do a single import that will
make every numeric work with ops automatically:

import Numeric.Implicits._

def add[A : Numeric](x: A, y: A) = x + y

Lesson 6: Ordering

Another type class you might be interested in is Ordering, which is
Scala's version of Comparator. Same stuff applies.

Matthias Kluwe
Joined: 2011-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: First steps into generic types

Hi!

On 19 Mai, 18:23, Daniel Sobral wrote:
> On Thu, May 19, 2011 at 15:16, Matthias Kluwe wrote:
>
> >> To use Numeric implicit conversions you have to import it.
>
> > I do not know how to do that until now.
>
> Ok, basic lessons.
>
> [...]
>
> import Numeric.Implicits._
>
> def add[A : Numeric](x: A, y: A) = x + y

Wow, pretty much overwhelming.

Thank you for the elaborate answer!

I made this (simple) example working by adding the mentioned import
and changing the bound to "context bounds". I've yet to understand
what that *is*.

The answer to http://stackoverflow.com/questions/2982276/what-is-a-context-bound-in-scala
says it is a "shorthand form" "for passing a ClassManifest[T] into the
method as an implicit parameter". Phoey.

Regards,
Matthias

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: First steps into generic types

On Fri, May 20, 2011 at 17:01, Matthias Kluwe wrote:
>
> I made this (simple) example working by adding the mentioned import
> and changing the bound to "context bounds". I've yet to understand
> what that *is*.
>
> The answer to http://stackoverflow.com/questions/2982276/what-is-a-context-bound-in-scala
> says it is a "shorthand form" "for passing a ClassManifest[T] into the
> method as an implicit parameter". Phoey.

Perhaps you'll like this one better:
http://stackoverflow.com/questions/4465948/context-and-view-bounds-again...

Jiansen
Joined: 2011-04-27,
User offline. Last seen 1 year 10 weeks ago.
Generic types

Hi all,

Could anyone suggest why following code gives such an unexpected
output?

class C[R,S] {
def apply(i:Any) = i match {
case i:R => println("case 1")
case i:S => println("case 2")
case _ => println("Other")
}
}

object mytest extends Application{

val c = new C[Int, Double]
c(1)
c(1.0)
c("Hello")
}

output:
case 1
case 1
case 1

whereas I think the output should be:
case 1
case 2
Other

With Thanks
Jiasnsen

nt2010
Joined: 2010-11-09,
User offline. Last seen 1 year 18 weeks ago.
Re: Generic types

Hi,

this seems to be due to type erasure in JVM. All your cases are reduced
to case i: Object since type parameters of C are reduced to C[Object,
Object]. Therefore all three examples match the first case.

Did you get compiler warning for that?

> Hi all,
>
> Could anyone suggest why following code gives such an unexpected
> output?
>
> class C[R,S] {
> def apply(i:Any) = i match {
> case i:R => println("case 1")
> case i:S => println("case 2")
> case _ => println("Other")
> }
> }
>
> object mytest extends Application{
>
> val c = new C[Int, Double]
> c(1)
> c(1.0)
> c("Hello")
> }
>
> output:
> case 1
> case 1
> case 1
>
> whereas I think the output should be:
> case 1
> case 2
> Other
>
> With Thanks
> Jiasnsen

Simon Olofsson
Joined: 2011-06-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Generic types

Jiasnsen,

On 2011-06-17 9:20, Jiansen wrote:
> Could anyone suggest why following code gives such an unexpected
> output?

this happens because of type erasure. If you run the scala compiler with
-unchecked you will see the following warning:

[...]
warning: abstract type R in type pattern R is unchecked since it is
eliminated by erasure
case i:R => println("case 1")
[...]

The information about type parameters is not available at runtime. You
can read a detailed explanation in "Programming in Scala", section 15.2
or at [1].

[1] http://bit.ly/ZJ2UO

Regards
Simon

Matthew Pocock 3
Joined: 2010-07-30,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Generic types
Variations on this issue have come up a lot recently. Is there a compelling reason why the warning that's displayed in this circumstance with -unchecked should not be enabled by default? Also, is there somewhere that this is documented as an FAQ : my code won't compile because... entry?
Thanks,
Matthew

On 17 June 2011 08:52, Simon Olofsson <simon@olofsson.de> wrote:
Jiasnsen,

On 2011-06-17 9:20, Jiansen wrote:
Could anyone suggest why following code gives such an unexpected
output?

this happens because of type erasure. If you run the scala compiler with -unchecked you will see the following warning:

[...]
warning: abstract type R in type pattern R is unchecked since it is eliminated by erasure
   case i:R => println("case 1")
[...]

The information about type parameters is not available at runtime. You can read a detailed explanation in "Programming in Scala", section 15.2 or at [1].

[1] http://bit.ly/ZJ2UO

Regards
Simon




--
Matthew Pocockmailto: turingatemyhamster@gmail.comgchat: turingatemyhamster@gmail.com msn: matthew_pocock@yahoo.co.ukirc.freenode.net: drdozer(0191) 2566550
Matthew Pocock 3
Joined: 2010-07-30,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Generic types
Variations on this issue have come up a lot recently. Is there a compelling reason why the warning that's displayed in this circumstance with -unchecked should not be enabled by default? Also, is there somewhere that this is documented as an FAQ : my code won't compile because... entry?
Thanks,
Matthew

On 17 June 2011 08:52, Simon Olofsson <simon@olofsson.de> wrote:
Jiasnsen,

On 2011-06-17 9:20, Jiansen wrote:
Could anyone suggest why following code gives such an unexpected
output?

this happens because of type erasure. If you run the scala compiler with -unchecked you will see the following warning:

[...]
warning: abstract type R in type pattern R is unchecked since it is eliminated by erasure
   case i:R => println("case 1")
[...]

The information about type parameters is not available at runtime. You can read a detailed explanation in "Programming in Scala", section 15.2 or at [1].

[1] http://bit.ly/ZJ2UO

Regards
Simon




--
Matthew Pocockmailto: turingatemyhamster@gmail.comgchat: turingatemyhamster@gmail.com msn: matthew_pocock@yahoo.co.ukirc.freenode.net: drdozer(0191) 2566550
Simon Olofsson
Joined: 2011-06-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Generic types

On 2011-06-17 21:28, Matthew Pocock wrote:
> Is there a compelling reason why the warning that's displayed in this
> circumstance with -unchecked should not be enabled by default?

I don't know the exact reason, but my guess would be that it's "just a
warning" and it may be too verbose. You get a hint what to do:
warning: there were 1 unchecked warnings; re-run with -unchecked for
details
Also, there might be cases when you don't care about such warnings :)

Simon

AlanP
Joined: 2011-05-31,
User offline. Last seen 42 years 45 weeks ago.
Re: Generic types

Jiasnsen,

You can accomplish what you want using Manifests. It just adds a
little more verbosity to your case statements:

scala> class C[R:Manifest,S:Manifest] {
| def apply[T: Manifest](i: T) = i match {
| case i if(implicitly[Manifest[T]] == implicitly[Manifest[R]])
=> println("case 1")
| case i if(implicitly[Manifest[T]] == implicitly[Manifest[S]])
=> println("case 2")
| case _ => println("other")
| }}
defined class C

scala> val c = new C[Int,Double]
c: C[Int,Double] = C@22721290

scala> c(1)
case 1

scala> c(1.0)
case 2

scala> c("Hello")
other

Regards,

Alan

On Jun 17, 4:20 am, Jiansen wrote:
> Hi all,
>
> Could anyone suggest why following code gives such an unexpected
> output?
>
> class C[R,S] {
>   def apply(i:Any) = i match {
>     case i:R => println("case 1")
>     case i:S => println("case 2")
>     case _ => println("Other")
>   }
>
> }
>
> object mytest extends Application{
>
>   val c = new C[Int, Double]
>   c(1)
>   c(1.0)
>   c("Hello")
>
> }
>
> output:
>   case 1
>   case 1
>   case 1
>
> whereas I think the output should be:
>   case 1
>   case 2
>   Other
>
> With Thanks
> Jiasnsen

Ismael Juma 2
Joined: 2011-01-22,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Generic types
On Fri, Jun 17, 2011 at 8:28 PM, Matthew Pocock <turingatemyhamster@gmail.com> wrote:
Variations on this issue have come up a lot recently. Is there a compelling reason why the warning that's displayed in this circumstance with -unchecked should not be enabled by default?

Personally, I think -unchecked and -deprecated should be enabled by default. It's what I do for all my projects.
Best,Ismael 
Naftoli Gugenheim
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Generic types
That makes sense --- let more advanced users turn it off if they want, but newbies should get them by default!

On Sun, Jun 19, 2011 at 2:17 PM, Ismael Juma <ismael@juma.me.uk> wrote:
On Fri, Jun 17, 2011 at 8:28 PM, Matthew Pocock <turingatemyhamster@gmail.com> wrote:
Variations on this issue have come up a lot recently. Is there a compelling reason why the warning that's displayed in this circumstance with -unchecked should not be enabled by default?

Personally, I think -unchecked and -deprecated should be enabled by default. It's what I do for all my projects.
Best,Ismael 

Ruediger Keller 2
Joined: 2010-04-30,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Generic types

+1

I agree that the default should be to enable these settings.

Regards,
Rüdiger

2011/6/19 Ismael Juma :
> On Fri, Jun 17, 2011 at 8:28 PM, Matthew Pocock
> wrote:
>>
>> Variations on this issue have come up a lot recently. Is there a
>> compelling reason why the warning that's displayed in this circumstance with
>> -unchecked should not be enabled by default?
>
> Personally, I think -unchecked and -deprecated should be enabled by default.
> It's what I do for all my projects.
> Best,
> Ismael

pkolaczk
Joined: 2010-01-14,
User offline. Last seen 2 years 38 weeks ago.
Re: Generic types

W dniu 2011-06-18 02:37, AlanP pisze:
> Jiasnsen,
>
> You can accomplish what you want using Manifests. It just adds a
> little more verbosity to your case statements:
>
> scala> class C[R:Manifest,S:Manifest] {
> | def apply[T: Manifest](i: T) = i match {
> | case i if(implicitly[Manifest[T]] == implicitly[Manifest[R]])
> => println("case 1")
> | case i if(implicitly[Manifest[T]] == implicitly[Manifest[S]])
> => println("case 2")
> | case _ => println("other")
> | }}
> defined class C

Hmm, if we have this magic Manifest thing that brings back full generic
type information to runtime, and in the type spec of the class Manifests
are listed for the generic types, wouldn't it be a good idea if such
Manifest checking code be generated automatically by the compiler?

So:

class C[R,S] {
def apply(i:Any) = i match {
case i:R => println("case 1")
case i:S => println("case 2")
case _ => println("Other")
}
}

generates a warning, so I add Manifests to it:

class C[R : Manifest, S : Manifest] {
def apply[T: Manifest](i:T) = i match {
case i:R => println("case 1")
case i:S => println("case 2")
case _ => println("Other")
}
}

and voilla, the types are checked and the matching works as intended?
Of course, this could also affect the .isInstanceOf operator.

What do you think?

Regards,
Piotr

>
> scala> val c = new C[Int,Double]
> c: C[Int,Double] = C@22721290
>
> scala> c(1)
> case 1
>
> scala> c(1.0)
> case 2
>
> scala> c("Hello")
> other
>
> Regards,
>
> Alan
>
>
>
> On Jun 17, 4:20 am, Jiansen wrote:
>> Hi all,
>>
>> Could anyone suggest why following code gives such an unexpected
>> output?
>>
>> class C[R,S] {
>> def apply(i:Any) = i match {
>> case i:R => println("case 1")
>> case i:S => println("case 2")
>> case _ => println("Other")
>> }
>>
>> }
>>
>> object mytest extends Application{
>>
>> val c = new C[Int, Double]
>> c(1)
>> c(1.0)
>> c("Hello")
>>
>> }
>>
>> output:
>> case 1
>> case 1
>> case 1
>>
>> whereas I think the output should be:
>> case 1
>> case 2
>> Other
>>
>> With Thanks
>> Jiasnsen
>

Naftoli Gugenheim
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Generic types
No, because it requires the calling code to also have Manifest information, and so on.

2011/6/20 Piotr Kołaczkowski <pkolaczk@elka.pw.edu.pl>
W dniu 2011-06-18 02:37, AlanP pisze:
Jiasnsen,

You can accomplish what you want using Manifests. It just adds a
little more verbosity to your case statements:

scala>  class C[R:Manifest,S:Manifest] {
     | def apply[T: Manifest](i: T) = i match {
     | case i if(implicitly[Manifest[T]] == implicitly[Manifest[R]])
=>  println("case 1")
     | case i if(implicitly[Manifest[T]] == implicitly[Manifest[S]])
=>  println("case 2")
     | case _ =>  println("other")
     | }}
defined class C


Hmm, if we have this magic Manifest thing that brings back full generic type information to runtime, and in the type spec of the class Manifests are listed for the generic types, wouldn't it be a good idea if such Manifest checking code be generated automatically by the compiler?


So:

class C[R,S] {
 def apply(i:Any) = i match {
   case i:R => println("case 1")
   case i:S => println("case 2")
   case _ => println("Other")
 }
}


generates a warning, so I add Manifests to it:

class C[R : Manifest, S : Manifest] {
 def apply[T: Manifest](i:T) = i match {
   case i:R => println("case 1")
   case i:S => println("case 2")
   case _ => println("Other")
 }
}

and voilla, the types are checked and the matching works as intended?
Of course, this could also affect the .isInstanceOf operator.

What do you think?

Regards,
Piotr





scala>  val c = new C[Int,Double]
c: C[Int,Double] = C@22721290

scala>  c(1)
case 1

scala>  c(1.0)
case 2

scala>  c("Hello")
other

Regards,

Alan



On Jun 17, 4:20 am, Jiansen<jianse...@gmail.com>  wrote:
Hi all,

Could anyone suggest why following code gives such an unexpected
output?

class C[R,S] {
  def apply(i:Any) = i match {
    case i:R =>  println("case 1")
    case i:S =>  println("case 2")
    case _ =>  println("Other")
  }

}

object mytest extends Application{

  val c = new C[Int, Double]
  c(1)
  c(1.0)
  c("Hello")

}

output:
  case 1
  case 1
  case 1

whereas I think the output should be:
  case 1
  case 2
  Other

With Thanks
Jiasnsen




pkolaczk
Joined: 2010-01-14,
User offline. Last seen 2 years 38 weeks ago.
Re: Generic types

I can't see how the proposition affects the calling code. I haven't said
anything about the compiler *adding* Manifest declarations itself, just
*using* it, when present.

What I propose is to make the compiler use the Manifest information if
it is available (appropriate Manifest passed as an argument to the
method or class constructor), or to fallback to current behaviour if it
is not available (generating an unchecked warning).

Regards,
Piotr

W dniu 2011-06-21 00:27, Naftoli Gugenheim pisze:
> No, because it requires the calling code to also have Manifest
> information, and so on.
>
> 2011/6/20 Piotr Kołaczkowski
> >
>
> W dniu 2011-06-18 02:37, AlanP pisze:
>
> Jiasnsen,
>
> You can accomplish what you want using Manifests. It just adds a
> little more verbosity to your case statements:
>
> scala> class C[R:Manifest,S:Manifest] {
> | def apply[T: Manifest](i: T) = i match {
> | case i if(implicitly[Manifest[T]] ==
> implicitly[Manifest[R]])
> => println("case 1")
> | case i if(implicitly[Manifest[T]] ==
> implicitly[Manifest[S]])
> => println("case 2")
> | case _ => println("other")
> | }}
> defined class C
>
>
>
> Hmm, if we have this magic Manifest thing that brings back full
> generic type information to runtime, and in the type spec of the
> class Manifests are listed for the generic types, wouldn't it be a
> good idea if such Manifest checking code be generated automatically
> by the compiler?
>
>
> So:
>
>
> class C[R,S] {
> def apply(i:Any) = i match {
> case i:R => println("case 1")
> case i:S => println("case 2")
> case _ => println("Other")
> }
> }
>
>
> generates a warning, so I add Manifests to it:
>
>
> class C[R : Manifest, S : Manifest] {
> def apply[T: Manifest](i:T) = i match {
> case i:R => println("case 1")
> case i:S => println("case 2")
> case _ => println("Other")
> }
> }
>
> and voilla, the types are checked and the matching works as intended?
> Of course, this could also affect the .isInstanceOf operator.
>
> What do you think?
>
> Regards,
> Piotr
>
>
>
>
>
>
> scala> val c = new C[Int,Double]
> c: C[Int,Double] = C@22721290
>
> scala> c(1)
> case 1
>
> scala> c(1.0)
> case 2
>
> scala> c("Hello")
> other
>
> Regards,
>
> Alan
>
>
>
> On Jun 17, 4:20 am,
> Jiansen > wrote:
>
> Hi all,
>
> Could anyone suggest why following code gives such an unexpected
> output?
>
> class C[R,S] {
> def apply(i:Any) = i match {
> case i:R => println("case 1")
> case i:S => println("case 2")
> case _ => println("Other")
> }
>
> }
>
> object mytest extends Application{
>
> val c = new C[Int, Double]
> c(1)
> c(1.0)
> c("Hello")
>
> }
>
> output:
> case 1
> case 1
> case 1
>
> whereas I think the output should be:
> case 1
> case 2
> Other
>
> With Thanks
> Jiasnsen
>
>
>
>
>

James Iry
Joined: 2008-08-19,
User offline. Last seen 1 year 23 weeks ago.
Re: Re: Generic types
That's pretty much what the current behavior is
def f[A : Manifest] = {   def g = new Array[A](0)   g}
g uses the manifest from its enclosing scope to create an array.
Same deal here
class X[A : Manifest] {   def g = new Array[A](0) }
Don't know what you mean by "unchecked" warning. The check that a manifest is available is static.  It occurs at compile time, not runtime.

2011/6/21 Piotr Kołaczkowski <pkolaczk@elka.pw.edu.pl>
What I propose is to make the compiler use the Manifest information if it is available (appropriate Manifest passed as an argument to the method or class constructor), or to fallback to current behaviour if it is not available (generating an unchecked warning).

Regards,
Piotr

pkolaczk
Joined: 2010-01-14,
User offline. Last seen 2 years 38 weeks ago.
Re: Generic types

No, it is not what I meant.

What about this:

def f[A : Manifest](x: Any) = x.isInstanceOf[A] // unchecked warning

Actually, in this example, the compiler has all the information required
to generate proper runtime type checking code, so unchecked warning here
is really not required. I think adding an isInstanceOf method working
this way is even possible to do now, without touching the compiler, only
by means of manifests and implicit conversions (it must have a different
name, though).

Or this:

def f[A : Manifest](x: Any) = x match {
case _: A =>
case _: Any =>
}

A solution for this has already been proposed in this thread, using
manifests in guards directly, but it is really not readable and looks
like boilerplate code. Isn't the whole point of Scala avoiding
boilerplate code?

If I have some spare time, I'll try to code a compiler plugin for this ;)

Regards,
Piotr

W dniu 2011-06-21 19:33, James Iry pisze:
> That's pretty much what the current behavior is
>
> def f[A : Manifest] = {
> def g = new Array[A](0)
> g
> }
>
> g uses the manifest from its enclosing scope to create an array.
>
> Same deal here
>
> class X[A : Manifest] {
> def g = new Array[A](0)
> }
>
> Don't know what you mean by "unchecked" warning. The check that a
> manifest is available is static. It occurs at compile time, not runtime.
>
> 2011/6/21 Piotr Kołaczkowski
> >
>
> What I propose is to make the compiler use the Manifest information
> if it is available (appropriate Manifest passed as an argument to
> the method or class constructor), or to fallback to current
> behaviour if it is not available (generating an unchecked warning).
>
> Regards,
> Piotr
>

Matthew Pocock 3
Joined: 2010-07-30,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Generic types

From my phone so it may make comedy errors. It is the run time that has theknowledge, not the compiler. A ptddggagdmtjw clever compiler perhaps could handle this, but we don't have side effects and psi in the compiler.

Matthew

On 21 Jun 2011 19:14, "Piotr Kołaczkowski" <pkolaczk@elka.pw.edu.pl> wrote:

No, it is not what I meant.

What about this:

def f[A : Manifest](x: Any) = x.isInstanceOf[A]  // unchecked warning

Actually, in this example, the compiler has all the information required to generate proper runtime type checking code, so unchecked warning here is really not required. I think adding an isInstanceOf method working this way is even possible to do now, without touching the compiler, only by means of manifests and implicit conversions (it must have a different name, though).

Or this:

def f[A : Manifest](x: Any) = x match {
 case _: A =>
 case _: Any =>
}

A solution for this has already been proposed in this thread, using manifests in guards directly, but it is really not readable and looks like boilerplate code. Isn't the whole point of Scala avoiding boilerplate code?

If I have some spare time, I'll try to code a compiler plugin for this ;)

Regards,
Piotr

W dniu 2011-06-21 19:33, James Iry pisze:

>
> That's pretty much what the current behavior is
>
> def f[A : Manifest] = {
>    def g = new Arr...

<mailto:pkolaczk [at] elka [dot] pw [dot] edu.pl>>


>
>    What I propose is to make the compiler use the Manifest information
>    if it is available ...



Naftoli Gugenheim
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Generic types


2011/6/21 Matthew Pocock <turingatemyhamster@gmail.com>

ptddggagdmtjw


Was that the comedy? 

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