In Haskell, we have 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 pure
and (<*>)
as follows:
fmap x = (<*>) (pure x)
I can also write (<*>)
in terms (=<<)
and pure
as follows:
m1 <*> m2 = (\x -> (\y -> pure (x y)) =<< m2) =<< m1
Having noticed earlier, I threw the binding operator from normal (>>=)
to (=<<)
. The reason I did this is because now I want to generalize such functions:
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 pure
and in (<*>)
exactly the same way as before:
fmap x = (<*>) (pure x)
, (<*>)
pure
(=<<)
. ? , , , (<*>)
pure
(=<<)
, . , .
, , , :
class Category cat => SpecialCategory cat where
...
instance SpecialCategory (->) where
...
instance SpecialCategory SomeOtherCategory where
...
, (<*>)
(=<<)
pure
.
? ?