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

2.8, type parameters, manifests and traits

28 replies
David Pollak
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
Howdy,

In 2.8, is it possible to have the manifest for a type parameter defined on a trait reified someplace that's accessible to the trait.  The following works with classes:

class Foo[T: Manifest] {
  def myType(implicit man: Manifest[T]): Manifest[T] = man
}

But it seems that because traits don't take parameters, you can't do trait Foo[T: Manifest] ....

It would be very, very helpful to have a reification of trait type parameters.  Any ideas on how this could be done?

Thanks,

David

--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics
Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: 2.8, type parameters, manifests and traits

I was hopeful you could do something clever with Predef.=:=, however
the type system doesn't know that Manifest[TT] is the same as
Manifest[T] and the type inferencer can't infer TT, which renders this
approach useless.

trait Foo[T] {
def myType[TT](implicit man: Manifest[TT], tteqt: TT =:= T):
Manifest[TT] = man
}
//(new Foo[Int] {}).myType //compile error
(new Foo[Int] {}).myType[Int]
//(new Foo[Int] {}).myType[String] //compile error

Alternatively, you could provide the manifest as a member:

trait Foo[T] {
def myType: Manifest[T]
}

class Bar[X: Manifest] extends Foo[X] {
val myType: Manifest[X] = implicitly
}

new Bar[Int].myType

Hopefully someone else has a better way!

-jason

On Fri, Feb 5, 2010 at 2:25 AM, David Pollak
wrote:
> Howdy,
>
> In 2.8, is it possible to have the manifest for a type parameter defined on
> a trait reified someplace that's accessible to the trait.  The following
> works with classes:
>
> class Foo[T: Manifest] {
>   def myType(implicit man: Manifest[T]): Manifest[T] = man
> }
>
> But it seems that because traits don't take parameters, you can't do trait
> Foo[T: Manifest] ....
>
> It would be very, very helpful to have a reification of trait type
> parameters.  Any ideas on how this could be done?
>
> Thanks,
>
> David
>
> --
> Lift, the simply functional web framework http://liftweb.net
> Beginning Scala http://www.apress.com/book/view/1430219890
> Follow me: http://twitter.com/dpp
> Surf the harmonics
>

Colin Bullock
Joined: 2009-01-23,
User offline. Last seen 42 years 45 weeks ago.
Re: 2.8, type parameters, manifests and traits

trait Foo[T] {
 def myType[TT](implicit man: Manifest[TT], tteqt: TT =:= T):
Manifest[TT] = man
}

You can get pretty close just using type bounds:

trait Foo[T] {
  def myType[TT >: T <: T : Manifest]: Manifest[TT] = implicitly
}

- Colin

Arthur Peters 2
Joined: 2009-01-10,
User offline. Last seen 42 years 45 weeks ago.
Re: 2.8, type parameters, manifests and traits

I'm pretty sure you can just do:

trait Foo[T] {
   def func(...)(implicit mt : Manifest[T]) = ...
}

You would have to include the manifest parameter in every function that needs the manifest and it would have to be available in every scope that called one of those functions but it should work. I have used it.

-Arthur (sent from phone)

On Feb 5, 2010 8:26 AM, "Colin Bullock" <cmbullock@gmail.com> wrote:


> trait Foo[T] {
>  def myType[TT](implicit man: Manifest[TT], tteqt: TT =:= T):
> Manifest[TT] = ma...


You can get pretty close just using type bounds:

trait Foo[T] {
  def myType[TT >: T <: T : Manifest]: Manifest[TT] = implicitly
}

- Colin

Colin Bullock
Joined: 2009-01-23,
User offline. Last seen 42 years 45 weeks ago.
Re: 2.8, type parameters, manifests and traits


On Fri, Feb 5, 2010 at 8:58 AM, Arthur Peters <amp@singingwizard.org> wrote:

I'm pretty sure you can just do:

trait Foo[T] {
   def func(...)(implicit mt : Manifest[T]) = ...
}


Ah... of course... ***goes to get more coffee***

- Colin
David Pollak
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
Re: 2.8, type parameters, manifests and traits


On Fri, Feb 5, 2010 at 6:58 AM, Arthur Peters <amp@singingwizard.org> wrote:

I'm pretty sure you can just do:

trait Foo[T] {
   def func(...)(implicit mt : Manifest[T]) = ...
}


You actually can't do this because T is not know in every context.


For example:

object Bar {
  def calcFooManifest[T](foo: Foo[T]): Manifest[T] = foo.myType // we don't know what T is here
}

So... the net-net is that traits don't take constructor parameters for a bunch of well know and documented reasons.  Traits do take type parameters.  It seems to me that in the case of traits with type parameters marked as Manifest could only be mixed into classes that have the corresponding type parameter marked as Manifest... just like abstract methods on a trait must be implemented on implementing classes.  In the case of an anonymous class that's being instantiated (new Trait[DefinedType] {}), the type is known and the anonymous class could contain the Manifest.  I guess the third case is "class Foo extends Trait[Int]" but in that case, the compiler knows the type and can generate a manifest for it.

This would be *very helpful*.

 

You would have to include the manifest parameter in every function that needs the manifest and it would have to be available in every scope that called one of those functions but it should work. I have used it.

-Arthur (sent from phone)

On Feb 5, 2010 8:26 AM, "Colin Bullock" <cmbullock@gmail.com> wrote:


> trait Foo[T] {
>  def myType[TT](implicit man: Manifest[TT], tteqt: TT =:= T):
> Manifest[TT] = ma...


You can get pretty close just using type bounds:

trait Foo[T] {
  def myType[TT >: T <: T : Manifest]: Manifest[TT] = implicitly
}

- Colin




--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics
Johannes Rudolph
Joined: 2008-12-17,
User offline. Last seen 29 weeks 20 hours ago.
Re: 2.8, type parameters, manifests and traits

On Fri, Feb 5, 2010 at 6:17 PM, David Pollak
wrote:
> On Fri, Feb 5, 2010 at 6:58 AM, Arthur Peters wrote:
>>
>> I'm pretty sure you can just do:
>>
>> trait Foo[T] {
>>    def func(...)(implicit mt : Manifest[T]) = ...
>> }
>
> You actually can't do this because T is not know in every context.
>
>
> For example:
>
> object Bar {
>   def calcFooManifest[T](foo: Foo[T]): Manifest[T] = foo.myType // we don't
> know what T is here
> }
>
> So... the net-net is that traits don't take constructor parameters for a
> bunch of well know and documented reasons.  Traits do take type parameters.
> It seems to me that in the case of traits with type parameters marked as
> Manifest could only be mixed into classes that have the corresponding type
> parameter marked as Manifest... just like abstract methods on a trait must
> be implemented on implementing classes.

So you mean

trait Test[X: Manifest[X]]

would be desugared as

trait Test[X] {
implicit val mfX: Manifest[X]
}

and

class Impl[X: Manifest[X]] extends Test[X]

would desugar as

class Impl[X](implicit val mfX: Manifest[X]) extends Test[X]

?

That seems reasonable to me.

> In the case of an anonymous class
> that's being instantiated (new Trait[DefinedType] {}), the type is known and
> the anonymous class could contain the Manifest.  I guess the third case is
> "class Foo extends Trait[Int]" but in that case, the compiler knows the type
> and can generate a manifest for it.

So, it boils down to this: Exactly as the compiler can find implicit
*parameter* values for method calls, it should find implicits for a
class' abstract member values. Is that possible?

Johannes Rudolph
Joined: 2008-12-17,
User offline. Last seen 29 weeks 20 hours ago.
Re: 2.8, type parameters, manifests and traits

On Fri, Feb 5, 2010 at 6:29 PM, Johannes Rudolph
wrote:
> So you mean
>
> trait Test[X: Manifest[X]]

That's of course

trait Test[X: Manifest]

a.s.o.

Jorge Ortiz
Joined: 2008-12-16,
User offline. Last seen 29 weeks 3 days ago.
Re: 2.8, type parameters, manifests and traits
It can be done manually, it just requires a bit of housekeeping:

  trait A[T] {
    implicit val t: Manifest[T]
  }

  class B extends A[Int] {
    override val t = manifest[Int]
  }

The possibility of having traits take constructor parameters has been mentioned before. I don't know how far work on this front has gone, but I suspect that more general feature would solve this particular problem.

--j

On Thu, Feb 4, 2010 at 5:25 PM, David Pollak <feeder.of.the.bears@gmail.com> wrote:
Howdy,

In 2.8, is it possible to have the manifest for a type parameter defined on a trait reified someplace that's accessible to the trait.  The following works with classes:

class Foo[T: Manifest] {
  def myType(implicit man: Manifest[T]): Manifest[T] = man
}

But it seems that because traits don't take parameters, you can't do trait Foo[T: Manifest] ....

It would be very, very helpful to have a reification of trait type parameters.  Any ideas on how this could be done?

Thanks,

David

--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics

daniel
Joined: 2008-08-20,
User offline. Last seen 44 weeks 14 hours ago.
Re: 2.8, type parameters, manifests and traits
I can't corroborate this personally, but I've been told (by someone in the field of type theory) that traits would be generally unsound if they could take constructor parameters.  I don't know if this holds for implicit params (I would imagine so).  As I said, I can't personally confirm this information, but I thought it was worth throwing out there.

Daniel
On Feb 6, 2010, at 4:18 PM, "Jorge Ortiz" <jorge.ortiz@gmail.com> wrote:

It can be done manually, it just requires a bit of housekeeping:

  trait A[T] {
    implicit val t: Manifest[T]
  }

  class B extends A[Int] {
    override val t = manifest[Int]
  }

The possibility of having traits take constructor parameters has been mentioned before. I don't know how far work on this front has gone, but I suspect that more general feature would solve this particular problem.

--j

On Thu, Feb 4, 2010 at 5:25 PM, David Pollak < (feeder [dot] of [dot] the [dot] bears [at] gmail [dot] com> wrote:
Howdy,

In 2.8, is it possible to have the manifest for a type parameter defined on a trait reified someplace that's accessible to the trait.  The following works with classes:

class Foo[T: Manifest] {
  def myType(implicit man: Manifest[T]): Manifest[T] = man
}

But it seems that because traits don't take parameters, you can't do trait Foo[T: Manifest] ....

It would be very, very helpful to have a reification of trait type parameters.  Any ideas on how this could be done?

Thanks,

David

--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics

Jorge Ortiz
Joined: 2008-12-16,
User offline. Last seen 29 weeks 3 days ago.
Re: 2.8, type parameters, manifests and traits
I know nothing of type theory, but I do know that adding trait constructor parameters has been mentioned by the Scala team in the past. See, for example, this thread: http://old.nabble.com/-scala--Constructor-parameters-for-traits-to20796791.html

In particular, Ingo Maier's response.

--j

On Sat, Feb 6, 2010 at 3:43 PM, Daniel Spiewak <djspiewak@gmail.com> wrote:
I can't corroborate this personally, but I've been told (by someone in the field of type theory) that traits would be generally unsound if they could take constructor parameters.  I don't know if this holds for implicit params (I would imagine so).  As I said, I can't personally confirm this information, but I thought it was worth throwing out there.

Daniel
On Feb 6, 2010, at 4:18 PM, "Jorge Ortiz" <jorge.ortiz@gmail.com> wrote:

It can be done manually, it just requires a bit of housekeeping:

  trait A[T] {
    implicit val t: Manifest[T]
  }

  class B extends A[Int] {
    override val t = manifest[Int]
  }

The possibility of having traits take constructor parameters has been mentioned before. I don't know how far work on this front has gone, but I suspect that more general feature would solve this particular problem.

--j

On Thu, Feb 4, 2010 at 5:25 PM, David Pollak <feeder.of.the.bears@gmail.comfeeder.of.the.bears@gmail.com> wrote:
Howdy,

In 2.8, is it possible to have the manifest for a type parameter defined on a trait reified someplace that's accessible to the trait.  The following works with classes:

class Foo[T: Manifest] {
  def myType(implicit man: Manifest[T]): Manifest[T] = man
}

But it seems that because traits don't take parameters, you can't do trait Foo[T: Manifest] ....

It would be very, very helpful to have a reification of trait type parameters.  Any ideas on how this could be done?

Thanks,

David

--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics


Mushtaq Ahmed
Joined: 2009-03-07,
User offline. Last seen 30 weeks 2 days ago.
Re: 2.8, type parameters, manifests and traits
And also this one with a response from Donna Malayeri:
http://old.nabble.com/Re:-How-are-Trait-Constructors-coming-along--p26994243.html

On Sun, Feb 7, 2010 at 5:35 AM, Jorge Ortiz <jorge.ortiz@gmail.com> wrote:
I know nothing of type theory, but I do know that adding trait constructor parameters has been mentioned by the Scala team in the past. See, for example, this thread: http://old.nabble.com/-scala--Constructor-parameters-for-traits-to20796791.html

In particular, Ingo Maier's response.

--j

On Sat, Feb 6, 2010 at 3:43 PM, Daniel Spiewak <djspiewak@gmail.com> wrote:
I can't corroborate this personally, but I've been told (by someone in the field of type theory) that traits would be generally unsound if they could take constructor parameters.  I don't know if this holds for implicit params (I would imagine so).  As I said, I can't personally confirm this information, but I thought it was worth throwing out there.

Daniel
On Feb 6, 2010, at 4:18 PM, "Jorge Ortiz" <jorge.ortiz@gmail.com> wrote:

It can be done manually, it just requires a bit of housekeeping:

  trait A[T] {
    implicit val t: Manifest[T]
  }

  class B extends A[Int] {
    override val t = manifest[Int]
  }

The possibility of having traits take constructor parameters has been mentioned before. I don't know how far work on this front has gone, but I suspect that more general feature would solve this particular problem.

--j

On Thu, Feb 4, 2010 at 5:25 PM, David Pollak <feeder.of.the.bears@gmail.comfeeder.of.the.bears@gmail.com> wrote:
Howdy,

In 2.8, is it possible to have the manifest for a type parameter defined on a trait reified someplace that's accessible to the trait.  The following works with classes:

class Foo[T: Manifest] {
  def myType(implicit man: Manifest[T]): Manifest[T] = man
}

But it seems that because traits don't take parameters, you can't do trait Foo[T: Manifest] ....

It would be very, very helpful to have a reification of trait type parameters.  Any ideas on how this could be done?

Thanks,

David

--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics



Donna Malayeri
Joined: 2009-10-21,
User offline. Last seen 42 years 45 weeks ago.
Re: 2.8, type parameters, manifests and traits
No, there wouldn't be unsoundness per-se, but there would be problems in initializing objects, due to the diamond problem.

I'm looking into solutions; my current thoughts are to disallow diamond inheritance when a trait has constructor parameters. If you do need diamond inheritance AND constructor parameters, you should restructure your class hierarchy using self-types (see the post someone mentioned, http://old.nabble.com/Re:-How-are-Trait-Constructors-coming-along--p26994243.html).

The manifest example is a great use case, so I'll see if I can devote more time to the trait constructor parameter issue.

Donna

On Sun, Feb 7, 2010 at 12:43 AM, Daniel Spiewak <djspiewak@gmail.com> wrote:
I can't corroborate this personally, but I've been told (by someone in the field of type theory) that traits would be generally unsound if they could take constructor parameters.  I don't know if this holds for implicit params (I would imagine so).  As I said, I can't personally confirm this information, but I thought it was worth throwing out there.

Daniel
On Feb 6, 2010, at 4:18 PM, "Jorge Ortiz" <jorge.ortiz@gmail.com> wrote:

It can be done manually, it just requires a bit of housekeeping:

  trait A[T] {
    implicit val t: Manifest[T]
  }

  class B extends A[Int] {
    override val t = manifest[Int]
  }

The possibility of having traits take constructor parameters has been mentioned before. I don't know how far work on this front has gone, but I suspect that more general feature would solve this particular problem.

--j

On Thu, Feb 4, 2010 at 5:25 PM, David Pollak <feeder.of.the.bears@gmail.comfeeder.of.the.bears@gmail.com> wrote:
Howdy,

In 2.8, is it possible to have the manifest for a type parameter defined on a trait reified someplace that's accessible to the trait.  The following works with classes:

class Foo[T: Manifest] {
  def myType(implicit man: Manifest[T]): Manifest[T] = man
}

But it seems that because traits don't take parameters, you can't do trait Foo[T: Manifest] ....

It would be very, very helpful to have a reification of trait type parameters.  Any ideas on how this could be done?

Thanks,

David

--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics


James Iry
Joined: 2008-08-19,
User offline. Last seen 1 year 23 weeks ago.
Re: 2.8, type parameters, manifests and traits
If traits had constructor parameters then Scala would have full blown multiple inheritance the same way C++ does.  That's not unsound, but it's very tricky to deal with diamond inheritance.

trait Foo(val x : Int)
trait Bar extends Foo(1)
trait Baz extends Foo(2)
object Quuz extends Bar with Baz

What's the value of Quux.x?

On Sat, Feb 6, 2010 at 3:43 PM, Daniel Spiewak <djspiewak@gmail.com> wrote:
I can't corroborate this personally, but I've been told (by someone in the field of type theory) that traits would be generally unsound if they could take constructor parameters.  I don't know if this holds for implicit params (I would imagine so).  As I said, I can't personally confirm this information, but I thought it was worth throwing out there.

Daniel
On Feb 6, 2010, at 4:18 PM, "Jorge Ortiz" <jorge.ortiz@gmail.com> wrote:

It can be done manually, it just requires a bit of housekeeping:

  trait A[T] {
    implicit val t: Manifest[T]
  }

  class B extends A[Int] {
    override val t = manifest[Int]
  }

The possibility of having traits take constructor parameters has been mentioned before. I don't know how far work on this front has gone, but I suspect that more general feature would solve this particular problem.

--j

On Thu, Feb 4, 2010 at 5:25 PM, David Pollak <feeder.of.the.bears@gmail.comfeeder.of.the.bears@gmail.com> wrote:
Howdy,

In 2.8, is it possible to have the manifest for a type parameter defined on a trait reified someplace that's accessible to the trait.  The following works with classes:

class Foo[T: Manifest] {
  def myType(implicit man: Manifest[T]): Manifest[T] = man
}

But it seems that because traits don't take parameters, you can't do trait Foo[T: Manifest] ....

It would be very, very helpful to have a reification of trait type parameters.  Any ideas on how this could be done?

Thanks,

David

--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics


Jan Kriesten
Joined: 2009-01-13,
User offline. Last seen 2 years 39 weeks ago.
Re: 2.8, type parameters, manifests and traits

> trait Foo(val x : Int)
> trait Bar extends Foo(1)
> trait Baz extends Foo(2)
> object Quuz extends Bar with Baz
> What's the value of Quux.x?

It's not really that different from the current view on methods, I suppose. Last
added implementation wins (Quux.x == 2), so there shouldn't be any ambiguities.

Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Re: 2.8, type parameters, manifests and traits
Scala uses a kind of linearization here, so I think you could get away with it, as every class/object/trait had a defined path to the parent.  It may be awkward to wield though, like virtual inheritance. 

Sent from my iPhone 
On Feb 19, 2010, at 11:16 AM, James Iry <jamesiry@gmail.com> wrote:

If traits had constructor parameters then Scala would have full blown multiple inheritance the same way C++ does.  That's not unsound, but it's very tricky to deal with diamond inheritance.

trait Foo(val x : Int)
trait Bar extends Foo(1)
trait Baz extends Foo(2)
object Quuz extends Bar with Baz

What's the value of Quux.x?

On Sat, Feb 6, 2010 at 3:43 PM, Daniel Spiewak < (djspiewak [at] gmail [dot] com> wrote:
I can't corroborate this personally, but I've been told (by someone in the field of type theory) that traits would be generally unsound if they could take constructor parameters.  I don't know if this holds for implicit params (I would imagine so).  As I said, I can't personally confirm this information, but I thought it was worth throwing out there.

Daniel
On Feb 6, 2010, at 4:18 PM, "Jorge Ortiz" < (jorge [dot] ortiz [at] gmail [dot] com> wrote:

It can be done manually, it just requires a bit of housekeeping:

  trait A[T] {
    implicit val t: Manifest[T]
  }

  class B extends A[Int] {
    override val t = manifest[Int]
  }

The possibility of having traits take constructor parameters has been mentioned before. I don't know how far work on this front has gone, but I suspect that more general feature would solve this particular problem.

--j

On Thu, Feb 4, 2010 at 5:25 PM, David Pollak <feeder.of.the.bears@gmail.com (feeder [dot] of [dot] the [dot] bears [at] gmail [dot] com> wrote:
Howdy,

In 2.8, is it possible to have the manifest for a type parameter defined on a trait reified someplace that's accessible to the trait.  The following works with classes:

class Foo[T: Manifest] {
  def myType(implicit man: Manifest[T]): Manifest[T] = man
}

But it seems that because traits don't take parameters, you can't do trait Foo[T: Manifest] ....

It would be very, very helpful to have a reification of trait type parameters.  Any ideas on how this could be done?

Thanks,

David

--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics


Mushtaq Ahmed
Joined: 2009-03-07,
User offline. Last seen 30 weeks 2 days ago.
Re: 2.8, type parameters, manifests and traits
Hello James,
As pointed out by others, the current rules of linearisation can be applied to your example, or am I missing something?
How about the following example:
trait Foo(val x : Int)
trait Bar(val x: Int) extends Foo(x)
trait Baz(val x: Int) extends Foo(x)
object Quuz extends Bar(1) with Baz(2)
The linearisation of the last line is Quizz -> Baz -> Bar -> Foo. But this can not work given that Baz can not be initialized without also initializing Foo (because of the constructors).
Is that the real issue with trait constructors?
Thanks,Mushtaq
On Fri, Feb 19, 2010 at 9:46 PM, James Iry <jamesiry@gmail.com> wrote:
If traits had constructor parameters then Scala would have full blown multiple inheritance the same way C++ does.  That's not unsound, but it's very tricky to deal with diamond inheritance.

trait Foo(val x : Int)
trait Bar extends Foo(1)
trait Baz extends Foo(2)
object Quuz extends Bar with Baz

What's the value of Quux.x?

On Sat, Feb 6, 2010 at 3:43 PM, Daniel Spiewak <djspiewak@gmail.com> wrote:
I can't corroborate this personally, but I've been told (by someone in the field of type theory) that traits would be generally unsound if they could take constructor parameters.  I don't know if this holds for implicit params (I would imagine so).  As I said, I can't personally confirm this information, but I thought it was worth throwing out there.

Daniel
On Feb 6, 2010, at 4:18 PM, "Jorge Ortiz" <jorge.ortiz@gmail.com> wrote:

It can be done manually, it just requires a bit of housekeeping:

  trait A[T] {
    implicit val t: Manifest[T]
  }

  class B extends A[Int] {
    override val t = manifest[Int]
  }

The possibility of having traits take constructor parameters has been mentioned before. I don't know how far work on this front has gone, but I suspect that more general feature would solve this particular problem.

--j

On Thu, Feb 4, 2010 at 5:25 PM, David Pollak <feeder.of.the.bears@gmail.comfeeder.of.the.bears@gmail.com> wrote:
Howdy,

In 2.8, is it possible to have the manifest for a type parameter defined on a trait reified someplace that's accessible to the trait.  The following works with classes:

class Foo[T: Manifest] {
  def myType(implicit man: Manifest[T]): Manifest[T] = man
}

But it seems that because traits don't take parameters, you can't do trait Foo[T: Manifest] ....

It would be very, very helpful to have a reification of trait type parameters.  Any ideas on how this could be done?

Thanks,

David

--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics



Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Re: 2.8, type parameters, manifests and traits
I believe that is the issue James was getting at.  It can be "solved" be linearizing super initializations and picking a "winner" for arguments, but gets rather unwieldy very quickly.

Sent from my iPhone
On Feb 20, 2010, at 10:58 PM, Mushtaq Ahmed <mushtaq.a@gmail.com> wrote:

Hello James,
As pointed out by others, the current rules of linearisation can be applied to your example, or am I missing something?
How about the following example:
trait Foo(val x : Int)
trait Bar(val x: Int) extends Foo(x)
trait Baz(val x: Int) extends Foo(x)
object Quuz extends Bar(1) with Baz(2)
The linearisation of the last line is Quizz -> Baz -> Bar -> Foo. But this can not work given that Baz can not be initialized without also initializing Foo (because of the constructors).
Is that the real issue with trait constructors?
Thanks,Mushtaq
On Fri, Feb 19, 2010 at 9:46 PM, James Iry < (jamesiry [at] gmail [dot] com> wrote:
If traits had constructor parameters then Scala would have full blown multiple inheritance the same way C++ does.  That's not unsound, but it's very tricky to deal with diamond inheritance.

trait Foo(val x : Int)
trait Bar extends Foo(1)
trait Baz extends Foo(2)
object Quuz extends Bar with Baz

What's the value of Quux.x?

On Sat, Feb 6, 2010 at 3:43 PM, Daniel Spiewak < (djspiewak [at] gmail [dot] com> wrote:
I can't corroborate this personally, but I've been told (by someone in the field of type theory) that traits would be generally unsound if they could take constructor parameters.  I don't know if this holds for implicit params (I would imagine so).  As I said, I can't personally confirm this information, but I thought it was worth throwing out there.

Daniel
On Feb 6, 2010, at 4:18 PM, "Jorge Ortiz" < (jorge [dot] ortiz [at] gmail [dot] com> wrote:

It can be done manually, it just requires a bit of housekeeping:

  trait A[T] {
    implicit val t: Manifest[T]
  }

  class B extends A[Int] {
    override val t = manifest[Int]
  }

The possibility of having traits take constructor parameters has been mentioned before. I don't know how far work on this front has gone, but I suspect that more general feature would solve this particular problem.

--j

On Thu, Feb 4, 2010 at 5:25 PM, David Pollak <feeder.of.the.bears@gmail.com (feeder [dot] of [dot] the [dot] bears [at] gmail [dot] com> wrote:
Howdy,

In 2.8, is it possible to have the manifest for a type parameter defined on a trait reified someplace that's accessible to the trait.  The following works with classes:

class Foo[T: Manifest] {
  def myType(implicit man: Manifest[T]): Manifest[T] = man
}

But it seems that because traits don't take parameters, you can't do trait Foo[T: Manifest] ....

It would be very, very helpful to have a reification of trait type parameters.  Any ideas on how this could be done?

Thanks,

David

--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics



adriaanm
Joined: 2010-02-08,
User offline. Last seen 31 weeks 4 days ago.
Re: 2.8, type parameters, manifests and traits
just to illustrate the issues with trait constructor arguments with a quick, contrived, example: (example with implicit Manifest arguments left as an exercise to the reader)
trait Stream(defaultBufferSize: Int)
trait OutputStream extends Stream(512) trait InputStream extends Stream(256)
class IOStream extends InputStream with OutputStream // pick 512?// or: class IOStream extends OutputStream with InputStream // pick 256?
in principle, we don't want linearisation order to influence program behaviour (*), as it's supposed to stay behind the scenes
In situations like this, I guess the compiler could require the programmer to disambiguate by explicitly specifying the constructor arguments that are multiply inherited:
class IOStream extends Stream(override 512) with InputStream with OutputStream
not sure whether we should require the override keyword, but I like the symmetry with the example below (*) 
cheersadriaan
(*) that's why this is not allowed:trait A {  def foo = 1}
trait B {  def foo = 2 }
trait AB extends A with B /* but this fixes it: {  override def foo = 3} */
adriaanm
Joined: 2010-02-08,
User offline. Last seen 31 weeks 4 days ago.
Re: 2.8, type parameters, manifests and traits
just to illustrate the issues with trait constructor arguments with a quick, contrived, example: (example with implicit Manifest arguments left as an exercise to the reader)
trait Stream(defaultBufferSize: Int)
trait OutputStream extends Stream(512) trait InputStream extends Stream(256)
class IOStream extends InputStream with OutputStream // pick 512?// or: class IOStream extends OutputStream with InputStream // pick 256?
in principle, we don't want linearisation order to influence program behaviour (*), as it's supposed to stay behind the scenes
In situations like this, I guess the compiler could require the programmer to disambiguate by explicitly specifying the constructor arguments that are multiply inherited:
class IOStream extends Stream(override 512) with InputStream with OutputStream
not sure whether we should require the override keyword, but I like the symmetry with the example below (*) 
cheersadriaan
(*) that's why this is not allowed:trait A {  def foo = 1}
trait B {  def foo = 2 }
trait AB extends A with B /* but this fixes it: {  override def foo = 3} */
imaier
Joined: 2008-07-01,
User offline. Last seen 23 weeks 2 days ago.
Re: 2.8, type parameters, manifests and traits

On 2/22/10 10:15 AM, Adriaan Moors wrote:
> in principle, we don't want linearisation order to influence program
> behaviour (*), as it's supposed to stay behind the scenes

I am not sure. It already does influence program behavior:

trait A {
def f = 0
}

trait B extends A {
override def f = 2 * super.f
}

trait C extends A {
override def f = 1 + super.f
}

(new B with C).f == 1
(new C with B).f == 2

While I agree that an override modifier of some sort might be nice, in
our current proposal trait constructors will have different semantics
from class contructors. Trait constructor arguments would rather
designate a preference rather than a requirement for the value of a
parameter which might be changed in the final class composition. I find
the stream example would rather nicely fit into this line of thought, as
client code dealing with traits probably shouldn't depend on the actual
buffer size. In the end it would be a compromise between multiple
inheritance with traits and single inheritance with classes but a
guarantee for constructor arguments. I don't know in what sense Donna's
proposal is different and whether it allows a more fine-grained compromise.

Ingo

>
> In situations like this, I guess the compiler could require the
> programmer to disambiguate by explicitly specifying the constructor
> arguments that are multiply inherited:
>
> class IOStream extends Stream(override 512) with InputStream with
> OutputStream
>
> not sure whether we should require the override keyword, but I like the
> symmetry with the example below (*)
>
> cheers
> adriaan
>
> (*) that's why this is not allowed:
> trait A {
> def foo = 1
> }
>
> trait B {
> def foo = 2
> }
>
> trait AB extends A with B /* but this fixes it: {
> override def foo = 3
> } */

imaier
Joined: 2008-07-01,
User offline. Last seen 23 weeks 2 days ago.
Re: 2.8, type parameters, manifests and traits

On 2/22/10 10:15 AM, Adriaan Moors wrote:
> in principle, we don't want linearisation order to influence program
> behaviour (*), as it's supposed to stay behind the scenes

I am not sure. It already does influence program behavior:

trait A {
def f = 0
}

trait B extends A {
override def f = 2 * super.f
}

trait C extends A {
override def f = 1 + super.f
}

(new B with C).f == 1
(new C with B).f == 2

While I agree that an override modifier of some sort might be nice, in
our current proposal trait constructors will have different semantics
from class contructors. Trait constructor arguments would rather
designate a preference rather than a requirement for the value of a
parameter which might be changed in the final class composition. I find
the stream example would rather nicely fit into this line of thought, as
client code dealing with traits probably shouldn't depend on the actual
buffer size. In the end it would be a compromise between multiple
inheritance with traits and single inheritance with classes but a
guarantee for constructor arguments. I don't know in what sense Donna's
proposal is different and whether it allows a more fine-grained compromise.

Ingo

>
> In situations like this, I guess the compiler could require the
> programmer to disambiguate by explicitly specifying the constructor
> arguments that are multiply inherited:
>
> class IOStream extends Stream(override 512) with InputStream with
> OutputStream
>
> not sure whether we should require the override keyword, but I like the
> symmetry with the example below (*)
>
> cheers
> adriaan
>
> (*) that's why this is not allowed:
> trait A {
> def foo = 1
> }
>
> trait B {
> def foo = 2
> }
>
> trait AB extends A with B /* but this fixes it: {
> override def foo = 3
> } */

adriaanm
Joined: 2010-02-08,
User offline. Last seen 31 weeks 4 days ago.
Re: 2.8, type parameters, manifests and traits


On Mon, Feb 22, 2010 at 10:51 AM, Ingo Maier <ingo.maier@epfl.ch> wrote:
On 2/22/10 10:15 AM, Adriaan Moors wrote:
in principle, we don't want linearisation order to influence program
behaviour (*), as it's supposed to stay behind the scenes

I am not sure. It already does influence program behavior:
Ok, let me retro-actively rephrase :-)It only influences program behaviour when lured from behind the scenes with the "override" keyword (so you had it coming).  
trait A {
 def f = 0
}

trait B extends A {
 override def f = 2 * super.f
}

trait C extends A {
 override def f = 1 + super.f
}

(new B with C).f == 1
(new C with B).f == 2
Right. I didn't think of the case where both members have the override modifier... 
While I agree that an override modifier of some sort might be nice, in our current proposal trait constructors will have different semantics from class contructors. Trait constructor arguments would rather designate a preference rather than a requirement for the value of a parameter which might be changed in the final class composition. 
I find the stream example would rather nicely fit into this line of thought, as client code dealing with traits probably shouldn't depend on the actual buffer size. In the end it would be a compromise between multiple inheritance with traits and single inheritance with classes but a guarantee for constructor arguments.
I haven't looked at the proposal in detail, but it sounds a little difficult to explain to programmers.To me, this sounds simpler: Constructors are constructors, no matter where they're defined (trait/class). When an ambiguity arises, solve it there using override, just like you would for members.  
cheersadriaan
adriaanm
Joined: 2010-02-08,
User offline. Last seen 31 weeks 4 days ago.
Re: 2.8, type parameters, manifests and traits


On Mon, Feb 22, 2010 at 10:51 AM, Ingo Maier <ingo.maier@epfl.ch> wrote:
On 2/22/10 10:15 AM, Adriaan Moors wrote:
in principle, we don't want linearisation order to influence program
behaviour (*), as it's supposed to stay behind the scenes

I am not sure. It already does influence program behavior:
Ok, let me retro-actively rephrase :-)It only influences program behaviour when lured from behind the scenes with the "override" keyword (so you had it coming).  
trait A {
 def f = 0
}

trait B extends A {
 override def f = 2 * super.f
}

trait C extends A {
 override def f = 1 + super.f
}

(new B with C).f == 1
(new C with B).f == 2
Right. I didn't think of the case where both members have the override modifier... 
While I agree that an override modifier of some sort might be nice, in our current proposal trait constructors will have different semantics from class contructors. Trait constructor arguments would rather designate a preference rather than a requirement for the value of a parameter which might be changed in the final class composition. 
I find the stream example would rather nicely fit into this line of thought, as client code dealing with traits probably shouldn't depend on the actual buffer size. In the end it would be a compromise between multiple inheritance with traits and single inheritance with classes but a guarantee for constructor arguments.
I haven't looked at the proposal in detail, but it sounds a little difficult to explain to programmers.To me, this sounds simpler: Constructors are constructors, no matter where they're defined (trait/class). When an ambiguity arises, solve it there using override, just like you would for members.  
cheersadriaan
imaier
Joined: 2008-07-01,
User offline. Last seen 23 weeks 2 days ago.
Re: 2.8, type parameters, manifests and traits

On 2/22/10 11:05 AM, Adriaan Moors wrote:
> I haven't looked at the proposal in detail, but it sounds a little
> difficult to explain to programmers.
> To me, this sounds simpler: Constructors are constructors, no matter
> where they're defined (trait/class). When an ambiguity arises, solve it
> there using override, just like you would for members.

When you have the chance to override them, they designate a mere
preferences from the perspective of the argument passing subtrait
(IStream and OStream in your example). Requiring an override modifier in
another subtrait/class (IOStream) to disambiguate does not change that,
it just adds an annotation telling us that we might mess around with the
base traits constructor arguments. When I use constructor arguments in
classes, no subclass can mess around with them, unless they have the
val/var keyword and are not private or final. So, in that sense, we
already have that distinction and trait constructor arguments could just
be val/var arguments but with a refined intialization semantics.

Ingo

>
> cheers
> adriaan

imaier
Joined: 2008-07-01,
User offline. Last seen 23 weeks 2 days ago.
Re: 2.8, type parameters, manifests and traits

On 2/22/10 11:05 AM, Adriaan Moors wrote:
> I haven't looked at the proposal in detail, but it sounds a little
> difficult to explain to programmers.
> To me, this sounds simpler: Constructors are constructors, no matter
> where they're defined (trait/class). When an ambiguity arises, solve it
> there using override, just like you would for members.

When you have the chance to override them, they designate a mere
preferences from the perspective of the argument passing subtrait
(IStream and OStream in your example). Requiring an override modifier in
another subtrait/class (IOStream) to disambiguate does not change that,
it just adds an annotation telling us that we might mess around with the
base traits constructor arguments. When I use constructor arguments in
classes, no subclass can mess around with them, unless they have the
val/var keyword and are not private or final. So, in that sense, we
already have that distinction and trait constructor arguments could just
be val/var arguments but with a refined intialization semantics.

Ingo

>
> cheers
> adriaan

Andrew McCallum
Joined: 2009-06-30,
User offline. Last seen 42 years 45 weeks ago.
Re: 2.8, type parameters, manifests and traits

I also have been wanting constructor parameters on traits for well
over a year... As with David, my main need is to get a Manifest for
a trait's type parameters.

I was told by Geoffrey Washburn (former postdoc at EPFL) that this was
originally planned for Scala 2.8. Although it didn't make it into
2.8, my understanding is that it is still on the table for a future
release.

On 9/15/2008 Geoffrey Alan Washburn wrote:
> One solution would be to wait until Scala 2.8.0, which I believe
> will support constructor arguments for traits. I am pretty sure
> Martin and some students met to discuss this on Friday, actually.

Some of the technical issues (related to the linearization you mention
here, and beyond) were resolved in a recent Masters thesis (which
Geoffrey pointed me to, but unfortunately I can't find right now).

The skeleton for a SIP is at
http://lampsvn.epfl.ch/trac/scala/browser/lamp-sip/trait-params/sip-0000...

best,
Andrew

On Feb 21, 2010, at 4:58 AM, Mushtaq Ahmed wrote:
> Hello James,
>
> As pointed out by others, the current rules of linearisation can be
> applied to your example, or am I missing something?
>
> How about the following example:
>
> trait Foo(val x : Int)
> trait Bar(val x: Int) extends Foo(x)
> trait Baz(val x: Int) extends Foo(x)
> object Quuz extends Bar(1) with Baz(2)
>
> The linearisation of the last line is Quizz -> Baz -> Bar -> Foo.
> But this can not work given that Baz can not be initialized without
> also initializing Foo (because of the constructors).
>
> Is that the real issue with trait constructors?
>
> Thanks,
> Mushtaq
>
> On Fri, Feb 19, 2010 at 9:46 PM, James Iry wrote:
> If traits had constructor parameters then Scala would have full
> blown multiple inheritance the same way C++ does. That's not
> unsound, but it's very tricky to deal with diamond inheritance.
>
> trait Foo(val x : Int)
> trait Bar extends Foo(1)
> trait Baz extends Foo(2)
> object Quuz extends Bar with Baz
>
> What's the value of Quux.x?
>
>
> On Sat, Feb 6, 2010 at 3:43 PM, Daniel Spiewak
> wrote:
> I can't corroborate this personally, but I've been told (by someone
> in the field of type theory) that traits would be generally unsound
> if they could take constructor parameters. I don't know if this
> holds for implicit params (I would imagine so). As I said, I can't
> personally confirm this information, but I thought it was worth
> throwing out there.
>
> Daniel
>
> On Feb 6, 2010, at 4:18 PM, "Jorge Ortiz"
> wrote:
>
>> It can be done manually, it just requires a bit of housekeeping:
>>
>> trait A[T] {
>> implicit val t: Manifest[T]
>> }
>>
>> class B extends A[Int] {
>> override val t = manifest[Int]
>> }
>>
>> The possibility of having traits take constructor parameters has
>> been mentioned before. I don't know how far work on this front has
>> gone, but I suspect that more general feature would solve this
>> particular problem.
>>
>> --j
>>
>> On Thu, Feb 4, 2010 at 5:25 PM, David Pollak > > wrote:
>> Howdy,
>>
>> In 2.8, is it possible to have the manifest for a type parameter
>> defined on a trait reified someplace that's accessible to the
>> trait. The following works with classes:
>>
>> class Foo[T: Manifest] {
>> def myType(implicit man: Manifest[T]): Manifest[T] = man
>> }
>>
>> But it seems that because traits don't take parameters, you can't
>> do trait Foo[T: Manifest] ....
>>
>> It would be very, very helpful to have a reification of trait type
>> parameters. Any ideas on how this could be done?
>>
>> Thanks,
>>
>> David
>>

Donna Malayeri
Joined: 2009-10-21,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: 2.8, type parameters, manifests and traits
Ingo, as far as I can tell, my proposal doesn't allow the flexibility of yours (do you have the details written up somewhere?), but the advantage is simplicity. I can see the utility of Adriaan's suggestion regarding overriding the constructor call, but I think it's too ad-hoc: it feels too similar to how C++ has done things with virtual inheritance.

To clarify things, my proposal would be based on my CZ language design (http://www.cs.cmu.edu/~donna/public/oopsla09.pdf). The general rule would be that if a trait has a constructor parameter, then it cannot be the root of an inheritance diamond. Using self-types (extended to provide subtyping when desired), a diamond hierarchy could be decomposed to a diamond-free hierarchy. This design might involve more "manual" intervention by the programmer, but I think when dealing with something as tricky as multiple inheritance, it's best to err on the side of caution.

I'm also thinking of working on a refactoring to convert existing code (which may have inheritance diamonds) to one that does not, so that trait constructors could be added more easily. It would of course be possible to change the language design so that less code re-writing would be necessary, but first I want to get an idea for the general shape of inheritance hierarchies in Scala programs.

Donna

On Mon, Feb 22, 2010 at 10:51 AM, Ingo Maier <ingo.maier@epfl.ch> wrote:
On 2/22/10 10:15 AM, Adriaan Moors wrote:
in principle, we don't want linearisation order to influence program
behaviour (*), as it's supposed to stay behind the scenes

I am not sure. It already does influence program behavior:

trait A {
 def f = 0
}

trait B extends A {
 override def f = 2 * super.f
}

trait C extends A {
 override def f = 1 + super.f
}

(new B with C).f == 1
(new C with B).f == 2

While I agree that an override modifier of some sort might be nice, in our current proposal trait constructors will have different semantics from class contructors. Trait constructor arguments would rather designate a preference rather than a requirement for the value of a parameter which might be changed in the final class composition. I find the stream example would rather nicely fit into this line of thought, as client code dealing with traits probably shouldn't depend on the actual buffer size. In the end it would be a compromise between multiple inheritance with traits and single inheritance with classes but a guarantee for constructor arguments. I don't know in what sense Donna's proposal is different and whether it allows a more fine-grained compromise.

Ingo



In situations like this, I guess the compiler could require the
programmer to disambiguate by explicitly specifying the constructor
arguments that are multiply inherited:

class IOStream extends Stream(override 512) with InputStream with
OutputStream

not sure whether we should require the override keyword, but I like the
symmetry with the example below (*)

cheers
adriaan

(*) that's why this is not allowed:
trait A {
  def foo = 1
}

trait B {
  def foo = 2
}

trait AB extends A with B /* but this fixes it: {
  override def foo = 3
} */


Donna Malayeri
Joined: 2009-10-21,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: 2.8, type parameters, manifests and traits
Ingo, as far as I can tell, my proposal doesn't allow the flexibility of yours (do you have the details written up somewhere?), but the advantage is simplicity. I can see the utility of Adriaan's suggestion regarding overriding the constructor call, but I think it's too ad-hoc: it feels too similar to how C++ has done things with virtual inheritance.

To clarify things, my proposal would be based on my CZ language design (http://www.cs.cmu.edu/~donna/public/oopsla09.pdf). The general rule would be that if a trait has a constructor parameter, then it cannot be the root of an inheritance diamond. Using self-types (extended to provide subtyping when desired), a diamond hierarchy could be decomposed to a diamond-free hierarchy. This design might involve more "manual" intervention by the programmer, but I think when dealing with something as tricky as multiple inheritance, it's best to err on the side of caution.

I'm also thinking of working on a refactoring to convert existing code (which may have inheritance diamonds) to one that does not, so that trait constructors could be added more easily. It would of course be possible to change the language design so that less code re-writing would be necessary, but first I want to get an idea for the general shape of inheritance hierarchies in Scala programs.

Donna

On Mon, Feb 22, 2010 at 10:51 AM, Ingo Maier <ingo.maier@epfl.ch> wrote:
On 2/22/10 10:15 AM, Adriaan Moors wrote:
in principle, we don't want linearisation order to influence program
behaviour (*), as it's supposed to stay behind the scenes

I am not sure. It already does influence program behavior:

trait A {
 def f = 0
}

trait B extends A {
 override def f = 2 * super.f
}

trait C extends A {
 override def f = 1 + super.f
}

(new B with C).f == 1
(new C with B).f == 2

While I agree that an override modifier of some sort might be nice, in our current proposal trait constructors will have different semantics from class contructors. Trait constructor arguments would rather designate a preference rather than a requirement for the value of a parameter which might be changed in the final class composition. I find the stream example would rather nicely fit into this line of thought, as client code dealing with traits probably shouldn't depend on the actual buffer size. In the end it would be a compromise between multiple inheritance with traits and single inheritance with classes but a guarantee for constructor arguments. I don't know in what sense Donna's proposal is different and whether it allows a more fine-grained compromise.

Ingo



In situations like this, I guess the compiler could require the
programmer to disambiguate by explicitly specifying the constructor
arguments that are multiply inherited:

class IOStream extends Stream(override 512) with InputStream with
OutputStream

not sure whether we should require the override keyword, but I like the
symmetry with the example below (*)

cheers
adriaan

(*) that's why this is not allowed:
trait A {
  def foo = 1
}

trait B {
  def foo = 2
}

trait AB extends A with B /* but this fixes it: {
  override def foo = 3
} */


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