{-# LANGUAGE CPP            #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE Rank2Types     #-}

-- | Functor of Functors
module Data.FFunctor where

#ifdef HAVE_TRANSFORMERS
import           Control.Monad.Trans.Class (MonadTrans, lift)
#endif

class FFunctor (f :: (* -> *) -> *) where
--ffmap :: (Functor m, Functor n) => (m ~> n) -> f m -> f n
  ffmap :: (Functor m, Functor n) => (forall a . (m a -> n a)) -> f m -> f n

#ifdef HAVE_TRANSFORMERS
-- | Lifts a record of functions (that has an FFunctor) into a monad transformer.
--
--   e.g. `luft logger` lifts a `Logger m` into a `Logger (ReaderT m Foo)`
luft :: FFunctor f => Monad m => MonadTrans t => Functor (t m) => f m -> f (t m)
luft = ffmap lift
#endif