{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes #-}
import Prelude hiding (filter)
import Control.Monad ((<=<))
import Data.Function ((&))
import Data.Maybe (mapMaybe)
data KleisliCoyoneda :: (* -> *) -> (* -> *) -> * -> * where
KleisliCoyoneda :: (b -> m a) -> f b -> KleisliCoyoneda m f a
instance (Functor m) => Functor (KleisliCoyoneda m f) where
fmap f (KleisliCoyoneda k x) = KleisliCoyoneda (fmap f . k) x
filter :: (Monad m) => (a -> m b) -> KleisliCoyoneda m f a -> KleisliCoyoneda m f b
filter k (KleisliCoyoneda l x) = KleisliCoyoneda (k <=< l) x
liftKleisliCoyoneda :: (Applicative m) => f a -> KleisliCoyoneda m f a
liftKleisliCoyoneda = KleisliCoyoneda pure
runKleisliCoyoneda :: (forall b. (b -> m a) -> f b -> g a) -> KleisliCoyoneda m f a -> g a
runKleisliCoyoneda f (KleisliCoyoneda k m) = f k m
main :: IO ()
main = print $ [1, 2, 3, 4]
& liftKleisliCoyoneda
& filter (\x -> if even x then Just x else Nothing)
& fmap (* 2)
& runKleisliCoyoneda mapMaybe