Составление функций уровня типа с неявными свидетелями

Я экспериментирую с довольно сложными вычислениями на уровне типов. Там у меня есть несколько типов тегов (скажем, A, B, а также C) и работающие над ними функции, которые представлены неявными свидетелями с зависимыми от пути типами результатов:

class A
class B
class C

trait F1[T] { type result }
trait F2[T] { type result }

implicit object f1OfA extends F1[A] { type result = B }
implicit object f2OfB extends F2[B] { type result = C }

trait Composed[T] { type result }

В ходе расчетов при "внедрении" ComposedМне нужно использовать тот факт, что я могу, учитывая приведенный выше код, в принципе преобразовать A в C (в этом примере мне просто нужна композиция, но на самом деле в нее вовлечено больше вещей).

Тем не менее, я не знаю, как выразить композицию, так как я всегда ограничен ограничением, что импликации не применяются транзитивно; следующий код завершается с ошибкой "неявный не найден":

implicit def composed1[X](implicit f2DotF1OfX: F2[F1[X]]): Composed[X] =  
  new Composed[X] { type result = f2DotF1OfX.result }

implicitly[Composed[C]]

Сначала я попытался написать следующее:

implicit def composed2[X](implicit f1OfX: F1[X], f2OfLast: F2[f1OfX.result]): Composed[X] =
  new Composed[X] { type result = f2OfLast.result }

Это, конечно, не удалось, потому что там я использовал f1OfLast в том же списке параметров это определено. Если бы это был неявный параметр, я мог бы написать

implicit def composed3a[X](f1OfX: F1[X])(f2OfLast: F2[f1OfX.result]): Composed[X] =
   new Composed[X] { type result = f2OfLast.result }

Но это невозможно сделать с помощью двух неявных списков параметров, поскольку они запрещены языком.


Короче говоря: как я могу получить свидетельство для F2[F1[X]] в приведенных выше примерах? При необходимости я мог бы также изменить способ написания функций уровня типа, но я пока не нашел другого способа выразить их.

1 ответ

Решение

Вы используете другой параметр типа и затем требуете f1OfX.result быть таким:

implicit def composed4[X, Y](implicit f1OfX: F1[X] { type result = Y },
  f2OfLast: F2[Y]): Composed[X] =
    new Composed[X] { type result = f2OfLast.result }
Другие вопросы по тегам