Scala Typeclasses with generics -
i've been playing typeclass pattern in scala, haven't been able figure out how implement implicit companion object when type i'm working generic.
for example, let's i've defined trait typeclass provides functions putting things box
es.
case class box[a](value: a) trait boxer[a] { def box(instance: a): box[a] def unbox(box: box[a]): } implicit object intboxer extends boxer[int] { def box(instance: int) = box(instance) def unbox(box: box[int]) = box.value } def box[a : boxer](value: a) = implicitly[boxer[a]].box(value) def unbox[a : boxer](box: box[a]) = implicitly[boxer[a]].unbox(box)
this works expected, allowing me provide implementations of boxer
various types. however, have no idea how when type wish act on generic itself. let's wanted able use boxer
on seq[a]
. object
s in scala cannot include type parameters, i'm @ loss go:
// not compile - object cannot have type arguments implicit object seqboxer[a] extends boxer[seq[a]] { ... } // not compile - 'a' unrecognized implicit object seqboxer extends boxer[seq[a]] { ... } // compiles fails on execution, doesn't implement implicit // conversion _specific_ instances of seq implicit object seqboxer extends boxer[seq[_]] { def box(instance: seq[_]) = box(instance) def unbox(box: box[seq[_]]) = box.value } // not compile - doesn't technically implement boxer[seq[_]] implicit object seqboxer extends boxer[seq[_]] { def box[a](instance: seq[a]) = box(instance) def unbox[a](box: box[seq[a]]) = box.value } // compiles, won't resolve 'implicitly[boxer[seq[foo]]]' // had high hopes one, :( implicit def seqboxer[a]() = new boxer[seq[a]] { def box(instance: seq[a]) = box(instance) def unbox(box: box[seq[a]]) = box.value }
is there way support implicit conversions of generic types without having implicit separate object each internal type?
you're close, actually. need remove parentheses seqboxer[a]
. otherwise, compiler sees implicit conversion () => boxer[seq[a]]
, rather available implicit boxer[seq[a]]
. measure, idea make return type of implicit method explicit.
implicit def seqboxer[a]: boxer[seq[a]] = new boxer[seq[a]] { def box(instance: seq[a]) = box(instance) def unbox(box: box[seq[a]]) = box.value } scala> box(seq(1, 2, 3)) res16: box[seq[int]] = box(list(1, 2, 3))
you can use same approach create generic boxer[a]
a
, should required behave same way.
implicit def boxer[a]: boxer[a] = new boxer[a] { def box(instance: a): box[a] = box(instance) def unbox(box: box[a]): = box.value } scala> box("abc") res19: box[string] = box(abc) scala> box(list(1, 2, 3)) res20: box[list[int]] = box(list(1, 2, 3)) scala> unbox(res20) res22: list[int] = list(1, 2, 3) scala> box(false) res23: box[boolean] = box(false)
Comments
Post a Comment