Ответ 1
Итак, если f
и g
являются правильными функторами, forall a. f a -> g a
является естественным преобразованием. Мы могли бы сделать это немного красивее:
type f ~> g = forall a. f a -> g a
Естественные преобразования, подобные этому, образуют категорию Haskell Functors, так что у вас есть функтор от этого к какой-либо другой категории.
Следуя шагам нормальных Haskell Functors, возможно, имеет смысл иметь x
быть endofunctor, отображая Функторы для других Функторов. Это похоже, но не идентично тому, что у вас есть:
class FFunctor x where
ffmap :: (f ~> g) -> (x f ~> x g)
Однако в вашем случае x f
и x g
не являются функторами, а x f -> x g
является нормальной функцией, а не естественным преобразованием. Тем не менее, шаблон достаточно близок, чтобы быть интригующим.
Имея это в виду, кажется, что x
все еще является примером функтора, только между двумя разными категориями. Он относится к категории Функторов к категории x
с различными структурами. Каждый возможный x
, например Foo
, формирует категорию с объектами типа Foo []
и Foo Maybe
и преобразования между ними (Foo [] -> Foo Maybe
). Ваша функция interleaveHomomorphism
"поднимет" естественные преобразования в эти x-morphisms
, точно так же, как fmap
"поднимет" нормальные (a -> b
) функции в функции на изображении функтора (f a -> f b
).
Итак, да: ваш typeclass - это функтор, как Functor
, за исключением двух разных категорий. Я не знаю конкретного имени для него, в основном потому, что я не знаю конкретного имени для конструкций вроде x
.
В более общем плане, я даже не уверен, что конкретное имя имеет смысл. На данный момент нам, вероятно, понравится классный класс-класс, который будет проходить между любыми двумя категориями. Может быть, что-то вроде:
class (Category catA, Category catB) => GFunctor f catA catB where
gfmap :: catA a b -> catB (f a) (f b)
Возможно, это уже существует в библиотеке.
К сожалению, этот конкретный подход к определению различных функторов потребует кучу дополнительного шума нового типа, поскольку (->)
уже является категорией. Фактически, получение всех типов для правильного выравнивания будет немного больным.
Так что, наверное, проще всего назвать это XFunctor
или что-то еще. Кроме того, представьте себе потенциал каста!
EDIT: похоже, что categories
предоставляет тип CFunctor
, но немного умнее:
class (Category r, Category s) => CFunctor f r s | f r -> s, f s -> r where
cmap :: r a b -> s (f a) (f b)
Однако я не уверен, что даже это достаточно общее! Я думаю, что мы могли бы хотеть, чтобы он был более полиморфным по видам.