diff --git a/examples/do_constructor_pitfalls/bin/do_constructor_pitfalls.dart b/examples/do_constructor_pitfalls/bin/do_constructor_pitfalls.dart
deleted file mode 100644
index f130b599..00000000
--- a/examples/do_constructor_pitfalls/bin/do_constructor_pitfalls.dart
+++ /dev/null
@@ -1,58 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-/// This file demonstrates some common pitfalls when using the `Do` constructor in the `fpdart` package.
-/// These are practices that should be avoided when using it.
-
-void main(List args) {}
-
-/// This function demonstrates that the `Do` constructor should not contain a `throw` statement.
-/// Throwing an exception inside a `Do` constructor can lead to unexpected behavior and should be avoided.
-/// Instead, use the `Option` type to handle errors.
-void doConstructorShouldNotContainThrow() {
- const testOption = const Option.of('test');
- Option.Do(
- ($) {
- if ($(testOption) == 'test') {
- // Do not throw inside a Do constructor
- throw Exception('Error');
- }
- return 'success';
- },
- );
-}
-
-/// This function demonstrates that the `Do` constructor should not contain an `await` statement without executing the `$` function.
-void doConstructorShouldNotAwaitWithoutExecutingDollarFunction() {
- Future future = Future.value('test');
- const testOption = const Option.of('test');
- Option.Do(
- ($) async {
- // Do not use `await` without executing the `$` function
- await future;
- return $(testOption);
- },
- );
-}
-
-// This function demonstrates that the `Do` constructor should not be nested.
-/// Nesting `Do` constructors can lead to unexpected behavior and should be avoided.
-void doConstructorShouldNotBeNested() {
- const testOption = const Option.of('test');
- // Do not nest Do constructors
- Option.Do(
- ($) => Option.Do(
- ($) => $(testOption),
- ),
- );
-}
-
-/// This function demonstrates that the `Do` constructor should not call the `$` function inside a callback.
-void doConstructorShouldNotCallDollarFunctionInCallback() {
- const testOption = const Option>.of(['test']);
- Option.Do(
- ($) => $(testOption).map(
- // Do not call the `$` function inside a callback
- (stringValue) => $(optionOf(stringValue)),
- ),
- );
-}
diff --git a/examples/do_constructor_pitfalls/pubspec.yaml b/examples/do_constructor_pitfalls/pubspec.yaml
deleted file mode 100644
index bfc18f84..00000000
--- a/examples/do_constructor_pitfalls/pubspec.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-name: fpdart_do_constructor_pitfalls
-publish_to: none
-version: 0.1.0
-homepage: https://www.sandromaglione.com/
-repository: https://github.com/SandroMaglione/fpdart
-description: Example of Functional programming in Dart and Flutter using fpdart. Pitfalls to avoid when using the do constructor.
-
-environment:
- sdk: ">=3.0.0 <4.0.0"
-
-dependencies:
- fpdart:
- path: ../../packages/fpdart
-
-dev_dependencies:
- lint: ^2.1.2
- test: ^1.24.3
- mocktail: ^0.3.0
diff --git a/examples/do_constructor_pitfalls/test/do_constructor_pitfalls_test.dart b/examples/do_constructor_pitfalls/test/do_constructor_pitfalls_test.dart
deleted file mode 100644
index ab73b3a2..00000000
--- a/examples/do_constructor_pitfalls/test/do_constructor_pitfalls_test.dart
+++ /dev/null
@@ -1 +0,0 @@
-void main() {}
diff --git a/examples/file_read_stream/.gitignore b/examples/file_read_stream/.gitignore
new file mode 100644
index 00000000..66e4ee6b
--- /dev/null
+++ b/examples/file_read_stream/.gitignore
@@ -0,0 +1 @@
+lib/output.json
\ No newline at end of file
diff --git a/examples/file_read_stream/analysis_options.yaml b/examples/file_read_stream/analysis_options.yaml
new file mode 100644
index 00000000..027c612f
--- /dev/null
+++ b/examples/file_read_stream/analysis_options.yaml
@@ -0,0 +1,12 @@
+include: package:lints/recommended.yaml
+
+linter:
+ rules:
+ annotate_overrides: true
+ prefer_void_to_null: false
+
+analyzer:
+ language:
+ strict-casts: true
+ strict-inference: true
+ strict-raw-types: true
diff --git a/examples/file_read_stream/lib/main.dart b/examples/file_read_stream/lib/main.dart
new file mode 100644
index 00000000..b8350a15
--- /dev/null
+++ b/examples/file_read_stream/lib/main.dart
@@ -0,0 +1,130 @@
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:fpdart/fpdart.dart';
+
+import './word.dart';
+
+typedef Env = ({
+ String wordPairCsv,
+ String wordsCsv,
+ String outputPath,
+});
+
+final wordPairs = Effect>.gen(($) async {
+ final env = $.sync(Effect.env());
+ final inputFile = File(env.wordPairCsv);
+
+ final lines = inputFile.openRead().transform(utf8.decoder).transform(
+ LineSplitter(),
+ );
+
+ final wordCollection = [];
+ await for (var line in lines) {
+ final split = line.split(',');
+ if (split.length != 3) {
+ return $.sync(Effect.fail("Missing word-pair info at: '$line'"));
+ }
+
+ final wordInfo = $
+ .sync(Effect.all([
+ Effect.fromNullable(
+ int.tryParse(split[0]),
+ onNull: () => "Missing id collection",
+ ),
+ Effect.fromNullable(
+ int.tryParse(split[1]),
+ onNull: () => "Missing id word1",
+ ),
+ Effect.fromNullable(
+ int.tryParse(split[2]),
+ onNull: () => "Missing id word2",
+ ),
+ ]))
+ .toList();
+
+ wordCollection.add(WordPair(wordInfo[0], wordInfo[1], wordInfo[2]));
+ }
+
+ return wordCollection;
+});
+
+final words = Effect>.gen(($) async {
+ final env = $.sync(Effect.env());
+ final wordCollection = await $.async(wordPairs);
+
+ final inputFile = File(env.wordsCsv);
+ final lines = inputFile.openRead().transform(utf8.decoder).transform(
+ LineSplitter(),
+ );
+
+ final wordMap = {};
+ await for (var line in lines) {
+ final split = line.split(',');
+ if (split.length < 2) {
+ return $.sync(Effect.fail("Missing word info at: '$line'"));
+ }
+
+ final idWord = $.sync(Effect.fromNullable(
+ int.tryParse(split[0]),
+ onNull: () => "Missing id word",
+ ));
+ final word = split[1];
+
+ wordMap[idWord] = word;
+ }
+
+ final wordFullList = [];
+ for (var entry in wordCollection) {
+ final word1 = $.sync(Effect.fromNullable(
+ wordMap[entry.idWord1],
+ onNull: () => "Missing word 1 at: $entry",
+ ));
+ final word2 = $.sync(Effect.fromNullable(
+ wordMap[entry.idWord2],
+ onNull: () => "Missing word 2 at: $entry",
+ ));
+
+ wordFullList.add(
+ WordFull(
+ entry.idCollection,
+ Word(entry.idWord1, word1),
+ Word(entry.idWord2, word2),
+ ),
+ );
+ }
+
+ return wordFullList.toSet().toList();
+});
+
+final program = Effect.gen(($) async {
+ final env = $.sync(Effect.env());
+ final wordFullList = await $.async(words);
+
+ final outputFile = File(env.outputPath);
+ await $.async(
+ Effect.tryCatch(
+ execute: () => outputFile.writeAsString(
+ "[${wordFullList.map((e) => e.toJson()).join(",\n")}]",
+ ),
+ onError: (_, __) => "Error while writing output file",
+ ),
+ );
+
+ return unit;
+});
+
+void main() async {
+ await program.provideEnv((
+ wordPairCsv: "./lib/word_pairs.csv",
+ wordsCsv: "./lib/words.csv",
+ outputPath: "./lib/output.json",
+ )).matchCause(
+ onFailure: (cause) {
+ print(cause);
+ },
+ onSuccess: (_) {
+ print("Success");
+ },
+ ).runFutureExit();
+}
diff --git a/examples/file_read_stream/lib/word.dart b/examples/file_read_stream/lib/word.dart
new file mode 100644
index 00000000..80e2d1b8
--- /dev/null
+++ b/examples/file_read_stream/lib/word.dart
@@ -0,0 +1,53 @@
+import 'package:equatable/equatable.dart';
+
+class WordPair {
+ final int idCollection;
+ final int idWord1;
+ final int idWord2;
+ const WordPair(this.idCollection, this.idWord1, this.idWord2);
+
+ @override
+ String toString() {
+ return "($idCollection)$idWord1|$idWord2";
+ }
+}
+
+class Word extends Equatable {
+ final int idWord;
+ final String word;
+ const Word(this.idWord, this.word);
+
+ @override
+ String toString() {
+ return "($idWord)$word";
+ }
+
+ @override
+ List
+> 🏗️ Pre-release version of `fpdart v2`
+
## Introduction
-> **fpdart is fully documented. You do not need to have any previous experience with functional programming to start using `fpdart`. Give it a try!**
+> **fpdart is fully documented. You do not need to have any previous experience with functional effect systems to start using `fpdart`. Give it a try!**
-fpdart is inspired by [fp-ts](https://gcanti.github.io/fp-ts/), [cats](https://typelevel.org/cats/typeclasses.html#type-classes-in-cats), and [dartz](https://github.com/spebbe/dartz).
+fpdart is inspired by [effect](https://www.effect.website/) and [dartz](https://github.com/spebbe/dartz).
> Follow my [**Twitter**](https://twitter.com/SandroMaglione) for updates, or [subscribe to the newsletter](https://www.sandromaglione.com/newsletter)
@@ -120,10 +122,8 @@ Interested in what `fpdart` is and how it came to be?
## 💻 Installation
-```yaml
-# pubspec.yaml
-dependencies:
- fpdart: ^1.1.0
+```shell
+dart pub add fpdart:'v2.0.0-dev.3'
```
## ✨ Examples
@@ -499,6 +499,11 @@ In general, **any contribution or feedback is welcome** (and encouraged!).
## 📃 Versioning
+- v2.0.0-dev.2 - 29 March 2024
+- v2.0.0-dev.1 - 23 March 2024
+
+***
+
- v1.1.0 - 13 August 2023
- **v1.0.0** - 26 July 2023
diff --git a/packages/fpdart/analysis_options.yaml b/packages/fpdart/analysis_options.yaml
index 4701dcd9..d9d369f6 100644
--- a/packages/fpdart/analysis_options.yaml
+++ b/packages/fpdart/analysis_options.yaml
@@ -3,6 +3,7 @@ include: package:lints/recommended.yaml
linter:
rules:
annotate_overrides: true
+ prefer_const_constructors: true
analyzer:
language:
diff --git a/packages/fpdart/example/api_requests/try_catch_validation.dart b/packages/fpdart/example/api_requests/try_catch_validation.dart
deleted file mode 100644
index 5cf6593d..00000000
--- a/packages/fpdart/example/api_requests/try_catch_validation.dart
+++ /dev/null
@@ -1,107 +0,0 @@
-import 'dart:convert';
-
-import 'package:fpdart/fpdart.dart';
-
-/// Example of API request with `fpdart` with validation
-/// Source: https://github.com/SandroMaglione/fpdart/issues/50#issue-1372504529
-
-/// Mock [Response] implementation
-class Response {
- final String body;
- Response(this.body);
-}
-
-/// Mock for `post` API request
-Response post(
- Uri uri, {
- Map? headers,
-}) =>
- Response('');
-
-TaskEither request() => TaskEither.tryCatch(
- () async {
- final Response getPrice = await post(
- Uri.parse("URL"),
- headers: {
- 'Content-Type': 'application/json; charset=UTF-8',
- },
- );
-
- final Map json =
- jsonDecode(getPrice.body) as Map;
-
- if (!json.containsKey("pricing")) {
- throw Exception("I don't have price");
- }
-
- return json["pricing"].toString();
- },
- (error, stackTrace) {
- return error.toString();
- },
- );
-
-/// Instead of placing all the request + validation inside `tryCatch`
-/// we want to chain different [TaskEither] methods.
-///
-/// This allows to create a pipeline where each step is responsible
-/// for a specific purpose (request, extract parameters, validation).
-///
-/// It's also important to implement a solid error reporting system,
-/// ideally by adding our own [Error] class.
-///
-/// Finally, in order for the request to be a **pure function** we want to
-/// pass all the parameters as inputs to the function
-typedef Pricing = String;
-
-abstract class RequestError {
- String get message;
-}
-
-class ApiRequestError implements RequestError {
- final Object error;
- final StackTrace stackTrace;
-
- ApiRequestError(this.error, this.stackTrace);
-
- @override
- String get message => "Error in the API request";
-}
-
-class MissingPricingRequestError implements RequestError {
- @override
- String get message => "Missing pricing in API response";
-}
-
-TaskEither makeRequest(String url) =>
- TaskEither.tryCatch(
- () async => post(
- Uri.parse(url),
- headers: {
- 'Content-Type': 'application/json; charset=UTF-8',
- },
- ),
- (error, stackTrace) => ApiRequestError(error, stackTrace),
- );
-
-Map mapToJson(Response response) =>
- jsonDecode(response.body) as Map;
-
-TaskEither> mappingRequest(String url) =>
- makeRequest(url).map(mapToJson);
-
-TaskEither validationRequest(Map json) =>
- !json.containsKey("pricing")
- ? TaskEither.left(MissingPricingRequestError())
- : TaskEither.of(json["pricing"].toString());
-
-TaskEither requestTE(String url) =>
- makeRequest(url).map(mapToJson).flatMap(validationRequest);
-
-/// **Note**: Ideally we should not access `post`, `Uri.parse`, and `jsonDecode` inside the function.
-///
-/// We should instead pass them as inputs to the function. This will allow to make the function
-/// completely pure, without hidden dependencies (i.e. accessing variables in the global scope).
-///
-/// Furthermore, doing this will help with testing, since we can provide our own mock
-/// implementation of those function for testing purposes.
diff --git a/packages/fpdart/example/do_notation/main.dart b/packages/fpdart/example/do_notation/main.dart
deleted file mode 100644
index adec7179..00000000
--- a/packages/fpdart/example/do_notation/main.dart
+++ /dev/null
@@ -1,83 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-TaskEither getUsernameFromId(int id) => TaskEither.of('sandro');
-TaskEither getProfilePicture(String username) =>
- TaskEither.of('image');
-int getPictureWidth(String image) => 10;
-TaskEither updatePictureWidth(int width) => TaskEither.of(true);
-
-Future getUsernameFromIdLinear(int id) async => 'sandro';
-Future getProfilePictureLinear(String username) async => 'image';
-int getPictureWidthLinear(String image) => 10;
-Future updatePictureWidthLinear(int width) async => true;
-
-/// Linear (no fpdart)
-Future changePictureSizeFromIdLinear(int id) async {
- final username = await getUsernameFromIdLinear(id);
- final image = await getProfilePictureLinear(username);
- final width = getPictureWidthLinear(image);
- return updatePictureWidthLinear(width);
-}
-
-/// Chaining
-TaskEither changePictureSizeFromId(int id) =>
- getUsernameFromId(id)
- .flatMap((username) => getProfilePicture(username))
- .map((image) => getPictureWidth(image))
- .flatMap((width) => updatePictureWidth(width));
-
-/// Do notation
-TaskEither changePictureSizeFromIdDo(int id) =>
- TaskEither.Do(
- (_) async {
- final username = await _(getUsernameFromId(id));
- final image = await _(getProfilePicture(username));
- final width = getPictureWidth(image);
- return _(updatePictureWidth(width));
- },
- );
-
-/// [map]: Update value inside [Option]
-Option map() => Option.of(10)
- .map(
- (a) => a + 1,
- )
- .map(
- (b) => b * 3,
- )
- .map(
- (c) => c - 4,
- );
-
-Option mapDo() => Option.Do((_) {
- final a = _(Option.of(10));
- final b = a + 1;
- final c = b * 3;
- return c - 4;
- });
-
-/// [flatMap]: Chain [Option]
-Option flatMap() => Option.of(10)
- .flatMap(
- (a) => Option.of(a + 1),
- )
- .flatMap(
- (b) => Option.of(b * 3),
- )
- .flatMap(
- (c) => Option.of(c - 4),
- );
-
-Option flatMapDo() => Option.Do((_) {
- final a = _(Option.of(10));
- final b = _(Option.of(a + 1));
- final c = _(Option.of(b * 3));
- return _(Option.of(c - 4));
- });
-
-/// [andThen]: Chain [Option] without storing its value
-Option andThen() => Option.of(10).andThen(() => Option.of(20));
-Option andThenDo() => Option.Do((_) {
- _(Option.of(10)); // Chain Option, but do not store the result
- return 20;
- });
diff --git a/packages/fpdart/example/logger/logger.dart b/packages/fpdart/example/logger/logger.dart
deleted file mode 100644
index 9b195ab5..00000000
--- a/packages/fpdart/example/logger/logger.dart
+++ /dev/null
@@ -1,78 +0,0 @@
-enum Level {
- verbose,
- debug,
- info,
- warning,
- error,
- wtf,
- nothing,
-}
-
-class LogEvent {
- final Level level;
- final dynamic message;
- final dynamic error;
- final StackTrace? stackTrace;
-
- LogEvent(this.level, this.message, this.error, this.stackTrace);
-}
-
-class OutputEvent {
- final Level level;
- final List lines;
-
- OutputEvent(this.level, this.lines);
-}
-
-abstract class LogFilter {
- bool shouldLog(LogEvent logEvent);
-}
-
-abstract class LogPrinter {
- List log(LogEvent logEvent);
-}
-
-abstract class LogOutput {
- void output(OutputEvent outputEvent);
-}
-
-class Logger {
- static Level level = Level.verbose;
- final bool _active = true;
- final LogFilter _filter;
- final LogPrinter _printer;
- final LogOutput _output;
-
- Logger(this._filter, this._printer, this._output);
-
- /// Log a message with [level].
- void log(
- Level level,
- dynamic message, [
- dynamic error,
- StackTrace? stackTrace,
- ]) {
- if (!_active) {
- throw ArgumentError('Logger has already been closed.');
- } else if (error != null && error is StackTrace) {
- throw ArgumentError('Error parameter cannot take a StackTrace!');
- } else if (level == Level.nothing) {
- throw ArgumentError('Log events cannot have Level.nothing');
- }
- var logEvent = LogEvent(level, message, error, stackTrace);
-
- if (_filter.shouldLog(logEvent)) {
- var output = _printer.log(logEvent);
-
- if (output.isNotEmpty) {
- var outputEvent = OutputEvent(level, output);
- try {
- _output.output(outputEvent);
- } catch (e, s) {
- print(e);
- print(s);
- }
- }
- }
- }
-}
diff --git a/packages/fpdart/example/logger/main.dart b/packages/fpdart/example/logger/main.dart
deleted file mode 100644
index a6d1fec5..00000000
--- a/packages/fpdart/example/logger/main.dart
+++ /dev/null
@@ -1,121 +0,0 @@
-/// Convert `log` function from `logger` package
-/// from Imperative to Functional code using `fpdart`
-///
-/// Repository: https://github.com/leisim/logger
-import 'package:fpdart/fpdart.dart';
-
-import 'logger.dart';
-
-class Logger {
- static Level level = Level.verbose;
- bool _active = true;
- final LogFilter _filter;
- final LogPrinter _printer;
- final LogOutput _output;
- Logger(this._filter, this._printer, this._output);
-
- /// Imperative (not-functional) code
- ///
- /// From https://github.com/leisim/logger/blob/6832ee0f5c430321f6a74dce99338b242861161d/lib/src/logger.dart#L104
- void log(
- Level level,
- dynamic message, [
- dynamic error,
- StackTrace? stackTrace,
- ]) {
- if (!_active) {
- throw ArgumentError('Logger has already been closed.');
- } else if (error != null && error is StackTrace) {
- throw ArgumentError('Error parameter cannot take a StackTrace!');
- } else if (level == Level.nothing) {
- throw ArgumentError('Log events cannot have Level.nothing');
- }
- var logEvent = LogEvent(level, message, error, stackTrace);
-
- if (_filter.shouldLog(logEvent)) {
- var output = _printer.log(logEvent);
-
- if (output.isNotEmpty) {
- var outputEvent = OutputEvent(level, output);
- try {
- _output.output(outputEvent);
- } catch (e, s) {
- print(e);
- print(s);
- }
- }
- }
- }
-}
-
-/// Functional approach 💪
-/// ----------------------------------------------------------------
-/// Use [IOEither] to handle errors and avoid throwing exceptions 🔨
-///
-/// Use [Unit] instead of `void` to represent a function that returns nothing 🎭
-IOEither logFunctional({
- required Level level,
- required dynamic message,
- required dynamic error,
- StackTrace? stackTrace,
-
- /// Add all external dependencies as input to make the function pure 🥼
- required bool active,
- required LogFilter filter,
- required LogPrinter printer,
- required LogOutput output,
-}) {
- /// Handle errors using [Either] instead of throwing errors 💥
- if (!active) {
- return IOEither.left('Logger has already been closed.');
- } else if (error != null && error is StackTrace) {
- return IOEither.left('Error parameter cannot take a StackTrace!');
- } else if (level == Level.nothing) {
- return IOEither.left('Log events cannot have Level.nothing');
- }
-
- /// Declare all the variables as `const` or `final` 🧱
- final logEvent = LogEvent(level, message, error, stackTrace);
-
- /// Make sure to handle all the cases using [Option] 🎉
- ///
- /// Use the `identity` function to return the input parameter as it is
- final shouldLogOption = Option.fromPredicate(
- filter.shouldLog(logEvent),
- identity,
- );
-
- /// Using [Option], you must specify both `true` and `false` cases 🌎
- return shouldLogOption.match(
- /// Simply return a [Unit] in the else case 🎁
- () => IOEither.of(unit),
-
- /// Use another [Option] to evaluate `printer.log`
- (_) => Option>.fromPredicate(
- printer.log(logEvent),
- (v) => v.isNotEmpty,
- ).match(
- /// Simply return a [Unit] in the else case 🎁
- () => IOEither.of(unit),
-
- (lines) {
- /// All variables are `final` 🧱
- final outputEvent = OutputEvent(level, lines);
- return IOEither.tryCatch(
- () {
- output.output(outputEvent);
-
- /// Return [Unit] 🎁
- return unit;
- },
- (e, s) {
- /// Return an error message 🔨
- ///
- /// Do not `print`, it would make the function impure! 🤯
- return 'An error occurred: $e';
- },
- );
- },
- ),
- );
-}
diff --git a/packages/fpdart/example/main.dart b/packages/fpdart/example/main.dart
index b046fff2..c93f5f84 100644
--- a/packages/fpdart/example/main.dart
+++ b/packages/fpdart/example/main.dart
@@ -1,124 +1,16 @@
import 'package:fpdart/fpdart.dart';
-void main() {}
-
-void overview() {
- /// [Option]
- const int? a = null;
- final Option b = none();
-
- /// You must manually handle missing values
- int resultI = 0;
- if (a != null) {
- resultI = a * 2;
- }
-
- /// No need to check for `null`
- final resultF = b.getOrElse(() => 0) * 2;
-}
-
-void imperativeVSfunctional() {
- /// Sum elements of a list
- const List list = [1, 2, 3, 4];
-
- /// Imperative solution
- int sumI = 0;
- for (int i = 0; i < list.length; ++i) {
- sumI = sumI + list[i];
- }
-
- /// Functional solution
- final sumF = list.fold(0, (p, c) => p + c);
-
- /// Composability
- /// Sum all elements of a list that are greater than 2
- /// Imperative solution
- int sum2I = 0;
- for (int i = 0; i < list.length; ++i) {
- final value = list[i];
- if (value > 2) {
- sum2I = sum2I + value;
- }
- }
-
- /// Functional solution
- final sum2F = list.where((e) => e > 2).fold(0, (p, c) => p + c);
-
- /// Extreme example
- ///
- /// How can you achieve the same result with Imperative code?
- /// Is it even possible? 🤷♂️
- final result = list
- .where((e) => e > 2)
- .concat([1, 2, 3])
- .drop(2)
- .intersect([1, 2, 3])
- .map((e) => e * 2)
- .take(3)
- .first;
-}
-
-void option() {
- /// Create an instance of [Some]
- final option = Option.of(10);
-
- /// Create an instance of [None]
- final none = Option.none();
-
- /// Map [int] to [String]
- final map = option.map((a) => '$a');
-
- /// Extract the value from [Option]
- final value = option.getOrElse(() => -1);
-
- /// Pattern matching
- final match = option.match(
- () => print('None'),
- (a) => print('Some($a)'),
- );
-
- /// Convert to [Either]
- final either = option.toEither(() => 'missing');
-
- /// Chain computations
- final flatMap = option.flatMap((a) => Option.of(a + 10));
-
- /// Return [None] if the function throws an error
- final tryCatch = Option.tryCatch(() => int.parse('invalid'));
-}
-
-void either() {
- /// Create an instance of [Right]
- final right = Either.of(10);
-
- /// Create an instance of [Left]
- final left = Either.left('none');
-
- /// Map the right value to a [String]
- final mapRight = right.map((a) => '$a');
-
- /// Map the left value to a [int]
- final mapLeft = right.mapLeft((a) => a.length);
-
- /// Return [Left] if the function throws an error.
- /// Otherwise return [Right].
- final tryCatch = Either.tryCatch(
- () => int.parse('invalid'),
- (e, s) => 'Error: $e',
- );
-
- /// Extract the value from [Either]
- final value = right.getOrElse((l) => -1);
-
- /// Chain computations
- final flatMap = right.flatMap((a) => Either.of(a + 10));
-
- /// Pattern matching
- final match = right.match(
- (l) => print('Left($l)'),
- (r) => print('Right($r)'),
- );
-
- /// Convert to [Option]
- final option = right.toOption();
-}
+typedef Env = ({String url, int seed});
+typedef Error = String;
+typedef Success = int;
+
+final either = Right(10);
+final option = Some(10);
+
+final effect = Effect.gen(($) async {
+ final eitherValue = $.sync(either);
+ final optionValue = $.sync(option);
+ final deferred = $.sync(Deferred.make().withEnv());
+ final value = await $.async(deferred.wait());
+ return eitherValue + optionValue;
+});
diff --git a/packages/fpdart/example/screenshot_fpdart.png b/packages/fpdart/example/screenshot_fpdart.png
index 4d120e5b..3ce61447 100644
Binary files a/packages/fpdart/example/screenshot_fpdart.png and b/packages/fpdart/example/screenshot_fpdart.png differ
diff --git a/packages/fpdart/example/src/either/cast.dart b/packages/fpdart/example/src/either/cast.dart
deleted file mode 100644
index f6dc0aca..00000000
--- a/packages/fpdart/example/src/either/cast.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-void main() {
- int intValue = 10;
-
- /// Unhandled exception: type 'int' is not a subtype of type 'List' in type cast
- final waitWhat = intValue as List;
- final first = waitWhat.first;
- print(first);
-
- /// Safe 🎯
- final wellYeah = Either>.safeCast(
- intValue,
- (dynamic value) => 'Not an List!',
- );
- final firstEither = wellYeah.map((list) => list.first);
- print(firstEither);
-
- /// Verify using `is`
- dynamic locationJson = 0;
-
- if (locationJson is List) {
- final first = locationJson.first;
- print(first);
- }
-}
diff --git a/packages/fpdart/example/src/either/chain_either.dart b/packages/fpdart/example/src/either/chain_either.dart
deleted file mode 100644
index 0dca6499..00000000
--- a/packages/fpdart/example/src/either/chain_either.dart
+++ /dev/null
@@ -1,88 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-class Cart {
- const Cart();
-}
-
-class User {
- String get uid => '';
-}
-
-class Order {
- const Order();
- factory Order.fromCart({required String userId, required Cart cart}) {
- return Order();
- }
-}
-
-class AuthRepository {
- User? get currentUser {
- return null;
- }
-}
-
-class CartRepository {
- Cart fetchCart(String uid) => Cart();
- Future setCart(String uid, Cart cart) {
- return Future.value();
- }
-}
-
-class OrdersRepository {
- Future addOrder(String uid, Order order) {
- return Future.value();
- }
-}
-
-final cartRepository = CartRepository();
-final authRepository = AuthRepository();
-final ordersRepository = OrdersRepository();
-
-Future placeOrder() async {
- /// Imperative try-catch code
- /// Source: https://codewithandrea.com/articles/flutter-exception-handling-try-catch-result-type/#when-the-result-type-doesnt-work-well
- try {
- final uid = authRepository.currentUser!.uid;
- // first await call
- final cart = await cartRepository.fetchCart(uid);
- final order = Order.fromCart(userId: uid, cart: cart);
- // second await call
- await ordersRepository.addOrder(uid, order);
- // third await call
- await cartRepository.setCart(uid, const Cart());
- } catch (e) {
- // TODO: Handle exceptions from any of the methods above
- }
-
- /// Same code using fpart and Functional programming
- Either.fromNullable(
- authRepository.currentUser?.uid,
- () => 'Missing uid',
- ).toTaskEither().flatMap(
- (uid) => TaskEither.tryCatch(
- () async => cartRepository.fetchCart(uid),
- (_, __) => 'Error while fetching cart',
- )
- .flatMap(
- (cart) => TaskEither.tryCatch(
- () async => ordersRepository.addOrder(
- uid,
- Order.fromCart(
- userId: uid,
- cart: cart,
- ),
- ),
- (_, __) => 'Error while adding order',
- ),
- )
- .flatMap(
- (_) => TaskEither.tryCatch(
- () async => cartRepository.setCart(
- uid,
- const Cart(),
- ),
- (_, __) => 'Error while setting cart',
- ),
- ),
- );
-}
diff --git a/packages/fpdart/example/src/either/either1.dart b/packages/fpdart/example/src/either/either1.dart
deleted file mode 100644
index 50d76458..00000000
--- a/packages/fpdart/example/src/either/either1.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-int? getNoEither(int index, List list) {
- if (index < 0 || index >= list.length) {
- return null;
- }
-
- return list[index];
-}
-
-Either getEither(int index, List list) {
- if (index < 0 || index >= list.length) {
- return Either.left('index not valid');
- }
-
- return Either.of(list[index]);
-}
-
-int multiply(int value) => value * 2;
-
-void main() {
- const list = [1, 2, 3];
-
- /// Without [Either], you must check that the value is not null.
- /// You must also remember to handle the case in which the value is null,
- /// what would happen then?
- final noEither = getNoEither(-1, list);
- if (noEither != null) {
- print(multiply(noEither));
- }
-
- /// With [Either], you are required to handle all cases. You will never run
- /// in unspecified edge cases.
- final withEither = getEither(-1, list);
- withEither.match((l) => print(l), (r) => print(multiply(r)));
-}
diff --git a/packages/fpdart/example/src/either/overview.dart b/packages/fpdart/example/src/either/overview.dart
deleted file mode 100644
index f22dd7ad..00000000
--- a/packages/fpdart/example/src/either/overview.dart
+++ /dev/null
@@ -1,60 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-/// Don't do that! ⚠
-int divideI(int x, int y) => x ~/ y; // this will throw if y == 0
-
-/// Error handling without exceptions using [Either] 🎉
-Either divideF(int x, int y) {
- if (y == 0) {
- return left('Cannot divide by 0');
- }
- return right(x ~/ y);
-}
-
-/// Error handling with exceptions using [Either] 🎉
-Either divide2F(int x, int y) {
- /// Easy way with caveat: first param type 'object' due to dart limitation
- return Either.tryCatch(() => x ~/ y, (o, s) => o.toString());
-}
-
-void main() {
- /// Create an instance of [Right]
- final right = Either.of(10);
-
- /// Create an instance of [Left]
- final left = Either.left('none');
-
- /// Map the right value to a [String]
- final mapRight = right.map((a) => '$a');
-
- /// Map the left value to a [int]
- final mapLeft = right.mapLeft((a) => a.length);
-
- /// Return [Left] if the function throws an error.
- /// Otherwise return [Right].
- final tryCatch = Either.tryCatch(
- () => int.parse('invalid'),
- (e, s) => 'Error: $e',
- );
-
- /// Extract the value from [Either]
- final value = right.getOrElse((l) => -1);
-
- /// Chain computations
- final flatMap = right.flatMap((a) => Either.of(a + 10));
-
- /// Pattern matching
- final match = right.match(
- (l) => print('Left($l)'),
- (r) => print('Right($r)'),
- );
-
- /// or use Dart's pattern matching as well 🤝
- final dartMatch = switch (right) {
- Left(value: final l) => 'Left($l)',
- Right(value: final r) => 'Right($r)',
- };
-
- /// Convert to [Option]
- final option = right.toOption();
-}
diff --git a/packages/fpdart/example/src/either/shopping/functional.dart b/packages/fpdart/example/src/either/shopping/functional.dart
deleted file mode 100644
index 75a519e0..00000000
--- a/packages/fpdart/example/src/either/shopping/functional.dart
+++ /dev/null
@@ -1,81 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-class Market {
- const Market();
-
- // I want to buy a Banana, an Apple, and a Pear. If either one
- // of these is missing, I will not but anything 😒
- Either buyBanana() => getRandomEither('🍌', "We got no 🍌");
- Either buyApple() => getRandomEither('🍎', "We got no 🍎");
- Either buyPear() => getRandomEither('🍐', "We got no 🍐");
-
- Either buyAmount() =>
- getRandomEither(randomInt(1, 10).run(), "Empty 💁🏼♂️");
-}
-
-Either getRandomEither(R right, L left) => randomBool
- .map>(
- (isValid) => isValid ? Either.of(right) : Either.left(left),
- )
- .run();
-
-// I go shopping in the Shopping Center. If it is closed, then
-// I will go to the Local Market (which is always open 🥇).
-Either goToShoppingCenter() =>
- getRandomEither(const Market(), "Shopping center closed ☝️");
-Either goToLocalMarket() => Either.of(const Market());
-
-// Combine all the instructions and go shopping! 🛒
-String goShopping() => goToShoppingCenter()
- .alt(goToLocalMarket)
- .flatMap(
- (market) => market.buyBanana().flatMap(
- (banana) => market.buyApple().flatMap(
- (apple) => market.buyPear().flatMap(
- (pear) => Either.of('Shopping: $banana, $apple, $pear'),
- ),
- ),
- ),
- )
- .getOrElse(identity);
-
-// Combine all the instructions and go shopping! 🛒
-String goShoppingDo() => Either.Do(
- (_) {
- final market = _(goToShoppingCenter().alt(goToLocalMarket));
- final amount = _(market.buyAmount());
-
- final banana = _(market.buyBanana());
- final apple = _(market.buyApple());
- final pear = _(market.buyPear());
-
- return 'Shopping: $banana, $apple, $pear';
- },
- ).getOrElse(identity);
-
-// Combine all the instructions and go shopping! 🛒
-String goShoppingDoFlatMap() => goToShoppingCenter()
- .alt(goToLocalMarket)
- .flatMap(
- /// Not required types here, since [Left] inferred from chain,
- /// and [Right] from the return type of `Do`
- (market) => Either.Do((_) {
- final banana = _(market.buyBanana());
- final apple = _(market.buyApple());
- final pear = _(market.buyPear());
- return 'Shopping: $banana, $apple, $pear';
- }),
- )
- .getOrElse(identity);
-
-void main() {
- for (int i = 0; i < 100; i++) {
- final shopping = goShopping();
- print(shopping);
- }
-
- for (int i = 0; i < 100; i++) {
- final shopping = goShoppingDo();
- print('[Do]: $shopping');
- }
-}
diff --git a/packages/fpdart/example/src/function/const_f.dart b/packages/fpdart/example/src/function/const_f.dart
deleted file mode 100644
index 3bdc3816..00000000
--- a/packages/fpdart/example/src/function/const_f.dart
+++ /dev/null
@@ -1,8 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-void main() {
- final c = constF(10);
- print(c('none')); // -> 10
- print(c('any')); // -> 10
- print(c(112.12)); // -> 10
-}
diff --git a/packages/fpdart/example/src/function/curry.dart b/packages/fpdart/example/src/function/curry.dart
deleted file mode 100644
index c0dd7655..00000000
--- a/packages/fpdart/example/src/function/curry.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-int sum(int param1, int param2) => param1 + param2;
-
-double sumMultiplyDivide(int param1, int param2, int param3, int param4) =>
- (param1 + param2) * param3 / param4;
-
-void main() {
- /// Convert a function with 2 parameters to a function that
- /// takes the first parameter and returns a function that takes
- /// the seconds parameter.
- final sumCurry = sum.curry;
- final sumBy2 = sumCurry(2);
- final sumBy10 = sumCurry(10);
- print(sumBy2(10));
- print(sumBy10(2));
-
- /// Same as above but with 4 parameters.
- final sumMultiplyDivideCurry = sumMultiplyDivide.curryAll;
- final sumBy5 = sumMultiplyDivideCurry(5);
- final multiplyBy2 = sumBy5(2);
- final divideBy3 = multiplyBy2(3);
- print(divideBy3(10));
- print(sumMultiplyDivideCurry(5)(2)(3)(10));
-
- /// Using the extension
- final sumBy2Extension = sum.curry(2);
- final sumBy10Extension = sum.curry(10);
- print(sumBy2Extension(10));
- print(sumBy10Extension(2));
-
- final fourParamsCurry = sumMultiplyDivide.curryAll;
- final fourParamsUncurry = fourParamsCurry.uncurry;
-}
diff --git a/packages/fpdart/example/src/function/identity.dart b/packages/fpdart/example/src/function/identity.dart
deleted file mode 100644
index c8e44c26..00000000
--- a/packages/fpdart/example/src/function/identity.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-Future main() async {
- final either = Either.of(10);
-
- /// Without using `identity`, you must write a function to return
- /// the input parameter `(l) => l`.
- final noId = either.match((l) => l, (r) => '$r');
-
- /// Using `identity`/`id`, the function just returns its input parameter.
- final withIdentity = either.match(identity, (r) => '$r');
-
- /// Using `identityFuture`/`idFuture`, the function just returns its input
- /// parameter, wrapped in `Future.value`.
- final withIdentityFuture = await either.match(
- identityFuture,
- (r) async => '$r',
- );
-}
diff --git a/packages/fpdart/example/src/io/overview.dart b/packages/fpdart/example/src/io/overview.dart
deleted file mode 100644
index 070911dd..00000000
--- a/packages/fpdart/example/src/io/overview.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-Future main() async {
- /// Create instance of [IO] from a value
- final IO io = IO.of(10);
-
- /// Create instance of [IO] from a sync function
- final ioRun = IO(() => 10);
-
- /// Map [int] to [String]
- final IO map = io.map((a) => '$a');
-
- /// Extract the value inside [IO] by running its function
- final int value = io.run();
-
- /// Chain another [IO] based on the value of the current [IO]
- final flatMap = io.flatMap((a) => IO.of(a + 10));
-}
diff --git a/packages/fpdart/example/src/list/fold.dart b/packages/fpdart/example/src/list/fold.dart
deleted file mode 100644
index e53af715..00000000
--- a/packages/fpdart/example/src/list/fold.dart
+++ /dev/null
@@ -1,33 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-void main() {
- const list = [1, 2, 3];
-
- print('--- Visualize fold left');
- final fl = list.foldLeft(0, (b, t) {
- print("([$b] - [$t])");
- return b - t;
- });
- print('== $fl');
-
- print('--- Visualize fold right');
- final fr = list.foldRight(0, (b, t) {
- print("([$b] - [$t])");
- return b - t;
- });
- print('== $fr');
-
- print('--- Visualize fold left with index');
- final fli = list.foldLeftWithIndex(0, (b, t, i) {
- print("([$b] - [$t] - [$i])");
- return b - t - i;
- });
- print('== $fli');
-
- print('--- Visualize fold right with index');
- final fri = list.foldRightWithIndex(0, (b, t, i) {
- print("([$b] - [$t] - [$i])");
- return b - t - i;
- });
- print('== $fri');
-}
diff --git a/packages/fpdart/example/src/list/overview.dart b/packages/fpdart/example/src/list/overview.dart
deleted file mode 100644
index 3d811213..00000000
--- a/packages/fpdart/example/src/list/overview.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-void main() {
- /// Dart: `1`
- [1, 2, 3, 4].first;
-
- /// fpdart: `Some(1)`
- [1, 2, 3, 4].head;
-
- /// Dart: Throws a [StateError] ⚠️
- [].first;
-
- /// fpdart: `None()`
- [].head;
-}
diff --git a/packages/fpdart/example/src/list/zip.dart b/packages/fpdart/example/src/list/zip.dart
deleted file mode 100644
index 71031c77..00000000
--- a/packages/fpdart/example/src/list/zip.dart
+++ /dev/null
@@ -1,8 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-void main() {
- final list1 = ['a', 'b'];
- final list2 = [1, 2];
- final zipList = list1.zip(list2);
- print(zipList); // -> [(a, 1), (b, 2)]
-}
diff --git a/packages/fpdart/example/src/map/overview.dart b/packages/fpdart/example/src/map/overview.dart
deleted file mode 100644
index 05e21e88..00000000
--- a/packages/fpdart/example/src/map/overview.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-void main() {
- final d1 = DateTime(2001, 1, 1);
- final d2 = DateTime(2001, 1, 2);
-
- /// Use `eq` based on the `DateTime` year to upsert in the map.
- ///
- /// The first date `d1` will be overwritten by the second date `d2`,
- /// since the year is the same.
- final map = {}
- .upsertAt(
- Eq.dateEqYear,
- d1,
- 1,
- )
- .upsertAt(
- Eq.dateEqYear,
- d2,
- 2,
- );
-
- print(map); // {2001-01-02 00:00:00.000: 2}
-}
diff --git a/packages/fpdart/example/src/option/cheat_sheet.md b/packages/fpdart/example/src/option/cheat_sheet.md
deleted file mode 100644
index b208bb60..00000000
--- a/packages/fpdart/example/src/option/cheat_sheet.md
+++ /dev/null
@@ -1,120 +0,0 @@
-# `Option` Cheat Sheet 👀
-
-```dart
-[_] -> None
-[🍌] -> Some(🍌)
-
-🤷♂️ -> null
-💥 -> Exception
-```
-
-## Constructors
-
-```dart
-some(🍌) -> [🍌]
-none() -> [_]
-
- 👆 same as 👇
-
-Option.of(🍌) -> [🍌]
-Option.none() -> [_]
-```
-
-```dart
-optionOf(🤷♂️) -> [_]
-optionOf(🍌) -> [🍌]
-
- 👆 same as 👇
-
-Option.fromNullable(🤷♂️) -> [_]
-Option.fromNullable(🍌) -> [🍌]
-```
-
-```dart
-option(🍌, (b) => b == 🍌) -> [🍌]
-option(🍌, (b) => b == 🍎) -> [_]
-
- 👆 same as 👇
-
-Option.fromPredicate(🍌, (b) => b == 🍌) -> [🍌]
-Option.fromPredicate(🍌, (b) => b == 🍎) -> [_]
-```
-
-```dart
-Option.tryCatch(() => 🍌) -> [🍌]
-Option.tryCatch(() => 💥) -> [_]
-```
-
-```dart
-Option.flatten([ [🍌] ]) -> [🍌]
-```
-
-## Methods
-
-### `match`
-
-```dart
-[🍌].match((🍌) => 🍌 * 2, () => 🍎) -> 🍌🍌
-
-[_].match((🍌) => 🍌 * 2, () => 🍎) -> 🍎
-```
-
-### `getOrElse`
-
-```dart
-[🍌].getOrElse(() => 🍎) -> 🍌
-
-[_].getOrElse(() => 🍎) -> 🍎
-
- 👆 same as 👇
-
-[🍌].match((🍌) => 🍌, () => 🍎)
-```
-
-### `map`
-
-```dart
-[🥚].map((🥚) => 👨🍳(🥚)) -> [🍳]
-
-[_].map((🥚) => 👨🍳(🥚)) -> [_]
-```
-
-### `alt`
-
-```dart
-[🍌].alt(() => [🍎]) -> [🍌]
-
-[_].alt(() => [🍎]) -> [🍎]
-```
-
-### `andThen`
-
-```dart
-[🍌].andThen(() => [🍎]) -> [🍎]
-
-[_].andThen(() => [🍎]) -> [_]
-```
-
-### `flatMap`
-
-```dart
-[😀].flatMap(
- (😀) => [👻(😀)]
- ) -> [😱]
-
-[😀].flatMap(
- (😀) => [👻(😀)]
- ).flatMap(
- (😱) => [👨⚕️(😱)]
- ) -> [🤕]
-
-[😀].flatMap(
- (😀) => [_]
- ).flatMap(
- (_) => [👨⚕️(_)]
- ) -> [_]
-
-[_].flatMap(
- (😀) => [👻(😀)]
- ) -> [_]
-```
diff --git a/packages/fpdart/example/src/option/get-price/functional.dart b/packages/fpdart/example/src/option/get-price/functional.dart
deleted file mode 100644
index 8932094f..00000000
--- a/packages/fpdart/example/src/option/get-price/functional.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-Option getPrice(String productName) {
- if (productName.length > 6) {
- return none();
- }
-
- return some(productName.length);
-}
-
-void main() {
- final price = getPrice('my product name');
- price.match(
- () {
- print('Sorry, no product found!');
- },
- (a) {
- print('Total price is: $price');
- },
- );
-}
diff --git a/packages/fpdart/example/src/option/get-price/non_functional.dart b/packages/fpdart/example/src/option/get-price/non_functional.dart
deleted file mode 100644
index 1d1834e9..00000000
--- a/packages/fpdart/example/src/option/get-price/non_functional.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-int? getPrice(String productName) {
- if (productName.length > 6) {
- return null;
- }
-
- return productName.length;
-}
-
-void main() {
- final price = getPrice('my product name');
- if (price == null) {
- print('Sorry, no product found!');
- } else {
- print('Total price is: $price');
- }
-}
diff --git a/packages/fpdart/example/src/option/nullable/option_nullable.dart b/packages/fpdart/example/src/option/nullable/option_nullable.dart
deleted file mode 100644
index fef3765b..00000000
--- a/packages/fpdart/example/src/option/nullable/option_nullable.dart
+++ /dev/null
@@ -1,64 +0,0 @@
-// ignore_for_file: unchecked_use_of_nullable_value, undefined_getter, unnecessary_null_comparison
-import 'package:fpdart/fpdart.dart';
-import 'package:glados/glados.dart';
-
-int doSomething(String str) => str.length + 10 * 2;
-int doSomethingElse(int number) => number + 10 * 2;
-
-void main(List args) {
- int? nullableInt = 10;
- if (nullableInt == null) {
- print("Missing ‼️");
- } else {
- print("Found $nullableInt 🎯");
- }
-
- /// 👆 Exactly the same as 👇
-
- Option optionInt = Option.of(10);
- optionInt.match(() {
- print("Missing ‼️");
- }, (t) {
- print("Found $nullableInt 🎯");
- });
-
- /// Null safety and `Option` save you from `null` 🚀
- String? str = Random().nextBool() ? "string" : null;
- Option optionStr = Random().nextBool() ? some("string") : none();
-
- /// ⛔️ The property 'toLowerCase' can't be unconditionally accessed because the receiver can be 'null'.
- str.toLowerCase;
-
- /// ⛔️ The getter 'toLowerCase' isn't defined for the type 'Option'.
- optionStr.toLowerCase;
-
- /// Option has methods that makes it more powerful (chain methods) ⛓
- String? strNullable = Random().nextBool() ? "string" : null;
- Option optionNullable = some("string");
-
- /// Declarative API: more readable and composable 🎉
- Option optionIntNullable = optionNullable
- .map(doSomething)
- .alt(() => some(20))
- .map(doSomethingElse)
- .flatMap((t) => some(t / 2));
-
- /// Not really clear what is going on here 🤔
- double? intNullable = (strNullable != null
- ? doSomethingElse(doSomething(strNullable))
- : doSomethingElse(20)) /
- 2;
-
- if (optionNullable.isSome()) {
- /// Still type `Option`, not `Some` 😐
- optionIntNullable;
- }
-
- if (strNullable != null) {
- /// This is now `String` 🤝
- strNullable;
- }
-
- List? list = Random().nextBool() ? [1, 2, 3, 4] : null;
- list.map((e) => /** What type is `e`? 😐 */ null);
-}
diff --git a/packages/fpdart/example/src/option/nullable/overview.dart b/packages/fpdart/example/src/option/nullable/overview.dart
deleted file mode 100644
index 102d7c2d..00000000
--- a/packages/fpdart/example/src/option/nullable/overview.dart
+++ /dev/null
@@ -1,46 +0,0 @@
-import 'dart:math';
-
-import 'package:fpdart/fpdart.dart';
-
-int? nullable() => Random().nextBool() ? 10 : null;
-
-String takesNullable(int? nullInt) => "$nullInt";
-
-void main(List args) {
- int noNull = 10;
- int? canBeNull = nullable();
-
- /// `bool`
- final noNullIsEven = noNull.isEven;
-
- /// final canBeNullIsEven = canBeNull.isEven; ⛔️
-
- /// `bool?`
- final canBeNullIsEven = canBeNull?.isEven;
-
- /// ☑️
- takesNullable(canBeNull);
-
- /// ☑️
- takesNullable(noNull);
-
- /// ☑️
- noNull.abs();
-
- /// ☑️
- canBeNull?.abs();
-
- Option optionInt = Option.of(10);
- int? nullInt = nullable();
-
- nullInt?.abs();
- optionInt.map((t) => t.abs());
-
- nullInt?.isEven;
- optionInt.map((t) => t.isEven);
-
- takesNullable(nullInt);
-
- /// takesNullable(optionInt); ⛔️
- takesNullable(optionInt.toNullable());
-}
diff --git a/packages/fpdart/example/src/option/option1.dart b/packages/fpdart/example/src/option/option1.dart
deleted file mode 100644
index 65cc871e..00000000
--- a/packages/fpdart/example/src/option/option1.dart
+++ /dev/null
@@ -1,30 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-void printString(String str) {
- print(str);
-}
-
-void main() {
- final String? str = 'name';
-
- /// Error: The argument type 'String?' can't be assigned to the parameter type 'String'
- // printString(str);
-
- /// With dart null-safety, you must check that the value is not null
- /// before calling the function
- ///
- /// What will happen if the value is `null` instead?
- /// You are not required to handle such case, which can lead to errors!
- if (str != null) {
- printString(str);
- }
-
- final Option mStr = Option.of('name');
-
- /// Using [Option] you are required to specify every possible case.
- /// The type system helps you to find and define edge-cases and avoid errors.
- mStr.match(
- () => print('I have no string to print 🤷♀️'),
- printString,
- );
-}
diff --git a/packages/fpdart/example/src/option/option2.dart b/packages/fpdart/example/src/option/option2.dart
deleted file mode 100644
index a4f6d818..00000000
--- a/packages/fpdart/example/src/option/option2.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-double sumToDouble(int a, int b) => (a + b).toDouble();
-
-void main() {
- final a = Option.of(10);
- final b = Option.of(20);
-
- /// `map` takes one parameter [int] and returns `sumToDouble`.
- /// We therefore have a function inside a [Option] that we want to
- /// apply to another value!
- final Option map = a.map(
- (a) => (int b) => sumToDouble(a, b),
- );
-
- /// Using `ap`, we get the final `Option` that we want 🚀
- final result = b.ap(map);
-}
diff --git a/packages/fpdart/example/src/option/option3.dart b/packages/fpdart/example/src/option/option3.dart
deleted file mode 100644
index 5e1637e9..00000000
--- a/packages/fpdart/example/src/option/option3.dart
+++ /dev/null
@@ -1,51 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-int? stringToIntNull(String a) {
- if (a.isNotEmpty) {
- return a.length;
- } else {
- return null;
- }
-}
-
-double? intToDoubleNull(int a) {
- if (a != 0) {
- return a / 2;
- } else {
- return null;
- }
-}
-
-Option stringToInt(String a) => Option.fromPredicateMap(
- a,
- (str) => str.isNotEmpty,
- (str) => str.length,
- );
-
-Option intToDouble(int a) =>
- Option.fromPredicateMap(a, (v) => v != 0, (v) => v / 2);
-
-void main() {
- /// Using `null`, you are required to check that the value is not
- /// `null` every time you call a function.
- ///
- /// Furthermore, you left unspecified what will happen when one of the
- /// values is a `null` 🤦♂️
- const aNull = 'name';
- final intNull = stringToIntNull(aNull);
- if (intNull != null) {
- final doubleNull = intToDoubleNull(intNull);
- }
-
- /// Using `flatMap`, you can forget that the value may be missing and just
- /// use it as if it was there.
- ///
- /// In case one of the values is actually missing, you will get a [None]
- /// at the end of the chain ⛓
- final a = Option.of('name');
- final Option result = a.flatMap(
- (s) => stringToInt(s).flatMap(
- (i) => intToDouble(i),
- ),
- );
-}
diff --git a/packages/fpdart/example/src/option/overview.dart b/packages/fpdart/example/src/option/overview.dart
deleted file mode 100644
index c1e103ff..00000000
--- a/packages/fpdart/example/src/option/overview.dart
+++ /dev/null
@@ -1,66 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-/// Don't do that! ⚠
-int divideI(int x, int y) => x ~/ y; // this will throw if y == 0
-
-/// Error handling without exceptions using [Option] 🎉
-Option divideF(int x, int y) {
- if (y == 0) {
- return none();
- }
- return some(x ~/ y);
-}
-
-/// Error handling with exceptions using [Option] 🎉
-Option divide2F(int x, int y) => Option.tryCatch(() => x ~/ y);
-
-void main() {
- // --- Initialize an Option 👇 --- //
- const someInit = Some(10);
- const noneInit = None();
-
- final someInit2 = some(10);
- final noneInit2 = none();
-
- /// Create an instance of [Some]
- final option = Option.of(10);
-
- /// Create an instance of [None]
- final noneInit3 = Option.none();
-
- /// If the predicate is `true`, then [Some], otherwise [None]
- final predicate = Option.fromPredicate(10, (a) => a > 5);
-
- /// If no exception, then [Some], otherwise [None]
- final tryCatchInit = Option.tryCatch(() => int.parse('10'));
-
- /// When the value is not `null`, then [Some], otherwise [None]
- final nullable = Option.fromNullable(10);
-
- /// Map [int] to [String]
- final map = option.map((a) => '$a');
-
- /// Extract the value from [Option]
- final value = option.getOrElse(() => -1);
-
- /// Pattern matching
- final match = option.match(
- () => print('None'),
- (a) => print('Some($a)'),
- );
-
- /// or use Dart's pattern matching as well 🤝
- final dartMatch = switch (option) {
- None() => 'None',
- Some(value: final a) => 'Some($a)',
- };
-
- /// Convert to [Either]
- final either = option.toEither(() => 'missing');
-
- /// Chain computations
- final flatMap = option.flatMap((a) => Option.of(a + 10));
-
- /// Return [None] if the function throws an error
- final tryCatch = Option.tryCatch(() => int.parse('invalid'));
-}
diff --git a/packages/fpdart/example/src/option/shopping/functional.dart b/packages/fpdart/example/src/option/shopping/functional.dart
deleted file mode 100644
index d6d10293..00000000
--- a/packages/fpdart/example/src/option/shopping/functional.dart
+++ /dev/null
@@ -1,83 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-class Market {
- const Market();
-
- // I want to buy a Banana, an Apple, and a Pear. If either one
- // of these is missing, I will not but anything 😒
- Option buyBanana() => getRandomOption('🍌');
- Option buyApple() => getRandomOption('🍎');
- Option buyPear() => getRandomOption('🍐');
-
- Option buyAmount() => getRandomOption(randomInt(1, 10).run());
-}
-
-Option getRandomOption(T value) => randomBool
- .map(
- (isValid) => isValid ? some(value) : none(),
- )
- .run();
-
-// I go shopping in the Shopping Center. If it is closed, then
-// I will go to the Local Market (which is always open 🥇).
-Option goToShoppingCenter() => getRandomOption(const Market());
-Option goToLocalMarket() => some(const Market());
-
-// Combine all the instructions and go shopping! 🛒
-String goShopping() => goToShoppingCenter()
- .alt(goToLocalMarket)
- .flatMap(
- (market) => market.buyBanana().flatMap(
- (banana) => market.buyApple().flatMap(
- (apple) => market.buyPear().flatMap(
- (pear) => Option.of('Shopping: $banana, $apple, $pear'),
- ),
- ),
- ),
- )
- .getOrElse(
- () => 'I did not find 🍌 or 🍎 or 🍐, so I did not buy anything 🤷♂️',
- );
-
-// Combine all the instructions and go shopping! 🛒
-String goShoppingDo() => Option.Do(
- (_) {
- final market = _(goToShoppingCenter().alt(goToLocalMarket));
- final amount = _(market.buyAmount());
-
- final banana = _(market.buyBanana());
- final apple = _(market.buyApple());
- final pear = _(market.buyPear());
-
- return 'Shopping: $banana, $apple, $pear';
- },
- ).getOrElse(
- () => 'I did not find 🍌 or 🍎 or 🍐, so I did not buy anything 🤷♂️',
- );
-
-// Combine all the instructions and go shopping! 🛒
-String goShoppingDoFlatMap() => goToShoppingCenter()
- .alt(goToLocalMarket)
- .flatMap(
- (market) => Option.Do((_) {
- final banana = _(market.buyBanana());
- final apple = _(market.buyApple());
- final pear = _(market.buyPear());
- return 'Shopping: $banana, $apple, $pear';
- }),
- )
- .getOrElse(
- () => 'I did not find 🍌 or 🍎 or 🍐, so I did not buy anything 🤷♂️',
- );
-
-void main() {
- for (int i = 0; i < 100; i++) {
- final shopping = goShopping();
- print(shopping);
- }
-
- for (int i = 0; i < 100; i++) {
- final shopping = goShoppingDo();
- print('[Do]: $shopping');
- }
-}
diff --git a/packages/fpdart/example/src/predicate/overview.dart b/packages/fpdart/example/src/predicate/overview.dart
deleted file mode 100644
index af75530b..00000000
--- a/packages/fpdart/example/src/predicate/overview.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-bool isEven(int n) => n % 2 == 0;
-bool isDivisibleBy3(int n) => n % 3 == 0;
-
-final isOdd = isEven.negate;
-final isEvenAndDivisibleBy3 = isEven.and(isDivisibleBy3);
-final isEvenOrDivisibleBy3 = isEven.or(isDivisibleBy3);
-final isStringWithEvenLength = isEven.contramap((n) => n.length);
diff --git a/packages/fpdart/example/src/pure_function.dart b/packages/fpdart/example/src/pure_function.dart
deleted file mode 100644
index 7ba7c820..00000000
--- a/packages/fpdart/example/src/pure_function.dart
+++ /dev/null
@@ -1,41 +0,0 @@
-/// `Impure function`
-///
-/// Modify input parameter
-List modifyInput(List list) {
- list.add(10); // <- Do not change input parameter 🙅♂️
- return list;
-}
-
-var global = 10;
-
-/// `Impure function`
-///
-/// Modify variable outside the scope of the function
-int modifyGlobal(int a) {
- global = global + a; // <- Do not change variable outside the function 🙅♂️
- return global;
-}
-
-/// `Impure function`
-///
-/// Side effects (Database, IO, API request)
-int sideEffect(int a) {
- print("Side effect"); // <- Do not introduce side effects 🙅♂️
- return global;
-}
-
-/// `Impure function`
-///
-/// Return `void`: Either the function does nothing, or a
-/// side effect is guaranteed to be executed
-void voidReturn(String str) {
- print(str); // <- Either side effect, or nothing 🙅♂️
- return;
-}
-
-/// `Impure function`
-///
-/// Throw [Exception] (use [Option] or [Either] instead)
-int throwException(int a) {
- throw Exception(); // <- Do not throw 🙅♂️
-}
diff --git a/packages/fpdart/example/src/reader/reader1.dart b/packages/fpdart/example/src/reader/reader1.dart
deleted file mode 100644
index 6bb26e3c..00000000
--- a/packages/fpdart/example/src/reader/reader1.dart
+++ /dev/null
@@ -1,51 +0,0 @@
-/// Source: https://gist.github.com/ruizb/554c17afb9cd3dedc76706862a9fa035
-import 'package:fpdart/src/reader.dart';
-
-/// Dependency
-abstract class Printer {
- String write(String message);
-}
-
-class BoldPrinter implements Printer {
- @override
- String write(String message) => '$message';
-}
-
-class ItalicPrinter implements Printer {
- @override
- String write(String message) => '$message';
-}
-
-/// Try 1: Supply the dependency every time you call the function
-String printing1(String name, Printer printer) => printer.write(name);
-
-/// Try 2: Hide the dependency by curring
-String Function(Printer) printing2(String name) =>
- (Printer printer) => printer.write(name);
-
-/// Try 3: Using the [Reader] monad to hide the dependency completely
-Reader printing3(String name) => Reader((r) => r.write(name));
-
-void main() {
- /// Required to pass [Printer] dependency, when all you would want is to
- /// pass the `name` and get the result.
- final String result1 = printing1('name', BoldPrinter());
- print(result1); // -> name
-
- /// Dependency on [Printer] hidden, but it is not possible to change
- /// the result from `render2` after `printing2` has been called (for example using `map`).
- final String Function(Printer) render2 = printing2('name');
- final String result2 = render2(BoldPrinter());
- print(result2); // -> name
-
- /// Dependency on [Printer] required only in the final call of `run`.
- /// Before that you can change the value without bothering about the [Printer].
- final Reader render3 = printing3('name');
- final Reader map = render3.map((a) => a.length);
-
- /// Reader allows dependency injection
- final String result3a = render3.run(BoldPrinter());
- final int result3b = map.run(ItalicPrinter());
- print(result3a); // -> name
- print(result3b); // -> 11
-}
diff --git a/packages/fpdart/example/src/reader/reader2.dart b/packages/fpdart/example/src/reader/reader2.dart
deleted file mode 100644
index 90d97942..00000000
--- a/packages/fpdart/example/src/reader/reader2.dart
+++ /dev/null
@@ -1,49 +0,0 @@
-/// Source: https://gist.github.com/ruizb/554c17afb9cd3dedc76706862a9fa035
-import 'package:fpdart/src/reader.dart';
-
-abstract class Dependency {
- void logger(String message);
- String get environment;
-}
-
-class PrintLog implements Dependency {
- @override
- String get environment => 'Production';
-
- @override
- void logger(String message) {
- print(message);
- }
-}
-
-/// Example 1: Without [Reader]
-///
-/// We are required to pass [Dependency] between all the intermediate functions
-/// (`b` and `a`), even if these functions do not use [Dependency]. Then just pass the
-/// value to `c`.
-int c(Dependency dependency) {
- dependency.logger('Current environment: ${dependency.environment}');
- return 1;
-}
-
-int b(Dependency dependency) => c(dependency) * 2;
-int a(Dependency dependency) => b(dependency) + 1;
-
-/// Example 2: Using [Reader]
-///
-/// Both `a` and `b` do not know about [Dependency]. The dependency is hidden
-/// being the [Reader]. `a` and `b` just care about the value [int].
-Reader cReader() => Reader((dependency) {
- dependency.logger('Current environment: ${dependency.environment}');
- return 1;
- });
-Reader bReader() => cReader().map((a) => a * 2);
-Reader aReader() => bReader().map((a) => a + 1);
-
-void main() {
- final resultNoReader = a(PrintLog());
- print(resultNoReader);
-
- final resultWithReader = aReader().run(PrintLog());
- print(resultWithReader);
-}
diff --git a/packages/fpdart/example/src/reader_task_either/overview.dart b/packages/fpdart/example/src/reader_task_either/overview.dart
deleted file mode 100644
index 1169079f..00000000
--- a/packages/fpdart/example/src/reader_task_either/overview.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-typedef Env = (int, String);
-typedef Error = String;
-typedef Success = String;
-
-void main(List args) async {
- final rte = ReaderTaskEither.Do((_) async {
- final a = 10;
- final val = await _(ReaderTaskEither.fromReader(
- Reader(
- (env) => env.$1 + env.$2.length,
- ),
- ));
- final env = await _(ReaderTaskEither.ask());
- final env2 = await _(ReaderTaskEither.asks((dep) => dep.$2));
-
- return "$a and $val and $env and $env2";
- });
-
- final result = await rte.run((30, "abc"));
- print(result);
-}
diff --git a/packages/fpdart/example/src/state/state1.dart b/packages/fpdart/example/src/state/state1.dart
deleted file mode 100644
index a007eafa..00000000
--- a/packages/fpdart/example/src/state/state1.dart
+++ /dev/null
@@ -1,57 +0,0 @@
-/// Source: http://www.learnyouahaskell.com/for-a-few-monads-more
-import 'package:fpdart/src/state.dart';
-import 'package:fpdart/src/unit.dart';
-
-/// [Stack] is an alias for [List].
-typedef Stack = List;
-
-const Stack stack = ['a', 'b', 'c'];
-
-/// Example Without State Monad
-///
-/// We need to explicitly pass the state [Stack] every time we call `pop` or `push`.
-
-(String, Stack) pop(Stack s) => (s.last, s.sublist(0, s.length - 1));
-
-(Unit, Stack) push(String value, Stack s) => (unit, [...s, value]);
-
-/// Example Using State Monad
-///
-/// The global variable [Stack] is hidden using [State].
-
-State popState() => State(
- (s) => (s.last, s.sublist(0, s.length - 1)),
- );
-
-State pushState(String value) => State(
- (s) => (unit, [...s, value]),
- );
-
-void main() {
- // Without State Monad
- final pop1NoState = pop(stack);
- final push1NoState = push('d', pop1NoState.$2);
- final pop2NoState = pop(push1NoState.$2);
- print('No State');
- print(stack);
- print('Pop');
- print(pop1NoState.$2);
- print(pop1NoState.$1);
- print("Push 'd'");
- print(push1NoState.$2);
- print('Pop');
- print(pop2NoState.$2);
- print(pop2NoState.$1);
-
- // Using State Monad
- print('---');
- print('Using State');
- final withState = popState().execute(
- pushState('d').execute(
- popState().run(stack).$2,
- ),
- );
- final withState2 = popState()(pushState('d'))(popState()).run(stack);
- print(withState);
- print(withState2);
-}
diff --git a/packages/fpdart/example/src/state_async/state_async1.dart b/packages/fpdart/example/src/state_async/state_async1.dart
deleted file mode 100644
index a44043c6..00000000
--- a/packages/fpdart/example/src/state_async/state_async1.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-Future add10(int previous) async => previous + 10;
-
-Future main() async {
- final stateAsync = StateAsync(
- (state) async => (unit, await add10(state)),
- );
-
- final result = await stateAsync.execute(10);
- print(result);
-}
diff --git a/packages/fpdart/example/src/task/overview.dart b/packages/fpdart/example/src/task/overview.dart
deleted file mode 100644
index 682885a9..00000000
--- a/packages/fpdart/example/src/task/overview.dart
+++ /dev/null
@@ -1,29 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-/// You must run one [Future] after the other, no way around this...
-Future asyncI() {
- return Future.value(10).then((value) => value * 10);
-}
-
-/// No need of `async`, you decide when to run the [Future] ⚡
-Task asyncF() {
- return Task(() async => 10).map((a) => a * 10);
-}
-
-Future main() async {
- /// Create instance of [Task] from a value
- final Task task = Task.of(10);
-
- /// Create instance of [Task] from an async function
- final taskRun1 = Task(() async => 10);
- final taskRun2 = Task(() => Future.value(10));
-
- /// Map [int] to [String]
- final Task map = task.map((a) => '$a');
-
- /// Extract the value inside [Task] by running its async function
- final int value = await task.run();
-
- /// Chain another [Task] based on the value of the current [Task]
- final flatMap = task.flatMap((a) => Task.of(a + 10));
-}
diff --git a/packages/fpdart/example/src/task/task_and_future.dart b/packages/fpdart/example/src/task/task_and_future.dart
deleted file mode 100644
index 1678ced8..00000000
--- a/packages/fpdart/example/src/task/task_and_future.dart
+++ /dev/null
@@ -1,92 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-/// Helper functions ⚙️ (sync)
-String addNamePrefix(String name) => "Mr. $name";
-String addEmailPrefix(String email) => "mailto:$email";
-String decodeName(int code) => "$code";
-
-/// API functions 🔌 (async)
-Future getUsername() => Future.value("Sandro");
-Future getEncodedName() => Future.value(10);
-
-Future getEmail() => Future.value("@");
-
-Future sendInformation(String usernameOrName, String email) =>
- Future.value(true);
-
-Future withFuture() async {
- late String usernameOrName;
- late String email;
-
- try {
- usernameOrName = await getUsername();
- } catch (e) {
- try {
- usernameOrName = decodeName(await getEncodedName());
- } catch (e) {
- throw Exception("Missing both username and name");
- }
- }
-
- try {
- email = await getEmail();
- } catch (e) {
- throw Exception("Missing email");
- }
-
- try {
- final usernameOrNamePrefix = addNamePrefix(usernameOrName);
- final emailPrefix = addEmailPrefix(email);
- return await sendInformation(usernameOrNamePrefix, emailPrefix);
- } catch (e) {
- throw Exception("Error when sending information");
- }
-}
-
-TaskEither withTask() => TaskEither.tryCatch(
- getUsername,
- (_, __) => "Missing username",
- )
- .alt(
- () => TaskEither.tryCatch(
- getEncodedName,
- (_, __) => "Missing name",
- ).map(
- decodeName,
- ),
- )
- .map(
- addNamePrefix,
- )
- .flatMap(
- (usernameOrNamePrefix) => TaskEither.tryCatch(
- getEmail,
- (_, __) => "Missing email",
- )
- .map(
- addEmailPrefix,
- )
- .flatMap(
- (emailPrefix) => TaskEither.tryCatch(
- () => sendInformation(usernameOrNamePrefix, emailPrefix),
- (_, __) => "Error when sending information",
- ),
- ),
- );
-
-Task getTask() => Task(() async {
- print("I am running [Task]...");
- return 10;
- });
-
-Future getFuture() async {
- print("I am running [Future]...");
- return 10;
-}
-
-void main() {
- Task taskInt = getTask();
- Future futureInt = getFuture();
-
- // Future taskRun = taskInt.run();
-}
diff --git a/packages/fpdart/example/src/task_either/async_flat_map/data.dart b/packages/fpdart/example/src/task_either/async_flat_map/data.dart
deleted file mode 100644
index 8cb51152..00000000
--- a/packages/fpdart/example/src/task_either/async_flat_map/data.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-class Student {
- final String name;
- Student(this.name);
-}
-
-class Course {
- final String name;
- Course(this.name);
-}
diff --git a/packages/fpdart/example/src/task_either/async_flat_map/failure.dart b/packages/fpdart/example/src/task_either/async_flat_map/failure.dart
deleted file mode 100644
index 402a7456..00000000
--- a/packages/fpdart/example/src/task_either/async_flat_map/failure.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-abstract class ApiFailure {}
-
-class StudentFailure implements ApiFailure {}
-
-class CourseFailure implements ApiFailure {}
diff --git a/packages/fpdart/example/src/task_either/async_flat_map/main.dart b/packages/fpdart/example/src/task_either/async_flat_map/main.dart
deleted file mode 100644
index c92fc1ee..00000000
--- a/packages/fpdart/example/src/task_either/async_flat_map/main.dart
+++ /dev/null
@@ -1,45 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-import 'data.dart';
-import 'failure.dart';
-import 'student_repo.dart';
-
-TaskEither> getStudents = TaskEither.tryCatch(
- () => StudentRepo.getAllStudents(),
- (_, __) => StudentFailure(),
-);
-
-TaskEither> getCoursesOfStudents(
- List studentList,
-) =>
- TaskEither.tryCatch(
- () => StudentRepo.getAllCourses(studentList),
- (_, __) => CourseFailure(),
- );
-
-String logFailure(ApiFailure apiFailure) {
- if (apiFailure is StudentFailure) {
- return 'Error while fetching list of students';
- } else if (apiFailure is CourseFailure) {
- return 'Error while fetching list of courses';
- } else {
- throw UnimplementedError();
- }
-}
-
-void main() async {
- /// How to call `getCoursesOfStudents` only if students is `Right`?
- ///
- /// Type: `TaskEither>`
- final taskEitherRequest = getStudents.flatMap(getCoursesOfStudents);
-
- /// In case of error map `ApiFailure` to `String` using `logFailure`
- ///
- /// Type: `TaskEither>`
- final taskRequest = taskEitherRequest.mapLeft(logFailure);
-
- /// Run everything at the end!
- ///
- /// Type: `Either>`
- final result = await taskRequest.run();
-}
diff --git a/packages/fpdart/example/src/task_either/async_flat_map/student_repo.dart b/packages/fpdart/example/src/task_either/async_flat_map/student_repo.dart
deleted file mode 100644
index 4de97f98..00000000
--- a/packages/fpdart/example/src/task_either/async_flat_map/student_repo.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-import 'data.dart';
-
-// ignore: avoid_classes_with_only_static_members
-class StudentRepo {
- static Future> getAllStudents() async => [
- Student("Juan"),
- Student("Maria"),
- ];
-
- static Future> getAllCourses(List studentList) async =>
- [
- Course("Math"),
- Course("Physics"),
- ];
-}
diff --git a/packages/fpdart/example/src/task_either/chain.dart b/packages/fpdart/example/src/task_either/chain.dart
deleted file mode 100644
index 7bc71991..00000000
--- a/packages/fpdart/example/src/task_either/chain.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-typedef MessageResponse = String;
-typedef AnalyticsResponse = int;
-
-TaskEither resendVerificationEmail =
- TaskEither.of("done");
-
-TaskEither registerAnalytics = TaskEither.of(1);
-
-Future main() async {
- /**
- * This will execute `resendVerificationEmail`
- *
- * If `resendVerificationEmail` is successful, then it will chain a call to `registerAnalytics`
- * while still returning the result from `resendVerificationEmail`
- */
- final taskEither = resendVerificationEmail.chainFirst(
- (_) => registerAnalytics,
- );
-
- final result = await taskEither.run();
- print(result); // Right("done")
-}
diff --git a/packages/fpdart/example/src/task_either/finally.dart b/packages/fpdart/example/src/task_either/finally.dart
deleted file mode 100644
index d1d92ce1..00000000
--- a/packages/fpdart/example/src/task_either/finally.dart
+++ /dev/null
@@ -1,50 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-Future apiRequestMock() => Future.value(10);
-
-/// Imperative code
-///
-/// `try` - `catch` - `finally`
-Future imperative() async {
- try {
- final response = await apiRequestMock();
- print(response);
- } catch (e) {
- print("Error: $e");
- } finally {
- print("Complete!");
- }
-}
-
-/// Functional code
-///
-/// `tryCatch`
-Future functional() async {
- final task = TaskEither.tryCatch(
- apiRequestMock,
- (e, _) => "Error: $e",
- ).match(
- (l) {
- print(l);
- return unit;
- },
- (r) {
- print(r);
- return unit;
- },
- ).chainFirst(
- (a) => Task(
- () async {
- print("Complete!");
- return unit;
- },
- ),
- );
-
- task.run();
-}
-
-void main() {
- imperative();
- functional();
-}
diff --git a/packages/fpdart/example/src/task_either/overview.dart b/packages/fpdart/example/src/task_either/overview.dart
deleted file mode 100644
index 5a7128dd..00000000
--- a/packages/fpdart/example/src/task_either/overview.dart
+++ /dev/null
@@ -1,57 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-/// From [Future] to [TaskEither]
-Future imperative(String str) async {
- try {
- return int.parse(str);
- } catch (e) {
- return -1; // What does -1 means? 🤨
- }
-}
-
-TaskEither functional(String str) {
- return TaskEither.tryCatch(
- () async => int.parse(str),
- // Clear error 🪄
- (error, stackTrace) => "Parsing error: $error",
- );
-}
-
-/// What error is that? What is [dynamic]?
-Future asyncI() {
- return Future.error('Some error!')
- .then((value) => value * 10)
- .catchError(
- (dynamic error) {
- print(error);
- return 0;
- },
- );
-}
-
-/// Handle all the errors easily ✨
-TaskEither asyncF() {
- return TaskEither(
- () async => left('Some error'),
- ).map((r) => r * 10);
-}
-
-// Methods 👇
-
-TaskEither mapLeftExample(TaskEither taskEither) =>
- taskEither.mapLeft(
- (string) => string.length,
- );
-
-TaskEither bimapExample(TaskEither taskEither) =>
- taskEither.bimap(
- (string) => string.length,
- (number) => number / 2,
- );
-
-TaskEither toTaskEitherExample(Either taskEither) =>
- taskEither.toTaskEither();
-
-/// Chain [Either] to [TaskEither]
-TaskEither binding =
- TaskEither.of("String").bindEither(Either.of(20));
diff --git a/packages/fpdart/example/src/task_either/sync_to_async.dart b/packages/fpdart/example/src/task_either/sync_to_async.dart
deleted file mode 100644
index 15bee753..00000000
--- a/packages/fpdart/example/src/task_either/sync_to_async.dart
+++ /dev/null
@@ -1,32 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-Future everythingIsFine(int a) async => a + 42;
-
-Future sendComplainRequest(String a) async =>
- '$a - What data is that!!!';
-
-Either validate() => Either.of(10);
-
-void main() {
- /// You have an [Either]. Now, suddenly a [Future] appears!
- /// What do you do?
- ///
- /// You need to change the context, moving from a sync [Either]
- /// to an async [TaskEither]! Simply use `toTaskEither`.
- final eitherToTaskEither = validate()
- .toTaskEither()
- .flatMap(
- (r) => TaskEither(
- () async => Either.of(
- await everythingIsFine(r),
- ),
- ),
- )
- .orElse(
- (l) => TaskEither(
- () async => Either.left(
- await sendComplainRequest(l),
- ),
- ),
- );
-}
diff --git a/packages/fpdart/example/src/task_option/future_task_option.dart b/packages/fpdart/example/src/task_option/future_task_option.dart
deleted file mode 100644
index 62c87326..00000000
--- a/packages/fpdart/example/src/task_option/future_task_option.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-import 'package:fpdart/fpdart.dart';
-
-late Future