У вас есть ваши перестановки, это все. Оптика, описанная там все формы
type Foo s t a b = forall f. SomeConstraints f => (a -> f b)-> (s -> f t)
Малая выдумка, призмы, что он должен работать с произвольным Choice
profunctor, но ->
является своим родом канонического примера такой структуры, чтобы мы могли специализироваться призмами чтобы работать только через этих профилакторов. Причина, почему этот процесс является законным идентичен тому, что мы будем делать с f
так приостановить неверия на минуту и читать на
Теперь, если мы создаем s
и t
, как a
и a
и b
как b
то получить
forall f. SomeConstraints f => (b -> f b) -> (a -> f a)
Теперь это означает, что если у нас есть некоторые оптические, как линзы, призмы, или обход, мы можем создать экземпляр его параметры типа, так что это почти в виде Handler
. Единственное отличие - наш гарантированно работает на любой f
при условии, что он удовлетворяет ограничениям, которые мы выбрали. Если мы знаем, что Constant (Endo x)
удовлетворяет этим ограничениям, то мы можем бесшумно специализировать эту оптику для работы только с этим f
. Это просто старая полиморфная инстанция! А так как Constant a
- это Functor
и Applicative
, он будет работать с любыми объективами или обходными дорожками. Этот неявный подтипирование и создание экземпляров лежат в основе создания пакета объективов, оставляя все эти вещи прозрачными. Haskell позволяет нам смешивать и сопоставлять абстракции, и он автоматически остановится на «самой большой нижней границе» любого набора оптики, который мы с помощью.
Все это сводится к тому, что в Haskell, если мы имеем e :: forall t. T
, то для любого соответствующего kinded tau
мы также имеем e :: [tau/t]T
. Есть несколько морщин, когда мы бросаем ограничения типов, но, во всяком случае, все дело в том, что в Haskell по умолчанию используется тиковое приложение.