generics.rs 4.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #![recursion_limit = "128"]
  2. #[macro_use]
  3. extern crate generic_array;
  4. use generic_array::typenum::consts::U4;
  5. use std::fmt::Debug;
  6. use std::ops::Add;
  7. use generic_array::{GenericArray, ArrayLength};
  8. use generic_array::sequence::*;
  9. use generic_array::functional::*;
  10. /// Example function using generics to pass N-length sequences and map them
  11. pub fn generic_map<S>(s: S)
  12. where
  13. S: FunctionalSequence<i32>, // `.map`
  14. S::Item: Add<i32, Output = i32>, // `x + 1`
  15. S: MappedGenericSequence<i32, i32>, // `i32` -> `i32`
  16. MappedSequence<S, i32, i32>: Debug, // println!
  17. {
  18. let a = s.map(|x| x + 1);
  19. println!("{:?}", a);
  20. }
  21. /// Complex example function using generics to pass N-length sequences, zip them, and then map that result.
  22. ///
  23. /// If used with `GenericArray` specifically this isn't necessary
  24. pub fn generic_sequence_zip_sum<A, B>(a: A, b: B) -> i32
  25. where
  26. A: FunctionalSequence<i32>, // `.zip`
  27. B: FunctionalSequence<i32, Length = A::Length>, // `.zip`
  28. A: MappedGenericSequence<i32, i32>, // `i32` -> `i32`
  29. B: MappedGenericSequence<i32, i32, Mapped = MappedSequence<A, i32, i32>>, // `i32` -> `i32`, prove A and B can map to the same output
  30. A::Item: Add<B::Item, Output = i32>, // `l + r`
  31. MappedSequence<A, i32, i32>: MappedGenericSequence<i32, i32> + FunctionalSequence<i32>, // `.map`
  32. SequenceItem<MappedSequence<A, i32, i32>>: Add<i32, Output=i32>, // `x + 1`
  33. MappedSequence<MappedSequence<A, i32, i32>, i32, i32>: Debug, // `println!`
  34. MappedSequence<MappedSequence<A, i32, i32>, i32, i32>: FunctionalSequence<i32>, // `.fold`
  35. SequenceItem<MappedSequence<MappedSequence<A, i32, i32>, i32, i32>>: Add<i32, Output=i32> // `x + a`, note the order
  36. {
  37. let c = a.zip(b, |l, r| l + r).map(|x| x + 1);
  38. println!("{:?}", c);
  39. c.fold(0, |a, x| x + a)
  40. }
  41. /// Super-simple fixed-length i32 `GenericArray`s
  42. pub fn generic_array_plain_zip_sum(a: GenericArray<i32, U4>, b: GenericArray<i32, U4>) -> i32 {
  43. a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a)
  44. }
  45. pub fn generic_array_variable_length_zip_sum<N>(a: GenericArray<i32, N>, b: GenericArray<i32, N>) -> i32
  46. where
  47. N: ArrayLength<i32>,
  48. {
  49. a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a)
  50. }
  51. pub fn generic_array_same_type_variable_length_zip_sum<T, N>(a: GenericArray<T, N>, b: GenericArray<T, N>) -> i32
  52. where
  53. N: ArrayLength<T> + ArrayLength<<T as Add<T>>::Output>,
  54. T: Add<T, Output=i32>,
  55. {
  56. a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a)
  57. }
  58. /// Complex example using fully generic `GenericArray`s with the same length.
  59. ///
  60. /// It's mostly just the repeated `Add` traits, which would be present in other systems anyway.
  61. pub fn generic_array_zip_sum<A, B, N: ArrayLength<A> + ArrayLength<B>>(a: GenericArray<A, N>, b: GenericArray<B, N>) -> i32
  62. where
  63. A: Add<B>,
  64. N: ArrayLength<<A as Add<B>>::Output> +
  65. ArrayLength<<<A as Add<B>>::Output as Add<i32>>::Output>,
  66. <A as Add<B>>::Output: Add<i32>,
  67. <<A as Add<B>>::Output as Add<i32>>::Output: Add<i32, Output=i32>,
  68. {
  69. a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a)
  70. }
  71. #[test]
  72. fn test_generics() {
  73. generic_map(arr![i32; 1, 2, 3, 4]);
  74. assert_eq!(generic_sequence_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28);
  75. assert_eq!(generic_array_plain_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28);
  76. assert_eq!(generic_array_variable_length_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28);
  77. assert_eq!(generic_array_same_type_variable_length_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28);
  78. assert_eq!(generic_array_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28);
  79. }