Skip to content

Commit

Permalink
uniplate: para is a fold, and prepare some stuff for zippers
Browse files Browse the repository at this point in the history
  • Loading branch information
niklasdewally committed Feb 7, 2024
1 parent ecb317e commit 8edde2c
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 37 deletions.
4 changes: 2 additions & 2 deletions crates/uniplate/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@
//!
//! # Acknowledgements / Related Work
//!
//! **This crate implements programming constructs from the following Haskell libraries and
//! papers:**
//! *This crate implements programming constructs from the following Haskell libraries and
//! papers:*
//!
//! * [Uniplate](https://hackage.haskell.org/package/uniplate).
//!
Expand Down
93 changes: 58 additions & 35 deletions crates/uniplate/src/uniplate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@ pub trait Uniplate
where
Self: Sized + Clone + Eq,
{
#[allow(clippy::type_complexity)]
fn uniplate(&self) -> (Vec<Self>, Box<dyn Fn(Vec<Self>) -> Self + '_>);

/// Get the DIRECT children of a node.
fn children(self) -> Vec<Self> {
self.uniplate().0
}

/// Get all children of a node, including itself and all children.
fn universe(self) -> Vec<Self> {
let mut results = vec![self.clone()];
Expand All @@ -18,6 +14,11 @@ where
results
}

/// Get the DIRECT children of a node.
fn children(self) -> Vec<Self> {
self.uniplate().0
}

/// Apply the given rule to all nodes bottom up.
fn transform(self, f: fn(Self) -> Self) -> Self {
let (children, context) = self.uniplate();
Expand All @@ -26,8 +27,12 @@ where
))
}

/// Rewrite by applying a rule everywhere you can.
fn rewrite(self, f: fn(Self) -> Option<Self>) -> Self {
todo!()
let (children, context) = self.uniplate();
let node: Self = context(children.into_iter().map(|a| a.rewrite(f)).collect());

f(node.clone()).unwrap_or(node)
}

/// Perform a transformation on all the immediate children, then combine them back.
Expand All @@ -39,41 +44,59 @@ where
context(children)
}

/// Perform a fold-like computation on each value, technically a paramorphism
fn para<T>(self, op: fn(Self, Vec<T>) -> T) -> T {
/// Perform a fold-like computation on each value.
///
/// Working from the bottom up, this applies the given callback function to each expression
///
/// Unlike [`transform`](Uniplate::transform), this returns an arbitrary type, and is not
/// limited to T -> T transformations. In other words, it can transform a type into a new
/// one.
///
/// The meaning of the callback function is the following:
///
/// f(element_to_fold, folded_children) -> folded_element
///
fn fold<T>(self, op: fn(Self, Vec<T>) -> T) -> T {
op(
self.clone(),
self.children().into_iter().map(|c| c.para(op)).collect(),
self.children().into_iter().map(|c| c.fold(op)).collect(),
)
}

fn zipper(self) -> Zipper<Self> {
todo!()
}
}

pub struct Zipper<T>
where
T: Uniplate,
{
hole: T,
// TODO
}

impl<T: Uniplate> Zipper<T> {
fn left(self) -> Option<Zipper<T>> {
todo!();
}

fn right(self) -> Option<Zipper<T>> {
todo!();
}
/// Get the nth one holed context.
///
/// A uniplate context for type T has holes where all the nested T's should be.
/// This is encoded as a function Vec<T> -> T.
///
/// On the other hand, the nth one-holed context has only one hole where the nth nested
/// instance of T would be.
///
/// Eg. for some type:
/// ```ignore
/// enum Expr {
/// F(A,Expr,A,Expr,A),
/// G(Expr,A,A)
/// }
/// ```
///
/// The 1st one-holed context of `F` (using 0-indexing) would be:
/// ```ignore
/// |HOLE| F(a,b,c,HOLE,e)
/// ```
///
/// Used primarily in the implementation of Zippers.
fn one_holed_context(&self, n: usize) -> Option<Box<dyn Fn(Self) -> Self + '_>> {
let (children, context) = self.uniplate();
let number_of_elems = children.len();

fn up(self) -> Option<Zipper<T>> {
todo!();
}
if n >= number_of_elems {
return None;
}

fn down(self) -> Option<Zipper<T>> {
todo!();
Some(Box::new(move |x| {
let mut children = children.clone();
children[n] = x;
context(children)
}))
}
}

0 comments on commit 8edde2c

Please sign in to comment.