Ok, so I implement the state monad in java. However, I cannot get generics to work correctly. I have the code below and I try to avoid these cases.
public interface Monad<M, A> { <B, R extends Monad<M, B>> R bind(Function<? super A, R> p_function); } public class State<S, A> implements Monad<State<S, ?>, A> { private Function<S, Pair<S, A>> m_function; public State(Function<S, Pair<S, A>> p_function) { m_function = p_function; } public final Pair<S, A> run(S p_state) { return m_function.apply(p_state); } @Override public <B, R extends Monad<State<S, ?>, B>> R bind( final Function<? super A, R> p_function) {
Note. I know that if I can add the bind signature to <B> Monad<M, B> bind(Function<? super A, ? extends Monad<M, B>> p_function);
Cast can be avoided. However, this causes a compilation error in the following method
public static <A, B, C, M, MB extends Monad<M, B>, MC extends Monad<M, C>> Function<A, MC> compose( Function<? super A, MB> p_first, Function<? super B, MC> p_second) {
Now I also tried changing the compose signature in a similar way. that is, instead of MB extends Monad<M, B> I used Monad<M, B> , where MB was used and similarly for MC. This allows you to compile the compose method. However, the return type cannot be correctly deduced by callers compose ie
Function<String, State<Integer, String>> left = ...; Function<String, State<Integer, String>> right = ...; Function<String, State<Integer, String>> composed = Monad.compose(left, right);
It does not work without specifying types in a method call, whereas earlier it was done.
How do I make all of these generics work well together?