{-# LANGUAGE TupleSections #-} module CTT where import Control.Applicative import Data.List import Data.Maybe import Pretty -------------------------------------------------------------------------------- -- | Terms data Loc = Loc { locFile :: String , locPos :: (Int, Int) } deriving Eq type Ident = String type Label = String type Binder = (Ident,Loc) noLoc :: String -> Binder noLoc x = (x, Loc "" (0,0)) -- Branch of the form: c x1 .. xn -> e type Brc = (Label,([Binder],Ter)) -- Telescope (x1 : A1) .. (xn : An) type Tele = [(Binder,Ter)] -- Labelled sum: c (x1 : A1) .. (xn : An) type LblSum = [(Binder,Tele)] -- Context gives type values to identifiers type Ctxt = [(Binder,Val)] -- Mutual recursive definitions: (x1 : A1) .. (xn : An) and x1 = e1 .. xn = en type Decls = [(Binder,Ter,Ter)] data ODecls = ODecls Decls | Opaque Binder | Transp Binder deriving (Eq,Show) declIdents :: Decls -> [Ident] declIdents decl = [ x | ((x,_),_,_) <- decl] declBinders :: Decls -> [Binder] declBinders decl = [ x | (x,_,_) <- decl] declTers :: Decls -> [Ter] declTers decl = [ d | (_,_,d) <- decl] declTele :: Decls -> Tele declTele decl = [ (x,t) | (x,t,_) <- decl] declDefs :: Decls -> [(Binder,Ter)] declDefs decl = [ (x,d) | (x,_,d) <- decl] -- Terms data Ter = App Ter Ter | Pi Ter Ter | Lam Binder Ter | Sigma Ter Ter | SPair Ter Ter | Fst Ter | Snd Ter | Where Ter ODecls | Var Ident | U -- constructor c Ms | Con Label [Ter] -- branches c1 xs1 -> M1,..., cn xsn -> Mn | Split Loc [Brc] -- labelled sum c1 A1s,..., cn Ans (assumes terms are constructors) | Sum Binder LblSum | PN PN deriving Eq -- Primitive notions data PN = Id | Refl -- Inh A is an h-prop stating that A is inhabited. -- Here we take h-prop A as (Pi x y : A) Id A x y. | Inh -- Inc a : Inh A for a:A (A not needed ??) | Inc -- Squash a b : Id (Inh A) a b | Squash -- InhRec B p phi a : B, -- p : hprop(B), phi : A -> B, a : Inh A (cf. HoTT-book p.113) | InhRec -- (A B : U) -> Id U A B -> A -> B -- For TransU we only need the eqproof and the element in A is needed | TransU -- (A B : U) -> Id U A B -> B -> A -- For TransU we only need the eqproof and the element in A is needed | TransInvU -- (A : U) -> (a : A) -> Id A a (transport A (refl U A) a) | TransURef -- (A : U) (a b:A) (p:Id A a b) -> Id (singl A a) (pair a (refl A a)) (pair b p) | CSingl -- (A B : U) (f : A -> B) (a b : A) -> -- (p : Id A a b) -> Id B (f a) (f b) -- TODO: remove? | MapOnPath -- (A B : U) (f g : A -> B) (a b : A) -> -- Id (A->B) f g -> Id A a b -> Id B (f a) (g b) | AppOnPath -- Ext B f g p : Id (Pi A B) f g, -- (p : (Pi x:A) Id (Bx) (fx,gx)); A not needed ?? -- | Ext -- Ext B f g p : Id (Pi A B) f g, -- (p : (Pi x y:A) IdS A (Bx) x y p fx gy) | HExt -- EquivEq A B f s t where -- A, B are types, f : A -> B, -- s : (y : B) -> fiber f y, and -- t : (y : B) (z : fiber f y) -> Id (fiber f y) (s y) z -- where fiber f y is Sigma x : A. Id B (f x) z. | EquivEq -- (A : U) -> (s : (y : A) -> pathTo A a) -> -- (t : (y : B) -> (v : pathTo A a) -> Id (path To A a) (s y) v) -> -- Id (Id U A A) (refl U A) (equivEq A A (id A) s t) | EquivEqRef -- (A B : U) -> (f : A -> B) (s : (y : B) -> fiber A B f y) -> -- (t : (y : B) -> (v : fiber A B f y) -> Id (fiber A B f y) (s y) v) -> -- (a : A) -> Id B (f a) (transport A B (equivEq A B f s t) a) | TransUEquivEq -- IdP : (A B :U) -> Id U A B -> A -> B -> U -- IdP A B p a b is the type of paths connecting a to b over p | IdP -- mapOnPathD : (A : U) (F : A -> U) (f : (x : A) -> F x) (a0 a1 : A) (p : Id A a0 a1) -> -- IdS A F a0 a1 p (f a0) (f a1) -- IdS : (A:U) (F:A -> U) (a0 a1:A) (p:Id A a0 a1) -> F a0 -> F a1 -> U -- IdS A F a0 a1 p = IdP (F a0) (F a1) (mapOnPath A U F a0 a1 p) -- TODO: remove in favor of AppOnPathD? | MapOnPathD -- AppOnPathD : (A : U) (F : A -> U) (f g : (x : A) -> F x) -> Id ((x : A) -> F x) f g -> -- (a0 a1 : A) (p : Id A a0 a1) -> IdS A F a0 a1 p (f a0) (g a1) -- | AppOnPathD -- mapOnPathS : (A:U)(F:A -> U) (C:U) (f: (x:A) -> F x -> C) (a0 a1 : A) (p:Id A a0 a1) -- (b0:F a0) (b1:F a1) (q : IdS A F a0 a1 p b0 b1) -> Id C (f a0 b0) (f a1 b1) | MapOnPathS -- TODO: AppOnPathS? -- S1 : U | Circle -- base : S1 | Base -- loop : Id S1 base base | Loop -- S1rec : (F : S1 -> U) (b : F base) (l : IdS F base base loop) (x : S1) -> F x | CircleRec -- I : U | I -- I0, I1 : Int | I0 | I1 -- line : Id Int I0 I1 | Line -- intrec : (F : I -> U) (s : F I0) (e : F I1) -- (l : IdS Int F I0 I1 line s e) (x : I) -> F x | IntRec -- undefined constant | Undef Loc deriving (Eq, Show) -- For an expression t, returns (u,ts) where u is no application -- and t = u t unApps :: Ter -> (Ter,[Ter]) unApps = aux [] where aux :: [Ter] -> Ter -> (Ter,[Ter]) aux acc (App r s) = aux (s:acc) r aux acc t = (t,acc) -- Non tail reccursive version: -- unApps (App r s) = let (t,ts) = unApps r in (t, ts ++ [s]) -- unApps t = (t,[]) mkApps :: Ter -> [Ter] -> Ter mkApps (Con l us) vs = Con l (us ++ vs) mkApps t ts = foldl App t ts mkLams :: [String] -> Ter -> Ter mkLams bs t = foldr Lam t [noLoc b | b <- bs] mkWheres :: [ODecls] -> Ter -> Ter mkWheres [] e = e mkWheres (d:ds) e = Where (mkWheres ds e) d -- Primitive notions primHandle :: [(Ident,Int,PN)] primHandle = [("Id" , 3, Id ), ("refl" , 2, Refl ), -- ("funExt" , 5, Ext ), ("funHExt" , 5, HExt ), ("inh" , 1, Inh ), ("inc" , 2, Inc ), ("squash" , 3, Squash ), ("inhrec" , 5, InhRec ), ("equivEq" , 5, EquivEq ), ("transport" , 4, TransU ), ("transpInv" , 4, TransInvU ), ("contrSingl" , 4, CSingl ), ("transportRef" , 2, TransURef ), ("equivEqRef" , 3, EquivEqRef ), ("transpEquivEq" , 6, TransUEquivEq), ("appOnPath" , 8, AppOnPath ), ("mapOnPath" , 6, MapOnPath ), ("IdP" , 5, IdP ), ("mapOnPathD" , 6, MapOnPathD ), ("mapOnPathS" , 10, MapOnPathS ), ("S1" , 0, Circle ), ("base" , 0, Base ), ("loop" , 0, Loop ), ("S1rec" , 4, CircleRec ), ("I" , 0, I ), ("I0" , 0, I0 ), ("I1" , 0, I1 ), ("line" , 0, Line ), ("intrec" , 5, IntRec )] reservedNames :: [String] reservedNames = [ s | (s,_,_) <- primHandle ] arity :: PN -> Int arity pn = fromMaybe 0 $ listToMaybe [n | (_,n,pn') <- primHandle, pn == pn'] mkPN :: String -> Maybe PN mkPN s = listToMaybe [pn | (s',_,pn) <- primHandle, s == s'] -------------------------------------------------------------------------------- -- | Names, dimension, and nominal type class type Name = Integer type Dim = [Name] gensym :: Dim -> Name gensym [] = 2 gensym xs = maximum xs + 1 gensyms :: Dim -> [Name] gensyms d = let x = gensym d in x : gensyms (x : d) class Nominal a where swap :: a -> Name -> Name -> a support :: a -> [Name] fresh :: Nominal a => a -> Name fresh = gensym . support freshs :: Nominal a => a -> [Name] freshs = gensyms . support instance (Nominal a, Nominal b) => Nominal (a, b) where support (a, b) = support a `union` support b swap (a, b) x y = (swap a x y, swap b x y) instance Nominal a => Nominal [a] where support vs = unions (map support vs) swap vs x y = [swap v x y | v <- vs] -- Make Name an instance of Nominal instance Nominal Integer where support 0 = [] support 1 = [] support n = [n] swap z x y | z == x = y | z == y = x | otherwise = z -------------------------------------------------------------------------------- -- | Boxes -- TODO: abstract the type of Intervals instead of exposing the encoding type Dir = Integer mirror :: Dir -> Dir mirror 0 = 1 mirror 1 = 0 mirror n = error $ "mirror: 0 or 1 expected but " ++ show n ++ " given" up, down :: Dir up = 1 down = 0 type Side = (Name,Dir) allDirs :: [Name] -> [Side] allDirs [] = [] allDirs (n:ns) = (n,down) : (n,up) : allDirs ns data Box a = Box { dir :: Dir , pname :: Name , pface :: a , sides :: [(Side,a)] } deriving Eq instance Show a => Show (Box a) where show (Box dir n f xs) = "Box" <+> show dir <+> show n <+> show f <+> show xs mapBox :: (a -> b) -> Box a -> Box b mapBox f (Box d n x xs) = Box d n (f x) [ (nnd,f v) | (nnd,v) <- xs ] sequenceSnd :: Monad m => [(a,m b)] -> m [(a,b)] sequenceSnd [] = return [] sequenceSnd ((a,b):abs) = do b' <- b acs <- sequenceSnd abs return $ (a,b') : acs sequenceBox :: Monad m => Box (m a) -> m (Box a) sequenceBox (Box d n x xs) = do x' <- x xs' <- sequenceSnd xs return $ Box d n x' xs' mapBoxM :: Monad m => (a -> m b) -> Box a -> m (Box b) mapBoxM f = sequenceBox . mapBox f instance Functor Box where fmap = mapBox lookBox :: Show a => Side -> Box a -> a lookBox (y,dir) (Box d x v _) | x == y && mirror d == dir = v lookBox xd box@(Box _ _ _ nvs) = case lookup xd nvs of Just v -> v Nothing -> error $ "lookBox: box not defined on " ++ show xd ++ "\nbox = " ++ show box nonPrincipal :: Box a -> [Name] nonPrincipal (Box _ _ _ nvs) = nub $ map (fst . fst) nvs defBox :: Box a -> [(Name, Dir)] defBox (Box d x _ nvs) = (x,mirror d) : [ zd | (zd,_) <- nvs ] fromBox :: Box a -> [(Side,a)] fromBox (Box d x v nvs) = ((x, mirror d),v) : nvs modBox :: (Side -> a -> b) -> Box a -> Box b modBox f (Box dir x v nvs) = Box dir x (f (x,mirror dir) v) [ (nd,f nd v) | (nd,v) <- nvs ] modBoxM :: Monad m => (Side -> a -> m b) -> Box a -> m (Box b) modBoxM f = sequenceBox . modBox f -- Restricts the non-principal faces to np. subBox :: [Name] -> Box a -> Box a subBox np (Box dir x v nvs) = Box dir x v [ nv | nv@((n,_),_) <- nvs, n `elem` np] shapeOfBox :: Box a -> Box () shapeOfBox = mapBox (const ()) -- fst is down, snd is up consBox :: (Name,(a,a)) -> Box a -> Box a consBox (n,(v0,v1)) (Box dir x v nvs) = Box dir x v $ ((n,down),v0) : ((n,up),v1) : nvs appendBox :: [(Name,(a,a))] -> Box a -> Box a appendBox xs b = foldr consBox b xs appendSides :: [(Side, a)] -> Box a -> Box a appendSides sides (Box dir x v nvs) = Box dir x v (sides ++ nvs) transposeBox :: Box [a] -> [Box a] transposeBox b@(Box dir _ [] _) = [] transposeBox (Box dir x (v:vs) nvss) = Box dir x v [ (nnd,head vs) | (nnd,vs) <- nvss ] : transposeBox (Box dir x vs [ (nnd,tail vs) | (nnd,vs) <- nvss ]) -- Nominal for boxes instance Nominal a => Nominal (Box a) where support (Box dir n v nvs) = support ((n, v), nvs) swap (Box dir z v nvs) x y = Box dir z' v' nvs' where ((z',v'), nvs') = swap ((z, v), nvs) x y -------------------------------------------------------------------------------- -- | Values data KanType = Fill | Com deriving (Show, Eq) data Val = VU | Ter Ter OEnv | VPi Val Val | VId Val Val Val | VSigma Val Val | VSPair Val Val -- tag values which are paths | Path Name Val -- | VExt Name Val Val Val Val | VHExt Name Val Val Val Val -- inhabited | VInh Val -- inclusion into inhabited | VInc Val -- squash type - connects the two values along the name | VSquash Name Val Val | VCon Ident [Val] | Kan KanType Val (Box Val) -- of type U connecting a and b along x -- VEquivEq x a b f s t | VEquivEq Name Val Val Val Val Val -- names x, y and values a, s, t | VEquivSquare Name Name Val Val Val -- of type VEquivEq | VPair Name Val Val -- of type VEquivSquare | VSquare Name Name Val -- a value of type Kan Com VU (Box (type of values)) | VComp (Box Val) -- a value of type Kan Fill VU (Box (type of values minus name)) -- the name is bound | VFill Name (Box Val) -- circle | VCircle | VBase | VLoop Name -- has type VCircle and connects base along the name -- interval | VI | VI0 | VI1 | VLine Name -- connects start and end point along name -- neutral values | VApp Val Val -- the first Val must be neutral | VAppName Val Name | VSplit Val Val -- the second Val must be neutral | VVar String Dim | VInhRec Val Val Val Val -- the last Val must be neutral | VCircleRec Val Val Val Val -- the last Val must be neutral | VIntRec Val Val Val Val Val -- the last Val must be neutral | VFillN Val (Box Val) | VComN Val (Box Val) | VFst Val | VSnd Val deriving Eq vepair :: Name -> Val -> Val -> Val vepair x a b = VSPair a (Path x b) mkVar :: Int -> Dim -> Val mkVar k = VVar ('X' : show k) isNeutral :: Val -> Bool isNeutral (VApp u _) = isNeutral u isNeutral (VAppName u _) = isNeutral u isNeutral (VSplit _ v) = isNeutral v isNeutral (VVar _ _) = True isNeutral (VInhRec _ _ _ v) = isNeutral v isNeutral (VCircleRec _ _ _ v) = isNeutral v isNeutral (VIntRec _ _ _ _ v) = isNeutral v isNeutral (VFillN _ _) = True isNeutral (VComN _ _) = True isNeutral (VFst v) = isNeutral v isNeutral (VSnd v) = isNeutral v isNeutral _ = False fstVal, sndVal, unSquare :: Val -> Val fstVal (VPair _ a _) = a fstVal x = error $ "error fstVal: " ++ show x sndVal (VPair _ _ v) = v sndVal x = error $ "error sndVal: " ++ show x unSquare (VSquare _ _ v) = v unSquare v = error $ "unSquare bad input: " ++ show v unCon :: Val -> [Val] unCon (VCon _ vs) = vs unCon v = error $ "unCon: not a constructor: " ++ show v unions :: Eq a => [[a]] -> [a] unions = foldr union [] unionsMap :: Eq b => (a -> [b]) -> [a] -> [b] unionsMap f = unions . map f instance Nominal Val where support VU = [] support (Ter _ e) = support e support (VId a v0 v1) = support [a,v0,v1] support (Path x v) = delete x $ support v support (VInh v) = support v support (VInc v) = support v support (VPi v1 v2) = support [v1,v2] support (VCon _ vs) = support vs support (VSquash x v0 v1) = support (x, [v0,v1]) -- support (VExt x b f g p) = support (x, [b,f,g,p]) support (VHExt x b f g p) = support (x, [b,f,g,p]) support (Kan Fill a box) = support (a, box) support (VFillN a box) = support (a, box) support (VComN a box@(Box _ n _ _)) = delete n (support (a, box)) support (Kan Com a box@(Box _ n _ _)) = delete n (support (a, box)) support (VEquivEq x a b f s t) = support (x, [a,b,f,s,t]) -- names x, y and values a, s, t support (VEquivSquare x y a s t) = support ((x,y), [a,s,t]) support (VPair x a v) = support (x, [a,v]) support (VComp box@(Box _ n _ _)) = delete n $ support box support (VFill x box) = delete x $ support box support (VApp u v) = support (u, v) support (VAppName u n) = support (u, n) support (VSplit u v) = support (u, v) support (VVar x d) = support d support (VSigma u v) = support (u,v) support (VSPair u v) = support (u,v) support (VFst u) = support u support (VSnd u) = support u support (VInhRec b p h a) = support [b,p,h,a] support VCircle = [] support VBase = [] support (VLoop n) = [n] support (VCircleRec f b l s) = support [f,b,l,s] support VI = [] support VI0 = [] support VI1 = [] support (VLine n) = [n] support (VIntRec f s e l u) = support [f,s,e,l,u] support v = error ("support " ++ show v) swap u x y = let sw u = swap u x y in case u of VU -> VU Ter t e -> Ter t (swap e x y) VId a v0 v1 -> VId (sw a) (sw v0) (sw v1) Path z v | z /= x && z /= y -> Path z (sw v) | otherwise -> let z' = fresh ([x, y], v) v' = swap v z z' in Path z' (sw v') -- VExt z b f g p -> VExt (swap z x y) (sw b) (sw f) (sw g) (sw p) VHExt z b f g p -> VHExt (swap z x y) (sw b) (sw f) (sw g) (sw p) VPi a f -> VPi (sw a) (sw f) VInh v -> VInh (sw v) VInc v -> VInc (sw v) VSquash z v0 v1 -> VSquash (swap z x y) (sw v0) (sw v1) VCon c us -> VCon c (map sw us) VEquivEq z a b f s t -> VEquivEq (swap z x y) (sw a) (sw b) (sw f) (sw s) (sw t) VPair z a v -> VPair (swap z x y) (sw a) (sw v) VEquivSquare z w a s t -> VEquivSquare (swap z x y) (swap w x y) (sw a) (sw s) (sw t) VSquare z w v -> VSquare (swap z x y) (swap w x y) (sw v) Kan Fill a b -> Kan Fill (sw a) (swap b x y) VFillN a b -> VFillN (sw a) (swap b x y) Kan Com a b@(Box _ z _ _) | z /= x && z /= y -> Kan Com (sw a) (swap b x y) | otherwise -> let z' = fresh ([x, y], u) a' = swap a z z' in sw (Kan Com a' (swap b z z')) VComN a b@(Box _ z _ _) | z /= x && z /= y -> VComN (sw a) (swap b x y) | otherwise -> let z' = fresh ([x, y], u) a' = swap a z z' in sw (VComN a' (swap b z z')) VComp b@(Box _ z _ _) | z /= x && z /= y -> VComp (swap b x y) | otherwise -> let z' = fresh ([x, y], u) in sw (VComp (swap b z z')) VFill z b@(Box dir n _ _) | z /= x && z /= y -> VFill z (swap b x y) | otherwise -> let z' = fresh ([x, y], b) in sw (VFill z' (swap b z z')) VApp u v -> VApp (sw u) (sw v) VAppName u n -> VAppName (sw u) (swap n x y) VSplit u v -> VSplit (sw u) (sw v) VVar s d -> VVar s (swap d x y) VSigma u v -> VSigma (sw u) (sw v) VSPair u v -> VSPair (sw u) (sw v) VFst u -> VFst (sw u) VSnd u -> VSnd (sw u) VInhRec b p h a -> VInhRec (sw b) (sw p) (sw h) (sw a) VCircle -> VCircle VBase -> VBase VLoop z -> VLoop (swap z x y) VCircleRec f b l a -> VCircleRec (sw f) (sw b) (sw l) (sw a) VI -> VI VI0 -> VI0 VI1 -> VI1 VLine z -> VLine (swap z x y) VIntRec f s e l u -> VIntRec (sw f) (sw s) (sw e) (sw l) (sw u) -------------------------------------------------------------------------------- -- | Environments data Env = Empty | Pair Env (Binder,Val) | PDef [(Binder,Ter)] Env deriving Eq instance Show Env where show Empty = "" show (PDef xas env) = show env show (Pair env (x,u)) = parens $ showEnv1 env ++ show u where showEnv1 (Pair env (x,u)) = showEnv1 env ++ show u ++ ", " showEnv1 e = show e instance Nominal Env where swap e x y = mapEnv (\u -> swap u x y) e support Empty = [] support (Pair e (_,v)) = support (e, v) support (PDef _ e) = support e data OEnv = OEnv { env :: Env, opaques :: [Binder] } deriving Eq oEmpty :: OEnv oEmpty = OEnv Empty [] oPair :: OEnv -> (Binder,Val) -> OEnv oPair (OEnv e o) u = OEnv (Pair e u) o oPDef :: Bool -> ODecls -> OEnv -> OEnv oPDef _ (ODecls decls) (OEnv e o) = OEnv (PDef [(x,d) | (x,_,d) <- decls] e) o oPDef True (Opaque d) (OEnv e o) = OEnv e (d:o) oPDef True (Transp d) (OEnv e o) = OEnv e (d `delete` o) oPDef _ _ e = e instance Show OEnv where show (OEnv e s) = show e -- <+> parens ("with opaque:" <+> ccat s) instance Nominal OEnv where swap (OEnv e s) x y = OEnv (swap e x y) s support (OEnv e s) = support e upds :: OEnv -> [(Binder,Val)] -> OEnv upds = foldl oPair lookupIdent :: Ident -> [(Binder,a)] -> Maybe (Binder, a) lookupIdent x defs = lookup x [(y,((y,l),t)) | ((y,l),t) <- defs] getIdent :: Ident -> [(Binder,a)] -> Maybe a getIdent x defs = do (_,t) <- lookupIdent x defs; return t getBinder :: Ident -> [(Binder,a)] -> Maybe Binder getBinder x defs = do (b,_) <- lookupIdent x defs; return b mapEnv :: (Val -> Val) -> Env -> Env mapEnv _ Empty = Empty mapEnv f (Pair e (x,v)) = Pair (mapEnv f e) (x,f v) mapEnv f (PDef ts e) = PDef ts (mapEnv f e) mapEnvM :: Applicative m => (Val -> m Val) -> Env -> m Env mapEnvM _ Empty = pure Empty mapEnvM f (Pair e (x,v)) = Pair <$> mapEnvM f e <*> ( (x,) <$> f v) mapEnvM f (PDef ts e) = PDef ts <$> mapEnvM f e mapOEnv :: (Val -> Val) -> OEnv -> OEnv mapOEnv f (OEnv e o) = OEnv (mapEnv f e) o mapOEnvM :: Applicative m => (Val -> m Val) -> OEnv -> m OEnv mapOEnvM f (OEnv e o) = flip OEnv o <$> mapEnvM f e valOfEnv :: Env -> [Val] valOfEnv Empty = [] valOfEnv (Pair env (_,v)) = v : valOfEnv env valOfEnv (PDef _ env) = valOfEnv env valOfOEnv :: OEnv -> [Val] valOfOEnv (OEnv e o) = valOfEnv e -------------------------------------------------------------------------------- -- | Pretty printing instance Show Loc where show (Loc name (i,j)) = name ++ "_L" ++ show i ++ "_C" ++ show j instance Show Ter where show = showTer showTer :: Ter -> String showTer U = "U" showTer (App e0 e1) = showTer e0 <+> showTer1 e1 showTer (Pi e0 e1) = "Pi" <+> showTers [e0,e1] showTer (Lam (x,_) e) = '\\' : x <+> "->" <+> showTer e showTer (Fst e) = showTer e ++ ".1" showTer (Snd e) = showTer e ++ ".2" showTer (Sigma e0 e1) = "Sigma" <+> showTers [e0,e1] showTer (SPair e0 e1) = "pair" <+> showTers [e0,e1] showTer (Where e d) = showTer e <+> "where" <+> showODecls d showTer (Var x) = x showTer (Con c es) = c <+> showTers es showTer (Split l _) = "split " ++ show l showTer (Sum l _) = "sum " ++ show l showTer (PN pn) = showPN pn showTers :: [Ter] -> String showTers = hcat . map showTer1 showTer1 :: Ter -> String showTer1 U = "U" showTer1 (Con c []) = c showTer1 (Var x) = x showTer1 u@(Split{}) = showTer u showTer1 u@(Sum{}) = showTer u showTer1 u@(PN{}) = showTer u showTer1 u = parens $ showTer u -- Warning: do not use showPN as a Show instance as it will loop showPN :: PN -> String showPN (Undef l) = show l showPN pn = case [s | (s,_,pn') <- primHandle, pn == pn'] of [s] -> s _ -> error $ "showPN: unknown primitive " ++ show pn showDecls :: Decls -> String showDecls defs = ccat (map (\((x,_),_,d) -> x <+> "=" <+> show d) defs) showODecls :: ODecls -> String showODecls (ODecls defs) = showDecls defs showODecls (Opaque x) = "opaque" <+> show x showODecls (Transp x) = "transparent" <+> show x instance Show Val where show = showVal showVal :: Val -> String showVal VU = "U" showVal (Ter t env) = show t <+> show env showVal (VId a u v) = "Id" <+> showVal1 a <+> showVal1 u <+> showVal1 v showVal (Path n u) = abrack (show n) <+> showVal u -- showVal (VExt n b f g p) = "funExt" <+> show n <+> showVals [b,f,g,p] showVal (VHExt n b f g p) = "funHExt" <+> show n <+> showVals [b,f,g,p] showVal (VCon c us) = c <+> showVals us showVal (VPi a f) = "Pi" <+> showVals [a,f] showVal (VInh u) = "inh" <+> showVal1 u showVal (VInc u) = "inc" <+> showVal1 u showVal (VInhRec b p h a) = "inhrec" <+> showVals [b,p,h,a] showVal (VSquash n u v) = "squash" <+> show n <+> showVals [u,v] showVal (Kan Fill v box) = "Fill" <+> showVal1 v <+> parens (show box) showVal (Kan Com v box) = "Com" <+> showVal1 v <+> parens (show box) showVal (VFillN v box) = "FillN" <+> showVal1 v <+> parens (show box) showVal (VComN v box) = "ComN" <+> showVal1 v <+> parens (show box) showVal (VPair n u v) = "vpair" <+> show n <+> showVals [u,v] showVal (VSquare x y u) = "vsquare" <+> show x <+> show y <+> showVal1 u showVal (VComp box) = "vcomp" <+> parens (show box) showVal (VFill n box) = "vfill" <+> show n <+> parens (show box) showVal (VApp u v) = showVal u <+> showVal1 v showVal (VAppName u n) = showVal u <+> "@" <+> show n showVal (VSplit u v) = showVal u <+> showVal1 v showVal (VVar x d) = x <+> showDim d showVal (VEquivEq n a b f _ _) = "equivEq" <+> show n <+> showVals [a,b,f] showVal (VEquivSquare x y a s t) = "equivSquare" <+> show x <+> show y <+> showVals [a,s,t] showVal (VSPair u v) = "pair" <+> showVals [u,v] showVal (VSigma u v) = "Sigma" <+> showVals [u,v] showVal (VFst u) = showVal u ++ ".1" showVal (VSnd u) = showVal u ++ ".2" showVal VCircle = "S1" showVal VBase = "base" showVal (VLoop x) = "loop" <+> show x showVal (VCircleRec f b l s) = "S1rec" <+> showVals [f,b,l,s] showVal VI = "I" showVal VI0 = "I0" showVal VI1 = "I1" showVal (VLine n) = "line" <+> show n showVal (VIntRec f s e l u) = "intrec" <+> showVals [f,s,e,l,u] showDim :: Show a => [a] -> String showDim = parens . ccat . map show showVals :: [Val] -> String showVals = hcat . map showVal1 showVal1 :: Val -> String showVal1 VU = "U" showVal1 (VCon c []) = c showVal1 u@(VVar{}) = showVal u showVal1 u = parens $ showVal u