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

Re: How to find the type of an Option

9 replies
H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.

it is Int. it is right there is your code. it is not a type parameter.
there is no problem :)

Am 01.01.2012 18:51, schrieb Tim P:
> Is there any way to figure out what the type of an Option argument to
> a case class is?
> Does Manifest help me here? - I can't see how
>
> example:
>
> case class Product(id: String, size: Option[Int])
>
>

Tim P
Joined: 2011-07-28,
User offline. Last seen 1 year 4 weeks ago.
How to find the type of an Option

Is there any way to figure out what the type of an Option argument to
a case class is?
Does Manifest help me here? - I can't see how

example:

case class Product(id: String, size: Option[Int])

Peter 2
Joined: 2011-02-16,
User offline. Last seen 42 years 45 weeks ago.
Re: How to find the type of an Option

Hi Tim,

if you need the type at compile time just write

case class Product[T](id: String, size: Option[T])

If you nedd it at run time you add a manifest argument by

case class Product[T:Manifest](id: String, size: Option[T])

which is roughly a shortcut for

case class Product[T](id: String, size: Option[T])(implicit
sizeManifest: Manifest[T])

Peter

Tim P
Joined: 2011-07-28,
User offline. Last seen 1 year 4 weeks ago.
Re: How to find the type of an Option

Ok - a bit more background

I have

trait BaseProduct {
def id: String
}

In different variants of my model I could have

case class Product(id: String, size: Option[Int]) extends BaseProduct

or
case class Product(id: String, size: Int, weight: Option[Weight])
extends BaseProduct
or
case class Product(id: String, size: Int, description:
Option[String] ...) extends BaseProduct

or any sort of other combination of things. I actually have a set of 8
or 9 types which exhibit the same behaviour. Some of them refer to
each other and it's by way of being an internal DSL to define the
different problem types.

I was hoping to write a generic xml loader that would check names of
the case class arguments and build them for me using reflection -
something like

def buildProductFromXML[T <: BaseProduct : Manifest](xml: Node) =
Validated[T]

Within any model it is important that my case class definitions are
clear and simple. They certainly don't want to be parameterised.

Now I can obviously write a non-generic loader for the things. I could
write a generic loader if I didn't use Option and if push comes to
shove I could do something like

def bulidProductFromXML[T <: BaseProduct: Manifest](xml: Node,
optTypes: Seq[Class]) - and maybe that's the best solution. I just
wanted something a little prettier, especially since some of the sub-
classes could wind up with 10+ optional arguments.

With

On Jan 1, 6:04 pm, Sonnenschein wrote:
> Hi Tim,
>
> if you need the type at compile time just write
>
> case class Product[T](id: String, size: Option[T])
>
> If you nedd it at run time you add a manifest argument by
>
> case class Product[T:Manifest](id: String, size: Option[T])
>
> which is roughly a shortcut for
>
> case class Product[T](id: String, size: Option[T])(implicit
> sizeManifest: Manifest[T])
>
> Peter

H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.
Re: Re: How to find the type of an Option

case class Product(id: String, size: Option[Int]) extends BaseProduct

or
case class Product(id: String, size: Int, weight: Option[Weight])
extends BaseProduct
or
case class Product(id: String, size: Int, description:
Option[String] ...) extends BaseProduct

i am missing something. how can you declare the same case class several
times?
or is it actually just one, and the option's type can change? if so, as
suggested:

case class Product[A:Manifest](....x:Option[A])

Am 01.01.2012 19:49, schrieb Tim P:
> case class Product(id: String, size: Option[Int]) extends BaseProduct
>
> or
> case class Product(id: String, size: Int, weight: Option[Weight])
> extends BaseProduct
> or
> case class Product(id: String, size: Int, description:
> Option[String] ...) extends BaseProduct

Tim P
Joined: 2011-07-28,
User offline. Last seen 1 year 4 weeks ago.
Re: Re: How to find the type of an Option

I have different objects/packages corresponding to different models.
The case classes are defined within them.

On 1 January 2012 19:09, HamsterofDeath wrote:
> case class Product(id: String, size: Option[Int]) extends BaseProduct
>
> or
> case class Product(id: String, size: Int, weight: Option[Weight])
> extends BaseProduct
> or
> case class Product(id: String, size: Int, description:
> Option[String] ...) extends BaseProduct
>
>
>
> i am missing something. how can you declare the same case class several
> times?
> or is it actually just one, and the option's type can change? if so, as
> suggested:
>
> case class Product[A:Manifest](....x:Option[A])
>
> Am 01.01.2012 19:49, schrieb Tim P:
>> case class Product(id: String, size: Option[Int]) extends BaseProduct
>>
>> or
>> case class Product(id: String, size: Int, weight: Option[Weight])
>> extends BaseProduct
>> or
>> case class Product(id: String, size: Int, description:
>> Option[String] ...) extends BaseProduct
>

Derek Williams 3
Joined: 2011-08-12,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: How to find the type of an Option
How about this (no reflection required):
case class ProductOne(id: String, size: Option[Int])
case class ProductTwo(id: String, description: Option[String])
trait BuildFromXML[T] extends (xml.NodeSeq => Option[T]) { def apply(in: xml.NodeSeq): Option[T] }
object BuildFromXML {
  implicit def buildString: BuildFromXML[String] = new BuildFromXML[String] {    def apply(in: xml.NodeSeq): Option[String] = in.headOption map (_.text)   }
  implicit def buildInt: BuildFromXML[Int] = new BuildFromXML[Int] {     def apply(in: xml.NodeSeq): Option[Int] = try { in.headOption map (_.text.toInt) } catch { case _: NumberFormatException => None }  }
  implicit def buildOption[A](implicit builder: BuildFromXML[A]): BuildFromXML[Option[A]] = new BuildFromXML[Option[A]] {     def apply(in: xml.NodeSeq): Option[Option[A]] = Some(builder(in))  }
  implicit def buildTuple2[A, B](implicit buildA: BuildFromXML[A], buildB: BuildFromXML[B]): BuildFromXML[(A, B)] = new BuildFromXML[(A, B)] {     def apply(in: xml.NodeSeq): Option[(A, B)] = {      for {        a <- buildA(in \ "one")         b <- buildB(in \ "two")      } yield (a, b)    }   }
  implicit def buildTuple3[A, B, C](implicit buildA: BuildFromXML[A], buildB: BuildFromXML[B], buildC: BuildFromXML[C]): BuildFromXML[(A, B, C)] = new BuildFromXML[(A, B, C)] {     def apply(in: xml.NodeSeq): Option[(A, B, C)] = {      for {        a <- buildA(in \ "one")         b <- buildB(in \ "two")        c <- buildC(in \ "three")       } yield (a, b, c)    }  }
  def apply[T](in: xml.NodeSeq)(implicit builder: BuildFromXML[T]): Option[T] = builder(in)
  def apply[A,B](fn: (A) => B, in: xml.NodeSeq)(implicit builder: BuildFromXML[A]): Option[B] = builder(in) map fn
  def apply[A,B,C](fn: (A, B) => C, in: xml.NodeSeq)(implicit builder: BuildFromXML[(A, B)]): Option[C] = builder(in) map fn.tupled
  def apply[A,B,C,D](fn: (A, B, C) => D, in: xml.NodeSeq)(implicit builder: BuildFromXML[(A, B, C)]): Option[D] = builder(in) map fn.tupled
}
val xml1 = <product><one>the string</one><two>45</two></product> val xml2 = <product><one>the string</one></product>val xml3 = <product></product> val xml4 = <product><one>the string</one><two>the description</two></product>
assert(BuildFromXML(ProductOne, xml1) == Some(ProductOne("the string", Some(45))))assert(BuildFromXML(ProductOne, xml2) == Some(ProductOne("the string", None))) assert(BuildFromXML(ProductOne, xml3) == None)assert(BuildFromXML(ProductTwo, xml4) == Some(ProductTwo("the string", Some("the description")))) assert(BuildFromXML(ProductOne, xml4) == Some(ProductOne("the string", None)))


--
Derek Williams
Derek Williams 3
Joined: 2011-08-12,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: How to find the type of an Option
On Sun, Jan 1, 2012 at 1:21 PM, Derek Williams <derek [at] fyrie [dot] net> wrote:
How about this (no reflection required):

This of course doesn't work well if your case classes contain other case classes. In that case you would need to use reflection.
--
Derek Williams
Tim P
Joined: 2011-07-28,
User offline. Last seen 1 year 4 weeks ago.
Re: Re: How to find the type of an Option

Wow :-)
Is there a limit to the maximum number of parameters I can cope with
using this technique? Some of my records go past the length of normal
tuples. Do I hit something before the case class limit of 21 or
whatever it is?

Tim

On 1 January 2012 20:21, Derek Williams wrote:
> How about this (no reflection required):
>
> case class ProductOne(id: String, size: Option[Int])
>
> case class ProductTwo(id: String, description: Option[String])
>
> trait BuildFromXML[T] extends (xml.NodeSeq => Option[T]) { def apply(in:
> xml.NodeSeq): Option[T] }
>
> object BuildFromXML {
>
>   implicit def buildString: BuildFromXML[String] = new BuildFromXML[String]
> {
>     def apply(in: xml.NodeSeq): Option[String] = in.headOption map (_.text)
>   }
>
>   implicit def buildInt: BuildFromXML[Int] = new BuildFromXML[Int] {
>     def apply(in: xml.NodeSeq): Option[Int] = try { in.headOption map
> (_.text.toInt) } catch { case _: NumberFormatException => None }
>   }
>
>   implicit def buildOption[A](implicit builder: BuildFromXML[A]):
> BuildFromXML[Option[A]] = new BuildFromXML[Option[A]] {
>     def apply(in: xml.NodeSeq): Option[Option[A]] = Some(builder(in))
>   }
>
>   implicit def buildTuple2[A, B](implicit buildA: BuildFromXML[A], buildB:
> BuildFromXML[B]): BuildFromXML[(A, B)] = new BuildFromXML[(A, B)] {
>     def apply(in: xml.NodeSeq): Option[(A, B)] = {
>       for {
>         a <- buildA(in \ "one")
>         b <- buildB(in \ "two")
>       } yield (a, b)
>     }
>   }
>
>   implicit def buildTuple3[A, B, C](implicit buildA: BuildFromXML[A],
> buildB: BuildFromXML[B], buildC: BuildFromXML[C]): BuildFromXML[(A, B, C)] =
> new BuildFromXML[(A, B, C)] {
>     def apply(in: xml.NodeSeq): Option[(A, B, C)] = {
>       for {
>         a <- buildA(in \ "one")
>         b <- buildB(in \ "two")
>         c <- buildC(in \ "three")
>       } yield (a, b, c)
>     }
>   }
>
>   def apply[T](in: xml.NodeSeq)(implicit builder: BuildFromXML[T]):
> Option[T] = builder(in)
>
>   def apply[A,B](fn: (A) => B, in: xml.NodeSeq)(implicit builder:
> BuildFromXML[A]): Option[B] = builder(in) map fn
>
>   def apply[A,B,C](fn: (A, B) => C, in: xml.NodeSeq)(implicit builder:
> BuildFromXML[(A, B)]): Option[C] = builder(in) map fn.tupled
>
>   def apply[A,B,C,D](fn: (A, B, C) => D, in: xml.NodeSeq)(implicit builder:
> BuildFromXML[(A, B, C)]): Option[D] = builder(in) map fn.tupled
>
> }
>
> val xml1 = the string45
> val xml2 = the string
> val xml3 =
> val xml4 = the stringthe
> description
>
> assert(BuildFromXML(ProductOne, xml1) == Some(ProductOne("the string",
> Some(45))))
> assert(BuildFromXML(ProductOne, xml2) == Some(ProductOne("the string",
> None)))
> assert(BuildFromXML(ProductOne, xml3) == None)
> assert(BuildFromXML(ProductTwo, xml4) == Some(ProductTwo("the string",
> Some("the description"))))
> assert(BuildFromXML(ProductOne, xml4) == Some(ProductOne("the string",
> None)))
>
>
>
> --
> Derek Williams
>

Andreas Scheinert
Joined: 2011-02-11,
User offline. Last seen 42 years 45 weeks ago.
Re: How to find the type of an Option

Hi Tim,
I think you would need than an HList implementation. Miles Sabin has
one in his shapeless project: https://github.com/milessabin/shapeless
Hth Andreas

On Jan 2, 10:23 am, Tim Pigden wrote:
> Wow :-)
> Is there a limit to the maximum number of parameters I can cope with
> using this technique? Some of my records go past the length of normal
> tuples. Do I hit something before the case class limit of 21 or
> whatever it is?
>
> Tim
>
> On 1 January 2012 20:21, Derek Williams wrote:
>
>
>
>
>
> > How about this (no reflection required):
>
> > case class ProductOne(id: String, size: Option[Int])
>
> > case class ProductTwo(id: String, description: Option[String])
>
> > trait BuildFromXML[T] extends (xml.NodeSeq => Option[T]) { def apply(in:
> > xml.NodeSeq): Option[T] }
>
> > object BuildFromXML {
>
> >   implicit def buildString: BuildFromXML[String] = new BuildFromXML[String]
> > {
> >     def apply(in: xml.NodeSeq): Option[String] = in.headOption map (_.text)
> >   }
>
> >   implicit def buildInt: BuildFromXML[Int] = new BuildFromXML[Int] {
> >     def apply(in: xml.NodeSeq): Option[Int] = try { in.headOption map
> > (_.text.toInt) } catch { case _: NumberFormatException => None }
> >   }
>
> >   implicit def buildOption[A](implicit builder: BuildFromXML[A]):
> > BuildFromXML[Option[A]] = new BuildFromXML[Option[A]] {
> >     def apply(in: xml.NodeSeq): Option[Option[A]] = Some(builder(in))
> >   }
>
> >   implicit def buildTuple2[A, B](implicit buildA: BuildFromXML[A], buildB:
> > BuildFromXML[B]): BuildFromXML[(A, B)] = new BuildFromXML[(A, B)] {
> >     def apply(in: xml.NodeSeq): Option[(A, B)] = {
> >       for {
> >         a <- buildA(in \ "one")
> >         b <- buildB(in \ "two")
> >       } yield (a, b)
> >     }
> >   }
>
> >   implicit def buildTuple3[A, B, C](implicit buildA: BuildFromXML[A],
> > buildB: BuildFromXML[B], buildC: BuildFromXML[C]): BuildFromXML[(A, B, C)] =
> > new BuildFromXML[(A, B, C)] {
> >     def apply(in: xml.NodeSeq): Option[(A, B, C)] = {
> >       for {
> >         a <- buildA(in \ "one")
> >         b <- buildB(in \ "two")
> >         c <- buildC(in \ "three")
> >       } yield (a, b, c)
> >     }
> >   }
>
> >   def apply[T](in: xml.NodeSeq)(implicit builder: BuildFromXML[T]):
> > Option[T] = builder(in)
>
> >   def apply[A,B](fn: (A) => B, in: xml.NodeSeq)(implicit builder:
> > BuildFromXML[A]): Option[B] = builder(in) map fn
>
> >   def apply[A,B,C](fn: (A, B) => C, in: xml.NodeSeq)(implicit builder:
> > BuildFromXML[(A, B)]): Option[C] = builder(in) map fn.tupled
>
> >   def apply[A,B,C,D](fn: (A, B, C) => D, in: xml.NodeSeq)(implicit builder:
> > BuildFromXML[(A, B, C)]): Option[D] = builder(in) map fn.tupled
>
> > }
>
> > val xml1 = the string45
> > val xml2 = the string
> > val xml3 =
> > val xml4 = the stringthe
> > description
>
> > assert(BuildFromXML(ProductOne, xml1) == Some(ProductOne("the string",
> > Some(45))))
> > assert(BuildFromXML(ProductOne, xml2) == Some(ProductOne("the string",
> > None)))
> > assert(BuildFromXML(ProductOne, xml3) == None)
> > assert(BuildFromXML(ProductTwo, xml4) == Some(ProductTwo("the string",
> > Some("the description"))))
> > assert(BuildFromXML(ProductOne, xml4) == Some(ProductOne("the string",
> > None)))
>
> > --
> > Derek Williams
>
> --
> Tim Pigden
> Optrak Distribution Software Limited+44 (0)1992 517100http://www.linkedin.com/in/timpigdenhttp://optrak.com
> Optrak Distribution Software Ltd is a limited company registered in
> England and Wales.
> Company Registration No.2327613Registered Offices: Orland House,
> Mead Lane, Hertford, SG13 7AT England
> This email and any attachments to it may be confidential and are
> intended solely for the use of the individual to whom it is addressed.
> Any views or opinions expressed are solely those of the author and do
> not necessarily represent those of Optrak Distribution Software Ltd.
> If you are not the intended recipient of this email, you must neither
> take any action based upon its contents, nor copy or show it to
> anyone. Please contact the sender if you believe you have received
> this email in error.

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