either_option is a simple library typed for easy and safe error handling with functional programming style in Dart.
It aims to allow flutter/dart developpers to use the 2 most popular patterns and abstractions :
Either
and Option
, mainly used in FP language like Scala, Haskell, OCaml,...
Prerelease versions that support null safety
Package link on pub either_option In your pubspec.yaml dependencies add
either_option: ^2.0.0
Either
Represents a value of one of two possible types.
By convention we put missing or error value in an instance of Left
and expected success value in an instance of Right
.
For example, we fetch an url from a repository repository to get an User details and use Either<ServerError,User>
:
Future<Either<ServerError, User>> getUser(int id) async {
final baseUrl = "https://fakerestapi.azurewebsites.net/api/Users/$id";
final res = await http.get(baseUrl);
if (res.statusCode == 200) {
dynamic body = json.decode(res.body);
User user = User.fromJson(body);
return Right(user);
}
if (res.statusCode == 404)
return Left(ServerError("This user doesn't exist"));
return Left(ServerError("Unknown server error"));
}
So now to consume result we can use for example fold
method and say what to do with value :
main() async {
final Repository repository = Repository();
final Either<ServerError, User> res = await repository.getUser(3);
final defaultUser = User(id: 0, username: "ko", password: "ko");
final userName = res.fold((_) => defaultUser.username, (user) => user.username);
print(userName); // "User 3"
//if res was a Left, print(userName) would give "ko"
}
Option
Represents a value of one of two possible types.
By convention we consider missing value as an instance of None
and expected success value in an instance of Some
.
Future<Option<User>> getUserOpt(int id) async {
final res = await http.get(baseUrl);
return Option.cond(
res.statusCode == 200, User.fromJson(json.decode(res.body)));
}
// -----------------------------------------
main() async {
final Repository repository = Repository();
final Option<User> res = await repository.getUserOpt(3);
final defaultUser = User(id: 0, username: "ko", password: "ko");
final userName = res.getOrElse(defaultUser).username;
print(userName); // "User 3"
//if res was a None, print(userName) would give "ko"
}
Functions available :
Option | Either | |
---|---|---|
fold | 👍 | 👍 |
map | 👍 | 👍 |
flatMap | 👍 | 👍 |
getOrElse | 👍 | |
orElse | 👍 | |
toLeft | 👍 | |
toRight | 👍 | |
toEither | 👍 | |
Option.empty | 👍 | |
Option.of | 👍 | |
filter | 👍 | |
exists | 👍 | |
contains | 👍 | |
swap | 👍 | |
cond | 👍 | 👍 |