yoko-2.0: Data/Yoko/View.hs
{-# LANGUAGE TypeFamilies, TypeOperators, FlexibleContexts,
MultiParamTypeClasses, FlexibleInstances, UndecidableInstances, DataKinds,
PolyKinds, GADTs #-}
{- |
Module : Data.Yoko.View
Copyright : (c) The University of Kansas 2012
License : BSD3
Maintainer : nicolas.frisby@gmail.com
Stability : experimental
Portability : see LANGUAGE pragmas (... GHC)
The @yoko@ generic view.
-}
module Data.Yoko.View
{- (-- * Reflection
-- ** Fields types
Tag, Codomain0, Codi, DC(..),
-- ** Substitution
Subst, Subst0, Subst1,
-- ** Disbanded data types
DCs, DT(..)
) -} where
import Data.Yoko.W
import Data.Yoko.TypeBasics
import Data.Yoko.Representation
--import Data.Yoko.TypeSums (Embed, Partition, (:-:))
--import Data.Yoko.Each
import Type.Digits (Digit)
-- | @Tag@ returns a simulated type-level string that is the name of the
-- constructor that the @dc@ fields type represents.
type family Tag (dc :: k) :: Digit
-- | @Codomain@ is the data type that contains the constructor that the fields
-- type @dc@ represents. It can also be applied to sums of fields types, in
-- which case it just uses the left-most.
type family Codomain (dc :: k) :: k
type family Codomain0 (dcs :: * -> * -> *) :: *
type family Codomain1 (dcs :: * -> * -> *) :: * -> *
type family Codomain2 (dcs :: * -> * -> *) :: * -> * -> *
type instance Codomain0 (N dc) = Codomain dc
type instance Codomain1 (N dc) = Codomain dc
type instance Codomain2 (N dc) = Codomain dc
type instance Codomain0 (l :+: r) = Codomain0 l
type instance Codomain1 (l :+: r) = Codomain1 l
type instance Codomain2 (l :+: r) = Codomain2 l
data DTPos k = NonRecDT | RecDT [k] [k]
-- | Maps a type to its mutually recursive siblings.
type family DTs (t :: k) :: DTPos k
type NumDTs t = NumDTs' (DTs t)
type family NumDTs' (t :: DTPos k) :: Nat
type instance NumDTs' NonRecDT = Z
type instance NumDTs' (RecDT l r) = S (Length' (Length r) l)
type SiblingDTs t = SiblingDTs' t (DTs t)
type family SiblingDTs' (t :: k) (dpos :: DTPos k) :: [k]
type instance SiblingDTs' t NonRecDT = '[]
type instance SiblingDTs' t (RecDT l r) = Append l (t ': r)
-- | Any fields type can be further represented as a product-of-fields and can
-- be injected back into the original data type.
class (Generic dc, DT (Codomain dc)) => DC dc where rejoin :: Sym dc (Codomain dc) p1 p0
-- | The @DCs@ of a data type is sum of all of its fields types.
type family DCs (t :: k) :: * -> * -> *
-- | @DT@ disbands a data type.@
class DT t where disband :: W t (DCs t) p1 p0
-- take a representation, C or above and excluding Recs/Pars, to an actual *
-- type
type family Eval (r :: * -> * -> *) :: *
type instance Eval (T0 Dep t) = t
--type instance Eval Void = ???
type instance Eval (l :+: r) = Eval l -- equivalently, Eval r
type instance Eval (C (dc :: *) r) = Codomain dc
type instance Eval (N dc) = Codomain dc
data SubstSpec star = Sub0 star | Sub1 star | Sub10 star star
type family Subst (spec :: SubstSpec *) (r :: * -> * -> *) :: * -> * -> *
--type instance Subst spec Void = ???
type instance Subst spec (N dc) = N dc
type instance Subst spec (l :+: r) = Subst spec l :+: Subst spec r
type instance Subst spec (C dc r) = C dc (Subst spec r)
type instance Subst spec U = U
type instance Subst spec (l :*: r) = Subst spec l :*: Subst spec r
type instance Subst (Sub0 par0 ) Par0 = T0 Dep par0
type instance Subst (Sub1 par1 ) Par0 = Par0
type instance Subst (Sub10 par1 par0) Par0 = T0 Dep par0
type instance Subst (Sub1 par1 ) Par1 = T0 Dep par1
type instance Subst (Sub10 par1 par0) Par1 = T0 Dep par1
type instance Subst (Sub0 par0) (T1 (Rec lbl) t a) = T0 (Rec lbl) (t (Eval (Subst (Sub0 par0) a)))
--type instance Subst (Sub1 par1) (Rec0 lbl t) = undefined
--type instance Subst (Sub10 par1 par0) (Rec1 lbl t a) = undefined
--type instance Subst (Sub0 par0 (Rec2 lbl t b a) = undefined
type instance Subst (Sub1 par1) (T2 (Rec lbl) t b a) =
T1 (Rec lbl) (t (Eval (Subst (Sub1 par1) b))) (Subst (Sub1 par1) a)
type instance Subst (Sub10 par1 par0) (T2 (Rec lbl) t b a) =
T0 (Rec lbl) (t (Eval (Subst (Sub10 par1 par0) b)) (Eval (Subst (Sub10 par1 par0) a)))
type instance Subst spec (T0 Dep t) = T0 Dep t
type instance Subst spec (T1 Dep f x ) = T1 Dep f (Subst spec x)
type instance Subst spec (T2 Dep f x y) = T2 Dep f (Subst spec x) (Subst spec y)
type Subst0 t p0 = Subst (Sub0 p0) (Rep t)
type Subst1 t p1 = Subst (Sub1 p1) (Rep t)
type Subst10 t p1 p0 = Subst (Sub10 p1 p0) (Rep t)