Я люблю mapped
из пакета объективов.
mapped :: Prelude.Functor f => Setter (f a) (f b) a b
Однако недавно я начал использовать Functor
из пакета категорий (из здесь я буду ссылаться на Functor
категории так же, как Functor
и использовать Prelude.Functor
в противном случае), поэтому мой mapped
больше не работает.
Так что я хотел бы сделать версию mapped
это может работать с Functor
. В качестве освежающего напитка для всех, кому это нужно, вид подписи Functor
выглядит следующим образом:
class (Category s, Category t) => Functor (s :: α -> α -> *) (t :: β -> β -> *) (f :: α -> β) where
map :: s a b -> t (f a) (f b)
Это займет два из (->)
в ванили fmap
и заменит их на s
и t
, которые удовлетворяют Category
.
Так что, если мы хотим сделать замену для mapped
, нам нужно заменить соответствующие (->)
универсальными c Category
удовлетворяющими типами. Итак, мы имеем дело с Setter
:
mapped ::
Prelude.Functor f =>
( forall g. Settable g =>
(a -> g b) -> (f a) -> g (f b)
)
Чтобы двигаться вперед, мы посмотрим на over
, так как мы хотели бы, чтобы это было:
over mapped = map
Сейчас мы рассмотрим реализацию over
(распаковка ASetter
):
over :: ((a -> Identity b) -> s -> Identity t) -> (a -> b) -> s -> t
over l f = runIdentity #. l (Identity #. f)
Мы можем получить немного информации из этого. Мы знаем типы runIdentity
, (#.)
и цель. Если мы работаем задом наперед
(#.) runIdentity (mapped (Identity #. f)) ::
Category t => t (f a) (f b)
mapped (Identity #. f) ::
( Category t
, Profunctor t
, Coercible (f b) z
)
=> t (f a) z
, что является хорошим доказательством того, что третий (->)
должен быть заменен общей категорией c, и приличным доказательством того, что второе не должно.
mapped ::
( Functor s t f
, Category s
, Category t
) =>
( forall g. Settable g =>
(s a (g b)) -> t (f a) (g (f b))
)
И вот я застрял. Я чувствую, как будто я прижимаюсь к моей концептуальной поддержке здесь. Я не знаю, является ли этот тип правильным или я что-то упускаю. Даже если бы я знал тип, я не уверен, как бы я реализовал mapped
или over
. Я привык использовать готовые комбинаторы из комплекта линз для изготовления моих линз, и я не думаю, что они помогут мне, когда я перестану использовать Setter
.
Как мне добраться оттуда до работающей mapped
реализации для Functor
?