Merge branch 'woojin' into 'main'

add church

See merge request kaist-cp-class/cs220-private!23
This commit is contained in:
Woojin Lee
2023-08-22 05:43:21 +00:00
3 changed files with 147 additions and 0 deletions

View 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!()
}

View 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));
}
}
}

View File

@@ -5,7 +5,10 @@
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-08.sh` works fine. //! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-08.sh` works fine.
//! See `assignment08/*_grade.rs` and `/scripts/grade-08.sh` for the test script. //! See `assignment08/*_grade.rs` and `/scripts/grade-08.sh` for the test script.
pub mod church;
pub mod small_exercises; pub mod small_exercises;
mod church_grade;
mod small_exercises_grade; mod small_exercises_grade;
// TODO: add kyeongmin's church encoding asignment // TODO: add kyeongmin's church encoding asignment