14

我需要以下类别的功能:

class InterleavedHomomorphic x where
  interleaveHomomorphism :: (forall a . f a -> g a) -> x f -> x g

显然我为它发明的名字在任何方面都不是任何东西的官方术语,而且上面的类型类也不是很优雅。这是一个有名字的概念,甚至是某个库中的实现吗?有没有更合理的方法来做到这一点?


这个函数的目的是我有一些f注释一些数据的上下文(Foo并且Bar只是为了这个问题而随机的示例数据结构):

data Foo f = One (f (Bar f)) | Product (f (Foo f)) (f (Foo f))
data Bar f = Zero | Succ (f (Bar f))

我想以多态的方式转换数据的上下文;通过只知道上下文之间的同态而不(必然)关心数据本身。这将通过在上面的示例中提供instance InterleavedHomomorphic Foo和来完成。instance InterleavedHomomorphic Bar

4

3 回答 3

17

因此,假设fg是适当的函子,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)

但是,我不确定这是否足够普遍!我认为我们可能也希望它比种类更具多态性。

于 2014-06-06T22:45:03.590 回答
0

对于它的价值,您可以将示例的简化版本改写为

data Bar' r = Zero | Succ r
type Bar f = fix (Bar' . f)

对于每一对自然变换eta1 :: f ~> geta2 :: Bar' ~> h我们得到一个自然变换(eta2 . eta1) :: (Bar' . f) ~> (h . g)。我们可以用显而易见的方式将这个自然变换提升到不动点上,得到fixed (eta2 . eta1) :: Bar f -> fix (h . g). 因此,当我们有eta2 = id.

总的来说,这是一个相当标准的结构(特别是对于f单子或共单子的情况),尽管我不确定它是否有一个被广泛认可的特定名称。

于 2014-06-08T02:01:53.750 回答
0

Bar f看起来像Free Monad Free f ()

然后Foo是一个do与一个或两个<-。也许从那里继续......

于 2014-06-07T06:40:43.407 回答