Составление функций уровня типа с неявными свидетелями
Я экспериментирую с довольно сложными вычислениями на уровне типов. Там у меня есть несколько типов тегов (скажем, 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 }