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
N
must be in the range0..=n
.- The parameter of
Foo
at indexN
(not counting lifetime parameters) must beA
. In particular, it must be a type parameter, not a const generic. Foo::Output
must beFoo
with the parameter at indexN
replaced withB
.
Furthermore:
try_func_map_over
must 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_map
fails, 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
TryFuncMap
for 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.