Как использовать shapeless для абстрагирования клиента репозитория в универсальный модуль репозитория c - PullRequest
0 голосов
/ 11 апреля 2020

Я пытаюсь написать универсальный c модуль хранилища, который может обрабатывать различное количество ключей

  trait Repo[K, V] {
    def read(key: K): V
  }
trait DynamoDBRepo extends Repo[K,V]{

def aRepo[K:StringIdentifiable,V]() = new Repo[K,V]{

  val dynamoDBClient = ???

  override def read(key: K, tableName: String): V =  { 

  val tableKey: String = implicitly[StringIdentifiable].identify(key)

  dynamoDBClient.Table(tableName).get(tableKey)  //(*)
 }  
}

}

@typeclass trait StringIdentifiable[M] {
  def identify(id: M): String
}

(*) Однако, dynamoDBClient.Table(tableName).get(key) может также взять кортеж в качестве ключа (ключ раздела и ключ сортировки).

Поэтому я хочу каким-то образом извлечь String из K или (String, String) из (K, K) из ключа: K override def read(key: K)

Сначала я попытался this для извлечения типов из кортежа, который реализует класс типов StringIdentifiable. Я застрял.

Затем попытался переписать класс типа StringIdentifiable, который возвращал бы String, когда аргумент был одним ключом, но (String, String), когда аргумент для чтения был кортежем , Но я не смог использовать этот метод либо .

Как я могу решить его проблему, не потеряв при этом свою абстракцию

1 Ответ

2 голосов
/ 11 апреля 2020

Если требования этого вопроса - это все требования, которым должно соответствовать ваше решение, то бесформенные, зависящие от пути типы и классы типов вообще не нужны.

sealed trait RepoKey[K] // TBH I am not sure if genericness here is even needed in your case...
case class SimpleKey(key: K) extends RepoKey[K]
case class PartitionedKey(partition: K, key: K) extends RepoKey[K]

trait Repo[K, V] {
  def read(key: RepoKey[K]): V
}

class DynamoDBRepo(dynamoDBClient: ...) extends Repo[String, V] {

  def read(key: RepoKey[String]): V = key match { 
    case SimpleKey(key)                 => ...
    case PartitionedKey(partition, key) => ...
  }
}

Даже если вы храните ключ как нечто кроме String, единственный класс типов, который вам понадобится, будет выглядеть примерно так:

trait KeyExtractor[K] {
  def extract(key: RepoKey[K]): String
}

, который почти наверняка не потребует деривации, но одно явное определение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...