SandroMaglione / fpdart

Functional programming in Dart and Flutter. All the main functional programming types and patterns fully documented, tested, and with examples.
https://pub.dev/packages/fpdart
MIT License
533 stars 44 forks source link

Support for TaskEither.tryCatchK #135

Closed marcopeocchi closed 1 year ago

marcopeocchi commented 1 year ago

Hi and tanks for your awesome library!

When experimenting with your library I've encountered this issue when dealing with concatenating TaskEithers with the .flatMap method.
I've tried to recreate your setup of your blog post.

Heres an extract of my code.

  TaskEither<Failure, Quote> getRandom() => TaskEither.tryCatch(
        () => _makeRequest(),
        (error, stackTrace) => FetchFailure(
          error: error,
          stacktrace: stackTrace,
        ),
      ).flatMap((r) => _cacheTask(r))

  TaskEither<Failure, Quote> _cacheTask(Quote quote) => TaskEither.tryCatch(
        () => _cache(quote),
        (error, stackTrace) => SharedPreferenceFailure(
          error: error,
          stacktrace: stackTrace,
        ),
      );
The return type 'TaskEither<Failure, Quote>' isn't a 'TaskEither<FetchFailure, Quote>', as required by the closure's context.dart[return_of_invalid_type_from_closure](https://dart.dev/diagnostics/return_of_invalid_type_from_closure)
TaskEither<Failure, Quote> _cacheTask(Quote quote)
Type: TaskEither<Failure, Quote> Function(Quote)

package:mvvm_study/ye/repository/quotes_impl.dart

TaskEither<Failure, Quote> _cacheTask(Quote quote) => TaskEither.tryCatch(
      () => _cache(quote),

where Failure is

abstract class Failure {
  final String type;
  final String message;
  final FailureSeverity severity;
  final Object? error;
  final Object? stacktrace;

  const Failure({
    required this.type,
    required this.message,
    required this.severity,
    this.error,
    this.stacktrace,
  });
}

and Failures are

import 'package:mvvm_study/core/failure.dart';

class FetchFailure extends Failure {
  const FetchFailure({
    super.type = 'FetchFailure',
    super.message = 'An error occured while fetching data from the server',
    super.severity = FailureSeverity.high,
    super.stacktrace = '',
    super.error = '',
  });
}

class SharedPreferenceFailure extends Failure {
  const SharedPreferenceFailure({
    super.type = 'SharedPreferenceFailure',
    super.message = 'An error occured while fetching from SharedPreferences',
    super.severity = FailureSeverity.high,
    super.stacktrace = '',
    super.error = '',
  });
}
...

Even with

abstract class Failure {}

class SharedPreferenceFailure implements Failure {}
...

the resulting error is the same.

So here I'm thinking that a tryCatchK (widening) might be useful or I'm doing something terrible wrong with my code. Im running the current latest Dart SDK Dart 3.1.2.

marcopeocchi commented 1 year ago

I resolved by enforcing the return type

TaskEither<Failure, Quote> getRandom() => TaskEither<Failure, Quote>.tryCatch(
        () => _makeRequest(),
        (error, stackTrace) => FetchFailure(
          error: error,
          stacktrace: stackTrace,
        ),
      ).flatMap((r) => _cacheTask(r));

Silly me. Can be closed if no one thinks tryCatchK is useful.