From e9cf323ca2ef3befa8a20ff2fe92cd68044ffca2 Mon Sep 17 00:00:00 2001 From: timofey Date: Mon, 31 Jul 2023 19:42:30 +0000 Subject: [PATCH] more exercises --- src/SUMMARY.md | 5 ++- src/exercises/bind.md | 27 ++++++++++++++ src/exercises/bool_stream.md | 61 +++++++++++++++++++++++++++++++ src/exercises/multiple_blanket.md | 14 ++++--- src/exercises/refbind.md | 26 +++++++++++++ src/overview.md | 4 +- 6 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 src/exercises/bind.md create mode 100644 src/exercises/bool_stream.md create mode 100644 src/exercises/refbind.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index eaa9f01..d20b606 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -3,4 +3,7 @@ [Overview](./overview.md) - [Chapter 1](./chapter_1.md) - - [`A`/`A1`/`A2`](./exercises/multiple_blanket.md) + - [test0.rs (bind)](./exercises/bind.md) + - [test1.rs (refbind)](./exercises/refbind.md) + - [A/A1/A2](./exercises/multiple_blanket.md) + - [BoolStream](./exercises/bool_stream.md) diff --git a/src/exercises/bind.md b/src/exercises/bind.md new file mode 100644 index 0000000..8c94344 --- /dev/null +++ b/src/exercises/bind.md @@ -0,0 +1,27 @@ +```rust +# mod __ { +fn bind Option>(f: F, fa: Option) -> Option { + match fa { + Some(a) => f(a), + None => None, + } +} +# } +# fn bind Option>(f: F, fa: Option) -> Option { fa.and_then(f) } + +// don't change anything below + +assert_eq!(bind(|x: i32| Some(x + 3), Some(2)), Some(5)); +assert_eq!(bind(|x: i32| Some(x + 3), None), None); +assert_eq!(bind(|_: i32| None, Some(2)), None); +assert_eq!(bind(|_: i32| None, None), None); + +assert_eq!(bind(|x: &str| Some(x), Some("apple")), Some("apple")); +assert_eq!(bind(|_: &str| Some("banana"), Some("apple")), Some("banana")); + +let banana = "banana".to_string(); +assert_eq!( + bind(|_: String| Some(banana), Some("apple".to_string())), + Some("banana".to_string()), +); +``` diff --git a/src/exercises/bool_stream.md b/src/exercises/bool_stream.md new file mode 100644 index 0000000..83fd47a --- /dev/null +++ b/src/exercises/bool_stream.md @@ -0,0 +1,61 @@ +Make `test_covariance` compile by making `BoolStream<'a>` covariant `'a`. +- Can only change implementation details of `BoolStream` and its methods and add extra items outside of what's given, i.e. no signature/test change. +- Changed version must behave the same way. +```rust +pub struct BoolStream<'a>( + // change this +# /* + Box (bool, BoolStream<'a>)>, +# */ Box +); + +impl<'a> BoolStream<'a> { + pub fn new(f: impl 'a + FnOnce() -> (bool, Self)) -> Self { + // maybe change this +# /* + Self(Box::new(f)) +# */ Self(Box::new(Wrapper(f, PhantomData))) + } + + pub fn next(self) -> (bool, Self) { + // maybe change this +# /* + self.0() +# */ self.0.next() + } +} + +fn test_covariance<'a: 'b, 'b>(e: BoolStream<'a>) -> BoolStream<'b> { + e +} + +# use std::marker::PhantomData; +# struct Wrapper<'a, F>(F, PhantomData<&'a ()>); +# trait Next { +# fn next<'t>(self: Box) -> (bool, BoolStream<'t>) where Self: 't; +# } +# impl<'a, F: 'a + FnOnce() -> (bool, BoolStream<'a>)> Next for Wrapper<'a, F> { +# fn next<'t>(self: Box) -> (bool, BoolStream<'t>) where Self: 't { self.0() } +# } + +/// Tests to check that behaviour stays the same. + +fn get_true<'a>() -> BoolStream<'a> { + BoolStream::new(|| (true, get_false())) +} + +fn get_false<'a>() -> BoolStream<'a> { + BoolStream::new(|| (false, get_true())) +} + +let e = get_true(); +let (x, e) = e.next(); +assert!(x); +let (x, e) = e.next(); +assert!(!x); +let (x, e) = e.next(); +assert!(x); +let (x, e) = e.next(); +assert!(!x); +test_covariance(e); +``` diff --git a/src/exercises/multiple_blanket.md b/src/exercises/multiple_blanket.md index 7ac7000..3045051 100644 --- a/src/exercises/multiple_blanket.md +++ b/src/exercises/multiple_blanket.md @@ -1,9 +1,13 @@ Make this compile. -- `A1` doesn't know about/depend on `A2` -- `A2` doesn't know about/depend on `A1` -- `A1` doesn't know about/depend on `A` -- `A2` doesn't know about/depend on `A` -- can't edit definitions of `A`, `test`, `tes1`, `test2`; can only add code outside of those items +- `A1` doesn't know about/depend on `A2`. +- `A2` doesn't know about/depend on `A1`. +- `A1` doesn't know about/depend on `A`. +- `A2` doesn't know about/depend on `A`. +- Some types are `A1` but not `A2`. +- Some types are `A2` but not `A1`. +- Some types are `A` but not `A2`. +- Some types are `A` but not `A1`. +- Can't edit definitions of `A`, `test`, `tes1`, `test2`; can only add code outside of those items. ```rust trait A { fn a_ref(&self) -> u64; diff --git a/src/exercises/refbind.md b/src/exercises/refbind.md new file mode 100644 index 0000000..232822d --- /dev/null +++ b/src/exercises/refbind.md @@ -0,0 +1,26 @@ +```rust +# mod __ { +fn refbind Option<&T>>(f: F, fa: Option<&T>) -> Option<&T> { + match fa { + Some(a) => f(a), + None => None, + } +} +# } +# fn refbind<'a,'b,T:'a+?Sized>(f:impl'a+Fn(&'a T)->Option<&'b T>,fa:Option<&'a T>)->Option<&'b T>{fa.and_then(f)} + +// don't change anything below + +let apple = "apple".to_string(); +let banana = "banana".to_string(); +assert_eq!( + refbind(|_: &String| Some(&banana), Some(&apple)), + Some(&banana) +); + +let banana = "banana"; +assert_eq!( + refbind(|_: &str| Some(banana), Some("apple")), + Some(banana) +); +``` diff --git a/src/overview.md b/src/overview.md index c379ac0..2cd19cc 100644 --- a/src/overview.md +++ b/src/overview.md @@ -21,10 +21,10 @@ Some exercises may not include have the replaced parts greyed out: ```rust # mod __ { fn fix_me() { -# } +} # } # fn fixed_name() { -} +# } fn do_not_change_this() { fixed_name()