【发布时间】:2013-07-21 11:41:15
【问题描述】:
好的,所以我在 java 中实现了 state monad。但是,我似乎无法让泛型正常工作。我有下面的代码,并试图避免指示的情况。
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)
{
// I want to avoid the cast to R here
return (R) new State<S, B>((S state) -> {
Pair<S, A> run = run(state);
// And this cast, but they seem related
State<S, B> applied = (State<S, B>) p_function.apply(run.second());
return applied.run(run.first());
});
}
}
注意:我知道如果我将bind 的签名更改为 <B> Monad<M, B> bind(Function<? super A, ? extends Monad<M, B>> p_function);
演员表可以避免。但是,这会导致以下方法中的编译错误
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)
{
// have to use an anonymous class here, because using a closure causes a
// runtime error with the beta version of JDK 8
return new Function<A, MC>() {
@Override
public MC apply(A arg) {
MB monadOfB = p_first.apply(arg);
return monadOfB.<C> bind(p_second); // <-- type error here
}
};
}
现在,我也尝试以类似的方式更改compose 的签名。即,而不是MB extends Monad<M, B>,我使用Monad<M, B>,其中使用了MB,同样用于MC。这使得 compose 方法编译。但是,compose 的调用者无法正确推断返回类型,即
Function<String, State<Integer, String>> left = ...;
Function<String, State<Integer, String>> right = ...;
Function<String, State<Integer, String>> composed = Monad.compose(left, right);
如果没有在方法调用上指定类型就无法工作,而在它之前。
如何让所有这些泛型很好地结合在一起?
【问题讨论】:
-
我似乎无法理解第一个是如何工作的?
-
@f1sh:好吧,如果
State extends Monad(随意添加泛型)它可能会起作用。 -
可以添加
State和Monad的定义吗? -
OP 能否通过编造一些简单且可以证明您的问题的东西来简化您的问题?您的代码中有太多“噪音”,我认为没有人真正清楚地了解您的问题
-
@AdrianShum 我的简化尝试如下(在阅读了 OP 问题中的最新编辑后进行了更多编辑)。