pub trait TryFuncMap<A, B, P = TypeParam<0>>: Sizedwhere
P: FuncMarker<P>,{
type Output;
// Required method
fn try_func_map<E, F>(self, f: F) -> Result<Self::Output, E>
where F: FnMut(A) -> Result<B, E>;
// Provided method
fn try_func_map_over<Q, E, F>(self, f: F) -> Result<Self::Output, E>
where F: FnMut(A) -> Result<B, E>,
Q: FuncMarker<P> { ... }
}Expand description
Fallible functorial mapping of a generic type over any of its type parameters
§Deriving TryFuncMap
In most cases, implementations of this trait can and should be derived automatically:
#[derive(TryFuncMap)]
struct Foo<T> {
// ...
}See the crate-level documentation for details.
§Manually Implementing TryFuncMap
If you need to implement TryFuncMap manually, make sure to uphold the
following contract:
Let Foo be a type that is generic over the type or const parameters
T0, ..., Tn.
If Foo implements TryFuncMap<A, B, TypeParam<N>>, then
Nmust be in the range0..=n.- The parameter of
Fooat indexN(not counting lifetime parameters) must beA. In particular, it must be a type parameter, not a const generic. Foo::Outputmust beFoowith the parameter at indexNreplaced withB.
Furthermore:
try_func_map_overmust behave in exactly the same way astry_func_map. This is the default behavior and must not be changed.- If the closure provided to
try_func_mapfails, then the result must be the first error according to the order of the fields in the definition ofFoo:#[derive(TryFuncMap, Copy, Clone, Debug, PartialEq)] struct Foo<T> { value1: T, value2: T, } let foo = Foo { value1: "1a", value2: "" }; let result: Result<Foo<i32>, ParseIntError> = foo.try_func_map(|v| v.parse()); assert!(result.is_err()); assert_eq!(*result.unwrap_err().kind(), IntErrorKind::InvalidDigit); - When implementing
TryFuncMapfor different marker typesTypeParam<N>andTypeParam<M>, the result of mapping over both type parameters in sequence must not depend on the order of the two mappings, i.e.foo.try_func_map_over::<TypeParam<N>, _, _>(f) .and_then(|x| x.try_func_map_over::<TypeParam<M>, _, _>(g)) // must be equivalent to foo.try_func_map_over::<TypeParam<M>, _, _>(g) .and_then(|x| x.try_func_map_over::<TypeParam<N>, _, _>(f))
Required Associated Types§
Required Methods§
Provided Methods§
Sourcefn try_func_map_over<Q, E, F>(self, f: F) -> Result<Self::Output, E>
fn try_func_map_over<Q, E, F>(self, f: F) -> Result<Self::Output, E>
Tries to apply the closure f to self in a functorial way, allowing
explicit specification of the marker type P
This is a convenience method that has the exact same functionality as
try_func_map but can be used to specify the
marker type P in a convenient way in cases where it is ambiguous.
So if you have
#[derive(TryFuncMap, Debug, PartialEq)]
struct Foo<S, T> {
s: S,
t: T,
}
let foo = Foo {
s: "42",
t: "42",
};then instead of writing
let bar = TryFuncMap::<_, _, TypeParam<1>>::try_func_map(foo, |v| v.parse::<i32>());
assert_eq!(bar, Ok(Foo { s: "42", t: 42 }));you can more conveniently write
let bar = foo.try_func_map_over::<TypeParam<1>, _, _>(|v| v.parse::<i32>());
assert_eq!(bar, Ok(Foo { s: "42", t: 42 }));This lets you chain method calls more easily as in
foo.try_func_map_over::<TypeParam<0>, _, _>(|v| v.parse::<i32>())
.and_then(|foo| foo.try_func_map_over::<TypeParam<1>, _, _>(|v| v.parse::<i32>()))Note that you still need to specify the inferred type _ for the
error type E and the closure type F.
§Errors
Fails if and only if f fails, returning the first error according to
the order of the fields in the definition of Self
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.