yoko-0.1: Type/Yoko/TFunA.hs
{-# LANGUAGE TypeFamilies, FlexibleContexts, MultiParamTypeClasses,
FlexibleInstances, UndecidableInstances, QuasiQuotes, ScopedTypeVariables,
Rank2Types #-}
{- |
Module : Type.Yoko.TFunA
Copyright : (c) The University of Kansas 2011
License : BSD3
Maintainer : nicolas.frisby@gmail.com
Stability : experimental
Portability : see LANGUAGE pragmas (... GHC)
The type-level functionality of "Type.Yoko.FunA" functions.
-}
module Type.Yoko.TFunA (TApp, CMap(..), CApp) where
import Type.Yoko.TSTSS
import Type.Yoko.Fun
import Type.Yoko.FunA
import Type.Yoko.Type
import Type.Yoko.Universe
import Data.Yoko.CoreTypes
import Data.Yoko.Generic
import Control.Applicative (Applicative(pure))
import Data.Traversable (Traversable(traverse))
-- | The @TApp@ type family encodes the type-level functionality of
-- "Type.Yoko.Fun" functions.
type family TApp (fn :: * -> *) t
-- | @CMap fn m c@ applies @fn@ to all recursive occurrences (i.e. 'R') in a
-- "Data.Yoko.Core" type @c@ that's mediated by @m@. The domain ('Dom') is @RM
-- m c@ and the range ('Rng') is @RM m (CApp (fn m) c)@. The 'Idiom' is @Idiom
-- (fn m)@.
newtype CMap fn m c = CMap (forall t. fn m t)
type instance Dom (CMap fn m) c = RM m c
type instance Rng (CMap fn m) c = RM m (CApp (fn m) c)
type instance Idiom (CMap fn m) = Idiom (fn m)
-- | @CApp fn c@ applies the type-function @fn@ to all recursive occurrences
-- (i.e. 'R') in the "Data.Yoko.Core" type @c@.
type family CApp (fn :: * -> *) c
type instance CApp fn (D a) = D a
type instance CApp fn (F f c) = F f (CApp fn c)
type instance CApp fn (FF ff c d) = FF ff (CApp fn c) (CApp fn d)
type instance CApp fn (M i c) = M i (CApp fn c)
type instance CApp fn (R t) = R (TApp fn t)
type instance CApp fn U = U
type instance CApp fn V = V
pureDomain :: (Dom fn t ~ Rng fn t) => Domain fn t
pureDomain = AppBy $ \_ -> id
instance D a ::: Domain (CMap fn m) where inhabits = pureDomain
instance (c ::: Domain (CMap fn m), Traversable f
) => F f c ::: Domain (CMap fn m) where
inhabits = AppBy $ \(CMap fn) -> F . fmap (apply (CMap fn)) . unF
instance (c ::: Domain (CMap fn m), d ::: Domain (CMap fn m),
FunctorTSTSS ff
) => FF ff c d ::: Domain (CMap fn m) where
inhabits = AppBy $ \(CMap fn) -> FF .
fmapTSTSS (apply (CMap fn)) (apply (CMap fn)) . unFF
instance (c ::: Domain (CMap fn m)) => M i c ::: Domain (CMap fn m) where
inhabits = AppBy $ \(CMap fn) -> M . apply (CMap fn) . unM
instance (t ::: Domain (fn m), Wrapper (fn m),
Dom (fn m) t ~ Med m t, Rng (fn m) t ~ Med m (TApp (fn m) t)
) => R t ::: Domain (CMap fn m) where
inhabits = AppBy $ \(CMap fn) -> R . apply (fn :: fn m t) . unR
instance U ::: Domain (CMap fn m) where inhabits = pureDomain
instance V ::: Domain (CMap fn m) where inhabits = pureDomain
pureDomainA :: (Dom fn t ~ Rng fn t, Applicative (Idiom fn)) => DomainA fn t
pureDomainA = AppABy $ \_ -> pure
instance Applicative (Idiom (fn m)) => D a ::: DomainA (CMap fn m) where
inhabits = pureDomainA
instance (c ::: DomainA (CMap fn m), Applicative (Idiom (fn m)),
Traversable f) => F f c ::: DomainA (CMap fn m) where
inhabits = AppABy $ \(CMap fn) -> fmap F . traverse (applyA (CMap fn)) . unF
instance (c ::: DomainA (CMap fn m), d ::: DomainA (CMap fn m),
Applicative (Idiom (fn m)), TraversableTSTSS ff
) => FF ff c d ::: DomainA (CMap fn m) where
inhabits = AppABy $ \(CMap fn) -> fmap FF .
traverseTSTSS (applyA (CMap fn)) (applyA (CMap fn)) . unFF
instance (c ::: DomainA (CMap fn m), Functor (Idiom (fn m))
) => M i c ::: DomainA (CMap fn m) where
inhabits = AppABy $ \(CMap fn) -> fmap M . applyA (CMap fn) . unM
instance (t ::: DomainA (fn m), Functor (Idiom (fn m)), Wrapper (fn m),
Dom (fn m) t ~ Med m t, Rng (fn m) t ~ Med m (TApp (fn m) t)
) => R t ::: DomainA (CMap fn m) where
inhabits = AppABy $ \(CMap fn) -> fmap R . applyA (fn :: fn m t) . unR
instance Applicative (Idiom (fn m)) => U ::: DomainA (CMap fn m) where
inhabits = pureDomainA
instance Applicative (Idiom (fn m)) => V ::: DomainA (CMap fn m) where
inhabits = pureDomainA