Quantcast

Default type parameters

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Default type parameters

richard emberson-2
I'd like to be able to have a type parameterized class
so that when the type parameter is not given,
a default type is used.
Consider:

class Form[T](id: String, var obj: T) {
     def this(id: String) =
         this(id, null.asInstanceOf[T])
}

// not type give results in Form[Nothing]
val f0 = new Form("hi")
// explicit type give results in Form[Int]
val f1 = new Form[Int]("hi")
// compiler inferred type to be Form[Double]
val f32= new Form("hi", 0.3)

For f0, rather than getting Nothing as the type, I would
like to somehow specify in the class definition that the type
is, say, String when the type is not explicitly or compiler
inferred.

Can this be done in Scala?
Can it be done when there is more than one parameterized type?
Thanks.
Richard

--
Quis custodiet ipsos custodes
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Default type parameters

HamsterofDeath
it's possible if the type can be inferred and/or is bound (upper or lower):

object Sandbox {

  class Foo[T <: JComponent](val c:T)
  class Bar[T <: JComponent](val dummy:String)
 
  def main(args: Array[String]) {
    val foo = new Foo(new JLabel("foo")) // <- generic jlabel
    val bar = new Bar("bar") // <- generic jcomponent
  }
}



Am 01.01.2011 03:53, schrieb richard emberson:

> I'd like to be able to have a type parameterized class
> so that when the type parameter is not given,
> a default type is used.
> Consider:
>
> class Form[T](id: String, var obj: T) {
>     def this(id: String) =
>         this(id, null.asInstanceOf[T])
> }
>
> // not type give results in Form[Nothing]
> val f0 = new Form("hi")
> // explicit type give results in Form[Int]
> val f1 = new Form[Int]("hi")
> // compiler inferred type to be Form[Double]
> val f32= new Form("hi", 0.3)
>
> For f0, rather than getting Nothing as the type, I would
> like to somehow specify in the class definition that the type
> is, say, String when the type is not explicitly or compiler
> inferred.
>
> Can this be done in Scala?
> Can it be done when there is more than one parameterized type?
> Thanks.
> Richard
>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Default type parameters

Paul Phillips-3
In reply to this post by richard emberson-2
On Fri, Dec 31, 2010 at 06:53:41PM -0800, richard emberson wrote:

> I'd like to be able to have a type parameterized class so that when
> the type parameter is not given, a default type is used. Consider:
>
> class Form[T](id: String, var obj: T) {
>     def this(id: String) =
>         this(id, null.asInstanceOf[T])
> }
>
> // not type give results in Form[Nothing]
> val f0 = new Form("hi")

If you want to elbow Nothing out of the game, you can, but your type
parameter will have to wear an ankle bracelet.  That is, there's no way
to say "everything, except Nothing."

But you can do this:

package object form {
  type TypeJumble = Double with Int with String
}
import form._

class Form[T >: TypeJumble](id: String, var obj: T) {
  def this(id: String) = this(id, null.asInstanceOf[T])
}              
object Test {
  // not type give results in Form[Nothing]
  val f0 = new Form("hi")
  // explicit type give results in Form[Int]
  val f1 = new Form[Int]("hi")
  // compiler inferred type to be Form[Double]
  val f2 = new Form("hi", 0.3)
 
  def main(args: Array[String]): Unit = {
    List(f0, f1, f2) map (_.obj) foreach println
  }
}

Here's a variation with a manifest so you can see what's being inferred
a little more clearly.  But you don't need a manifest.

class Form[T >: TypeJumble : Manifest](id: String, var obj: T) {
  def this(id: String) = this(id, null.asInstanceOf[T])
  override def toString = manifest[T].toString
}              
// ...
// main: List(f0, f1, f2) foreach println

% scala Test
Double with Int with java.lang.String
Int
Double

You can no longer have Nothing even if you want it:

scala> new Form[Nothing]("hi")
<console>:5: error: type arguments [Nothing] do not conform to class Form's type parameter bounds [T >: form.package.TypeJumble]
       val res0 =
           ^
<console>:6: error: type arguments [Nothing] do not conform to class Form's type parameter bounds [T >: form.package.TypeJumble]
       new Form[Nothing]("hi")
           ^
                                                               
--
Paul Phillips      | Eschew mastication.
Everyman           |
Empiricist         |
ha! spill, pupil   |----------* http://www.improving.org/paulp/ *----------
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Default type parameters

Chris Twiner
In reply to this post by richard emberson-2

Use a companion apply to specify the default type.

On 1 Jan 2011 03:54, "richard emberson" <[hidden email]> wrote:

I'd like to be able to have a type parameterized class
so that when the type parameter is not given,
a default type is used.
Consider:

class Form[T](id: String, var obj: T) {
   def this(id: String) =
       this(id, null.asInstanceOf[T])
}

// not type give results in Form[Nothing]
val f0 = new Form("hi")
// explicit type give results in Form[Int]
val f1 = new Form[Int]("hi")
// compiler inferred type to be Form[Double]
val f32= new Form("hi", 0.3)

For f0, rather than getting Nothing as the type, I would
like to somehow specify in the class definition that the type
is, say, String when the type is not explicitly or compiler
inferred.

Can this be done in Scala?
Can it be done when there is more than one parameterized type?
Thanks.
Richard

--
Quis custodiet ipsos custodes

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Default type parameters

Andreas Flierl
In reply to this post by Paul Phillips-3

Paul Phillips wrote:
> package object form {
>  type TypeJumble = Double with Int with String
> }

Woah, I wasn't aware that this was even possible. It's kinda awesome.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Default type parameters

HamsterofDeath
i recently bought a book about functional programming where i learned
about this concept. it's pretty obvious once you think about how you
handle "inheritance" without classes. you need to define a "set of
types" and use it as a single type:
type AnyNumber = Integer | Double | Long | ....

but this was new to me:

class Form[T >: TypeJumble : Manifest]

is this equal to "class Form[T >: TypeJumble](implicit m:Manifest[T])"?
does it also work on method type parameters?


Am 01.01.2011 10:03, schrieb Andreas Flierl:
> Paul Phillips wrote:
>> package object form {
>>  type TypeJumble = Double with Int with String
>> }
> Woah, I wasn't aware that this was even possible. It's kinda awesome.
>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Default type parameters

Jason Zaugg
On Sat, Jan 1, 2011 at 11:38 AM, HamsterofDeath <[hidden email]> wrote:
> but this was new to me:
>
> class Form[T >: TypeJumble : Manifest]
>
> is this equal to "class Form[T >: TypeJumble](implicit m:Manifest[T])"?

Yes, precisely. [1]

> does it also work on method type parameters?

Yes.

-jason

[1] http://stackoverflow.com/questions/2982276/what-is-a-context-bound-in-scala
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Default type parameters

Miles Sabin
In reply to this post by Paul Phillips-3
On Sat, Jan 1, 2011 at 8:33 AM, Paul Phillips <[hidden email]> wrote:
> If you want to elbow Nothing out of the game, you can, but your type
> parameter will have to wear an ankle bracelet.  That is, there's no way
> to say "everything, except Nothing."

Actually, in this particular case (I'm not sure how or if what follows
can be generalized) we can get pretty close to that,

object Companions { // keep the REPL happy

  class Form[T](id : String, obj : T)

  object Form {
    // The easy case : fully explicit, no defaults
    def apply[T](id : String, obj : T) = new Form[T](id, obj)

    // No type param : default to String (this case eliminates Nothing)
    def apply(id : String) = new Form[String](id, null)

    // Some shenanigans to avoid an ambiguous overload for this case
    // which handles defaults with an explicit type parameter
    implicit def applyAux[T](id : String) : Form[T] = new Form[T](id,
null.asInstanceOf[T])
    def apply[T](f : Form[T]) = f
  }
}

import Companions._

Form("hi")
Form[Int]("hi")
Form("hi", 0.3)

scala> :load form.scala
Loading form.scala...
defined module Companions
import Companions._
res0: Companions.Form[String] = Companions$Form@fe0ce9
res1: Companions.Form[Int] = Companions$Form@230be4
res2: Companions.Form[Double] = Companions$Form@b5b80

Cheers,


Miles

--
Miles Sabin
tel: +44 7813 944 528
gtalk: [hidden email]
skype: milessabin
http://www.chuusai.com/
http://twitter.com/milessabin
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Default type parameters

Miles Sabin
In reply to this post by Paul Phillips-3
On Sat, Jan 1, 2011 at 8:33 AM, Paul Phillips <[hidden email]> wrote:
> If you want to elbow Nothing out of the game, you can, but your type
> parameter will have to wear an ankle bracelet.  That is, there's no way
> to say "everything, except Nothing."

After a bit more tinkering, I stumbled across this,

trait NotNothing[T] { type U }
implicit val nothingIsNothing = new NotNothing[Nothing] { type U = Any }
implicit def notNothing[T] = new NotNothing[T] { type U = T }

def foo[T : NotNothing](t : T) = t

scala> foo("bar")
res0: java.lang.String = bar

scala> foo(23)
res1: Int = 23

scala> foo(error("zip"))
<console>:10: error: ambiguous implicit values:
 both method notNothing in object $iw of type [T]java.lang.Object with
NotNothing[T]{type U = T}
 and value nothingIsNothing in object $iw of type => java.lang.Object
with NotNothing[Nothing]{type U = Any}
 match expected type NotNothing[T]
       foo(error("zip"))

This appears to be useful if rather than causing an unspecified type
parameter to default to some specific type you just want to exclude
the possibility of Nothing being inferred. For instance,

scala> class Form[T : NotNothing](id : String, obj : T = null.asInstanceOf[T])
defined class Form

scala> new Form("hi")
<console>:11: error: ambiguous implicit values:
 both method notNothing in object Test of type [T]java.lang.Object
with Test.NotNothing[T]{type U = T}
 and value nothingIsNothing in object Test of type => java.lang.Object
with Test.NotNothing[Nothing]{type U = Any}
 match expected type Test.NotNothing[T]
Error occurred in an application involving default arguments.
       new Form("hi")
       ^

scala> new Form[Int]("hi")
res0: Form[Int] = Form@6197cc

scala> new Form("hi", 0.3)
res1: Form[Double] = Form@5b84b

Cheers,


Miles

--
Miles Sabin
tel: +44 7813 944 528
gtalk: [hidden email]
skype: milessabin
http://www.chuusai.com/
http://twitter.com/milessabin
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Default type parameters

Norbert Tausch
In reply to this post by richard emberson-2
Hi,

there is another way of having a default type parameters in classes: use
default values for constructor arguments:

class Test[T](val arg1: Int, val arg2: T = "default")

Now you have a Test[String] when omitting the second argument:

val test = new Test(5)
println(test.arg2)

val test2 = new Test(5, new Test(10))
println(test2.arg2)

Hope this helps....


Am 01.01.2011 03:53, schrieb richard emberson:

> I'd like to be able to have a type parameterized class
> so that when the type parameter is not given,
> a default type is used.
> Consider:
>
> class Form[T](id: String, var obj: T) {
>     def this(id: String) =
>         this(id, null.asInstanceOf[T])
> }
>
> // not type give results in Form[Nothing]
> val f0 = new Form("hi")
> // explicit type give results in Form[Int]
> val f1 = new Form[Int]("hi")
> // compiler inferred type to be Form[Double]
> val f32= new Form("hi", 0.3)
>
> For f0, rather than getting Nothing as the type, I would
> like to somehow specify in the class definition that the type
> is, say, String when the type is not explicitly or compiler
> inferred.
>
> Can this be done in Scala?
> Can it be done when there is more than one parameterized type?
> Thanks.
> Richard
>
Loading...