Java 8 Générique de Générique pour Monad Transformer


J'utilise "totally lazy" et j'ai un désir de Either<String,Option<A>> dans un programme que j'écris. C'est un endroit formidable pour utiliser un transformateur Monade en option (similaire à celui qui existe dans Scalaz 7). Je n'arrive pas à obtenir les génériques correctement en Java 8. Le code ci-dessous est ce que j'aimerais pour qu'il ressemble (pour commencer). Toutes les suggestions sur la façon de le faire fonctionner/compiler seraient INCROYABLES!!! Aidez-moi à faire exister ce transformateur de monade pour mon code Java 8.

import com.googlecode.totallylazy.Monad;
import com.googlecode.totallylazy.Option;
import com.googlecode.totallylazy.functions.Function1;
import static com.google.common.base.Preconditions.checkNotNull;

public class OptionT<M extends Monad,A> {
   final M<Option<A>> run;

   public OptionT(final M<Option<A>> run){
       this.run = checkNotNull(run);
   }

   public <B> OptionT<M,B> map(Function1<A,B> f){
       return new OptionT<M,B>(run.map(o-> o.map(f)));
   }
}

EDIT: {[7] } J'obtiens l'échec du compilateur suivant:

OptionT.java:15: error: unexpected type
    final M<A> run;
          ^
  required: class
  found:    type parameter M
  where M is a type-variable:
    M extends Monad<Option<?>> declared in class OptionT
OptionT.java:17: error: unexpected type
    public OptionT(final M<A> run){
                         ^
  required: class
  found:    type parameter M
  where M is a type-variable:
    M extends Monad<Option<?>> declared in class OptionT
Author: jordan3, 2015-08-18

2 answers

Vous pouvez le faire avec lecyclope-monad-api , il y a un article de blog d'introductionque vous pourriez trouver utile ici . Je suis l'auteur de la bibliothèque et blog.

J'ai posté une implémentation de travail de votre exemple (pour JDK 8 facultatif) ci-dessous -

public class OptionT<A> {
   @Getter
   final AnyM<Optional<A>> run;

   public OptionT(final AnyM<Optional<A>> run){
       this.run = run;
   }

   public <B> OptionT<B> map(Function<A,B> f){
       return new OptionT<B>(run.map(o-> o.map(f)));
   }


}

@Test
public void test() {
    OptionT<Integer> optionT = new OptionT<>(AnyM.ofMonad(Stream.of(Optional.of(10))));
    System.out.println(optionT.map(num->"hello world"+num).getRun().asSequence().firstValue());
}

Imprimera

Optional[hello world10]

AnyM encapsule n'importe quel type de Monade. Java ne prend pas en charge les types de type supérieur, vous ne pouvez donc pas mettre de génériques sur des génériques. Vous pouvez cependant envelopper le type monad derrière une API commune, et c'est ce que AnyM n'.

Si quelqu'un est intéressé, le cyclope-monade-api dispose désormais d'une gamme croissante de Monade Transformateurs, inspiré par cette question - merci OP!

 2
Author: John McClean, 2016-02-04 15:26:36

Il y a un projet https://github.com/DanielGronau/highj sur github, qui tente de surmonter le manque de types de type supérieur de java.

Mais vous pouvez également épargner votre sueur et utiliser un langage de programmation fonctionnel avec des types de type supérieur appropriés, comme https://github.com/Frege/frege

 0
Author: Ingo, 2016-02-05 21:09:52