All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.tonivade.purefun.instances.EitherKInstances Maven / Gradle / Ivy

/*
 * Distributed under the terms of the MIT License
 */
package com.github.tonivade.purefun.instances;

import static com.github.tonivade.purefun.Precondition.checkNonNull;

import com.github.tonivade.purefun.Eq;
import com.github.tonivade.purefun.Function1;
import com.github.tonivade.purefun.Kind;
import com.github.tonivade.purefun.Pattern2;
import com.github.tonivade.purefun.Witness;
import com.github.tonivade.purefun.free.EitherK;
import com.github.tonivade.purefun.free.EitherKOf;
import com.github.tonivade.purefun.free.EitherK_;
import com.github.tonivade.purefun.typeclasses.Comonad;
import com.github.tonivade.purefun.typeclasses.Contravariant;
import com.github.tonivade.purefun.typeclasses.Functor;
import com.github.tonivade.purefun.typeclasses.InjectK;

public interface EitherKInstances {

  static  Eq, G>, T>> eq(
      Eq> leftEq, Eq> rightEq) {
    return (a, b) -> Pattern2., EitherK, Boolean>build()
        .when((x, y) -> x.isLeft() && y.isLeft())
          .then((x, y) -> leftEq.eqv(x.getLeft(), y.getLeft()))
        .when((x, y) -> x.isRight() && y.isRight())
          .then((x, y) -> rightEq.eqv(x.getRight(), y.getRight()))
        .otherwise()
          .returns(false)
        .apply(EitherKOf.narrowK(a), EitherKOf.narrowK(b));
  }

  static  Functor, G>> functor(
      Functor functorF, Functor functorG) {
    return EitherKFunctor.instance(checkNonNull(functorF), checkNonNull(functorG));
  }

  static  Contravariant, G>> contravariant(
      Contravariant contravariantF, Contravariant contravariantG) {
    return EitherKContravariant.instance(checkNonNull(contravariantF), checkNonNull(contravariantG));
  }

  static  Comonad, G>> comonad(
      Comonad comonadF, Comonad comonadG) {
    return EitherKComonad.instance(checkNonNull(comonadF), checkNonNull(comonadG));
  }

  @SuppressWarnings("unchecked")
  static  InjectK, G>> injectEitherKLeft() {
    return EitherKInjectKLeft.INSTANCE;
  }

  static 
      InjectK, R>> injectEitherKRight(InjectK inject) {
    return EitherKInjectKRight.instance(checkNonNull(inject));
  }
}

interface EitherKFunctor extends Functor, G>> {

  static  EitherKFunctor instance(Functor functorF, Functor functorG) {
    return new EitherKFunctor() {
      @Override
      public Functor f() { return functorF; }
      @Override
      public Functor g() { return functorG; }
    };
  }

  Functor f();
  Functor g();

  @Override
  default  EitherK map(
      Kind, G>, ? extends T> value, Function1 map) {
    return value.fix(EitherKOf::narrowK).map(f(), g(), map);
  }
}

interface EitherKContravariant
    extends Contravariant, G>> {

  static  EitherKContravariant instance(
      Contravariant contravariantF, Contravariant contravariantG) {
    return new EitherKContravariant() {
      @Override
      public Contravariant f() { return contravariantF; }
      @Override
      public Contravariant g() { return contravariantG; }
    };
  }

  Contravariant f();
  Contravariant g();

  @Override
  default  EitherK contramap(
      Kind, G>, ? extends A> value, Function1 map) {
    return value.fix(EitherKOf::narrowK).contramap(f(), g(), map);
  }
}

interface EitherKComonad
    extends Comonad, G>>, EitherKFunctor {

  static  EitherKComonad instance(Comonad comonadF, Comonad comonadG) {
    return new EitherKComonad() {
      @Override
      public Comonad f() { return comonadF; }
      @Override
      public Comonad g() { return comonadG; }
    };
  }

  @Override
  Comonad f();
  @Override
  Comonad g();

  @Override
  default  EitherK coflatMap(
      Kind, G>, ? extends A> value,
      Function1, G>, ? extends A>, ? extends B> map) {
    return value.fix(EitherKOf::narrowK).coflatMap(f(), g(), eitherK -> map.apply(eitherK));
  }

  @Override
  default  A extract(Kind, G>, ? extends A> value) {
    return value.fix(EitherKOf::narrowK).extract(f(), g());
  }
}

interface EitherKInjectKRight
    extends InjectK, R>> {

  static  EitherKInjectKRight instance(InjectK injectK) {
    return () -> injectK;
  }

  InjectK inject();

  @Override
  default   EitherK inject(Kind value) {
    return EitherK.right(inject().inject(value));
  }
}

interface EitherKInjectKLeft extends InjectK, G>> {

  @SuppressWarnings("rawtypes")
  EitherKInjectKLeft INSTANCE = new EitherKInjectKLeft() {};

  @Override
  default   EitherK inject(Kind value) {
    return EitherK.left(Kind.narrowK(value));
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy