Общий способ обеспечения неявного определения всегда имеет более высокий / низкий приоритет - PullRequest
2 голосов
/ 14 февраля 2020

У меня сложная ситуация с типом классов в следующем формате:

sealed trait TypeClass[S <: MyType] {
  type Out <: MyType
}

sealed trait LowPriorityTypeClass {
  // Case: OtherTypeClass is NOT defined for the input type S.
  // The output type is the same as the input type.
  implicit def default[S <: MyType]: TypeClass.Aux[S, S] = ???
}

object TypeClass extends LowPriorityTypeClass {
  type Aux[S <: MyType, O <: MyType] = TypeClass[S] { type Out = O }

  // Case: OtherTypeClass is defined for the input type S.
  // The output type is the same as in the OtherTypeClass definition.
  implicit def hasOtherTC[S <: MyType, O <: MyType](
    implicit otherTC: OtherTypeClass.Aux[S, O],
  ): TypeClass.Aux[S, O] = ???
}

Определение default было добавлено в черту LowPriorityTypeClass с намерением иметь более низкий приоритет. Однако неоднозначность с hasOtherTC все еще имеет место для некоторого типа S, очевидно, потому что объявление default более конкретно c, чем объявление hasOtherTC для этого типа S.

Существует ли общий способ гарантировать, что неявное определение всегда будет иметь более высокий / более низкий приоритет, чем другое определение? (Мой вопрос не относится к указанному выше c коду.)

Дайте мне знать, поможет ли размещение более полного примера кода.

1 Ответ

3 голосов
/ 14 февраля 2020

Пожалуйста, см. Почему происходит неявная неоднозначность? , включая комментарии.

В этом случае нет смысла вводить черту LowPriorityTypeClass, потому что в любом случае неявная default более конкретна c чем hasOtherTC.

Нет общего пути. Вы можете использовать классы типов Not (shapeless.Refute, implicitbox.Not) или shapeless.LowPriority, implicitbox.Priority или библиотека https://github.com/milessabin/export-hook.

object TypeClass {
  type Aux[S <: MyType, O <: MyType] = TypeClass[S] {type Out = O}

  implicit def hasOtherTC[S <: MyType, O <: MyType](implicit
                                                    otherTC: OtherTypeClass.Aux[S, O]
                                                   ): TypeClass.Aux[S, O] = ???

  implicit def default[S <: MyType](implicit 
                                    noOtherTC: Refute[OtherTypeClass[S]]
                                   ): TypeClass.Aux[S, S] = ???
}
...