4

Я использую «полностью ленивый», и у меня есть желание для Either<String,Option<A>> в программе, которую я пишу. Это потрясающее место для использования Monad Transformer for Option (аналогично удивительному, который существует в Scalaz 7). Кажется, я не могу получить Generics прямо в Java 8. Код ниже - это то, что мне хотелось бы, чтобы он выглядел (для начала). Любые предложения о том, как заставить его работать/компилироваться, будут УДИВИТЕЛЬНЫ !!! Пожалуйста, помогите мне получить этот Monad Transformer для моего кода Java 8.Java 8 Generic Generic для Monad Transformer

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: я получаю отказ компилятора:

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 
+2

Как это не работает? – immibis

+3

Вы не можете передавать общие параметры в общий параметр в Java ('M ', где M является общим). Это не будет транслироваться непосредственно из Scala; это значительно разные языки. – yshavit

+1

Система типа Java не поддерживает типы более высокого уровня. Вы не можете этого сделать. –

ответ

2

Вы можете сделать это с cyclops-monad-api, есть вводная blog post that you might find helpful here. Я являюсь автором библиотеки и сообщения в блоге.

Я отправил рабочую реализацию вашего примера (для JDK 8 опционных) ниже -

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()); 
} 

распечатает

Optional[hello world10] 

AnyM обертывания любого типа монады. Java не поддерживает типы более высокого качества, поэтому вы не можете вводить дженерики для генериков. Однако вы можете обернуть тип монады за общим API, и это то, что делает AnyM.

Если кому-то интересно, у циклопов-монад-апи теперь есть растущий диапазон Monad Transformers, вдохновленный этим вопросом - спасибо OP!

0

На github существует проект https://github.com/DanielGronau/highj, который пытается преодолеть отсутствие у Java более высоких типов.

Но вы также можете избавить свой пот и использовать функциональный язык программирования с соответствующими выше kinded типов, как https://github.com/Frege/frege

Смежные вопросы