Использование границ контекста «отрицательно», чтобы гарантировать, что экземпляр класса типа отсутствует в области видимости

ТЛ; др: Как мне сделать что-то вроде приведенного ниже кода:

def notFunctor[M[_] : Not[Functor]](m: M[_]) = s"$m is not a functor"

''Not[Functor]Будучи здесь вычурной частью.

Я хочу, чтобы это успешно, когда "м" при условии, что это не Functor, в противном случае произойдет сбой компилятора.

решаемая: пропустите остальную часть вопроса и перейдите прямо к ответу ниже.

Что я'я пытаюсь достичь, грубо говоря, "отрицательное доказательство ".

Псевдокод будет выглядеть примерно так:

// type class for obtaining serialization size in bytes.
trait SizeOf[A] { def sizeOf(a: A): Long }

// type class specialized for types whose size may vary between instances
trait VarSizeOf[A] extends SizeOf[A]

// type class specialized for types whose elements share the same size (e.g. Int)
trait FixedSizeOf[A] extends SizeOf[A] {
  def fixedSize: Long
  def sizeOf(a: A) = fixedSize
}

// SizeOf for container with fixed-sized elements and Length (using scalaz.Length)
implicit def fixedSizeOf[T[_] : Length, A : FixedSizeOf] = new VarSizeOf[T[A]] {
  def sizeOf(as: T[A]) = ... // length(as) * sizeOf[A]
}

// SizeOf for container with scalaz.Foldable, and elements with VarSizeOf
implicit def foldSizeOf[T[_] : Foldable, A : SizeOf] = new VarSizeOf[T[A]] {
  def sizeOf(as: T[A]) = ... // foldMap(a => sizeOf(a))
}

Имейте в виду, чтоfixedSizeOf() предпочтительнее, когда это уместно, поскольку это спасает нас от обхода коллекции.

Таким образом, для типов контейнеров, где толькоLength определяется (но неFoldable) и для элементов, гдеFixedSizeOf определяется, мы получаем улучшенную производительность.

В остальных случаях мы просматриваем коллекцию и суммируем индивидуальные размеры.

Моя проблема в тех случаях, когда обаLength а такжеFoldable определены для контейнера, иFixedSizeOf определяется для элементов. Это очень распространенный случай (например,List[Int] как определили).

Пример:

scala> implicitly[SizeOf[List[Int]]].sizeOf(List(1,2,3))
:24: error: ambiguous implicit values:
 both method foldSizeOf of type [T[_], A](implicit evidence$1: scalaz.Foldable[T], implicit evidence$2: SizeOf[A])VarSizeOf[T[A]]
 and method fixedSizeOf of type [T[_], A](implicit evidence$1: scalaz.Length[T], implicit evidence$2: FixedSizeOf[A])VarSizeOf[T[A]]
 match expected type SizeOf[List[Int]]
              implicitly[SizeOf[List[Int]]].sizeOf(List(1,2,3))

Я хотел бы иметь возможность полагаться наFoldable Тип класса только когда +LengthFixedSizeOf комбинация не применяется.

Для этой цели я могу изменить определениеfoldSizeOf() принятьVarSizeOf элементы:

implicit def foldSizeOfVar[T[_] : Foldable, A : VarSizeOf] = // ...

И теперь мы должны заполнить проблемную часть, которая охватываетFoldable контейнеры сFixedSizeOf элементы инетLength определенный, Я'Я не уверен, как подойти к этому, но псевдокод будет выглядеть примерно так:

implicit def foldSizeOfFixed[T[_] : Foldable : Not[Length], A : FixedSizeOf] = // ...

''Not[Length]очевидно, будучи здесь выдуманной частью.

Частичные решения, о которых я знаю

1) Определите класс для последствий с низким приоритетом и расширьте его, как показано в ''object Predef extends LowPriorityImplicits, Последнее неявное (foldSizeOfFixed()) может быть определен в родительском классе и будет переопределен альтернативой из класса-потомка.

Я не заинтересован в этом варианте, потому что яя хотел бы в конечном итоге иметь возможность поддерживать рекурсивное использованиеSizeOf, и это не позволит неявному базовому классу с низким приоритетом полагаться на таковые в подклассе (верно ли мое понимание здесь? РЕДАКТИРОВАТЬ: неправильно! неявный поиск работает из контекста подкласса, это жизнеспособное решение!)

2) Более грубый подход опирается наOption[TypeClass] (например.,:Option[Length[List]], Несколько из них, и я могу просто написать одну большую неявное, что выбираетFoldable а такжеSizeOf как обязательный иLength а такжеFixedSizeOf как необязательный, и полагается на последнее, если они доступны. (источник:Вот)

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

РЕДАКТИРОВАТЬ: Это лучшее, что я смог получить с дополнительными последствиями. Это'Там еще нет:

implicit def optionalTypeClass[TC](implicit tc: TC = null) = Option(tc)
type OptionalLength[T[_]] = Option[Length[T]]
type OptionalFixedSizeOf[T[_]] = Option[FixedSizeOf[T]]

implicit def sizeOfContainer[
    T[_] : Foldable : OptionalLength,
    A : SizeOf : OptionalFixedSizeOf]: SizeOf[T[A]] = new SizeOf[T[A]] {
  def sizeOf(as: T[A]) = {

    // optionally calculate using Length + FixedSizeOf is possible
    val fixedLength = for {
      lengthOf 

Ответы на вопрос(1)

Ваш ответ на вопрос