Conversation
core/src/hlist.rs
Outdated
| // this is how it's done at the type-level | ||
| // <<<Self as HList>::Len as typenum::IsEqual<typenum::U0>>::Output as typenum::Bit>::BOOL |
There was a problem hiding this comment.
I've left this in to illustrate that this change doesn't forec the new way of doing things. Things can get pretty gnarly.
core/src/hlist.rs
Outdated
| <<T1 as HZippable<T2>>::Zipped as HList>::Len: Add<UInt<UTerm, B1>>, | ||
| <<<T1 as HZippable<T2>>::Zipped as HList>::Len as Add<UInt<UTerm, B1>>>::Output: Unsigned, |
There was a problem hiding this comment.
a) we need to pull out the type-defined length of the post-zipped list, and ensure that it is a type that implements the Add trait, effectively "the type cat play the role of a in a + 1"
b) with that addition constaint satisfied, we need to get the output, and ensure that it is a type that can fill the roll of b in a + 1 = b
core/src/hlist.rs
Outdated
| let mut v = Vec::with_capacity(<Self as HList>::LEN); | ||
| let mut v = Vec::with_capacity(<<Self as HList>::Len as Unsigned>::USIZE); |
There was a problem hiding this comment.
One option is to return an array instead of a vector, because now the length is fundementally know at compile time. GenericArray could be used, making this a no_std compatable conversion
lloydmeta
left a comment
There was a problem hiding this comment.
Overall, I understand the motivation for this. At the same time, I'm weighing if this should be in frunk , and thus force a dependency on typenum and associated compile-time-hit, or whether users who need this should just enable nightly and use the generic_const_exprs option (playground example).
core/src/hlist.rs
Outdated
| /// assert_eq!(h.len(), 2); | ||
| /// # } | ||
| /// ``` | ||
| #[deprecated(since = "0.5.0", note = "Please use <Self as HList>::Len::[USIZE | U8 | U32 | ... ] instead")] |
There was a problem hiding this comment.
I think it would not make much sense to deprecate this method and push users towards using the Typenum-coupled type.
core/src/hlist.rs
Outdated
| /// # } | ||
| /// ``` | ||
| #[deprecated(since = "0.1.31", note = "Please use LEN instead")] | ||
| #[deprecated(since = "0.1.31", note = "Please use Len::USIZE instead")] |
There was a problem hiding this comment.
On the other hand, I think we should probably think about finally removing this long-deprecated method..
|
The problem arises when you want to apply constraints such as length. This fix addresses a limitation of compile-time constant generics, but doesn't fully leverage the type system. For example, what if I want to constrain to a particular length? or that any given trait implementation, two values assosciated with a trait must satisfy some sort of truth? (a == b/2, or a < b). I'm not aware of any features, nightly or otherwise, that says you can do something like this: trait SomeTrait<const LHS: usize, const RHS: u32>
where
LHS: < RHS,
LHS + RHS: 10,
{Const generics are a fine incremental improvement to the language, I have a strong opinion that it is no substitute for true compile-time, type-system-only, types-as-values utility. |
I understand. My proposal was that Pasted here: #![feature(generic_const_exprs)]
use typenum::*; // 1.17.0
trait HList {
const SIZE: usize;
}
trait HWApi<N> {
fn config<L>(hlist: L) -> ()
where
L: HList,
Const<{ <L as HList>::SIZE }>: IsEqual<N>;
} |
|
I wasn't familiar with that as an option. I can see it coming in handy, but I still hold the view that there is merit to type-level expression of length being a core-feature of an HList construct. An
vs not restricting to the
It makes sense to me to retain the number-component of an HList type-construction. I can also see it making sense to keep the The value of adding Also, there might be corner cases where the utility of the type-len is diminished by relying on As for the issue with typenum being an additional dependency, I'll have a look at making it a feature-gated dependency. Without that, how do you feel about re-exporting the typenum crate alongside HList? Next update of this PR will include restoration of the |
|
I've updated with the following changes:
...that last point is a bit hacky. It needs a nightly feature to do it, but I don't want to turn this into a crate that needs a nightly build, especially if it's just for documentation. To this end, I added a nightly feature, and anything that needs nightly is gated behand that: On my CI, I get a failure when building for thumbv6m-none-eabi: cargo check --target thumbv6m-none-eabi --no-default-features I get the same locally on my machine. Not exactly sure what's going on there. Will investigate and come back with findings. |
|
++ I like the new direction ( |
|
Big issues with the documentation. For me, I don't like the idea of This makes things a bit silly in CI, CD, the use of
of these, I'm leaning towards 3.
I also think 3 has a non-zero chance of smooth the way to resolving the CI issue. This CI fail also merits a discussion-issue regarding the std feature... |
I'm a bit confused about what you mean by "lie". To be clear are you saying that the compiler will error out if typenum is used w/o actually using the feature (as opposed to "warn", and succeed), telling the user to turn on the feature to resolve? If so, I think that is fine. I'm -1 on compiler simply warning and succeeding compilation. |
You are correct. I wrote "warn" when I meant "error". I'll go with opt 3 |
|
CI fixed on my end, and added typenum feature to the published docs. My main concern now is that with the typenum length, HList implementations need to add where-clauses that rely on that feature. As far as I know, you can't hide the where-clause behind a feature gate, and so duplicate implementations must be written, using #[cfg[(not](.... to choose between the two. this is not all that nice, and welcome suggestions to improve, but as it stands, it's a required compromise if we want to put the typed-length behind a feature gate. With that in mind, it might be worth adding some things to the CI work flow to run tests with/without the typenum feature, but I don't want to hack away at that too much, at least without your direction. |
| name = "frunk" | ||
| edition = "2021" | ||
| version = "0.4.2" | ||
| version = "0.5.0" |
There was a problem hiding this comment.
Does this version bumb still need to happen? except for the removal of a long-deprecated function, all changes are backwards compatable and additions are feature-gated. perhaps a bump to 0.4.3 instead?
...then again, pre-major reseales, bumps are pretty much free anyway...
| #[cfg(feature = "typenum")] | ||
| impl<H, T: HList> HList for HCons<H, T> | ||
| where | ||
| <T as HList>::Len: Add<B1>, | ||
| <<T as HList>::Len as Add<B1>>::Output: Unsigned, | ||
| { | ||
| type Len = <<T as HList>::Len as Add<B1>>::Output; | ||
| const LEN: usize = 1 + <T as HList>::LEN; | ||
| } | ||
| #[cfg(not(feature = "typenum"))] | ||
| impl<H, T: HList> HList for HCons<H, T> { | ||
| const LEN: usize = 1 + <T as HList>::LEN; |
There was a problem hiding this comment.
Any suggestions RE: this duplication? it's exactly the same except for the added where-clases, but if there's a way to feature gate where-clases only, I'm unfamiliar
| } | ||
| } | ||
|
|
||
| #[cfg(feature = "typenum")] |
There was a problem hiding this comment.
A bit out of scope for this PR, but I feel this should return an array of known-length, and it be up to the library user to say "no, I want it as a Vec".
Perhaps a middle ground though: implement the into array, and into vec is provided as a conveniece wrapper arround let ??? = list.into(); let vector = ???.into();
| #[cfg(feature = "typenum")] | ||
| assert_eq!(<HList![usize, &str, f32] as HList>::Len::USIZE, 3); |
|
...hold off on morging for a bit. I'm getting a feel for using it in practice. |
|
....there's a problem: impl<DCT: HList, P: SetDutyCycle, PinsT: HList> PWMPinSetter<HCons<u16, DCT>, HCons<P, PinsT>> {
fn set_pin(dc_list: HCons<u16, DCT>, pins: HCons<P, PinsT>) {
pins.head.set_duty_pct(dc_list.head);
PWMPinSetter::set_pin(dc_list.tail, pins.tail)
}
}...that's pretty damn close to what I want, but I get this error: error[E0277]: cannot add basically, the way I enterpret it, is that each time you prepend a new head to an existing list, I've set it up so that My stratagy was to set it such that thoughts? |
This creates a version bump and upgrades the HList assossciated assosciated const LEN to an assostiated
type: typenum::UnsignedMotivation is as follows: I have a trait that needs a fixed length heterogenous list, but the length is generic to only a few numbers. the non generic way of implementing it:
I the requirements for this library are for
HWApi[1, 2, 3, 4, 6]and I'd like to be able to define it as so:...This is only possible at the type level when HList has a canonical expression of its length at the type level as well.