more exercises

This commit is contained in:
AF 2023-07-31 19:42:30 +00:00
parent 4172ee7427
commit e9cf323ca2
6 changed files with 129 additions and 8 deletions

View File

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

27
src/exercises/bind.md Normal file
View File

@ -0,0 +1,27 @@
```rust
# mod __ {
fn bind<T, F: FnOnce(T) -> Option<T>>(f: F, fa: Option<T>) -> Option<T> {
match fa {
Some(a) => f(a),
None => None,
}
}
# }
# fn bind<T, F: FnOnce(T) -> Option<T>>(f: F, fa: Option<T>) -> Option<T> { 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()),
);
```

View File

@ -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<dyn 'a + FnOnce() -> (bool, BoolStream<'a>)>,
# */ Box<dyn 'a + Next>
);
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<Self>) -> (bool, BoolStream<'t>) where Self: 't;
# }
# impl<'a, F: 'a + FnOnce() -> (bool, BoolStream<'a>)> Next for Wrapper<'a, F> {
# fn next<'t>(self: Box<Self>) -> (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);
```

View File

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

26
src/exercises/refbind.md Normal file
View File

@ -0,0 +1,26 @@
```rust
# mod __ {
fn refbind<T, F: Fn(&T) -> 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)
);
```

View File

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