Module frunk::coproduct

source ·
Expand description

Module that holds Coproduct data structures, traits, and implementations

Think of “Coproduct” as ad-hoc enums; allowing you to do something like this

// For simplicity, assign our Coproduct type to a type alias
// This is purely optional.
type I32Bool = Coprod!(i32, bool);
// Inject things into our Coproduct type
let co1 = I32Bool::inject(3);
let co2 = I32Bool::inject(true);

// Getting stuff
let get_from_1a: Option<&i32> = co1.get();
let get_from_1b: Option<&bool> = co1.get();
assert_eq!(get_from_1a, Some(&3));
assert_eq!(get_from_1b, None);

let get_from_2a: Option<&i32> = co2.get();
let get_from_2b: Option<&bool> = co2.get();
assert_eq!(get_from_2a, None);
assert_eq!(get_from_2b, Some(&true));

// *Taking* stuff (by value)
let take_from_1a: Option<i32> = co1.take();
assert_eq!(take_from_1a, Some(3));

// Or with a Result
let uninject_from_1a: Result<i32, _> = co1.uninject();
let uninject_from_1b: Result<bool, _> = co1.uninject();
assert_eq!(uninject_from_1a, Ok(3));
assert!(uninject_from_1b.is_err());
Run

Or, if you want to “fold” over all possible values of a coproduct

// In the below, we use unreachable!() to make it obvious hat we know what type of
// item is inside our coproducts co1 and co2 but in real life, you should be writing
// complete functions for all the cases when folding coproducts
//
// to_ref borrows every item so that we can fold without consuming the coproduct.
assert_eq!(
    co1.to_ref().fold(hlist![|&i| format!("i32 {}", i),
                             |&b| unreachable!() /* we know this won't happen for co1 */ ]),
    "i32 3".to_string());
assert_eq!(
    co2.to_ref().fold(hlist![|&i| unreachable!() /* we know this won't happen for co2 */,
                             |&b| String::from(if b { "t" } else { "f" })]),
    "t".to_string());

// Here, we use the poly_fn! macro to declare a polymorphic function to avoid caring
// about the order in which declare handlers for the types in our coproduct
let folded = co1.fold(
      poly_fn![
        |_b: bool| -> String { unreachable!() }, /* we know this won't happen for co1 */
        |i:  i32 | -> String { format!("i32 {}", i) },
      ]
     );
assert_eq!(folded, "i32 3".to_string());
Run

Enums

  • Phantom type for signature purposes only (has no value)
  • Enum type representing a Coproduct. Think of this as a Result, but capable of supporting any arbitrary number of types instead of just 2.

Traits