3

In C++ we can get the abstract key/value type (key_type, value_type, http://en.cppreference.com/w/cpp/container/map) from the defined map. This is quite convenient when I need to change the map type later since the dependent type would change accordingly.

In Scala I'm also looking for such a feature. For example, I define a map type:

type MapTy : mutable.Map[Long, Int]

And I hope to return an entry of the map (whose type is Long->Int). The return type depends on MapTy and it had better be explicitly specified in the function signature, written as something like MapTy::key_type->MapTy::value_type. Therefore, when later I change MapTy to

type MapTy : mutable.Map[Int, Int]

The entry type would also change to Int->Int simultaneously.

Is it possible in Scala?

Hongxu Chen
  • 5,240
  • 2
  • 45
  • 85

2 Answers2

4

It entirely possible to do this kind of thing with type members and type refinements in Scala:

scala> case class WrappedMap[K, V](underlying: Map[K, V]) { type E = (K, V) }
defined class WrappedMap

scala> type MapTy = WrappedMap[Long, Int]
defined type alias MapTy

scala> val entry: MapTy#E = 1L -> 0
entry: (Long, Int) = (1,0)

scala> val entry: MapTy#E = 1L -> "foo"
<console>:14: error: type mismatch;
 found   : String("foo")
 required: Int
       val entry: MapTy#E = 1L -> "foo"
                                  ^

Or:

def entries(m: MapTy): List[MapTy#E] = m.underlying.toList

val myEntries: List[MapTy#E] = entries(WrappedMap(Map(1L -> 0)))

The standard collections library for the most part doesn't include type members representing element types, in part because working generically with the type parameters fits better with idiomatic Scala development practices, but there are situations where type members are useful, and if you really want to approximate what you're describing in C++, that may be one of them.

Travis Brown
  • 138,631
  • 12
  • 375
  • 680
2

In Scala generic types are lost in erasure, so it is not possible in runtime. Someone may show how to this, until then here is a workaround:

type Key = Int
type Value = Long
type Map = mutable.Map[Key, Value]

Also, this may be helpful.

Community
  • 1
  • 1
Krever
  • 1,371
  • 1
  • 13
  • 32
  • 1
    Sorry, but it's unclear to me what type erasure has to do with this situation—can you expand on that part? – Travis Brown Apr 10 '16 at 19:43
  • I must say I'm not an expert on self declared types but I assume they work just like any other types. So after the erasure, in runtime, type of the map is just `mutable.Map` and all the info about type of key and value is lost. This is why what you're asking is not possible in runtime. It may be possible in compile time, but I don't know any way to do this(but scala is suprising me every day, so don't assume it is impossible). – Krever Apr 12 '16 at 05:24