pub fn ty(&self) -> Option<Expr> {
        match self {
            _0 | _1 | Ty(_, _) => Some(I),
            I | Var(_) | Lam(_, _) => None,
            Type(a) => a.eval().ty()?.ty(),
            Ind(p, i) => {
                if let Pa(a, b) = &**p {
                    match &**i {
                        _0 => Some((**a).clone()),
                        _1 => Some((**b).clone()),
                        Tup(tup) => {
                            match tup.len() {
                                0 => None,
                                1 => ind((**p).clone(), tup[0].clone()).ty(),
                                _ => ind(ind((**p).clone(), tup[0].clone()).ty()?, Tup(tup[1..].into())).ty(),
                            }
                        }
                        _ => None,
                    }
                } else {
                    None
                }
            }
            Pa(a, b) => Some(pa(a.ty()?, b.ty()?)),
            App(a, b) => a.app(b)?.ty(),
            Un(a) => Some(un(a.ty()?)),
            Nu(a) => Some(nu(a.ty()?)),
            Tup(vs) => {
                let mut res = vec![];
                for item in vs {
                    res.push(item.ty()?);
                }
                Some(Tup(res))
            }
            All(lam) => {
                if let Lam(arg, _) = &**lam {
                    if let Ty(_, ty) = &**arg {
                        let members = ty.members();
                        let mut res_ty = None;
                        for mem in &members {
                            let val = lam.app(mem)?;
                            let res = val.ty()?;
                            if res_ty.is_none() {
                                res_ty = Some(res);
                            } else if let Some(r) = &res_ty {
                                match (r.is_false(), res.is_false()) {
                                    (true, true) | (false, false) =>
                                        if &res != r {return None},
                                    (false, true) => res_ty = Some(res),
                                    (true, false) => {}
                                }
                            }
                        }
                        res_ty.map(|r| if r.is_false() {nu(r)} else {un(r)})
                    } else {
                        None
                    }
                } else {
                    None
                }
            }
            Any(lam) => {
                if let Lam(arg, _) = &**lam {
                    if let Ty(_, ty) = &**arg {
                        let members = ty.members();
                        let mut res_ty = None;
                        for mem in &members {
                            let res = lam.app(mem)?.ty()?;
                            if res_ty.is_none() {
                                res_ty = Some(res);
                            } else if let Some(r) = &res_ty {
                                match (r.is_true(), res.is_true()) {
                                    (true, true) | (false, false) =>
                                        if &res != r {return None},
                                    (false, true) => res_ty = Some(res),
                                    (true, false) => {}
                                }
                            }
                        }
                        res_ty.map(|r| if r.is_true() {nu(r)} else {un(r)})
                    } else {
                        None
                    }
                } else {
                    None
                }
            }
            Lift(a) => Some(a.eval()),
            Not(a) => Some(not(a.ty()?).eval()),
            And(a, b) => Some(and(a.ty()?, b.ty()?).eval()),
            Or(a, b) => Some(or(a.ty()?, b.ty()?).eval()),
            Imply(a, b) => Some(imply(a.ty()?, b.ty()?).eval()),
            Eq(a, b) => Some(eq(a.ty()?, b.ty()?).eval()),
            Xor(a, b) => Some(xor(a.ty()?, b.ty()?).eval()),
        }
    }
/// Gets the type of an expression.
Gets the type of an expression.
Gets the type of an expression .
pub fn ty(&self) -> Option<Expr> {
        match self {
            _0 | _1 | Ty(_, _) => Some(I),
            I | Var(_) | Lam(_, _) => None,
            Type(a) => a.eval().ty()?.ty(),
            Ind(p, i) => {
                if let Pa(a, b) = &**p {
                    match &**i {
                        _0 => Some((**a).clone()),
                        _1 => Some((**b).clone()),
                        Tup(tup) => {
                            match tup.len() {
                                0 => None,
                                1 => ind((**p).clone(), tup[0].clone()).ty(),
                                _ => ind(ind((**p).clone(), tup[0].clone()).ty()?, Tup(tup[1..].into())).ty(),
                            }
                        }
                        _ => None,
                    }
                } else {
                    None
                }
            }
            Pa(a, b) => Some(pa(a.ty()?, b.ty()?)),
            App(a, b) => a.app(b)?.ty(),
            Un(a) => Some(un(a.ty()?)),
            Nu(a) => Some(nu(a.ty()?)),
            Tup(vs) => {
                let mut res = vec![];
                for item in vs {
                    res.push(item.ty()?);
                }
                Some(Tup(res))
            }
            All(lam) => {
                if let Lam(arg, _) = &**lam {
                    if let Ty(_, ty) = &**arg {
                        let members = ty.members();
                        let mut res_ty = None;
                        for mem in &members {
                            let val = lam.app(mem)?;
                            let res = val.ty()?;
                            if res_ty.is_none() {
                                res_ty = Some(res);
                            } else if let Some(r) = &res_ty {
                                match (r.is_false(), res.is_false()) {
                                    (true, true) | (false, false) =>
                                        if &res != r {return None},
                                    (false, true) => res_ty = Some(res),
                                    (true, false) => {}
                                }
                            }
                        }
                        res_ty.map(|r| if r.is_false() {nu(r)} else {un(r)})
                    } else {
                        None
                    }
                } else {
                    None
                }
            }
            Any(lam) => {
                if let Lam(arg, _) = &**lam {
                    if let Ty(_, ty) = &**arg {
                        let members = ty.members();
                        let mut res_ty = None;
                        for mem in &members {
                            let res = lam.app(mem)?.ty()?;
                            if res_ty.is_none() {
                                res_ty = Some(res);
                            } else if let Some(r) = &res_ty {
                                match (r.is_true(), res.is_true()) {
                                    (true, true) | (false, false) =>
                                        if &res != r {return None},
                                    (false, true) => res_ty = Some(res),
                                    (true, false) => {}
                                }
                            }
                        }
                        res_ty.map(|r| if r.is_true() {nu(r)} else {un(r)})
                    } else {
                        None
                    }
                } else {
                    None
                }
            }
            Lift(a) => Some(a.eval()),
            Not(a) => Some(not(a.ty()?).eval()),
            And(a, b) => Some(and(a.ty()?, b.ty()?).eval()),
            Or(a, b) => Some(or(a.ty()?, b.ty()?).eval()),
            Imply(a, b) => Some(imply(a.ty()?, b.ty()?).eval()),
            Eq(a, b) => Some(eq(a.ty()?, b.ty()?).eval()),
            Xor(a, b) => Some(xor(a.ty()?, b.ty()?).eval()),
        }
    }
pub fn ty ( & self ) -> Option < Expr > { match self { _0 | _1 | Ty ( _ , _ ) => Some ( I ) , I | Var ( _ ) | Lam ( _ , _ ) => None , Type ( a ) => a . eval ( ) . ty ( ) ? . ty ( ) , Ind ( p , i ) => { if let Pa ( a , b ) = & * * p { match & * * i { _0 => Some ( ( * * a ) . clone ( ) ) , _1 => Some ( ( * * b ) . clone ( ) ) , Tup ( tup ) => { match tup . len ( ) { 0 => None , 1 => ind ( ( * * p ) . clone ( ) , tup [ 0 ] . clone ( ) ) . ty ( ) , _ => ind ( ind ( ( * * p ) . clone ( ) , tup [ 0 ] . clone ( ) ) . ty ( ) ? , Tup ( tup [ 1 .. ] . into ( ) ) ) . ty ( ) , } } _ => None , } } else { None } } Pa ( a , b ) => Some ( pa ( a . ty ( ) ? , b . ty ( ) ? ) ) , App ( a , b ) => a . app ( b ) ? . ty ( ) , Un ( a ) => Some ( un ( a . ty ( ) ? ) ) , Nu ( a ) => Some ( nu ( a . ty ( ) ? ) ) , Tup ( vs ) => { let mut res = vec ! [ ] ; for item in vs { res . push ( item . ty ( ) ? ) ; } Some ( Tup ( res ) ) } All ( lam ) => { if let Lam ( arg , _ ) = & * * lam { if let Ty ( _ , ty ) = & * * arg { let members = ty . members ( ) ; let mut res_ty = None ; for mem in & members { let val = lam . app ( mem ) ? ; let res = val . ty ( ) ? ; if res_ty . is_none ( ) { res_ty = Some ( res ) ; } else if let Some ( r ) = & res_ty { match ( r . is_false ( ) , res . is_false ( ) ) { ( true , true ) | ( false , false ) => if & res != r { return None } , ( false , true ) => res_ty = Some ( res ) , ( true , false ) => { } } } } res_ty . map ( | r | if r . is_false ( ) { nu ( r ) } else { un ( r ) } ) } else { None } } else { None } } Any ( lam ) => { if let Lam ( arg , _ ) = & * * lam { if let Ty ( _ , ty ) = & * * arg { let members = ty . members ( ) ; let mut res_ty = None ; for mem in & members { let res = lam . app ( mem ) ? . ty ( ) ? ; if res_ty . is_none ( ) { res_ty = Some ( res ) ; } else if let Some ( r ) = & res_ty { match ( r . is_true ( ) , res . is_true ( ) ) { ( true , true ) | ( false , false ) => if & res != r { return None } , ( false , true ) => res_ty = Some ( res ) , ( true , false ) => { } } } } res_ty . map ( | r | if r . is_true ( ) { nu ( r ) } else { un ( r ) } ) } else { None } } else { None } } Lift ( a ) => Some ( a . eval ( ) ) , Not ( a ) => Some ( not ( a . ty ( ) ? ) . eval ( ) ) , And ( a , b ) => Some ( and ( a . ty ( ) ? , b . ty ( ) ? ) . eval ( ) ) , Or ( a , b ) => Some ( or ( a . ty ( ) ? , b . ty ( ) ? ) . eval ( ) ) , Imply ( a , b ) => Some ( imply ( a . ty ( ) ? , b . ty ( ) ? ) . eval ( ) ) , Eq ( a , b ) => Some ( eq ( a . ty ( ) ? , b . ty ( ) ? ) . eval ( ) ) , Xor ( a , b ) => Some ( xor ( a . ty ( ) ? , b . ty ( ) ? ) . eval ( ) ) , } }
Gets the type of an expression.
Gets the type of an expression .
&self
&self