Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the concept of an "interleaved homomorphism" a real thing?

I am in need of the following class of functions:

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

Obviously the name I invented for it is not in any way an official term for anything, and the type class above is not very elegant. Is this a concept that has a name, or even an implementation in some library? Is there some more reasonable way of doing this?


The purpose of this function would be that I have some context f that annotates some data (Foo and Bar are just random example data structures for the sake of this question):

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

I would like to transform the context of the data in a polymorphic way; by only knowing the homomorphism between the contexts and not (necessarily) caring about the data itself. This would be done by providing instance InterleavedHomomorphic Foo and instance InterleavedHomomorphic Bar in the example above.

like image 215
dflemstr Avatar asked Jun 06 '14 21:06

dflemstr


1 Answers

So, assuming f and g are proper functors, forall a. f a -> g a is a natural transformation. We could make it a bit prettier:

type f ~> g = forall a. f a -> g a

Natural transformations like this let us form a category of Haskell Functors, so what you have is a functor from that to some other category.

Following the steps of normal Haskell Functors, it would perhaps make sense to have x be an endofunctor, mapping Functors to other Functors. This is similar, but not identical, to what you have:

class FFunctor x where
  ffmap :: (f ~> g) -> (x f ~> x g)

However, in your case x f and x g are not functors, and x f -> x g is a normal function rather than a natural transformation. Still, the pattern is close enough to be intriguing.

With this in mind, it seems that x is still an example of a functor, just between two different categories. It goes from the category of Functors to the category of xs with different structures. Each possible x, like Foo, forms a category with objects like Foo [] and Foo Maybe and transformations between them (Foo [] -> Foo Maybe). Your interleaveHomomorphism function "lifts" natural transformations into these x-morphisms, just like fmap "lifts" normal (a -> b) functions into functions in the image of the functor (f a -> f b).

So yeah: your typeclass is a functor just like Functor, except between two different categories. I don't know of a specific name for it, largely because I don't know a specific name for constructs like x.

More generally, I'm not even sure a specific name would make sense. At this point, we'd probably like a nice generic functor typeclass that go between any two categories. Maybe something like:

class (Category catA, Category catB) => GFunctor f catA catB where
  gfmap :: catA a b -> catB (f a) (f b)

This probably already exists in a library somewhere.

Unfortunately, this particular approach to defining different functors would require a bunch of extra newtype noise since (->) is already a category. In fact, getting all the types to line up properly is going to be a bit of a pain.

So it's probably easiest just to call it an XFunctor or something. Besides, just imagine the pun potential!

EDIT: It looks like categories provides a CFunctor type like this, but a bit cleverer:

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)

However, I'm not certain that even this is general enough! I think that we might want it to be more polymorphic over kinds too.

like image 130
Tikhon Jelvis Avatar answered Nov 03 '22 08:11

Tikhon Jelvis