因此,假设f
和g
是适当的函子,forall a. f a -> g a
是一种自然的转换。我们可以让它更漂亮一点:
type f ~> g = forall a. f a -> g a
像这样的自然转换让我们形成了一个 Haskell 函子类别,所以你所拥有的是一个从那个类别到其他类别的函子。
按照普通 Haskell Functor 的步骤,拥有x
一个 endofunctor,将 Functor 映射到其他 Functor 可能是有意义的。这与您所拥有的相似但不完全相同:
class FFunctor x where
ffmap :: (f ~> g) -> (x f ~> x g)
但是,在您的情况下x f
,并且x g
不是函子,x f -> x g
而是正常的函数而不是自然的转换。尽管如此,该模式仍然足够接近以引起人们的兴趣。
考虑到这一点,它似乎x
仍然是函子的一个例子,只是在两个不同的类别之间。它从 Functors 的范畴到x
具有不同结构的 s 的范畴。每个可能的x
, likeFoo
形成一个类别,其中包含对象 likeFoo []
和Foo Maybe
以及它们之间的转换 ( Foo [] -> Foo Maybe
)。您的interleaveHomomorphism
函数将自然变换“提升”为这些x-morphisms
,就像fmap
将普通 ( a -> b
) 函数“提升”为仿函数 ( f a -> f b
) 中的函数一样。
所以是的:你的类型类是一个仿函数,就像Functor
,除了在两个不同的类别之间。我不知道它的具体名称,主要是因为我不知道像x
.
更一般地说,我什至不确定一个特定的名字是否有意义。在这一点上,我们可能想要一个很好的泛型函子类型类,它可以介于任何两个类别之间。也许是这样的:
class (Category catA, Category catB) => GFunctor f catA catB where
gfmap :: catA a b -> catB (f a) (f b)
这可能已经存在于某处的图书馆中。
不幸的是,这种定义不同函子的特殊方法需要一堆额外的新类型噪音,因为(->)
它已经是一个类别。事实上,让所有类型正确排列会有点痛苦。
因此,将其称为“XFunctor
或”可能是最简单的。此外,想象一下双关语的潜力!
编辑:看起来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)
但是,我不确定这是否足够普遍!我认为我们可能也希望它比种类更具多态性。