Определение бесформенного заменителя

Интересно, как я могу исправить этот код Scala с помощью библиотеки Shapeless, чтобы он компилировался:

object boo {

  import shapeless._

  sealed trait Bibby
  case class LittleBibby(i: Int) extends Bibby
  case class BigBibby(s: String) extends Bibby
  type Bibbies = LittleBibby :: BigBibby :: HNil

  val defaultBibbies: Bibbies = LittleBibby(1) :: BigBibby("beep") :: HNil

  def update(b: Bibby, bibbies: Bibbies) : Bibbies = bibbies.updatedElem(b)

  val demo: Bibbies = update(LittleBibby(3), defaultBibbies)

}

Я получаю следующее сообщение об ошибке:

could not find implicit value for parameter replacer:shapeless.Replacer[boo.Bibbies,boo.Bibby,boo.Bibby]
def update(b: Bibby, bibbies: Bibbies) : Bibbies = bibbies.updatedElem(b)

Я пытался просмотреть бесформенный исходный код, чтобы найти решение для создания отсутствующего неявного Replacer, но безрезультатно :/


person ahjohannessen    schedule 05.02.2014    source источник


Ответы (2)


Для shapeless.Replacer информация о фактическом типе элемента должна быть доступна во время компиляции. В Bibbies нет элемента типа Bibby, поэтому заменять нечем.

Вы должны использовать общий тип для b, а также вы должны добавить необходимый Replacer[Bibbies, B, B] в качестве неявного параметра, например:

def update[B <: Bibby](b: B, bibbies: Bibbies)(implicit r: Replacer[Bibbies, B, B]) =
  bibbies.updatedElem(b)

update(LittleBibby(3), defaultBibbies)
// LittleBibby(3) :: BigBibby(beep) :: HNil
person senia    schedule 05.02.2014

Вы отбросили информацию о том, является ли бибби маленьким или большим бибби:

def update(b: Bibby, bibbies: Bibbies) : Bibbies

Я понятия не имею, будет ли этого достаточно, но я бы начал с сохранения типа bibby:

def update[T <: Bibby](b: T, bibbies: Bibbies) : Bibbies

Затем вы должны добавить неявный параметр Replacer (как запрашивает сообщение об ошибке):

def update[T <: Bibby](b: T, bibbies: Bibbies)
                      (implicit ev: Replacer[Bibbies, T, T]): Bibbies
person Daniel C. Sobral    schedule 05.02.2014
comment
на самом деле вся необходимая информация содержится в сообщении об ошибке: for parameter replacer:shapeless.Replacer[boo.Bibbies,boo.Bibby,boo.Bibby]. - person senia; 05.02.2014
comment
@senia Да, но я понял это только тогда, когда переформатировал сообщение об ошибке. - person Daniel C. Sobral; 05.02.2014
comment
@DanielC.Sobral - Это означает, что если я использую обновление вместе с получением актера, мне нужно что-то вроде (в любом случае): def update : (Bibby ⇒ Bibbies) = { case lb: LittleBibby ⇒ update(lb, defaultBibbies) case bb: BigBibby ⇒ update(bb, defaultBibbies) } - person ahjohannessen; 06.02.2014
comment
@DanielC.Sobral — Вариант использования может быть примерно таким: def updated : ((Bibby, Bibbies) ⇒ Bibbies) = (b, bs) ⇒ b match { case lb: LittleBibby ⇒ update(lb, bs) case bb: BigBibby ⇒ update(bb, bs) } У меня есть несколько рабочих акторов, которых просят выполнить некоторую работу, и каждый отвечает экземпляром Bibby — таким образом, я начинаю с defaultBibbies, а с помощью context.become я могу запускать запросы и в конечном итоге строить до результата Bibbies, который передается инициирующему главному актеру. - person ahjohannessen; 06.02.2014
comment
@ahjohannessen В значительной степени. Актеры стирают информацию о типе, поэтому они противоречат строго типизированному коду, такому как Shapeless, который полагается на тип, который можно определить во время компиляции. - person Daniel C. Sobral; 06.02.2014