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

[question] cannot use .andThen in option #142

Closed linxkaa closed 9 months ago

linxkaa commented 9 months ago

Hi, I have this code:

  Either<String, Unit> get _emptyLeftErrorMsg {
    return FormValidator.emptyValidator(leftValue).fold(
      (failure) => failure.maybeMap(
        orElse: () => right(unit),
        empty: (_) => left('Left form must not be empty'),
      ),
      (_) => right(unit),
    );
  }

  Either<String, Unit> get _zeroRightErrorMsg => FormValidator.customValidator(validator: cannotBeDividedByZero).fold(
        (failure) => failure.maybeWhen(
          orElse: () => right(unit),
          costumError: () => left('Cannot be divided by zero'),
        ),
        (r) => right(unit),
      );

  Either<String, Unit> get _emptyRightErrorMsg {
    return FormValidator.emptyValidator(rightValue).fold(
      (failure) => failure.maybeMap(
        orElse: () => right(unit),
        empty: (_) => left("Right form must not be empty"),
      ),
      (data) => right(unit),
    );
  }

  String? get textErrorMsg {
    return _emptyLeftErrorMsg.andThen(() => _emptyRightErrorMsg).andThen(() => _zeroRightErrorMsg).fold(
          (errorText) => errorText,
          (formValid) => null,
        );
  }

This code works perfectly for instance the _emptyLeftErrorMsg return left('Left form must not be empty') then the textErrorMsg will return the errorText

But when I change to this code:

  Option<String> get _emptyLeftErrorMsg {
    return FormValidator.emptyValidator(leftValue).fold(
      (failure) => failure.maybeMap(
        orElse: () => none(),
        empty: (_) => some('Left form must not be empty'),
      ),
      (_) => none(),
    );
  }

  Option<String> get _zeroRightErrorMsg => FormValidator.customValidator(validator: cannotBeDividedByZero).fold(
        (failure) => failure.maybeWhen(
          orElse: () => none(),
          costumError: () => some('Cannot be divided by zero'),
        ),
        (r) => none(),
      );

  Option<String> get _emptyRightErrorMsg {
    return FormValidator.emptyValidator(rightValue).fold(
      (failure) => failure.maybeMap(
        orElse: () => none(),
        empty: (_) => some("Right form must not be empty"),
      ),
      (data) => none(),
    );
  }

  String? get textErrorMsg {
    return _emptyLeftErrorMsg.andThen(() => _emptyRightErrorMsg).andThen(() => _zeroRightErrorMsg).fold(
          () => null,
          (errorText) => errorText,
        );
  }

it always return null even though the _emptyLeftErrorMsg return some('Left form must not be empty')

Is there no way to use .andThen in Option?

SandroMaglione commented 9 months ago

Hi @linxkaa

Without knowing about the implementation of FormValidator I can say that somehow one of _emptyLeftErrorMsg, _emptyRightErrorMsg, or _zeroRightErrorMsg returns None.

In the case of Either since _emptyLeftErrorMsg returns Left then _emptyRightErrorMsg and _zeroRightErrorMsg are "skipped". This is not the case with some in Option

linxkaa commented 9 months ago

Hi @SandroMaglione thank you for answering.

But as you can see in the code, when Im using either it returns the correct statement which is left. And should've work the same with option, if the _emptyLeftErrorMsg is returning failure -> Should've returning some() I event print inside the _emptyLeftErrorMsg, and its returning some('Left form must not be empty')

So Im kind of confused why .andThen doesn't work in Option

SandroMaglione commented 9 months ago

andThen executes the function only when the current value is not Left (Either) or None (Option).

Your example works with Either because you wrap the result in left. andThen will therefore not execute at all and skip to fold.

With Option you return some, which instead continues the execution of andThen possibly causing a failure later in the code

linxkaa commented 9 months ago

I see, alright then. Closing this question. Thankyou!