Browse Source

ch1: challenges 1 and 2

master
Erin 8 years ago
parent
commit
4886621c8d
3 changed files with 59 additions and 0 deletions
  1. +11
    -0
      .gitignore
  2. +6
    -0
      ch1/Cargo.toml
  3. +42
    -0
      ch1/src/lib.rs

+ 11
- 0
.gitignore View File

@ -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

+ 6
- 0
ch1/Cargo.toml View File

@ -0,0 +1,6 @@
[package]
name = "ch1"
version = "0.1.0"
authors = ["Erin <erin@hashbang.sh>"]
[dependencies]

+ 42
- 0
ch1/src/lib.rs View File

@ -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<T>(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<A, B, C>(f: Box<Fn(B) -> C>, g: Box<Fn(A) -> 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.)));
}
}

Loading…
Cancel
Save