Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataCache trait doesn't allow to use bounds and typeclasses on keys and values #602

Open
DenisNovac opened this issue Feb 4, 2022 · 1 comment

Comments

@DenisNovac
Copy link

DenisNovac commented Feb 4, 2022

Hi everyone. I am having troubles using this trait:

trait DataCache[F[_]] {
  def lookup[I, A](i: I, data: Data[I, A]): F[Option[A]]

  def insert[I, A](i: I, v: A, data: Data[I, A]): F[DataCache[F]]
}

I want to use it with some underlying Cache[F[_], K:Hash, V] where K is my key and have implementation of cats' Hash. The problem is i can't do something like this:

class MyFetchCache[F[_], K: Hash, V](underlying: Cache[F, K, V]) extends DataCache[F] {
  def lookup[I, A](i: I, data: Data[I, A]): F[Option[A]] = underlying.put(i) // need to cast
  def insert[I, A](i: I, v: A, data: Data[I, A]): F[DataCache[F]] = underlying.put(i, v) // need to cast
}
class MyFetchCache[F[_], K, V](underlying: Cache[F, K, V]) extends DataCache[F] {
  def lookup[I: Hash, A](i: I, data: Data[I, A]): F[Option[A]] = underlying.get(i) // doesn't apply to interface
  def insert[I: Hash, A](i: I, v: A, data: Data[I, A]): F[DataCache[F]] = underlying.put(i, v) // doesn't apply to interface
}

I believe that my best option is to do something like this:

trait Data[I, A] 

class MyData[I: Hash, A] extends Data[I, A] {
   def hash(i: I) = Hash[I].hash(i)
}

class MyFetchCache[F[_], V](underlying: Cache[F, String, V]) extends DataCache[F] {
  def lookup[I, A](i: I, data: Data[I, A]): F[Option[A]] = {
   data match {
      case md: MyData => underlying.get(md.hash(i))
    }
  }
}

And even like this it seems that i'll need a lot of asInstanceOf casts.

@sloshy
Copy link
Contributor

sloshy commented Feb 16, 2022

Hello, can you please share the exact compiler messages you are getting when trying to implement this? I'm having trouble seeing the source of the issue. The third block of code won't work as you can't change the interface, so that makes sense, but what is your return value from calling underlying.get/put? If the result value isn't the same, then yes you'll want to do some conversion or wrapping perhaps, depending on the type. Your second example should be a good starting point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants