mirror of
https://github.com/kmc7468/cs220.git
synced 2025-12-12 21:08:45 +00:00
add church
This commit is contained in:
71
src/assignments/assignment08/church.rs
Normal file
71
src/assignments/assignment08/church.rs
Normal file
@@ -0,0 +1,71 @@
|
||||
//! Church Numerals
|
||||
//!
|
||||
//! This exercise involves the use of "Church numerals", a
|
||||
//! representation of natural numbers using lambda calculus, named after
|
||||
//! Alonzo Church. Each Church numeral corresponds to a natural number `n`
|
||||
//! and is represented as a higher-order function that applies a given function `f` `n` times.
|
||||
//!
|
||||
//! For more information, see:
|
||||
//! - <https://en.wikipedia.org/wiki/Church_encoding>
|
||||
//! - <https://opendsa-server.cs.vt.edu/OpenDSA/Books/PL/html/ChurchNumerals.html>
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
/// Church numerals are represented as higher-order functions that take a function `f`
|
||||
pub type Church<T> = Rc<dyn Fn(Rc<dyn Fn(T) -> T>) -> Rc<dyn Fn(T) -> T>>;
|
||||
|
||||
/// This function returns a Church numeral equivalent of the natural number 1.
|
||||
/// It takes a function `f` and applies it exactly once.
|
||||
pub fn one<T: 'static>() -> Church<T> {
|
||||
Rc::new(move |f| Rc::new(move |x| f(x)))
|
||||
}
|
||||
|
||||
/// This function returns a Church numeral equivalent of the natural number 2.
|
||||
/// It takes a function `f` and applies it twice.
|
||||
pub fn two<T: 'static>() -> Church<T> {
|
||||
Rc::new(move |f| Rc::new(move |x| f(f(x))))
|
||||
}
|
||||
|
||||
/// This function represents the Church numeral for zero. As zero applications
|
||||
/// of `f` should leave the argument unchanged, the function simply returns the input.
|
||||
pub fn zero<T: 'static>() -> Church<T> {
|
||||
Rc::new(|_| Rc::new(|x| x))
|
||||
}
|
||||
|
||||
/// Implement a function to add 1 to a given Church numeral.
|
||||
pub fn succ<T: 'static>(n: Church<T>) -> Church<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Implement a function to add two Church numerals.
|
||||
pub fn add<T: 'static>(n: Church<T>, m: Church<T>) -> Church<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Implement a function to multiply (mult) two Church numerals.
|
||||
pub fn mult<T: 'static>(n: Church<T>, m: Church<T>) -> Church<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Implement a function to raise one Church numeral to the power of another.
|
||||
/// This is the Church numeral equivalent of the natural number operation of exponentiation.
|
||||
/// Given two natural numbers `n` and `m`, the function should return a Church numeral
|
||||
/// that represents `n` to the power of `m`. The key is to convert `n` and `m` to Church numerals,
|
||||
/// and then apply the Church numeral for `m` (the exponent) to the Church numeral for `n` (the base).
|
||||
/// Note: This function should be implemented *WITHOUT* using the `to_usize` or any `pow`-like method.
|
||||
pub fn exp<T: 'static>(n: usize, m: usize) -> Church<T> {
|
||||
// ACTION ITEM: Uncomment the following lines and replace `todo!()` with your code.
|
||||
// let n = from_usize(n);
|
||||
// let m = from_usize(m);
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Implement a function to convert a Church numeral to a usize type.
|
||||
pub fn to_usize<T: 'static + Default>(n: Church<T>) -> usize {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Implement a function to convert a usize type to a Church numeral.
|
||||
pub fn from_usize<T: 'static>(n: usize) -> Church<T> {
|
||||
todo!()
|
||||
}
|
||||
73
src/assignments/assignment08/church_grade.rs
Normal file
73
src/assignments/assignment08/church_grade.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use rand::Rng;
|
||||
|
||||
use crate::assignments::assignment08::church::*;
|
||||
|
||||
#[test]
|
||||
fn you_must_pass_these_examples() {
|
||||
let c_zero = zero::<usize>();
|
||||
assert_eq!(to_usize(c_zero.clone()), 0);
|
||||
|
||||
let c_one = succ(c_zero.clone());
|
||||
assert_eq!(to_usize(c_one.clone()), to_usize(one::<()>()));
|
||||
|
||||
let c_two = add(c_one.clone(), c_one.clone());
|
||||
let c_three = add(c_one.clone(), c_two.clone());
|
||||
assert_eq!(to_usize(c_three.clone()), 3);
|
||||
|
||||
let c_product = mult(c_three.clone(), c_two.clone());
|
||||
assert_eq!(to_usize(c_product.clone()), 6);
|
||||
|
||||
let c_exponent = exp::<()>(6, 3);
|
||||
assert_eq!(to_usize(c_exponent), 216);
|
||||
|
||||
let c_exponent2 = exp::<()>(3, 0);
|
||||
assert_eq!(to_usize(c_exponent2), 1);
|
||||
}
|
||||
|
||||
fn id(n: usize) -> usize {
|
||||
to_usize(from_usize::<()>(n))
|
||||
}
|
||||
|
||||
fn c_id(n: Church<usize>) -> Church<usize> {
|
||||
from_usize(to_usize(n))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn engineering_isnt_just_mathematics() {
|
||||
const N: usize = 77777;
|
||||
assert_eq!(N, id(N));
|
||||
}
|
||||
|
||||
/// This test case is an optional challenge.
|
||||
/// While it's not necessary to pass this test,
|
||||
/// successfully doing so could provide a sense of satisfaction and achievement.
|
||||
// #[test]
|
||||
// fn i_said_engineering_isnt_just_mathematics() {
|
||||
// const N: usize = 777777777777777;
|
||||
// assert_eq!(N, id(N));
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn be_honest() {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
for _ in 0..77 {
|
||||
let x = rng.gen_range(0..=7);
|
||||
let y = rng.gen_range(0..=7);
|
||||
|
||||
let c_x = from_usize(x);
|
||||
let c_y = from_usize(y);
|
||||
|
||||
let c_sum = add(c_x.clone(), c_y.clone());
|
||||
assert_eq!(to_usize(c_id(c_sum)), x + y);
|
||||
|
||||
let c_prod = mult(c_x.clone(), c_y.clone());
|
||||
assert_eq!(to_usize(c_id(c_prod)), x * y);
|
||||
|
||||
let c_exp = exp(x, y);
|
||||
assert_eq!(to_usize(c_id(c_exp)), x.pow(y as u32));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,5 +5,8 @@
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-08.sh` works fine.
|
||||
//! See `small_problems_grade.rs` and `/scripts/grade-08.sh` for the test script.
|
||||
|
||||
pub mod church;
|
||||
pub mod small_exercises;
|
||||
|
||||
mod church_grade;
|
||||
mod small_exercises_grade;
|
||||
|
||||
Reference in New Issue
Block a user