use super::functions::*;
#[allow(dead_code)]
pub struct CurriedFn<A, B, C> {
f: Box<dyn Fn(A, B) -> C>,
}
impl<A: Clone + 'static, B: 'static, C: 'static> CurriedFn<A, B, C> {
#[allow(dead_code)]
pub fn new(f: impl Fn(A, B) -> C + 'static) -> Self {
Self { f: Box::new(f) }
}
#[allow(dead_code)]
pub fn apply(&self, a: A, b: B) -> C {
(self.f)(a, b)
}
#[allow(dead_code)]
pub fn curry_apply(&self, a: A) -> impl Fn(B) -> C + '_ {
move |b| (self.f)(a.clone(), b)
}
#[allow(dead_code)]
pub fn uncurried(&self, pair: (A, B)) -> C {
(self.f)(pair.0, pair.1)
}
}
#[derive(Debug, Clone, Default)]
pub struct AssocMap<K: PartialEq, V> {
data: Vec<(K, V)>,
}
impl<K: PartialEq, V> AssocMap<K, V> {
pub fn new() -> Self {
Self { data: Vec::new() }
}
pub fn with_capacity(cap: usize) -> Self {
Self {
data: Vec::with_capacity(cap),
}
}
pub fn insert(&mut self, key: K, value: V)
where
K: Clone,
V: Clone,
{
assoc_insert(&mut self.data, key, value);
}
pub fn get(&self, key: &K) -> Option<&V> {
assoc_lookup(&self.data, key)
}
pub fn remove(&mut self, key: &K) -> Option<V> {
assoc_remove(&mut self.data, key)
}
pub fn contains_key(&self, key: &K) -> bool {
assoc_mem(&self.data, key)
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &(K, V)> {
self.data.iter()
}
pub fn keys(&self) -> Vec<&K> {
self.data.iter().map(|(k, _)| k).collect()
}
pub fn values(&self) -> Vec<&V> {
self.data.iter().map(|(_, v)| v).collect()
}
pub fn map_values<W>(self, f: impl Fn(V) -> W) -> AssocMap<K, W> {
AssocMap {
data: self.data.into_iter().map(|(k, v)| (k, f(v))).collect(),
}
}
pub fn retain_keys(&mut self, pred: impl Fn(&K) -> bool) {
self.data.retain(|(k, _)| pred(k));
}
}
#[derive(Debug, Clone, Default)]
pub struct SigmaVec<A, B> {
items: Vec<Sigma<A, B>>,
}
impl<A, B> SigmaVec<A, B> {
pub fn new() -> Self {
Self { items: Vec::new() }
}
pub fn push(&mut self, witness: A, proof: B) {
self.items.push(Sigma::new(witness, proof));
}
pub fn len(&self) -> usize {
self.items.len()
}
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
pub fn get(&self, index: usize) -> Option<&Sigma<A, B>> {
self.items.get(index)
}
pub fn iter(&self) -> impl Iterator<Item = &Sigma<A, B>> {
self.items.iter()
}
pub fn witnesses(&self) -> Vec<&A> {
self.items.iter().map(|s| &s.fst).collect()
}
pub fn proofs(&self) -> Vec<&B> {
self.items.iter().map(|s| &s.snd).collect()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Sigma<A, B> {
pub fst: A,
pub snd: B,
}
impl<A, B> Sigma<A, B> {
pub fn new(fst: A, snd: B) -> Self {
Self { fst, snd }
}
pub fn into_parts(self) -> (A, B) {
(self.fst, self.snd)
}
pub fn map_snd<C>(self, f: impl FnOnce(B) -> C) -> Sigma<A, C> {
Sigma::new(self.fst, f(self.snd))
}
pub fn map_fst<C>(self, f: impl FnOnce(A) -> C) -> Sigma<C, B> {
Sigma::new(f(self.fst), self.snd)
}
pub fn elim<C>(self, f: impl FnOnce(A, B) -> C) -> C {
f(self.fst, self.snd)
}
}
#[derive(Debug, Clone)]
pub struct PairIter<T> {
pub(super) first: T,
pub(super) second: T,
pub(super) idx: usize,
}
impl<T: Clone> PairIter<T> {
pub fn new(fst: T, snd: T) -> Self {
Self {
first: fst,
second: snd,
idx: 0,
}
}
}
#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LexPair<A: Ord, B: Ord> {
pub fst: A,
pub snd: B,
}
impl<A: Ord, B: Ord> LexPair<A, B> {
#[allow(dead_code)]
pub fn new(fst: A, snd: B) -> Self {
Self { fst, snd }
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct Triple<A, B, C> {
pub fst: A,
pub snd: B,
pub thd: C,
}
impl<A, B, C> Triple<A, B, C> {
pub fn new(fst: A, snd: B, thd: C) -> Self {
Self { fst, snd, thd }
}
pub fn from_tuple((a, b, c): (A, B, C)) -> Self {
Self::new(a, b, c)
}
pub fn into_tuple(self) -> (A, B, C) {
(self.fst, self.snd, self.thd)
}
pub fn trimap<D, E, F>(
self,
f: impl FnOnce(A) -> D,
g: impl FnOnce(B) -> E,
h: impl FnOnce(C) -> F,
) -> Triple<D, E, F> {
Triple::new(f(self.fst), g(self.snd), h(self.thd))
}
pub fn fst_pair(self) -> Pair<A, B> {
Pair::new(self.fst, self.snd)
}
pub fn snd_pair(self) -> Pair<B, C> {
Pair::new(self.snd, self.thd)
}
}
#[allow(dead_code)]
pub struct ProdBimap<A, B, C, D> {
pub f: Box<dyn Fn(A) -> C>,
pub g: Box<dyn Fn(B) -> D>,
}
impl<A: 'static, B: 'static, C: 'static, D: 'static> ProdBimap<A, B, C, D> {
#[allow(dead_code)]
pub fn new(f: impl Fn(A) -> C + 'static, g: impl Fn(B) -> D + 'static) -> Self {
Self {
f: Box::new(f),
g: Box::new(g),
}
}
#[allow(dead_code)]
pub fn apply(&self, pair: (A, B)) -> (C, D) {
((self.f)(pair.0), (self.g)(pair.1))
}
}
#[allow(dead_code)]
pub struct ProdCone<A, B, Z> {
pub proj1: Box<dyn Fn(Z) -> A>,
pub proj2: Box<dyn Fn(Z) -> B>,
}
impl<A: 'static, B: 'static, Z: Clone + 'static> ProdCone<A, B, Z> {
#[allow(dead_code)]
pub fn new(p1: impl Fn(Z) -> A + 'static, p2: impl Fn(Z) -> B + 'static) -> Self {
Self {
proj1: Box::new(p1),
proj2: Box::new(p2),
}
}
#[allow(dead_code)]
pub fn mediate(&self, z: Z) -> (A, B) {
let z2 = z.clone();
((self.proj1)(z), (self.proj2)(z2))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct Pair<A, B> {
pub fst: A,
pub snd: B,
}
impl<A, B> Pair<A, B> {
pub fn new(fst: A, snd: B) -> Self {
Self { fst, snd }
}
pub fn from_tuple((a, b): (A, B)) -> Self {
Self::new(a, b)
}
pub fn into_tuple(self) -> (A, B) {
(self.fst, self.snd)
}
pub fn map_fst<C>(self, f: impl FnOnce(A) -> C) -> Pair<C, B> {
Pair::new(f(self.fst), self.snd)
}
pub fn map_snd<C>(self, f: impl FnOnce(B) -> C) -> Pair<A, C> {
Pair::new(self.fst, f(self.snd))
}
pub fn bimap<C, D>(self, f: impl FnOnce(A) -> C, g: impl FnOnce(B) -> D) -> Pair<C, D> {
Pair::new(f(self.fst), g(self.snd))
}
pub fn swap(self) -> Pair<B, A> {
Pair::new(self.snd, self.fst)
}
pub fn uncurry<C>(self, f: impl FnOnce(A, B) -> C) -> C {
f(self.fst, self.snd)
}
pub fn as_refs(&self) -> (&A, &B) {
(&self.fst, &self.snd)
}
}
impl<T: Clone> Pair<T, T> {
pub fn iter(&self) -> PairIter<T> {
PairIter::new(self.fst.clone(), self.snd.clone())
}
}
#[allow(dead_code)]
pub struct AssocTriple<A, B, C> {
pub value: ((A, B), C),
}
impl<A, B, C> AssocTriple<A, B, C> {
#[allow(dead_code)]
pub fn new(value: ((A, B), C)) -> Self {
Self { value }
}
#[allow(dead_code)]
pub fn assoc_right(self) -> (A, (B, C)) {
let ((a, b), c) = self.value;
(a, (b, c))
}
#[allow(dead_code)]
pub fn from_right(triple: (A, (B, C))) -> Self {
let (a, (b, c)) = triple;
Self { value: ((a, b), c) }
}
}