https://kotlinlang.org logo
#announcements
Title
# announcements
r

Ran Magen

01/03/2020, 7:29 PM
Hey, is there a common pattern in Kotlin to replace what you'd otherwise do with type classes in Scala? As an example, let's say I have this function, let's assume I can't change the various
T
types that are used when invoking this:
Copy code
fun <T> createFetcher(name: String, underlying: DataFetchingEnvironment.() -> T): NamedFetcher[T] { .. }
Now I decide I want to be able to wrap it with some caching. For that I need to ensure T has a codec to/from bytes. In Scala I would use a type class, e.g.:
Copy code
trait Codec[T] {
  def encode(t: T): ByteArray
  def decode(bytes: ByteArray): T
}
and then implement the wrapper such that
T
must have a corresponding concrete
Codec[T]
, e.g.
Copy code
class Cache[T: Codec] {
  def putIfAbsent(key: String, value: T): T = { val encoded = implicitly[Codec[T]].encode(value); bytesCache.putIfAbsent(...); value }
}

def createFetcher[T: Codec](name: String, underlying: DataFetchingEnvironment.() -> T, key: DataFetchingEnvironment.() -> String): NamedFetcher[T] = { 
  val env = makeEnv(name)
  cache.putIfAbsent(key(env)) { underlying(env) }
}
h

Hanno

01/04/2020, 12:12 PM
I would make the cache a constructor parameter of a special implementation of fetcher. But from then on your best bet is to have T: Encodeable or sth because you currently have nothing like typeclasses.
I hope your second sentence doesn't mean that you cant introduce a type bound as well
Other option would be to accept another parameter in the factory (maybe optional) that is your encoder. Your user has to pass in a encoder instance by hand then, which would make it the only thing that's different from your scala example
For known T you could then provide an overload with default parameters for encoder, but i don't know if that makes sense in your scenario
2 Views