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 fmapin terms pureand (<*>)as follows:
fmap x = (<*>) (pure x)
I can also write (<*>)in terms (=<<)and pureas 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 fmapin terms pureand 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.
? ?