-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Typenum list #232
base: master
Are you sure you want to change the base?
Typenum list #232
Changes from 4 commits
10960f6
5678174
001a667
bdad2d1
a024384
f2ff09c
91f4442
e0783fc
b1521ae
053516a
327efd1
e3995ca
cb668a9
56484d5
8f83135
8d687fe
6a86de8
02bbdf8
8a9775a
f39266f
ce74350
906c499
7cb7052
fb310a6
424d769
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
[package] | ||
name = "frunk" | ||
edition = "2021" | ||
version = "0.4.2" | ||
version = "0.5.0" | ||
authors = ["Lloyd <[email protected]>"] | ||
description = "Frunk provides developers with a number of functional programming tools like HList, Coproduct, Generic, LabelledGeneric, Validated, Monoid, Semigroup and friends." | ||
license = "MIT" | ||
|
@@ -19,7 +19,7 @@ time = "0.3" | |
[dependencies.frunk_core] | ||
path = "core" | ||
default-features = false | ||
version = "0.4.2" | ||
version = "0.5.0" | ||
|
||
[dependencies.frunk_proc_macros] | ||
path = "proc-macros" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
[package] | ||
name = "frunk_core" | ||
edition = "2021" | ||
version = "0.4.2" | ||
version = "0.5.0" | ||
authors = ["Lloyd <[email protected]>"] | ||
description = "Frunk core provides developers with HList, Coproduct, LabelledGeneric and Generic" | ||
license = "MIT" | ||
|
@@ -18,6 +18,7 @@ std = [] | |
|
||
[dependencies] | ||
serde = { version = "^1.0", optional = true, features = [ "derive" ] } | ||
typenum = { version = "1.17.0", default-features = false } | ||
|
||
[dev-dependencies.frunk_derives] | ||
path = "../derives" | ||
|
@@ -27,7 +28,7 @@ version = "0.4.1" | |
[dev-dependencies.frunk] | ||
path = ".." | ||
default-features = false | ||
version = "0.4.2" | ||
version = "0.5.0" | ||
|
||
[dev-dependencies.frunk_proc_macros] | ||
path = "../proc-macros" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,6 +59,8 @@ use crate::indices::{Here, Suffixed, There}; | |
use crate::traits::{Func, IntoReverse, Poly, ToMut, ToRef}; | ||
#[cfg(feature = "serde")] | ||
use serde::{Deserialize, Serialize}; | ||
use typenum::bit::B1; | ||
use typenum::{Unsigned, UInt, UTerm}; | ||
|
||
use std::ops::Add; | ||
|
||
|
@@ -67,19 +69,26 @@ use std::ops::Add; | |
/// An HList is a heterogeneous list, one that is statically typed at compile time. In simple terms, | ||
/// it is just an arbitrarily-nested Tuple2. | ||
pub trait HList: Sized { | ||
/// Returns the length of a given HList type without making use of any references, or | ||
/// in fact, any values at all. | ||
/// The type-level encapsulation of the lists length, using `typenum` under the hood. | ||
/// | ||
/// # Examples | ||
/// ``` | ||
/// # fn main() { | ||
/// use typenum::Unsigned; | ||
/// use frunk::prelude::*; | ||
/// use frunk_core::HList; | ||
/// | ||
/// assert_eq!(<HList![i32, bool, f32]>::LEN, 3); | ||
/// type LenThree = HList![bool, (), u8]; | ||
/// fn foo<T: typenum::IsEqual<typenum::U3>>() {} | ||
/// | ||
/// let _ = foo::<<LenThree as HList>::Len>(); | ||
/// let byte: u8 = <<LenThree as HList>::Len>::U8; | ||
/// | ||
/// | ||
/// assert_eq!(<LenThree as HList>::Len::USIZE, 3); | ||
/// # } | ||
/// ``` | ||
const LEN: usize; | ||
type Len: Unsigned; | ||
|
||
/// Returns the length of a given HList | ||
/// | ||
|
@@ -93,9 +102,10 @@ pub trait HList: Sized { | |
/// 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would not make much sense to deprecate this method and push users towards using the Typenum-coupled type. |
||
#[inline] | ||
fn len(&self) -> usize { | ||
Self::LEN | ||
<Self::Len as Unsigned>::USIZE | ||
} | ||
|
||
/// Returns whether a given HList is empty | ||
|
@@ -112,7 +122,7 @@ pub trait HList: Sized { | |
/// ``` | ||
#[inline] | ||
fn is_empty(&self) -> bool { | ||
Self::LEN == 0 | ||
<Self::Len as Unsigned>::USIZE == 0 | ||
} | ||
|
||
/// Returns the length of a given HList type without making use of any references, or | ||
|
@@ -127,7 +137,7 @@ pub trait HList: Sized { | |
/// assert_eq!(<HList![i32, bool, f32]>::static_len(), 3); | ||
/// # } | ||
/// ``` | ||
#[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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On the other hand, I think we should probably think about finally removing this long-deprecated method.. |
||
fn static_len() -> usize; | ||
|
||
/// Prepends an item to the current HList | ||
|
@@ -168,9 +178,9 @@ pub trait HList: Sized { | |
pub struct HNil; | ||
|
||
impl HList for HNil { | ||
const LEN: usize = 0; | ||
type Len = typenum::U0; | ||
fn static_len() -> usize { | ||
Self::LEN | ||
<Self::Len as Unsigned>::USIZE | ||
} | ||
} | ||
|
||
|
@@ -183,10 +193,14 @@ pub struct HCons<H, T> { | |
pub tail: T, | ||
} | ||
|
||
impl<H, T: HList> HList for HCons<H, T> { | ||
const LEN: usize = 1 + <T as HList>::LEN; | ||
impl<H, T: HList> HList for HCons<H, T> | ||
where | ||
<T as HList>::Len: Add<typenum::U1>, | ||
<<T as HList>::Len as Add<typenum::U1>>::Output: Unsigned | ||
{ | ||
type Len = <<T as HList>::Len as Add<typenum::U1>>::Output; | ||
fn static_len() -> usize { | ||
Self::LEN | ||
<Self::Len as Unsigned>::USIZE | ||
} | ||
} | ||
|
||
|
@@ -252,6 +266,9 @@ macro_rules! gen_inherent_methods { | |
pub fn len(&self) -> usize | ||
where Self: HList, | ||
{ | ||
// this is how it's done at the type-level | ||
// <Self as HList>::Len::USIZE | ||
#[allow(deprecated)] | ||
HList::len(self) | ||
} | ||
|
||
|
@@ -272,6 +289,8 @@ macro_rules! gen_inherent_methods { | |
where Self: HList, | ||
{ | ||
HList::is_empty(self) | ||
// 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've left this in to illustrate that this change doesn't forec the new way of doing things. Things can get pretty gnarly. |
||
} | ||
|
||
/// Prepend an item to the current HList | ||
|
@@ -1123,6 +1142,8 @@ impl HZippable<HNil> for HNil { | |
impl<H1, T1, H2, T2> HZippable<HCons<H2, T2>> for HCons<H1, T1> | ||
where | ||
T1: HZippable<T2>, | ||
<<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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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 |
||
{ | ||
type Zipped = HCons<(H1, H2), T1::Zipped>; | ||
fn zip(self, other: HCons<H2, T2>) -> Self::Zipped { | ||
|
@@ -1438,11 +1459,13 @@ where | |
impl<H, Tail> Into<Vec<H>> for HCons<H, Tail> | ||
where | ||
Tail: Into<Vec<H>> + HList, | ||
<Tail as HList>::Len: Add<UInt<UTerm, B1>>, | ||
<<Tail as HList>::Len as Add<UInt<UTerm, B1>>>::Output: Unsigned, | ||
{ | ||
fn into(self) -> Vec<H> { | ||
let h = self.head; | ||
let t = self.tail; | ||
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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One option is to return an array instead of a vector, because now the length is fundementally know at compile time. |
||
v.push(h); | ||
let mut t_vec: Vec<H> = t.into(); | ||
v.append(&mut t_vec); | ||
|
@@ -1905,7 +1928,7 @@ mod tests { | |
|
||
#[test] | ||
fn test_len_const() { | ||
assert_eq!(<HList![usize, &str, f32] as HList>::LEN, 3); | ||
assert_eq!(<HList![usize, &str, f32] as HList>::Len::USIZE, 3); | ||
} | ||
|
||
#[test] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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...