#functor #applicative #monad #category-theory

higher-cat

Functors, Applicatives, Monads and other bad ideas

2 releases

✓ Uses Rust 2018 edition

0.1.1 Aug 7, 2019
0.1.0 Feb 26, 2019

#369 in Data structures

MPL-2.0+

30KB
733 lines

higher

Higher kinded types and other bad ideas for Rust.

Crates

  • higher: traits for emulating higher kinded types
  • higher-derive: custom derives for the above
  • higher-cat: the functor hierarchy implemented with the above

Licence

Copyright 2019 Bodil Stokke

This software is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

Code of Conduct

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.


lib.rs:

The Functor hierarchy using higher.

But Why?

This is just a proof of concept implementation of PureScript's functor hierarchy in Rust, and you should probably not use it extensively in your own code, not because it's buggy or unfinished but because it's not likely to produce very nice Rust code. I'm sorry, but this is Rust, it works differently from Haskell.

Nevertheless, if you ever wanted comonads and profunctors in Rust, you've got them.

What Is The Functor Hierarchy?

Honestly, if you didn't already learn this from Haskell or Scala or PureScript, put down the crate and back away. As mentioned above, you are much better off using Rusty idioms to write your code, and I would recommend learning about these concepts in the context of a language (such as Haskell) where they belong.

If you still want to learn about functors and applicatives and monads, I highly recommend the Category Theory for Programmers series.

Custom Derives

The higher-derive crate provides a custom derive for Functor:

# use higher_derive::{Lift, Functor};
# use higher::Lift;
# use higher_cat::Functor;
# fn main() {
#[derive(Lift, Functor, PartialEq, Debug)]
enum MyLittleOption<A> {
    Definitely(A),
    NotReally,
}

// The derive will map any variant field of type `A`:
let i = MyLittleOption::Definitely(123);
let o = i.map(|value: u8| value.to_string());
assert_eq!(MyLittleOption::Definitely("123".to_string()), o);

// And it will leave variants without an `A` in them alone:
let i = MyLittleOption::NotReally;
let o = i.map(|value: u8| value.to_string());
assert_eq!(MyLittleOption::NotReally, o);
# }

Please note that this derive only maps types of A, and will not be able to work on types of eg. Vec<A>. You'll have to write your own Functor implementation for these.

Dependencies