Что такое индексированный функтор в Haskell и каковы его обычаи?

При изучении функторов в Haskell я придумал тип функтора Functor.Indexed. Этот функтор определяет операцию, называемую imap. Я не понял его определения и imap подпись: imap :: (a -> b) -> f j k a -> f j k b. Я попытался найти это формальное определение и нашел только это: http://ncatlab.org/nlab/show/indexed+functor. Но мне это действительно не помогло. Так может кто-то прояснить в более простых словах этот тип функтора и в каких случаях я должен его использовать? Спасибо.

Ответы

Ответ 1

Индексированным функтором является использование spaceuitburritoesque формулировки "контейнер, который также содержит отображение". То есть значение f j k a будет содержать "некоторый тип морфизма (s) j -> k (не обязательно функции, могут быть более общие стрелки) а также значения типа a.

Для этих значений a контейнер является функтором очевидным образом. На самом деле класс IxFunctor сам по себе довольно скучный -

instance IxFunctor f

в основном совпадает с

instance Functor (f j k)

Теперь, когда это становится интересным, вы рассматриваете более конкретные классы функторов. Эта монада на самом деле не находится в модуле Indexed, но я думаю, что это делает точку лучше:

class IxPointed f => IxMonad f where
  ijoin :: m j k (m k l a) -> m j l a

сравните это бок о бок:

(>>>) ::  (j->k) -> (k->l)   ->   j->l
ijoin :: m j  k   (m k  l a) -> m j  l a
join  :: m        (m      a) -> m      a

Итак, что мы делаем, присоединяясь к "контейнерным слоям", мы составляем морфизмы.

Очевидным примером является IxState. Вспомните стандартную монаду штата

newtype State s a = State { runState :: s -> (a, s) }

Это, когда используется в качестве монады, просто составляет аспект функции s -> s:

  join (State f) = State $ \s -> let (State f', s') = f s in f' s'

чтобы вы сначала передали состояние через f, затем через f'. Ну, действительно нет причин, по которым нам нужно, чтобы все государства имели один и тот же тип, верно? В конце концов, промежуточное состояние просто переходит к следующему действию. Здесь индексированная монада состояний,

newtype IxState i j a = IxState { runIxState :: i -> (a, j) }

Он делает именно это:

  ijoin (IxState f) = IxState $ \s -> let (IxState f', s') = f s in f' s'