Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is this thing similar to KleisliFunctor?

Here is how we can define KleisliFunctor:

class (Monad m, Functor f) => KleisliFunctor m f where
  kmap :: (a -> m b) -> f a -> f b
  kmap f = kjoin . fmap f

  kjoin :: f (m a) -> f a
  kjoin = kmap id

Does this type class

class (Functor f, Monad m) => Absorb f m where
  (>>~) :: f a -> (a -> m b) -> m b
  a >>~ f = ajoin $ fmap f a

  ajoin :: f (m a) -> m a
  ajoin a = a >>~ id

fit somewhere into category theory? What are the laws? Are they

a >>~ g . f     === fmap f a >>~ g
a >>~ (f >=> g) === a >>~ f >>= g

?

like image 720
user3237465 Avatar asked Nov 21 '16 09:11

user3237465


1 Answers

This is a speculative answer. Proceed with caution.

Let's first consider KleisliFunctor, focusing on the bind-like arrow mapping:

class (Monad m, Functor f) => KleisliFunctor m f where
  kmap :: (a -> m b) -> f a -> f b

For this to actually be a functor from the Kleisli category of m to Hask, kmap has to follow the relevant functor laws:

-- Mapping the identity gives identity (in the other category).
kmap return = id
-- Mapping a composed arrow gives a composed arrow (in the other category).
kmap (g <=< f) = kmap g . kmap f

The fact that there are two Functors involved makes things a little unusual, but not unreasonable -- for instance, the laws do hold for mapMaybe, which is the first concrete example the KleisliFunctor post alludes to.

As for Absorb, I will flip the bind-like method for the sake of clarity:

class (Functor f, Monad m) => Absorb f m where
  (~<<) :: (a -> m b) -> f a -> m b

If we are looking for something analogous to KleisliFunctor, a question that immediately arises is which category would have functions of type f a -> m b as arrows. It certainly cannot be Hask, as its identity (of type f a -> m a) cannot be id. We would have to figure out not only identity but also composition. For something that is not entirely unlike Monad...

idAbsorb :: f a -> m a
compAbsorb :: (f b -> m c) -> (f a -> m b) -> (f a -> m c)

... the only plausible thing I can think of right now is having a monad morphism as idAbsorb and using a second monad morphism in the opposite direction (that is, from m to f) so that compAbsorb can be implemented by applying the first function, then going back to f and finally applying the second function. We would need to work that out in order to see if my assumptions are appropriate, if this approach works, and if it leads to something useful for your purposes.

like image 113
duplode Avatar answered Oct 22 '22 03:10

duplode