Скажем, что Предикат является функцией A => Boolean, я хочу реализовать экземпляр класса типа Cats "Contravariant Functor" для предикатов. У меня также есть неявный класс PredicateOps, который определяет операторы объединения и пересечения для предикатов.
Мне удалось заставить экземпляр работать, используя псевдоним типа:
type Predicate[A] = A => Boolean
implicit val predicateContra = new Contravariant[Predicate] {
override def contramap[A, B](fa: Predicate[A])(f: B => A): Predicate[B] =
(b: B) => fa(f(b))
}
Но когда Я делаю это, я должен привести все свои предикатные функции к псевдониму, подобному следующему:
val even: Predicate[Int] = (i: Int) => i % 2 == 0
, что меня раздражает. Поэтому я подумал, можно ли вместо использования псевдонима типа определить предикат Contra непосредственно для Function1 из переменной типа A в Boolean, но я не смог заставить его работать. Обе следующие идеи дают мне ошибку компилятора:
implicit val predicateContra = new Contravariant[Function1[_, Boolean]] {
// "Function1[_, Boolean] takes no type parameters, expected: one"
implicit def predicateContra[A] = new Contravariant[Function1[A, Boolean]] {
// "A => Boolean takes no type parameters, expected: one"
Как я могу сказать компилятору, что первый параметр моего Function1 должен оставаться «дырой», в то время как второй должен быть зафиксирован как boolean? Это вообще возможно? Просматривая исходный код для кошек, я обнаружил звездочки в качестве параметров типа в нескольких местах, но это тоже не сработало для меня.