Java泛型推断类型

Java泛型推断类型,java,generics,Java,Generics,好的,我正在用java实现状态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,

好的,我正在用java实现状态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());
        });
    }
}

现在,我还尝试以类似的方式更改
compose
的签名。i、 e.在使用MB的地方,我使用了
Monad
,而不是
MB扩展Monad
,对于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);
函数左=。。。;
函数右=。。。;
函数组合=单子组合(左、右);
如果不在方法调用上指定类型,则无法工作,而之前是这样


如何使所有这些泛型很好地结合在一起?

为了让您的示例正常工作,您需要对类进行类似的定义:

class State<S, B> extends Monad<State<S, ?>, B> {}
class Monad<T, U> {}

编辑

我不熟悉您试图实现的目标,这种简化可能无法实现您的目标,但它可以编译(我已经删除了lambdas,因为目前没有安装jdk8编译器):

公共类Test1{
公共静态函数组合(最终函数,B>>p_函数){
//我想避免在这里演R
返回新状态(新函数(){
公共对应用(S状态){
成对运行=运行(状态);
//和这个演员,但他们似乎有关联
State applied=(State)p_函数.apply(run.second());
返回applied.run(run.first());
}
});
}
}

告诉我这种简化是否仍然能代表您的问题:

汇编如下:

public class TestClass {
    public interface Monad {
        <R extends Monad> R bind();
    }

    public class State implements Monad {
        @Override
        public <R extends Monad> R bind() {
            return (R) new State(); // [1]
        }
    }

    public <M extends Monad> M apply() {
        M subMonad = null;
        return subMonad.bind();
    }
}
公共类TestClass{
公共接口单子{
R结合();
}
公共类状态实现Monad{
@凌驾
公共R绑定(){
返回(R)新状态();//[1]
}
}
公共M apply(){
M subMonad=null;
返回subMonad.bind();
}
}
您想从[1]中删除强制类型转换。如果您这样做:

public class TestClass {
    public interface Monad {
        Monad bind();
    }

    public class State implements Monad {
        @Override
        public Monad bind() {
            return new State();
        }
    }

    public <M extends Monad> M apply() {
        M subMonad = null;
        return subMonad.bind(); // [2]
    }
}
公共类TestClass{
公共接口单子{
单子结合();
}
公共类状态实现Monad{
@凌驾
公共单子绑定(){
返回新状态();
}
}
公共M apply(){
M subMonad=null;
返回subMonad.bind();//[2]
}
}

那么[2]就不会编译。这是总结吗?如果是这样的话,
apply()
方法是否可以简单地返回一个
Monad

以下是通过Java 7类型检查器的版本:

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> Monad<State<S, ?>, B> bind(
            final Function<? super A, ? extends Monad<State<S, ?>, B>> p_function) {
        return new State<S, B>(
                new Function<S, Pair<S,B>>() {
                    public Pair<S,B> apply(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());
                    }
        });
    }

    public static <A, B, C, M> 
    Function<A, Monad<M,C>> compose(
            final Function<? super A, ? extends Monad<M,B>> p_first, 
            final Function<? super B, ? extends Monad<M,C>> p_second) {
        return new Function<A, Monad<M,C>>() {
            @Override
            public Monad<M,C> apply(A arg) {
                Monad<M,B> monadOfB = p_first.apply(arg);
                return monadOfB.<C>bind(p_second);
            }
        };
    }
}
类状态实现Monad{
私有函数m_函数;
公共状态(功能p_功能)
{
m_函数=p_函数;
}
公共最终配对运行(S p_状态)
{
返回m_函数。应用(p_状态);
}
@凌驾
公共单子绑定(
最终功能,B>>p_功能){
返回新状态(
新函数(){
公共对应用(S状态){
成对运行=运行(状态);
//和这个演员,但他们似乎有关联
State applied=(State)p_函数.apply(run.second());
返回applied.run(run.first());
}
});
}
公共静电
函数组合(
final Function(我在+1'ing jacobm的答案,我只是想详细说明一下潜在的问题。)

问题是,在Java中,
GenericClass
GenericClass
之间没有特殊的关系:我的意思是,两者都是
GenericType
的子类型,但是
GenericInterface
无法引用通过使用
getClass()获得的类型
并用
T
代替
S

在Haskell中,
Monad
typeclass的定义如下:

class Monad m where
    (>>=)  :: m a -> (a -> m b) -> m b
    return :: a -> m a
请注意,它通过同时使用
ma
mb
来定义
m
,这意味着“相同的参数化类型
m
,具有(可能)不同的类型参数
a
b
”。在Java中,不能创建
m
的超类型(即
m
的接口)这表示了这类事情,因为尽管超类型可以使用任意类型参数引用自身(因为它可以通过名称引用自身,就像它可以使用任何其他泛型类型一样),并且可以使用任何单个类型参数引用任意子类型(即它自己的),它无法引用具有任意类型参数的任意子类型。它不像Haskell类型类定义那样位于类型系统的“外部”


这意味着没有真正的方法来定义一个通用的
Monad
接口,它的实现是通用的monadic类型。

我似乎不明白第一个接口是如何工作的?@f1sh:如果
状态扩展Monad
(随意添加泛型)它可能会起作用。你能添加
State
Monad
的定义吗?你能通过编一些简单的东西来简化你的问题,并证明你的问题吗?你的代码中有太多的“噪音”,我想没有人真正理解你的问题clearly@AdrianShum下面是我简化的尝试(阅读OP问题中的最新编辑后进行了更多编辑)。值得注意的是,OP对该提案不满意,因为它删除了一层泛型。是的,我得到了这一部分…但我真正想要的是一些关于如何使我的所有泛型更好地发挥作用的指针该解决方案(从apply返回Monad)这正是@jacobm在上面建议的,只是以一种更简单的形式。这会带来其他问题,请参阅我文章中的最后一段代码。是的,我提到我已经尝试过这种解决方案。但是,它导致在c
public class TestClass {
    public interface Monad {
        Monad bind();
    }

    public class State implements Monad {
        @Override
        public Monad bind() {
            return new State();
        }
    }

    public <M extends Monad> M apply() {
        M subMonad = null;
        return subMonad.bind(); // [2]
    }
}
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> Monad<State<S, ?>, B> bind(
            final Function<? super A, ? extends Monad<State<S, ?>, B>> p_function) {
        return new State<S, B>(
                new Function<S, Pair<S,B>>() {
                    public Pair<S,B> apply(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());
                    }
        });
    }

    public static <A, B, C, M> 
    Function<A, Monad<M,C>> compose(
            final Function<? super A, ? extends Monad<M,B>> p_first, 
            final Function<? super B, ? extends Monad<M,C>> p_second) {
        return new Function<A, Monad<M,C>>() {
            @Override
            public Monad<M,C> apply(A arg) {
                Monad<M,B> monadOfB = p_first.apply(arg);
                return monadOfB.<C>bind(p_second);
            }
        };
    }
}
class Monad m where
    (>>=)  :: m a -> (a -> m b) -> m b
    return :: a -> m a