1use crate::{
4 brands::Brand,
5 hkt::{Apply, Kind},
6};
7
8macro_rules! hkt {
10 (
11 $KindN:ident,
13 $ApplyN:ident,
15 $BrandN:ident,
17 $kind_str:literal,
19 ($($T:ident),+)
21 ) => {
22 #[doc = "Trait for [brands][crate::brands] of [types][crate::types] of kind `"]
23 #[doc = stringify!($kind_str)]
24 #[doc = "`."]
25 pub trait $KindN<$($T),+> {
26 type Output;
27 }
28
29 #[doc = "Alias for [types][crate::types] of kind `"]
30 #[doc = stringify!($kind_str)]
31 #[doc = "`."]
32 pub type $ApplyN<Brand, $($T),+> = <Brand as $KindN<$($T),+>>::Output;
33
34 impl<Brand, $($T),+> Kind<($($T,)+)> for Brand
35 where
36 Brand: $KindN<$($T),+>,
37 {
38 type Output = $ApplyN<Brand, $($T),+>;
39 }
40
41 #[doc = "Brand trait for [types][crate::types] with kind `"]
42 #[doc = stringify!($kind_str)]
43 #[doc = "`."]
44 pub trait $BrandN<Concrete, $($T),+>
45 where
46 Self: Kind<($($T,)+)>,
47 {
48 fn inject(a: Concrete) -> Apply<Self, ($($T,)+)>;
49 fn project(a: Apply<Self, ($($T,)+)>) -> Concrete;
50 }
51
52 impl<Me, Concrete, $($T),+> Brand<Concrete, ($($T,)+)> for Me
53 where
54 Me: Kind<($($T,)+)> + $BrandN<Concrete, $($T),+>,
55 {
56 fn inject(a: Concrete) -> Apply<Self, ($($T,)+)> {
57 <Me as $BrandN<Concrete, $($T),+>>::inject(a)
58 }
59
60 fn project(a: Apply<Self, ($($T,)+)>) -> Concrete {
61 <Me as $BrandN<Concrete, $($T),+>>::project(a)
62 }
63 }
64 };
65}
66
67hkt!(Kind1, Apply1, Brand1, "* -> *", (A));
68hkt!(Kind2, Apply2, Brand2, "* -> * -> *", (A, B));
69hkt!(Kind3, Apply3, Brand3, "* -> * -> * -> *", (A, B, C));
70hkt!(Kind4, Apply4, Brand4, "* -> * -> * -> * -> *", (A, B, C, D));