diff --git a/radn-derive/src/lib.rs b/radn-derive/src/lib.rs index 0f1ff75..bd29b0d 100644 --- a/radn-derive/src/lib.rs +++ b/radn-derive/src/lib.rs @@ -5,7 +5,7 @@ use syn::{parse_macro_input, parse_quote, DeriveInput, GenericParam, Generics}; pub fn derive_shared_functor(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = parse_macro_input!(input as DeriveInput); let name = input.ident; - let generics = add_trait_bounds(input.generics); + let generics = add_clone_bounds(input.generics); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let expanded = quote! { impl #impl_generics SharedFunctor for #name #ty_generics #where_clause { @@ -31,7 +31,7 @@ pub fn derive_shared_functor(input: proc_macro::TokenStream) -> proc_macro::Toke proc_macro::TokenStream::from(expanded) } -fn add_trait_bounds(mut generics: Generics) -> Generics { +fn add_clone_bounds(mut generics: Generics) -> Generics { for param in &mut generics.params { if let GenericParam::Type(ref mut type_param) = *param { type_param.bounds.push(parse_quote!(Clone)); @@ -39,3 +39,22 @@ fn add_trait_bounds(mut generics: Generics) -> Generics { } generics } + +#[proc_macro_derive(CovariantFunctor)] +pub fn derive_covariant_functor(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let input = parse_macro_input!(input as DeriveInput); + let name = input.ident; + let generics = input.generics; + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let expanded = quote! { + impl #impl_generics CovariantFunctor for #name #ty_generics #where_clause { + fn variate<'a: 'b, 'b, A: 'a>(fa: Self::F<'a, A>) -> Self::F<'b, A> + where + Self: 'a, + { + fa + } + } + }; + proc_macro::TokenStream::from(expanded) +} diff --git a/src/func.rs b/src/func.rs index 468989e..1efdf45 100644 --- a/src/func.rs +++ b/src/func.rs @@ -19,7 +19,7 @@ pub mod tests; pub use self::istate::IState; use self::istate::IStateClass; -pub use radn_derive::SharedFunctor; +pub use radn_derive::{CovariantFunctor, SharedFunctor}; /// Part of Haskell's `Functor f` responsible to use `f a`. /// diff --git a/src/func/classes/future.rs b/src/func/classes/future.rs index ffe43de..db00e22 100644 --- a/src/func/classes/future.rs +++ b/src/func/classes/future.rs @@ -9,6 +9,7 @@ use futures::{future::Shared, join, FutureExt}; use crate::func::*; +#[derive(CovariantFunctor)] pub struct FutureClass; impl WeakFunctor for FutureClass { diff --git a/src/func/classes/lazy.rs b/src/func/classes/lazy.rs index 9120e6a..63169f6 100644 --- a/src/func/classes/lazy.rs +++ b/src/func/classes/lazy.rs @@ -11,6 +11,7 @@ use std::{cell::RefCell, rc::Rc}; use crate::func::*; +#[derive(CovariantFunctor)] pub struct LazyClass; impl WeakFunctor for LazyClass { diff --git a/src/func/classes/option.rs b/src/func/classes/option.rs index 6328533..4d7f752 100644 --- a/src/func/classes/option.rs +++ b/src/func/classes/option.rs @@ -9,7 +9,7 @@ use crate::func::*; -#[derive(SharedFunctor)] +#[derive(SharedFunctor, CovariantFunctor)] pub struct OptionClass; impl WeakFunctor for OptionClass { diff --git a/src/func/classes/result.rs b/src/func/classes/result.rs index dcc54f9..03d4424 100644 --- a/src/func/classes/result.rs +++ b/src/func/classes/result.rs @@ -9,7 +9,7 @@ use crate::func::*; -#[derive(SharedFunctor)] +#[derive(SharedFunctor, CovariantFunctor)] pub struct ResultClass(E); impl WeakFunctor for ResultClass { diff --git a/src/func/classes/solo.rs b/src/func/classes/solo.rs index a2d1112..18d17f8 100644 --- a/src/func/classes/solo.rs +++ b/src/func/classes/solo.rs @@ -4,7 +4,7 @@ use crate::func::*; -#[derive(SharedFunctor)] +#[derive(SharedFunctor, CovariantFunctor)] pub struct SoloClass; impl WeakFunctor for SoloClass {