Skip to content

A general optional sum of product type which can be Neither, Left, Right or Both.

License

Notifications You must be signed in to change notification settings

Trehinos/any_of

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

83 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AnyOf : a versatile type for Rust

Rust

This project implements a flexible Algebraic Data Type : AnyOf.

AnyOf is an optional sum of product of two types,
which enables clear and safe data representations in functional and type-driven programming.

Overview

At the core of the project is the AnyOf enum, a general-purpose algebraic type, alongside additional types as EitherOf and BothOf.

These abstractions allow to express dynamic states, optional values, and branching logic in a natural and explicit manner.

Key Types

  1. AnyOf<L, R>

    • A flexible type that represents four possible states:
      • Neither: No value is present.
      • Either:
        • Left: Only the left value is present.
        • Right: Only the right value is present.
      • Both: Both values are present.
    • It combines variants in the following way:
      AnyOf<L, R> = Neither
                  | Either(EitherOf<L, R>)
                  | Both(BothOf<L, R>)
      
    • Its cases are:
      AnyOf(l: L, r: R) = Neither 
                        | Either(Left(l))
                        | Either(Right(r)) 
                        | Both(BothOf{left = l, right = r})
      
    • This type can also be viewed as a product of two optional types:
      AnyOf<L, R>::any() -> (Option<L>, Option<R>)
      
      Cases :
      • Neither.any() returns (None, None)
      • Left(L).any() returns (Some(L), None)
      • Right(R).any() returns (None, Some(R))
      • Both(L, R).any() returns (Some(L), Some(R))
  2. EitherOf<L, R>

    • A simple sum type representing one of two values.
    • Variants:
      • Left(L)
      • Right(R)
    • Ideal for binary decision-making.
    • Implements any() too :
      • Left(L).any() returns (Some(L), None)
      • Right(R).any() returns (None, Some(R))
    • It is the type :
      EitherOf<L, R> = Left(L) | Right(R)
      
  3. BothOf<L, R>

    • A product type that pairs two values, left and right, of potentially different types.
    • Implements any() too :
      • BothOf{ left: L, right: R }.any() returns (Some(L), Some(R))
    • It is the type:
      BothOf<L, R> = {left: L, right: R}
      
    • It can be transformed into a tuple with:
      into_couple(self) -> Couple<L, R>,
    • And can be transformed from a tuple with:
      from_couple(Couple<L, R>) -> Self,
  4. Enhanced Type Composition

    • A Couple<T, U> is a (T, U),
    • A Pair<T> is a Couple<T, T>,
    • An Any<T, U> is a Couple<Option<T>, Option<U>>,
    • Complex types like AnyOf4, AnyOf8, and AnyOf16 are implemented for handling larger, structured combinations via nested AnyOf structures.
    • The LeftOrRight trait :
      • Provides the methods is_right(), is_left(), any(), left() and right().
      • Implemented by AnyOf, EitherOf and BothOf,
      • Can be implemented by a custom type.
    • Other useful traits : Unwrap<L, R>, Swap<L, R> and Map<L, R>.

Features and Utilities

  • Methods inspired by Rust's Option and Result types:

    • Creation utilities: new, new_left, new_both, etc.
    • State checks: is_neither, is_left, is_both, etc.
    • Transformations: map_left, map_right, swap, etc.
    • Unwrapping: unwrap_left, unwrap_right, unwrap_both.
  • Flexible combinations:

    • Operators :
      • + to combine AnyOf values, or,
      • - to filter AnyOf values, or,
      • ! to swap AnyOf, EitherOf and BothOf values,
      • >> to map AnyOf, EitherOf and BothOf values,
    • Default value handling and state manipulation methods.

Type diagram PNG

Download the type diagram.

Use Cases

AnyOf and its related types simplify dynamic state management and are well-suited for:

  • Branching logic in functional programming.
  • Handling optional or partial data.
  • Implementing explicit and exhaustive handling of all potential states.
  • Minimizing boilerplate for complex decision-making.

Motivation

The project aims to enrich Rust's type system with expressive and flexible types for representing data combinations and states.
It is inspired by the Haskel's Either type.

  • Unlike the Rust's Result type, the types AnyOf, EitherOf or LeftOrRight have not an "error" semantic, they are general purpose,
  • LeftOrRight<L, R>::any() can be represented by a (Option<L>, Option<R>) which is a product of two optional types, but the two types has not the same composition conciseness :
    AnyOf<AnyOf<LL, LR>, AnyOf<RL, RR>>
    vs
    (Option<(Option<LL>, Option<LR>)>, Option<(Option<RL>, Option<RR>)>)
    
    AnyOf<AnyOf<AnyOf<LLL, LLR>, AnyOf<LRL, LRR>>, AnyOf<AnyOf<RLL, RLR>, AnyOf<RRL, RRR>>>
    vs
    (Option<(Option<(Option<LLL>, Option<LLR>)>, Option<(Option<LRL>, Option<LRR>)>)>, Option<(Option<(Option<RLL>, Option<RLR>)>, Option<(Option<RRL>, Option<RRR>)>)>)
    

Status

The library may evolve following semantic versioning, so the API will be stable in a given major version.

Feedback is welcome!

License

© 2025 Sébastien Geldreich
Distributed under the MIT License.