use super::functions::*;
use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
#[derive(Clone, Debug)]
pub enum PcfValue {
Num(u64),
BoolVal(bool),
Bottom,
Fun(String),
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum GradualType {
Unknown,
Base(String),
Arrow(Box<GradualType>, Box<GradualType>),
Prod(Box<GradualType>, Box<GradualType>),
}
pub struct CubicalPath<A: Clone> {
pub dim: usize,
path_fn: Box<dyn Fn(Vec<bool>) -> A>,
}
impl<A: Clone + 'static> CubicalPath<A> {
pub fn constant(value: A) -> Self {
let v = value.clone();
Self {
dim: 0,
path_fn: Box::new(move |_face| v.clone()),
}
}
pub fn from_fn(f: impl Fn(bool) -> A + 'static) -> Self {
Self {
dim: 1,
path_fn: Box::new(move |face| {
let i = face.first().copied().unwrap_or(false);
f(i)
}),
}
}
pub fn at(&self, face: Vec<bool>) -> A {
(self.path_fn)(face)
}
pub fn left(&self) -> A {
self.at(vec![false])
}
pub fn right(&self) -> A {
self.at(vec![true])
}
pub fn face0(&self) -> A {
let mut face = vec![false; self.dim.max(1)];
face[0] = false;
self.at(face)
}
pub fn face1(&self) -> A {
let mut face = vec![false; self.dim.max(1)];
face[0] = true;
self.at(face)
}
pub fn meet(&self, j: bool) -> A {
self.at(vec![j])
}
pub fn join(&self, j: bool) -> A {
self.at(vec![!j])
}
pub fn reverse(self) -> CubicalPath<A>
where
A: 'static,
{
let f = self.path_fn;
CubicalPath {
dim: self.dim,
path_fn: Box::new(move |mut face| {
for b in face.iter_mut() {
*b = !*b;
}
f(face)
}),
}
}
}
pub struct LogicalRelation {
pub ty: SimpleType,
pub(super) pred: Box<dyn Fn(&str, &str) -> bool>,
}
impl LogicalRelation {
pub fn base(name: impl Into<String>, pred: impl Fn(&str, &str) -> bool + 'static) -> Self {
Self {
ty: SimpleType::Base(name.into()),
pred: Box::new(pred),
}
}
pub fn arrow(dom: LogicalRelation, cod: LogicalRelation) -> Self {
let dom_ty = dom.ty.clone();
let cod_ty = cod.ty.clone();
let dom_pred = dom.pred;
let cod_pred = cod.pred;
Self {
ty: SimpleType::Arrow(Box::new(dom_ty), Box::new(cod_ty)),
pred: Box::new(move |f, g| {
if f == g {
return true;
}
let fa = format!("{f}(x)");
let gb = format!("{g}(x)");
dom_pred("x", "x") && cod_pred(&fa, &gb)
}),
}
}
pub fn relates(&self, a: &str, b: &str) -> bool {
(self.pred)(a, b)
}
pub fn self_related(&self, term: &str) -> bool {
self.relates(term, term)
}
}
#[derive(Clone, Debug)]
pub enum ConsistencyEvidence {
Refl,
LeftDyn,
RightDyn,
ArrowCons(Box<ConsistencyEvidence>, Box<ConsistencyEvidence>),
ProdCons(Box<ConsistencyEvidence>, Box<ConsistencyEvidence>),
}
#[derive(Clone, Debug)]
pub struct RelationPair<A, B> {
pub left: A,
pub right: B,
}
pub struct GradualTyper;
impl GradualTyper {
pub fn consistent(a: &GradualType, b: &GradualType) -> Option<ConsistencyEvidence> {
match (a, b) {
(GradualType::Unknown, _) => Some(ConsistencyEvidence::LeftDyn),
(_, GradualType::Unknown) => Some(ConsistencyEvidence::RightDyn),
(GradualType::Base(x), GradualType::Base(y)) if x == y => {
Some(ConsistencyEvidence::Refl)
}
(GradualType::Arrow(a1, b1), GradualType::Arrow(a2, b2)) => {
let ev_a = Self::consistent(a1, a2)?;
let ev_b = Self::consistent(b1, b2)?;
Some(ConsistencyEvidence::ArrowCons(
Box::new(ev_a),
Box::new(ev_b),
))
}
(GradualType::Prod(a1, b1), GradualType::Prod(a2, b2)) => {
let ev_a = Self::consistent(a1, a2)?;
let ev_b = Self::consistent(b1, b2)?;
Some(ConsistencyEvidence::ProdCons(
Box::new(ev_a),
Box::new(ev_b),
))
}
_ => None,
}
}
pub fn unknown_is_consistent_with_any(b: &GradualType) -> bool {
Self::consistent(&GradualType::Unknown, b).is_some()
}
pub fn is_symmetric(a: &GradualType, b: &GradualType) -> bool {
Self::consistent(a, b).is_some() == Self::consistent(b, a).is_some()
}
pub fn precision(a: &GradualType, b: &GradualType) -> bool {
match (a, b) {
(_, GradualType::Unknown) => true,
(GradualType::Unknown, _) => false,
(GradualType::Base(x), GradualType::Base(y)) => x == y,
(GradualType::Arrow(a1, b1), GradualType::Arrow(a2, b2)) => {
Self::precision(a1, a2) && Self::precision(b1, b2)
}
(GradualType::Prod(a1, b1), GradualType::Prod(a2, b2)) => {
Self::precision(a1, a2) && Self::precision(b1, b2)
}
_ => false,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum SimpleType {
Base(String),
Arrow(Box<SimpleType>, Box<SimpleType>),
Product(Box<SimpleType>, Box<SimpleType>),
Forall(String, Box<SimpleType>),
}
pub struct FreeTheoremDeriver {
pub type_sig: String,
pub theorem: String,
}
impl FreeTheoremDeriver {
pub fn list_endomorphism() -> Self {
Self {
type_sig: "forall alpha. List alpha -> List alpha".into(),
theorem: "forall (A B : Type) (h : A -> B) (f : forall alpha, List alpha -> List alpha) (xs : List A), map h (f A xs) = f B (map h xs)"
.into(),
}
}
pub fn poly_identity() -> Self {
Self {
type_sig: "forall alpha. alpha -> alpha".into(),
theorem: "forall (A : Type) (f : forall alpha, alpha -> alpha) (x : A), f A x = x"
.into(),
}
}
pub fn poly_map() -> Self {
Self {
type_sig: "forall alpha beta. (alpha -> beta) -> List alpha -> List beta"
.into(),
theorem: "forall (A B C D : Type) (h : A -> B) (k : C -> D) (f : forall alpha beta, (alpha -> beta) -> List alpha -> List beta) (g : A -> C) (xs : List A), map k (f A C g xs) = f B D (k . g . h^-1) (map h xs)"
.into(),
}
}
pub fn verify_identity_theorem(xs: Vec<i32>) -> bool {
let mapped: Vec<i32> = xs.iter().map(|&x| x).collect();
mapped == xs
}
pub fn verify_reverse_naturality<A: Clone, B: Clone>(f: impl Fn(A) -> B, xs: Vec<A>) -> bool {
let mapped_then_rev: Vec<B> = xs
.iter()
.map(|x| f(x.clone()))
.collect::<Vec<_>>()
.into_iter()
.rev()
.collect();
let rev_then_mapped: Vec<B> = xs.into_iter().rev().map(f).collect();
mapped_then_rev.len() == rev_then_mapped.len()
&& mapped_then_rev
.iter()
.zip(rev_then_mapped.iter())
.all(|_| true)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum PcfType {
Nat,
Bool,
Fun(Box<PcfType>, Box<PcfType>),
}
pub struct RealizabilityModel {
pub ty: PcfType,
}
impl RealizabilityModel {
pub fn new(ty: PcfType) -> Self {
Self { ty }
}
pub fn is_realizer(&self, val: &PcfValue) -> bool {
match (&self.ty, val) {
(PcfType::Nat, PcfValue::Num(_)) => true,
(PcfType::Bool, PcfValue::BoolVal(_)) => true,
(PcfType::Fun(_, _), PcfValue::Fun(_)) => true,
(_, PcfValue::Bottom) => true,
_ => false,
}
}
pub fn per_equiv(&self, v1: &PcfValue, v2: &PcfValue) -> bool {
if !self.is_realizer(v1) || !self.is_realizer(v2) {
return false;
}
match (v1, v2) {
(PcfValue::Num(a), PcfValue::Num(b)) => a == b,
(PcfValue::BoolVal(a), PcfValue::BoolVal(b)) => a == b,
(PcfValue::Bottom, PcfValue::Bottom) => false,
(PcfValue::Fun(f), PcfValue::Fun(g)) => f == g,
_ => false,
}
}
pub fn domain(&self) -> impl Fn(&PcfValue) -> bool + '_ {
move |v| self.per_equiv(v, v)
}
}
#[derive(Clone, Debug)]
pub struct CubicalPoint<A: Clone> {
pub dim: usize,
pub value: A,
pub face: Vec<bool>,
}