Skip to content

Instantly share code, notes, and snippets.

@jimblandy
Created February 28, 2019 21:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jimblandy/a61a22a56805738fdbc54c7e453cb8ee to your computer and use it in GitHub Desktop.
Save jimblandy/a61a22a56805738fdbc54c7e453cb8ee to your computer and use it in GitHub Desktop.
Solution to the Squeeze challenge.
// You'll need this at the top of your crate:
// #![feature(optin_builtin_traits)]
//! The `squeeze` function.
//!
//! Omit unit values. That is:
//! - `squeeze(x, ())` returns `x`.
//! - `squeeze((), x)` returns `x`.
//! - `squeeze(x, y)` returns `(x, y)`, when neither `x` nor `y` is `()`.
//! - `squeeze((), ())` returns `()`.
//!
//! If you need to, you can write the return type of `squeeze(x, y)` as
//! `<(X, Y) as Squeeze>::Out`.
pub fn squeeze<X, Y>(x: X, y: Y) -> <X as Squeeze<Y>>::Output
where X: Squeeze<Y>
{
Squeeze::squeeze(x, y)
}
pub trait Squeeze<Y> {
type Output;
fn squeeze(self, other: Y) -> Self::Output;
}
pub auto trait NonTrivial { }
impl !NonTrivial for () { }
impl<X: NonTrivial, Y: NonTrivial> Squeeze<Y> for X {
type Output = (X, Y);
fn squeeze(self, other: Y) -> (X, Y) {
(self, other)
}
}
impl<X: NonTrivial> Squeeze<()> for X {
type Output = X;
fn squeeze(self, _other: ()) -> X {
self
}
}
impl<Y: NonTrivial> Squeeze<Y> for () {
type Output = Y;
fn squeeze(self, other: Y) -> Y {
other
}
}
impl Squeeze<()> for () {
type Output = ();
fn squeeze(self, _other: ()) -> () {
()
}
}
#[cfg(test)]
mod test {
use super::squeeze;
#[test]
fn test_squeeze() {
// The idea here is that any non-() type would work.
assert_eq!(squeeze(1i32, 2i32), (1, 2));
assert_eq!(squeeze(true, false), (true, false));
assert_eq!(squeeze("foo", Some("bar")), ("foo", Some("bar")));
assert_eq!(squeeze(1i32, ()), 1);
assert_eq!(squeeze("foo", ()), "foo");
assert_eq!(squeeze(Some(1.3), ()), Some(1.3));
assert_eq!(squeeze((), 2i32), 2);
assert_eq!(squeeze((), "foo"), "foo");
assert_eq!(squeeze((), Some(1.3)), Some(1.3));
assert_eq!(squeeze((), ()), ());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment