Provides functional types for dart.

Why should I use this library?
There are many libraries providing functional types, but they provide to many ways to opt-out of the safe handling of values. This library tries to enforce safe handling of values by clearly marking actions with 'unsafe', which could cause exceptions.

IMPORTANT

This is a pre-release version and the public api might change.

Features

Provides the following types:

  • x Option
  • x Either
  • x Result
    • ExTrace (Wrapper for Exception/Error and StackTrace)

Also provides extension-functions on Iterables of the above types.

Getting started

More examples are in the example folder of the git repository.

Usage

Option

void main(List<String>? nullableArgs) {
  final maybeArgs = Option.of(nullableArgs);

  // Match both cases
  maybeArgs.match(
          onSome: (args) => print('Arguments were provided'),
          onNone: () => print('Missing arguments'));

  // Match only on non-null value
  maybeArgs.ifSome((args) => print('Arguments were provided'));
  // async
          () async {
    await maybeArgs
            .ifSomeAsync((args) async => print('Arguments were provided'));
  }();

  // Match only on null value
  maybeArgs.ifNone(() => print('Missing arguments'));
  // async
          () async {
    await maybeArgs.ifNoneAsync(() async => print('Missing arguments'));
  }();

  // Safely get inner value
  maybeArgs.get(List.empty());
  // with function
  maybeArgs.getOr(() => List.empty());
  // async
          () async {
    await maybeArgs.getOrAsync(() async => List.empty());
  }();
}

Either

void main() {
  final num = one();

  // Match both cases
  num.match(
      onLeft: (oneStr) {
        print(oneStr.runtimeType == String);
      },
      onRight: (oneInt) {
        print(oneInt.runtimeType == int);
      }
  );

  // Match only one case
  num.ifLeft((left) => print(left.runtimeType == String));
  // async
  () {
    num.ifLeftAsync((left) async => print(left.runtimeType == String));
  }();

  // Safely get inner value
  num.left("2");
  // with function
  num.leftOr(() => "2");
  // async
  () async {
    await num.leftOrAsync(() async => "2");
  }();

  // Same for right ...
}

Either<String, int> one() {
  return Either.left("1");
}

Result

String failing() {
  throw Exception();
}

void main() {
  final stringResult = Result.tryCatch(() => failing());

  // Match both cases
  stringResult.match(
    onOk: (okStr) => print(okStr),
    onErr: (err) => print("${err.ex}: ${err.stackTrace}"),
  );

  // Match only on ok value
  stringResult.ifOk((str) => print(str));
  // async
  () async {
    await stringResult.ifOkAsync((str) async => print(str));
  }();

  // Match only on err value
  stringResult.ifErr((err) => print(err));
  // async
  () async {
    await stringResult.ifErrAsync((err) async => print(err));
  }();

  // Safely get inner value
  stringResult.ok("2");
  // with function
  stringResult.okOr(() => "2");
  // async
  () async {
    await stringResult.okOrAsync(() async => "2");
  }();

  // Safely get inner value
  stringResult.err(ExTrace(Exception(), StackTrace.current));
  // with function
  stringResult.errOr(() => ExTrace(Exception(), StackTrace.current));
  // async
  () async {
    await stringResult
        .errOrAsync(() async => ExTrace(Exception(), StackTrace.current));
  }();
}

Libraries

func_types
Support for doing something awesome.