Skip to main content

Bitraversable

Trait Bitraversable 

Source
pub trait Bitraversable: Bifunctor + Bifoldable {
    // Required method
    fn bi_traverse<'a, A: 'a + Clone, B: 'a + Clone, C: 'a + Clone, D: 'a + Clone, F: Applicative>(
        f: impl Fn(A) -> <F as Kind_cdc7cd43dac7585f>::Of<'a, C> + 'a,
        g: impl Fn(B) -> <F as Kind_cdc7cd43dac7585f>::Of<'a, D> + 'a,
        p: <Self as Kind_266801a817966495>::Of<'a, A, B>,
    ) -> <F as Kind_cdc7cd43dac7585f>::Of<'a, <Self as Kind_266801a817966495>::Of<'a, C, D>>;

    // Provided method
    fn bi_sequence<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
        ta: <Self as Kind_266801a817966495>::Of<'a, <F as Kind_cdc7cd43dac7585f>::Of<'a, A>, <F as Kind_cdc7cd43dac7585f>::Of<'a, B>>,
    ) -> <F as Kind_cdc7cd43dac7585f>::Of<'a, <Self as Kind_266801a817966495>::Of<'a, A, B>>
       where <F as Kind_cdc7cd43dac7585f>::Of<'a, A>: Clone,
             <F as Kind_cdc7cd43dac7585f>::Of<'a, B>: Clone { ... }
}
Expand description

A type class for data structures with two type arguments that can be traversed.

A Bitraversable represents a container with two type parameters whose elements can be traversed with effectful functions, accumulating results in an applicative context. A traversal requires two functions, one for each type argument.

§Minimal Implementation

A minimal implementation requires Bitraversable::bi_traverse to be defined directly. Bitraversable::bi_sequence is derived from it via identity.

Note: defining both defaults creates a circular dependency and will not terminate.

§Laws

Bitraversable instances must be consistent with Bifunctor and Bifoldable:

  • Traverse/sequence consistency: bi_traverse(f, g, x) = bi_sequence(bimap(f, g, x)).

§Examples

Bitraversable laws for Result:

use fp_library::{
	brands::*,
	functions::*,
};

// ResultBrand has Of<E, A> = Result<A, E>, so the first function handles errors
// and the second function handles ok values.
let f = |e: String| if e.is_empty() { None } else { Some(e.len()) };
let g = |a: i32| if a > 0 { Some(a * 2) } else { None };

// Traverse/sequence consistency (Ok case):
// bi_traverse(f, g, x) = bi_sequence(bimap(f, g, x))
let ok: Result<i32, String> = Ok(5);
assert_eq!(
	bi_traverse::<ResultBrand, _, _, _, _, OptionBrand>(f, g, ok.clone()),
	bi_sequence::<ResultBrand, _, _, OptionBrand>(bimap::<ResultBrand, _, _, _, _>(f, g, ok)),
);

// Traverse/sequence consistency (Err case):
let err: Result<i32, String> = Err("hello".to_string());
assert_eq!(
	bi_traverse::<ResultBrand, _, _, _, _, OptionBrand>(f, g, err.clone()),
	bi_sequence::<ResultBrand, _, _, OptionBrand>(bimap::<ResultBrand, _, _, _, _>(f, g, err)),
);

Required Methods§

Source

fn bi_traverse<'a, A: 'a + Clone, B: 'a + Clone, C: 'a + Clone, D: 'a + Clone, F: Applicative>( f: impl Fn(A) -> <F as Kind_cdc7cd43dac7585f>::Of<'a, C> + 'a, g: impl Fn(B) -> <F as Kind_cdc7cd43dac7585f>::Of<'a, D> + 'a, p: <Self as Kind_266801a817966495>::Of<'a, A, B>, ) -> <F as Kind_cdc7cd43dac7585f>::Of<'a, <Self as Kind_266801a817966495>::Of<'a, C, D>>

Traverses the bitraversable structure with two effectful functions.

This method applies f to values of the first type and g to values of the second type, accumulating all effects in the applicative context F.

§Type Signature

forall A B C D F. Applicative F => (A -> F C, B -> F D, Self A B) -> F (Self C D)

§Type Parameters
  • 'a: The lifetime of the values.
  • A: The type of the first-position elements.
  • B: The type of the second-position elements.
  • C: The output type for first-position elements.
  • D: The output type for second-position elements.
  • F: The applicative context.
§Parameters
  • f: The function for first-position elements.
  • g: The function for second-position elements.
  • p: The bitraversable structure to traverse.
§Returns

The transformed structure wrapped in the applicative context.

§Examples
use fp_library::{
	brands::*,
	functions::*,
};

let x: Result<i32, i32> = Err(3);
let y = bi_traverse::<ResultBrand, _, _, _, _, OptionBrand>(
	|e: i32| Some(e + 1),
	|s: i32| Some(s * 2),
	x,
);
assert_eq!(y, Some(Err(4)));

Provided Methods§

Source

fn bi_sequence<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>( ta: <Self as Kind_266801a817966495>::Of<'a, <F as Kind_cdc7cd43dac7585f>::Of<'a, A>, <F as Kind_cdc7cd43dac7585f>::Of<'a, B>>, ) -> <F as Kind_cdc7cd43dac7585f>::Of<'a, <Self as Kind_266801a817966495>::Of<'a, A, B>>
where <F as Kind_cdc7cd43dac7585f>::Of<'a, A>: Clone, <F as Kind_cdc7cd43dac7585f>::Of<'a, B>: Clone,

Sequences a bitraversable structure containing applicative values.

Collapses a structure of effectful values into a single effectful structure, applying identity to both positions via Bitraversable::bi_traverse.

§Type Signature

forall A B F. Applicative F => Self (F A) (F B) -> F (Self A B)

§Type Parameters
  • 'a: The lifetime of the values.
  • A: The type of the first-position elements.
  • B: The type of the second-position elements.
  • F: The applicative context.
§Parameters
  • ta: The bitraversable structure containing applicative values.
§Returns

The applicative context wrapping the bitraversable structure.

§Examples
use fp_library::{
	brands::*,
	functions::*,
};

let x: Result<Option<i32>, Option<i32>> = Ok(Some(5));
let y = bi_sequence::<ResultBrand, _, _, OptionBrand>(x);
assert_eq!(y, Some(Ok(5)));

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§