Generalising Applicative and Monad to more categories

Viewed 131

In Haskell, we've got the functions:

fmap :: Functor f => (a -> b) -> (f a -> f b)
pure :: Applicative f => a -> f a
(<*>) :: Applicative f => f (a -> b) -> (f a -> f b)
(=<<) :: Monad f => (a -> f b) -> (f a -> f b)

I can write fmap in terms of pure and (<*>) like so:

fmap x = (<*>) (pure x)

I can also write (<*>) in terms of (=<<) and pure like so:

m1 <*> m2 = (\x -> (\y -> pure (x y)) =<< m2) =<< m1

Noticed earlier I flipped the bind operator from it's usual (>>=) to (=<<). The reason I did this is because I now want to generalise the functions like so:

fmap :: (Functor f, Category cat) => cat a b -> cat (f a) (f b)
pure :: (Applicative f, Category cat) => a -> f a
(<*>) :: (Applicative f, Category cat) => f (cat a b) -> cat (f a) (f b)
(=<<) :: (Monad f, Category cat) => cat a (f b) -> cat (f a) (f b)

Interestingly, I can still write fmap in terms of pure and (<*>) exactly the same as before:

fmap x = (<*>) (pure x)

However, I work out how can't write (<*>) in terms of pure and (=<<). Is it possible? I suspect it isn't, but I also suspect it's possible to write (<*>) in terms of pure and (=<<) for more categories other than ordinary functions. I also suspect to do this my category needs a few extra functions.

So I'm guessing perhaps I need a class and a few instances, like so:

class Category cat => SpecialCategory cat where
  ...

instance SpecialCategory (->) where
  ...

instance SpecialCategory SomeOtherCategory where
  ...

With this approach I should be able to define any special characteristics a category needs to be able to define (<*>) in terms of (=<<) and pure.

What are those characteristics? Or am I completely off track in my approach to making this generalisation?

0 Answers
Related