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

How do I create a Map type that allows multiple types for both keys and values?

6 replies
Derek N.
Joined: 2010-06-05,
User offline. Last seen 42 years 45 weeks ago.

I'm trying to create a Map type so something like the below is possible:

VariantMap(1) = "Test"
VariantMap("a") = 42

My current code requires me to access the map like this:

VariantMap[String](1)

Current code:

object VariantMap {
import scala.reflect.Manifest

private var _map= Map.empty[Any,(Manifest[_], Any)]

def update[T](name: Any, item: T)(implicit m: Manifest[T]) {
_map = _map(name) = (m, item)
}

def apply[T](key:Any)(implicit m : Manifest[T]): Option[T] = {
val o = _map.get(key)
o match {
case Some((om: Manifest[_], s : Any)) => if (om <:< m)
Some(s.asInstanceOf[T]) else None
case _ => None
}
}
}

Is something like what I am trying to do possible?

Thanks for your time - Derek

Derek N.
Joined: 2010-06-05,
User offline. Last seen 42 years 45 weeks ago.
Re: How do I create a Map type that allows multiple types for
I realized I wasn't clear in what I meant in my first email.
I would like to access the map like this:
val temp = VariantMap(1)
and have temp by of type Option[String]
Currently if I try to do that the return type is Option[Nothing].
Thanks

On Sat, Jun 5, 2010 at 12:48 PM, Derek N. <myspam456 [at] gmail [dot] com> wrote:

I'm trying to create a Map type so something like the below is possible:

VariantMap(1) = "Test"
VariantMap("a") = 42

My current code requires me to access the map like this:

VariantMap[String](1)

Current code:

object VariantMap {
  import scala.reflect.Manifest

  private var _map= Map.empty[Any,(Manifest[_], Any)]

  def update[T](name: Any, item: T)(implicit m: Manifest[T]) {
     _map = _map(name) = (m, item)
  }

  def apply[T](key:Any)(implicit m : Manifest[T]): Option[T] = {
    val o = _map.get(key)
    o match {
      case Some((om: Manifest[_], s : Any)) => if (om <:< m)
Some(s.asInstanceOf[T]) else None
      case _ => None
    }
 }
}

Is something like what I am trying to do possible?

Thanks for your time - Derek
--
View this message in context: http://scala-programming-language.1934581.n4.nabble.com/How-do-I-create-a-Map-type-that-allows-multiple-types-for-both-keys-and-values-tp2244431p2244431.html
Sent from the Scala - User mailing list archive at Nabble.com.

Randall R Schulz
Joined: 2008-12-16,
User offline. Last seen 1 year 29 weeks ago.
Re: How do I create a Map type that allows multiple types for

On Saturday June 5 2010, myspam456 wrote:
> I realized I wasn't clear in what I meant in my first email.

I think it would be best if you asked either on Stack Overflow or here,
but not start in one place and then switch to the other.

While this is not exactly apropos your question, I'll start with it to
provide some background: When you create a Map in a manner equivalent
to this:

val m1 = Map(1 -> "one", "one" -> 1)

The compiler finds an upper bound (ideally the least upper bound) of all
the keys and (separately, of course) of all the values and uses those
as the inferred key and value type for the resulting Map:

m1: scala.collection.immutable.Map[Any,Any] = Map((1,one), (one,1))

There's no other way in a statically typed language to accommodate such
a variety of types.

> I would like to access the map like this:
>
> val temp = VariantMap(1)
>
> and have temp by of type Option[String]
>
> Currently if I try to do that the return type is Option[Nothing].

First, I believe you want to define a class, not an object.

Secondly, you may be unaware that the type parameters T in update(...)
and apply(...) are unrelated. If you defined a class in this manner:

class VariantMap[T] { ... }

Then every occurrence of T within that class (when not shadowed locally)
would be co-referrent to the actual type used when instantiating the
class. You'd still need to remove the type parameters T from update and
apply to meet the "not shadowed locally" criterion.

As it stands, because apply(...) has an unbounded type parameter and
uses that in its return, nothing is statically known about it and the
compiler infers Nothing for T. If you used T in the formal arguments,
then each use of apply would supply some type information derived
(statically) from the value passed. But without that, you're asking the
compiler (or the runtime) to know the unknowable. (The use of Manifest
is entirely a red herring here.)

Randall Schulz

> On Sat, Jun 5, 2010 at 12:48 PM, Derek N. wrote:
> > I'm trying to create a Map type so something like the below is
> > possible:
> >
> > VariantMap(1) = "Test"
> > VariantMap("a") = 42
> >
> > My current code requires me to access the map like this:
> >
> > VariantMap[String](1)
> >
> > Current code:
> >
> > object VariantMap {
> > import scala.reflect.Manifest
> >
> > private var _map= Map.empty[Any,(Manifest[_], Any)]
> >
> > def update[T](name: Any, item: T)(implicit m: Manifest[T]) {
> > _map = _map(name) = (m, item)
> > }
> >
> > def apply[T](key:Any)(implicit m : Manifest[T]): Option[T] = {
> > val o = _map.get(key)
> > o match {
> > case Some((om: Manifest[_], s : Any)) => if (om <:< m)
> > Some(s.asInstanceOf[T]) else None
> > case _ => None
> > }
> > }
> > }
> >
> > Is something like what I am trying to do possible?

H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.
Re: How do I create a Map type that allows multiple types for

why not simply new HashMap[_,_] ? what do you need the manifest for?

Linas
Joined: 2009-09-02,
User offline. Last seen 42 years 45 weeks ago.
Re: How do I create a Map type that allows multiple types for

What you want is not possible with scala.

Linas.

On Sat, 2010-06-05 at 14:11 -0500, myspam456 wrote:
> I realized I wasn't clear in what I meant in my first email.
>
>
> I would like to access the map like this:
>
>
> val temp = VariantMap(1)
>
>
> and have temp by of type Option[String]
>
>
> Currently if I try to do that the return type is Option[Nothing].
>
>
> Thanks
>
> On Sat, Jun 5, 2010 at 12:48 PM, Derek N. wrote:
>
> I'm trying to create a Map type so something like the below is
> possible:
>
> VariantMap(1) = "Test"
> VariantMap("a") = 42
>
> My current code requires me to access the map like this:
>
> VariantMap[String](1)
>
> Current code:
>
> object VariantMap {
> import scala.reflect.Manifest
>
> private var _map= Map.empty[Any,(Manifest[_], Any)]
>
> def update[T](name: Any, item: T)(implicit m: Manifest[T]) {
> _map = _map(name) = (m, item)
> }
>
> def apply[T](key:Any)(implicit m : Manifest[T]): Option[T] =
> {
> val o = _map.get(key)
> o match {
> case Some((om: Manifest[_], s : Any)) => if (om <:< m)
> Some(s.asInstanceOf[T]) else None
> case _ => None
> }
> }
> }
>
> Is something like what I am trying to do possible?
>
> Thanks for your time - Derek
> --
> View this message in context:
> http://scala-programming-language.1934581.n4.nabble.com/How-do-I-create-...
> Sent from the Scala - User mailing list archive at Nabble.com.
>
>

H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.
Re: How do I create a Map type that allows multiple types for
*storing* anything as key and value in the same map is possible. (Map[_, _])
making the compiler aware of what value has which type is not. you have to manually cast the returned option. but why would you want that? why not use a simple field in this case?

Linas schrieb:
What you want is not possible with scala.

Linas.

On Sat, 2010-06-05 at 14:11 -0500, myspam456 wrote:
  
I realized I wasn't clear in what I meant in my first email.


I would like to access the map like this:


val temp = VariantMap(1)


and have temp by of type Option[String]


Currently if I try to do that the return type is Option[Nothing].


Thanks

On Sat, Jun 5, 2010 at 12:48 PM, Derek N. myspam456 [at] gmail [dot] com (<myspam456 [at] gmail [dot] com>) wrote:
        
        I'm trying to create a Map type so something like the below is
        possible:
        
        VariantMap(1) = "Test"
        VariantMap("a") = 42
        
        My current code requires me to access the map like this:
        
        VariantMap[String](1)
        
        Current code:
        
        object VariantMap {
          import scala.reflect.Manifest
        
          private var _map= Map.empty[Any,(Manifest[_], Any)]
        
          def update[T](name: Any, item: T)(implicit m: Manifest[T]) {
             _map = _map(name) = (m, item)
          }
        
          def apply[T](key:Any)(implicit m : Manifest[T]): Option[T] =
        {
            val o = _map.get(key)
            o match {
              case Some((om: Manifest[_], s : Any)) => if (om <:< m)
        Some(s.asInstanceOf[T]) else None
              case _ => None
            }
         }
        }
        
        Is something like what I am trying to do possible?
        
        Thanks for your time - Derek
        --
        View this message in context:
        http://scala-programming-language.1934581.n4.nabble.com/How-do-I-create-a-Map-type-that-allows-multiple-types-for-both-keys-and-values-tp2244431p2244431.html
        Sent from the Scala - User mailing list archive at Nabble.com.


    

  

Mark Harrah
Joined: 2008-12-18,
User offline. Last seen 35 weeks 3 days ago.
Re: How do I create a Map type that allows multiple types for b

You aren't too specific about what you want to allow, but one thing you can do is use a heterogeneous map class:
http://github.com/harrah/up/blob/master/TypedMap.scala
http://github.com/harrah/up/blob/master/TypedMapTest.scala

Sample usage:

// map that allows only:
// String -> Int
// String -> Boolean
class TypeMap1 extends TypeMap {
implicit val StrToBool = new TypeMapping[String, Boolean] {}
implicit val StrToInt = new TypeMapping[String, Int] {}
}

val m = new TypeMap1

import m._

m("a") = 3
m("a") = true
// compile error
//m("a") = "string"

assert( m.getOr("a", 5) == 3)
assert( m.getOr("b", 5) == 5)
assert( m.getOr("a", false) == true)
assert( m.getOr("b", false) == false)

// compile errors
//m.getOr("a", 'z')
//m.getOr(3, true)

-Mark

On Saturday 05 June 2010, myspam456 wrote:
> I realized I wasn't clear in what I meant in my first email.
>
> I would like to access the map like this:
>
> val temp = VariantMap(1)
>
> and have temp by of type Option[String]
>
> Currently if I try to do that the return type is Option[Nothing].
>
> Thanks
>
> On Sat, Jun 5, 2010 at 12:48 PM, Derek N. wrote:
>
> >
> > I'm trying to create a Map type so something like the below is possible:
> >
> > VariantMap(1) = "Test"
> > VariantMap("a") = 42
> >
> > My current code requires me to access the map like this:
> >
> > VariantMap[String](1)
> >
> > Current code:
> >
> > object VariantMap {
> > import scala.reflect.Manifest
> >
> > private var _map= Map.empty[Any,(Manifest[_], Any)]
> >
> > def update[T](name: Any, item: T)(implicit m: Manifest[T]) {
> > _map = _map(name) = (m, item)
> > }
> >
> > def apply[T](key:Any)(implicit m : Manifest[T]): Option[T] = {
> > val o = _map.get(key)
> > o match {
> > case Some((om: Manifest[_], s : Any)) => if (om <:< m)
> > Some(s.asInstanceOf[T]) else None
> > case _ => None
> > }
> > }
> > }
> >
> > Is something like what I am trying to do possible?
> >
> > Thanks for your time - Derek

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