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

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

/*
 * Copyright (c) 2018-2019, Antonio Gabriel Muñoz Conejo 
 * Distributed under the terms of the MIT License
 */
package com.github.tonivade.purefun.instances;

import com.github.tonivade.purefun.Eq;
import com.github.tonivade.purefun.Function1;
import com.github.tonivade.purefun.Function2;
import com.github.tonivade.purefun.Higher1;
import com.github.tonivade.purefun.Instance;
import com.github.tonivade.purefun.Kind;
import com.github.tonivade.purefun.data.ImmutableList;
import com.github.tonivade.purefun.data.Sequence;
import com.github.tonivade.purefun.type.Eval;
import com.github.tonivade.purefun.typeclasses.Alternative;
import com.github.tonivade.purefun.typeclasses.Applicative;
import com.github.tonivade.purefun.typeclasses.Foldable;
import com.github.tonivade.purefun.typeclasses.Monoid;
import com.github.tonivade.purefun.typeclasses.MonoidK;
import com.github.tonivade.purefun.typeclasses.Semigroup;
import com.github.tonivade.purefun.typeclasses.SemigroupK;
import com.github.tonivade.purefun.typeclasses.Traverse;

public interface SequenceInstances {

  static  Eq> eq(Eq eqElement) {
    return (a, b) -> {
      Sequence seq1 = Sequence.narrowK(a);
      Sequence seq2 = Sequence.narrowK(b);
      return seq1.size() == seq2.size()
          && Sequence.zip(seq1, seq2).allMatch(tuple -> eqElement.eqv(tuple.get1(), tuple.get2()));
    };
  }

  static  Semigroup> semigroup() {
    return new SequenceSemigroup() {};
  }

  static  Monoid> monoid() {
    return new SequenceMonoid() {};
  }

  static SemigroupK semigroupK() {
    return new SequenceSemigroupK() {};
  }

  static MonoidK monoidK() {
    return new SequenceMonoidK() {};
  }

  static Alternative alternative() {
    return new SequenceAlternative() {};
  }

  static Traverse traverse() {
    return new SequenceTraverse() {};
  }

  static Foldable foldable() {
    return new SequenceFoldable() {};
  }
}

@Instance
interface SequenceSemigroup extends Semigroup> {

  @Override
  default Sequence combine(Sequence t1, Sequence t2) {
    return t1.appendAll(t2);
  }
}

@Instance
interface SequenceMonoid extends SequenceSemigroup, Monoid> {

  @Override
  default Sequence zero() {
    return ImmutableList.empty();
  }
}

@Instance
interface SequenceSemigroupK extends SemigroupK {

  @Override
  default  Sequence combineK(Higher1 t1, Higher1 t2) {
    return Sequence.narrowK(t1).appendAll(Sequence.narrowK(t2));
  }
}

@Instance
interface SequenceMonoidK extends MonoidK, SequenceSemigroupK {

  @Override
  default  Sequence zero() {
    return ImmutableList.empty();
  }
}

@Instance
interface SequenceApplicative extends Applicative {

  @Override
  default  Sequence pure(T value) {
    return ImmutableList.of(value);
  }

  @Override
  default  Sequence ap(Higher1 value, Higher1> apply) {
    return Sequence.narrowK(apply).flatMap(map -> Sequence.narrowK(value).map(map));
  }
}

@Instance
interface SequenceAlternative extends SequenceApplicative, SequenceMonoidK, Alternative {}

@Instance
interface SequenceFoldable extends Foldable {

  @Override
  default  B foldLeft(Higher1 value, B initial, Function2 mapper) {
    return Sequence.narrowK(value).foldLeft(initial, mapper);
  }

  @Override
  default  Eval foldRight(Higher1 value, Eval initial, Function2, Eval> mapper) {
    return Sequence.narrowK(value).foldRight(initial, mapper);
  }
}

@Instance
interface SequenceTraverse extends Traverse, SequenceFoldable {

  @Override
  default  Higher1> traverse(
      Applicative applicative, Higher1 value,
      Function1> mapper) {
    return Sequence.narrowK(value).foldRight(applicative.pure(ImmutableList.empty()),
        (a, acc) -> applicative.map2(mapper.apply(a), acc,
            (e, seq) -> Sequence.listOf(e).appendAll(Sequence.narrowK(seq))));
  }
}