Representable
представляют собой контейнероподобные функторы, которые имеют «особые отношения» с другим типом, который служит индексом в Representable
. В определении Haskell этот тип индекса задается соответствующим семейством типов type Rep f :: *
.
Для каждого значения индекса и для каждого значения Representable
мы можем вызвать функцию index :: f a -> Rep f -> a
, чтобы получить соответствующий элемент. И tabulate :: (Rep f -> a) -> f a
создает контейнер, в котором каждый элемент является производным от своего собственного индекса.
А теперь пример НЕпредставимого функтора: типичный список Haskell типа []
. Можно наивно подумать, что его можно проиндексировать чем-то вроде Natural
, но проблема в том, что списки могут быть пустыми или содержать недостаточно элементов для достижения заданного индекса.
Всегда бесконечный тип, такой как data Stream a = Stream a (Stream a)
, является Representable
и индексируется Natural
, потому что всегда будет значение для любого заданного Natural
, которое мы передаем в index
.
Точно так же однородная пара data Pair a = Pair a a
индексируется типом Bool
: индекс говорит нам, какой из компонентов выбрать.
Если мы получим зависимость, исправлено- векторы размеров равны Representable
и индексируются конечные натуральные числа, ограниченные размером вектора. Они не индексируются неограниченными Natural
s, потому что тогда у нас может быть доступ за пределами границ!
Чтение различных экземпляров, определенных для Representable
, поучительно, но, похоже, нам нужно перейти к исходному коду, потому что связанные типы не видны в Haddocks. Некоторые интересные мелочи:
Функтор Identity
индексируется типом модуля ()
, это имеет смысл, потому что Identity
имеет, так сказать, только один «слот», поэтому нам не нужно предоставлять какую-либо информацию.
Тип "функции из некоторого типа" ((->) e)
индексируется самим исходным типом. А index
это просто id
. Это то, что подразумевается под «изоморфной монаде читателя», потому что монада Reader e
является просто новым типом над ((->) e)
.
Composition
( вложенность) двух представимых функторов снова равна Representable
, и он индексируется парой исходных индексов! В этом есть смысл: сначала мы должны знать, как индексировать во внешний функтор, а затем во внутренний.
Product
( пары) двух функторов Representable
индексируется суммой (Either
) исходных индексов. Ветка Either
говорит нам, в какую часть продукта индексировать.
Заметное упущение (потому что в общем случае это неверно): экземпляра (Representable f, Representable g) => Representable (Sum f g)
нет.
person
danidiaz
schedule
19.01.2019