Skip to content

Commit fcc1422

Browse files
Merge pull request #2 from jacobaraujo7/main
Added new functions and wrapper (bind, bindFuture, id, fold, left, right)
2 parents 2680b7c + 2b3964a commit fcc1422

6 files changed

Lines changed: 125 additions & 2 deletions

File tree

.packages

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#
44
# For more info see: https://dart.dev/go/dot-packages-deprecation
55
#
6-
# Generated by pub on 2021-06-15 19:06:22.469619.
6+
# Generated by pub on 2021-06-20 14:14:38.902319.
77
_fe_analyzer_shared:file:///C:/Users/Sandro%20Maglione/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/_fe_analyzer_shared-22.0.0/lib/
88
analyzer:file:///C:/Users/Sandro%20Maglione/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/analyzer-1.7.0/lib/
99
args:file:///C:/Users/Sandro%20Maglione/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/args-2.1.0/lib/

example/src/function/identity.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import 'package:fpdart/fpdart.dart';
2+
3+
void main() {
4+
final either = Either<String, int>.of(10);
5+
6+
/// Without using `identity`, you must write a function to return
7+
/// the input parameter `(l) => l`.
8+
final noId = either.match((l) => l, (r) => '$r');
9+
10+
/// Using `identity`/`id`, the function just returns its input parameter.
11+
final withIdentity = either.match(identity, (r) => '$r');
12+
final withId = either.match(id, (r) => '$r');
13+
}

lib/src/either.dart

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
11
import 'function.dart';
22
import 'option.dart';
3+
import 'task_either.dart';
34
import 'tuple.dart';
45
import 'typeclass/typeclass.export.dart';
56

7+
/// Return a `Right(r)`.
8+
///
9+
/// Shortcut for `Either.of(r)`.
10+
Either<L, R> right<L, R>(R r) => Right<L, R>(r);
11+
12+
/// Return a `Left(l)`.
13+
///
14+
/// Shortcut for `Either.left(l)`.
15+
Either<L, R> left<L, R>(L l) => Left<L, R>(l);
16+
617
/// Tag the [HKT2] interface for the actual [Either].
718
abstract class _EitherHKT {}
819

@@ -92,6 +103,8 @@ abstract class Either<L, R> extends HKT2<_EitherHKT, L, R>
92103
/// You can extract the value of every [Right] in the chain without
93104
/// handling all possible missing cases.
94105
/// If any of the functions in the chain returns [Left], the result is [Left].
106+
///
107+
/// Same as `bind`.
95108
@override
96109
Either<L, C> flatMap<C>(covariant Either<L, C> Function(R a) f);
97110

@@ -135,6 +148,22 @@ abstract class Either<L, R> extends HKT2<_EitherHKT, L, R>
135148
Either<L, R> filterOrElse(bool Function(R r) f, L Function(R r) onFalse) =>
136149
flatMap((r) => f(r) ? Either.of(r) : Either.left(onFalse(r)));
137150

151+
/// Used to chain multiple functions that return a [Either].
152+
///
153+
/// You can extract the value of every [Right] in the chain without
154+
/// handling all possible missing cases.
155+
/// If any of the functions in the chain returns [Left], the result is [Left].
156+
///
157+
/// Same as `flatMap`.
158+
Either<L, R2> bind<R2>(Either<L, R2> Function(R r) f) => flatMap(f);
159+
160+
/// Used to chain multiple functions that return a `Future<Either>`.
161+
///
162+
/// When this value is [Right], it returns a [TaskEither] that will resolve to
163+
/// the result of calling `f`.
164+
/// Otherwise, if this value is [Left], it returns `TaskEither.left()`.
165+
TaskEither<L, R2> bindFuture<R2>(Future<Either<L, R2>> Function(R r) f);
166+
138167
/// If the [Either] is [Left], then change its value from type `L` to
139168
/// type `C` using function `f`.
140169
Either<C, R> mapLeft<C>(C Function(L a) f);
@@ -176,8 +205,16 @@ abstract class Either<L, R> extends HKT2<_EitherHKT, L, R>
176205
R getOrElse(R Function(L l) orElse);
177206

178207
/// Execute `onLeft` when value is [Left], otherwise execute `onRight`.
208+
///
209+
/// Same as `fold`.
179210
C match<C>(C Function(L l) onLeft, C Function(R r) onRight);
180211

212+
/// Execute `onLeft` when value is [Left], otherwise execute `onRight`.
213+
///
214+
/// Same as `match`.
215+
C fold<C>(C Function(L l) onLeft, C Function(R r) onRight) =>
216+
match<C>(onLeft, onRight);
217+
181218
/// Return `true` when value of `r` is equal to the value inside this [Either].
182219
/// If this [Either] is [Left], then return `false`.
183220
bool elem(R r, Eq<R> eq);
@@ -320,6 +357,10 @@ class Right<L, R> extends Either<L, R> {
320357

321358
@override
322359
String toString() => 'Right($_value)';
360+
361+
@override
362+
TaskEither<L, R2> bindFuture<R2>(Future<Either<L, R2>> Function(R r) f) =>
363+
TaskEither(() async => f(_value));
323364
}
324365

325366
class Left<L, R> extends Either<L, R> {
@@ -396,4 +437,8 @@ class Left<L, R> extends Either<L, R> {
396437

397438
@override
398439
String toString() => 'Left($_value)';
440+
441+
@override
442+
TaskEither<L, R2> bindFuture<R2>(Future<Either<L, R2>> Function(R r) f) =>
443+
TaskEither.left(_value);
399444
}

lib/src/function.dart

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,41 @@
11
typedef Endo<A> = A Function(A a);
22

33
/// Returns the given `a`.
4+
///
5+
/// Same as `id`.
6+
///
7+
/// Shortcut function to return the input parameter:
8+
/// ```dart
9+
/// final either = Either<String, int>.of(10);
10+
///
11+
/// /// Without using `identity`, you must write a function to return
12+
/// /// the input parameter `(l) => l`.
13+
/// final noId = either.match((l) => l, (r) => '$r');
14+
///
15+
/// /// Using `identity`/`id`, the function just returns its input parameter.
16+
/// final withIdentity = either.match(identity, (r) => '$r');
17+
/// final withId = either.match(id, (r) => '$r');
18+
/// ```
419
T identity<T>(T a) => a;
520

21+
/// Returns the given `a`.
22+
///
23+
/// Same as `identity`.
24+
///
25+
/// Shortcut function to return the input parameter:
26+
/// ```dart
27+
/// final either = Either<String, int>.of(10);
28+
///
29+
/// /// Without using `identity`, you must write a function to return
30+
/// /// the input parameter `(l) => l`.
31+
/// final noId = either.match((l) => l, (r) => '$r');
32+
///
33+
/// /// Using `identity`/`id`, the function just returns its input parameter.
34+
/// final withIdentity = either.match(identity, (r) => '$r');
35+
/// final withId = either.match(id, (r) => '$r');
36+
/// ```
37+
T id<T>(T a) => a;
38+
639
/// Converts a binary function into a unary function that returns a unary function.
740
///
841
/// Enables the use of partial application of functions.

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: fpdart
2-
version: 0.0.4
2+
version: 0.0.5
33
homepage: https://www.sandromaglione.com/
44
repository: https://github.com/SandroMaglione/fpdart
55
description: Functional programming in Dart and Flutter. All the main functional programming types and patterns fully documented, tested, and with examples.

test/src/either_test.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,4 +721,36 @@ void main() {
721721
});
722722
});
723723
});
724+
725+
group('bind', () {
726+
test('Right', () {
727+
final either1 = Either<String, int>.of(10);
728+
final result = either1.bind((r) => Either<String, int>.of(r + 10));
729+
expect(result.getOrElse((l) => 0), 20);
730+
});
731+
732+
test('Left', () {
733+
final either1 = Either<String, int>.left('String');
734+
final result = either1.bind((r) => Either<String, int>.of(r + 10));
735+
expect(result.getOrElse((l) => 0), 0);
736+
expect(result.getLeft().getOrElse(() => ''), 'String');
737+
});
738+
});
739+
740+
group('bindFuture', () {
741+
test('Right', () async {
742+
final either1 = Either<String, int>.of(10);
743+
final asyncEither = either1.bindFuture((r) async => Either.of(r + 10));
744+
final result = await asyncEither.run();
745+
expect(result.getOrElse((l) => 0), 20);
746+
});
747+
748+
test('Left', () async {
749+
final either1 = Either<String, int>.left('String');
750+
final asyncEither = either1.bindFuture((r) async => Either.of(r + 10));
751+
final result = await asyncEither.run();
752+
expect(result.getOrElse((l) => 0), 0);
753+
expect(result.getLeft().getOrElse(() => ''), 'String');
754+
});
755+
});
724756
}

0 commit comments

Comments
 (0)