Lets for example create a parser for integers:
fn parse_i32(s: &str) -> IResult<&str, i32> {
map_res(digit1, |s: &str| s.parse())(s)
}
That just works, but I see two issues here:
- It cannot be used with different error or input types
- It would be better if this function returned a parser instead of being a parser itself. It would be cleaner and may be more effective.
When I try to make it generic over input type, like this: parse_i32<I>(s: I) -> IResult<I, i32>
, it starts making me add lots of constraints over type I
, and I feel like there should be one or two constraint over this type. Also, I cannot use FromStr
to parse i32
, because the input type now is not &str
.
When I try to make it return a parser without making it general over input type, and possibly making it general over error type, I get errors that I just do not understand:
fn parse_i32_2() -> impl FnMut(&str) -> IResult<&str, i32> {
map_res(digit1, |s: &str| s.parse())
}
And the errors are:
error: implementation of `FnMut` is not general enough
--> src/day13/input_parser.rs:17:5
|
17 | map_res(digit1, |s: &str| s.parse())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnMut` is not general enough
|
= note: `impl FnMut(&'2 str) -> Result<(&'2 str, i32), nom::Err<nom::error::Error<&str>>>` must implement `FnMut<(&'1 str,)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnMut<(&'2 str,)>`, for some specific lifetime `'2`
error[E0308]: mismatched types
--> src/day13/input_parser.rs:17:5
|
17 | map_res(digit1, |s: &str| s.parse())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
::: /Users/romamik/.cargo/registry/src/github.com-1ecc6299db9ec823/nom-7.1.1/src/combinator/mod.rs:107:6
|
107 | ) -> impl FnMut(I) -> IResult<I, O2, E>
| ----------------------------------
| |
| the expected opaque type
| the found opaque type
|
= note: expected associated type `<impl FnMut(&str) -> Result<(&str, i32), nom::Err<nom::error::Error<&str>>> as FnOnce<(&str,)>>::Output`
found associated type `<impl FnMut(&str) -> Result<(&str, i32), nom::Err<nom::error::Error<&str>>> as FnOnce<(&str,)>>::Output`
I think these errors can be solved by adding named lifetimes, but making parser generic over I
will also resolve them and I prefer making it generic.
What is the right way to make such a parser?