{-# language DataKinds              #-}
{-# language PolyKinds              #-}
{-# language GADTs                  #-}
{-# language TypeOperators          #-}
{-# language MultiParamTypeClasses  #-}
{-# language ScopedTypeVariables    #-}
{-# language FunctionalDependencies #-}
{-# language TypeApplications       #-}
{-# language AllowAmbiguousTypes    #-}
{-# language TypeFamilies           #-}
module Data.PolyKinded.Functor where
import Data.PolyKinded
class KFunctor (f :: k) (v :: Variances) (as :: LoT k) (bs :: LoT k) | f -> v where
  
  kfmap :: Mappings v as bs -> f :@@: as -> f :@@: bs
kmapo :: forall f v as bs. (KFunctor f v as bs)
      => Mappings v as bs -> f :@@: as -> f :@@: bs
kmapo = kfmap @_ @f
data Variance = Co       
              | Contra   
              | Phantom  
type Variances = [Variance]
type family Mapping (v :: Variance) a b where
  Mapping 'Co      a b = a -> b
  Mapping 'Contra  a b = b -> a
  Mapping 'Phantom a b = ()
infixr 5 :^:
data Mappings (v :: Variances) (x :: LoT k) (y :: LoT k) where
  M0    :: Mappings '[] 'LoT0 'LoT0
  (:^:) :: Mapping v a b -> Mappings vs as bs
        -> Mappings (v ': vs) (a ':&&: as) (b ':&&: bs)