ribs_core 1.0.0-dev.16 copy "ribs_core: ^1.0.0-dev.16" to clipboard
ribs_core: ^1.0.0-dev.16 copied to clipboard

Functional programming (FP) kernel. Provides common FP datatypes like Option, Either, State, Validated, as well as collection hierarchy inspired by the Scala programming language.

ribs_core #

Functional programming (FP) kernel for Dart. Provides common FP datatypes like Option, Either, State, and Validated, as well as a comprehensive immutable collection hierarchy inspired by the Scala programming language.

Full documentation is available at the ribs website.

Core Data Types #

Option #

Option represents optional values. Instances of Option are either a Some or None. It brings a wide variety of combinators not available on standard nullable types.

import 'package:ribs_core/ribs_core.dart';

final Option<int> someValue = Some(42);
final Option<int> noValue = none();

// Map and flatMap allow safe transformations
final result = someValue
  .map((v) => v * 2)
  .filter((v) => v > 50)
  .getOrElse(() => 0); // 84

Either #

Either represents one of two possible values (a disjoint union). It is right-biased, meaning methods like map and flatMap operate on the Right value. It is usually used for safe error handling.

Either<String, int> parse(String str) {
  try {
    return Right(int.parse(str));
  } catch (_) {
    return Left('Not a number');
  }
}

final valid = parse("42").map((n) => n + 1); // Right(43)
final invalid = parse("foo").map((n) => n + 1); // Left('Not a number')

Validated #

Unlike Either, Validated does not form a Monad (has no flatMap), but it supports error accumulation, usually in the form of ValidatedNel (a Validated instance where errors are collected in a NonEmptyIList).

ValidatedNel<String, User> validateUser(String name, int age) {
  final vName = name.isEmpty ? "Name cannot be empty".invalidNel<String>() : name.validNel<String>();
  final vAge = age < 18 ? "Must be 18 or older".invalidNel<int>() : age.validNel<String>();

  return vName.product(vAge).map((t) => User(t.$1, t.$2));
}

State #

State models state transitions of type S, yielding a value of type A. It allows for pure functional representations of state mutation.

final nextInt = State<int, int>((seed) {
  final next = (seed * 1103515245 + 12345) & 0x7FFFFFFF;
  return (next, next);
});

final (finalState, value) = nextInt.run(42);

Tuple Extensions #

ribs_core provides extensive syntax extensions for tuples up to 22 elements, adding utility methods like appended, prepended, map, head, tail, last, and more.

final t2 = (1, "A");
final t3 = t2.appended(true); // (1, "A", true)
final first = t3.head; // 1
final last = t3.last; // true

Collections Library #

ribs_core offers an immutable collections hierarchy inspired by Scala. These provide safer, more flexible alternatives to built-in collections.

  • IList: Immutable linked list, perfect for fast prepends and recursive algorithms.
  • IVector: Immutable vector, providing fast random access and updates.
  • IMap: Immutable key-value map.
  • IChain: Constant time append/prepend connection.
  • NonEmptyIList: An IList guaranteed to contain at least one element.
  • ILazyList: A lazy, potentially infinite linked list.
  • IMultiDict: Immutable map that associates keys with multiple values.
  • Many More!

Mutable variants also exist (ListBuffer, Array, HashMap, etc.) for use when performance dictates mutability under the hood.

Small Snippets #

// IList: standard linked list
final list = ilist([1, 2, 3]);
final more = list.prepended(0).appended(4); // IList(0, 1, 2, 3, 4)

// IVector: ideal for random lookups
final vec = ivec(["a", "b", "c"]);
final updatedVec = vec.updated(1, "z"); // IVector("a", "z", "c")

// IMap: immutable mapping
final map = imap({"test": 1});
final newMap = map.updated("other", 2); // IMap({"test": 1, "other": 2})

// Collection traversals
final evens = list.filter((x) => x % 2 == 0);

Rich Collections API #

The collections API includes hundreds of methods for transforming, filtering, and aggregating data, many of which are not available in the standard Dart SDK:

  • foldLeft / foldRight: Explicitly ordered reductions.
  • zip / zipWithIndex: Combine collections or pair elements with their indices.
  • partition: Split a collection into two based on a predicate.
  • collect: Filter and transform elements in a single pass.
  • groupBy: Organize elements into a map based on a key selector.
  • sliding / grouped: Windowed or chunked iteration.
  • distinctBy: Filter for unique elements based on a specific property.
  • Many More!
final items = ilist([1, 2, 3, 4, 5]);

// Partition into evens and odds
final (evens, odds) = items.partition((x) => x % 2 == 0);

// Sliding window of size 2
final windows = items.sliding(2); // [[1, 2], [2, 3], [3, 4], [4, 5]]

In-Depth Examples #

For a more comprehensive look at ribs_core features working together to solve problems robustly, check out the example located at example/example.dart in the package source.

1
likes
150
points
191
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Functional programming (FP) kernel. Provides common FP datatypes like Option, Either, State, Validated, as well as collection hierarchy inspired by the Scala programming language.

Homepage
Repository (GitHub)
View/report issues

Topics

#functional-programming #collections #immutable #option #either

License

unknown (license)

Dependencies

meta

More

Packages that depend on ribs_core