functor_derive

Crates.iofunctor_derive
lib.rsfunctor_derive
version0.4.3
sourcesrc
created_at2023-10-28 10:33:59.558604
updated_at2024-04-12 08:01:14.068198
descriptionA derive macro to derive a functor for a type.
homepage
repositoryhttps://github.com/binary-banter/functor_derive
max_upload_size
id1016839
size78,008
Julia (Vlamonster)

documentation

README

Functor Derive

githubcrates-iodocs-rs

This crate can generate a functor for generic structs and enums.

A functor is a trait that contains an fmap function that maps a generic parameter. This enables you to transform the contents of any type without altering its shape.

The following example demonstrates how to derive a functor, providing you with an fmap method. For more intricate examples, refer to the tests directory in the project repository.

use functor_derive::Functor;

#[derive(Functor)]
struct MyType<T> {
    value: T,
    list: Vec<T>,
    unaffected: bool,
}

fn main() {
    let original = MyType { value: 42, list: vec![1, 3], unaffected: false };
    let transformed = original.fmap(|x| (x, x * 2));

    assert_eq!(transformed.value, (42, 84));
    assert_eq!(transformed.list, vec![(1, 2), (3, 6)]);
}

Additionally, a try_fmap function is generated. This can be useful for fallible transformations.

let original = MyType { value: "42", list: vec!["1", "3"], unaffected: false };
let transformed = original.try_fmap(|x| x.parse::<u64>())?;

Attribute

You can invoke the derive macro in multiple ways. Omitting the attribute defaults to deriving the Functor trait for the first generic type parameter, as illustrated in the first example above.

Alternatively, you can specify a default type to override the derive macro, which will prevent the derive macro choosing the first generic type parameter. This is done as follows:

#[derive(Functor)]
#[functor(T2)]
struct MyType<T1, T2> {
    field_1: T1,
    field_2: T2,
}

Sometimes, you might want to rename your fmap function using the as keyword. The following example generates the method fmap_keys.

#[derive(Functor)]
#[functor(K as keys)]
struct MyType<K> {
    keys: Vec<K>
}

The above options can be combined to generate multiple implementations, by separating the options with commas. The code below generates 3 methods: fmap, fmap_keys and fmap_values.

use std::collections::HashMap;
use std::hash::Hash;

#[functor(V, K as keys, V as values)]
struct MyHashMap<K: Hash + Eq, V> {
    v: HashMap<K, V>
}

Supported features

This crate can handle the following perfectly:

  • Structs - except for unit structs, which cannot be generic
  • Enums
  • Arrays
  • Tuples
  • std::collections: Vec, VecDeque, LinkedList, HashSet, HashMap, BTreeMap, Result, Option, PhantomData
  • Nested types, like Option<Box<T>>
  • (Mutually) recursive types
  • Bounded parameters, like T: Display

If you find a case where the derive macro fails, feel free to open an issue here

Commit count: 64

cargo fmt