From 4886621c8d967b48f311b82360d6069180fc4146 Mon Sep 17 00:00:00 2001 From: Erin Date: Sun, 15 Oct 2017 17:57:17 -0500 Subject: [PATCH] ch1: challenges 1 and 2 --- .gitignore | 11 +++++++++++ ch1/Cargo.toml | 6 ++++++ ch1/src/lib.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 .gitignore create mode 100644 ch1/Cargo.toml create mode 100644 ch1/src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b0722a8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# Generated by Cargo +# will have compiled files and executables +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + diff --git a/ch1/Cargo.toml b/ch1/Cargo.toml new file mode 100644 index 0000000..5d67871 --- /dev/null +++ b/ch1/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "ch1" +version = "0.1.0" +authors = ["Erin "] + +[dependencies] diff --git a/ch1/src/lib.rs b/ch1/src/lib.rs new file mode 100644 index 0000000..6fb6552 --- /dev/null +++ b/ch1/src/lib.rs @@ -0,0 +1,42 @@ +#![feature(conservative_impl_trait)] +#![feature(box_syntax)] + +/// The identity function. Maps a categorical object onto itself. +/// +/// # Haskell +/// ```text +/// id :: a -> a +/// id x = x +/// ``` +pub fn id(x: T) -> T { x } + +/// The composition function. Chains two functions together. +/// +/// # Haskell +/// ```text +/// compose :: (b -> c) -> (a -> b) -> (a -> c) +/// compose f g = λx -> f $ g x +/// ``` +/// +/// # Notes +/// I don't like that this takes `Box`ed functions. Rust doesn't like parameterizing on functions +/// with generic arguments, even if those arguments are sized +/// (`rustc` complains that `std::ops::Fn(A) -> B + 'static` does not have a constant size known at compile-time) +pub fn compose(f: Box C>, g: Box B>) -> impl Fn(A) -> C { + move |x| { f(g(x)) } +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn compose_smoketest() { + fn f(x: f64) -> f64 { x.powi(2) } + fn g(x: f64) -> f64 { x + 3. } + let h = compose(box g, box f); + + assert_eq!(h(3.), g(f(3.))); + } +}