Skip to content

Commit

Permalink
no Never env, maybe void
Browse files Browse the repository at this point in the history
  • Loading branch information
SandroMaglione committed Mar 23, 2024
1 parent e27399e commit de6395d
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 67 deletions.
42 changes: 9 additions & 33 deletions packages/fpdart/lib/src/effect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ final class _EffectThrow<L> implements Exception {
}
}

EffectGen<E, L> _effectGen<E, L>(E? env) => (
EffectGen<E, L> _effectGen<E, L>(E env) => (
async: <A>(effect) => Future.sync(
() => effect.asEffect._unsafeRun(env).then(
(exit) => switch (exit) {
Expand Down Expand Up @@ -59,11 +59,7 @@ abstract interface class IEffect<E, L, R> {
}

final class Effect<E, L, R> extends IEffect<E, L, R> {
/// `E?` is optional to allow [Never] to work.
///
/// In practice a user of the library should never be allowed to pass `null` as [E].
final FutureOr<Exit<L, R>> Function(E? env) _unsafeRun;

final FutureOr<Exit<L, R>> Function(E env) _unsafeRun;
const Effect._(this._unsafeRun);

@override
Expand Down Expand Up @@ -155,10 +151,12 @@ final class Effect<E, L, R> extends IEffect<E, L, R> {
try {
return f(_effectGen<E, L>(env)).then(
Right.new,
onError: (dynamic error) {
onError: (error) {
if (error is _EffectThrow<L>) {
return Left<Cause<L>, R>(error.cause);
}

return Left<Cause<L>, R>(Die.current(error));
},
);
} on _EffectThrow<L> catch (genError) {
Expand Down Expand Up @@ -282,14 +280,12 @@ final class Effect<E, L, R> extends IEffect<E, L, R> {
///
/// {@category do_notation}
Effect<V, L, R> provide<V>(E Function(V env) f) => Effect._(
// ignore: null_check_on_nullable_type_parameter
(env) => _unsafeRun(f(env!)),
(env) => _unsafeRun(f(env)),
);

/// {@category do_notation}
static Effect<E, L, E> env<E, L>() => Effect._(
// ignore: null_check_on_nullable_type_parameter
(env) => Right(env!),
(env) => Right(env),
);

/// {@category combining}
Expand Down Expand Up @@ -555,31 +551,11 @@ final class Effect<E, L, R> extends IEffect<E, L, R> {
);
}

extension ProvideNever<L, R> on Effect<Never, L, R> {
/// Add a required dependency instead of [Never].
extension ProvideVoid<L, R> on Effect<void, L, R> {
/// Add a required dependency instead of [void].
///
/// {@category do_notation}
Effect<V, L, R> withEnv<V>() => Effect._(
(env) => _unsafeRun(null),
);

/// {@category execution}
R runSyncNoEnv() => Effect<void, L, R>._(
(_) => _unsafeRun(null),
).runSync(null);

/// {@category execution}
Exit<L, R> runSyncExitNoEnv() => Effect<void, L, R>._(
(_) => _unsafeRun(null),
).runSyncExit(null);

/// {@category execution}
Future<R> runFutureNoEnv() async => Effect<void, L, R>._(
(_) => _unsafeRun(null),
).runFuture(null);

/// {@category execution}
Future<Exit<L, R>> runFutureExitNoEnv() async => Effect<void, L, R>._(
(_) => _unsafeRun(null),
).runFutureExit(null);
}
7 changes: 5 additions & 2 deletions packages/fpdart/lib/src/extension/future_or_extension.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import 'dart:async';

extension FutureOrThenExtension<A> on FutureOr<A> {
FutureOr<B> then<B>(FutureOr<B> Function(A a) f, {Function? onError}) =>
FutureOr<B> then<B>(FutureOr<B> Function(A a) f,
{B Function(Object error)? onError}) =>
switch (this) {
final Future<A> self => self.then(f, onError: onError),
final Future<A> self => self.then(f, onError: (Object error) {
if (onError != null) onError(error);
}),
final A self => f(self),
};
}
64 changes: 32 additions & 32 deletions packages/fpdart/test/src/effect/effect_constructors_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,46 +49,46 @@ void main() {
final result = main.runSync(null);
expect(result, 10);
});
});

group('gen', () {
test('sync succeed', () {
final main = Effect.gen(($) {
final value = $.sync(Effect.succeed(10));
return value;
});
final result = main.runSyncNoEnv();
expect(result, 10);
group('gen', () {
test('sync succeed', () {
final main = Effect<void, Never, int>.gen(($) {
final value = $.sync(Effect.succeed(10));
return value;
});
final result = main.runSync(null);
expect(result, 10);
});

test('sync fail', () {
final main = Effect<Never, String, int>.gen(($) {
final value = $.sync(Effect.fail("abc"));
return value;
});
final result = main.flip().runSyncNoEnv();
expect(result, "abc");
test('sync fail', () {
final main = Effect<void, String, int>.gen(($) {
final value = $.sync(Effect.fail("abc"));
return value;
});
final result = main.flip().runSync(null);
expect(result, "abc");
});

test('async succeed', () async {
final main = Effect.gen(($) async {
final value =
await $.async(Effect.functionSucceed(() => Future.value(10)));
return value;
});
final result = await main.runFutureNoEnv();
expect(result, 10);
test('async succeed', () async {
final main = Effect<void, Never, int>.gen(($) async {
final value =
await $.async(Effect.functionSucceed(() => Future.value(10)));
return value;
});
final result = await main.runFuture(null);
expect(result, 10);
});

test('fail when running async as sync', () async {
final main = Effect.gen(($) {
final value = $.sync(Effect.functionSucceed(
() async => Future.value(10),
));
return value;
});

expect(() => main.runSyncNoEnv(), throwsA(isA<Die>()));
test('fail when running async as sync', () async {
final main = Effect<void, Never, int>.gen(($) {
final value = $.sync(Effect.functionSucceed(
() async => Future.value(10),
));
return value;
});

expect(() => main.runSync(null), throwsA(isA<Die>()));
});
});
},
Expand Down

0 comments on commit de6395d

Please sign in to comment.