collections - Binding Existential types in Scala -
this basic cmap map classes (class[t] t) type of value.
scala> type cmap = map[class[t] forsome{type t}, any] defined type alias cmap scala> val cmap: cmap = map(classof[int]->5, classof[string]->"abc", classof[double]->"ddd") cmap: cmap = map(int -> 5, class java.lang.string -> abc, double -> ddd) now want "bound" cmap (call cmapbind). cmap, maps classes (any classes) values (any values). unlike cmap, cmapbind has type binding between key , value, meaning hope following behavior:
val cmapbind: cmapbind = map(classof[int]->5, classof[string]-> "aa") // should compile val cmapbind: cmapbind = map(classof[int]->5, classof[string]-> 0) // should fail compile how implement cmapbind?
i know following 2 won't work syntactically/logically.
scala> type cmapbind = map[class[t] forsome{type t}, t] <console>:8: error: not found: type t type cmapbind = map[class[t] forsome{type t}, t] scala> type cmapbind = map[class[t], t] forsome{type t} scala> val cmapbind: cmapbind = map(classof[int]->5, classof[string]->"str") <console>:8: error: type mismatch; found : scala.collection.immutable.map[class[_ >: string int],any] required: cmapbind (which expands to) map[class[t],t] forsome { type t } val cmapbind: cmapbind = map(classof[int]->5, classof[string]->"str") note here using type constructor class[t] example illustrate question. in code have own types, e.g. trait animal[s, t], class dog extends animal[int, string].
edit 1: should have mentioned using immutable map example, need mutable heterogeneous map).
let's try implement mutable hmap. explanations scala type system here @milessabin: http://www.chuusai.com/2011/07/16/fundeps-in-scala/
the idea statically check constructor (here see, it's arity depends on hands, possible generate or smth else), , insert method. way, same way immutable hmap implemented in shapeless.
import scala.collection.mutable.map class hmapbuilder[r[_, _]] { // constructor arity 2 def apply[k1, v1](e1: (k1, v1))(implicit ev1: r[k1, v1]) = new hmap[r](map(e1)) def apply[k1, v1, k2, v2](e1: (k1, v1), e2: (k2, v2)) (implicit ev1: r[k1, v1], ev2: r[k2, v2]) = new hmap[r](map(e1, e2)) } so constructor of our map. evidences statically check types of inserting data. next, lets wrap default scala collection:
class hmap[r[_, _]](underlying : map[any, any] = map.empty) { def get[k, v](k : k)(implicit ev : r[k, v]) : option[v] = underlying.get(k).asinstanceof[option[v]] def +=[k, v](kv : (k, v))(implicit ev : r[k, v]) : hmap[r] = { underlying += kv } def -=[k](k : k) : hmap[r] = { underlying -= k } override def tostring = underlying.tostring } finally wrapping hmapbuilder, make pleasant constructor:
object hmap { def apply[r[_, _]] = new hmapbuilder[r] def empty[r[_, _]] = new hmap[r] def empty[r[_, _]](underlying : map[any, any]) = new hmap[r](underlying) } in result, usage similar shapeless hmap:
class mapping[k, v] implicit def mappingfromclass[a] = new mapping[class[a], a] val hm = hmap[mapping](classof[int] -> 5) // ok hm += (classof[string] -> "string") // ok hm += (classof[boolean] -> false) // ok hm += (classof[double] -> "sss") // compile fail works expected. implemented insert , remove functions, other functions possible define same way.
Comments
Post a Comment