5

monad 的一般情况可以在 Java 6 中表达吗?注意“一般情况”这个词——monad 的一般情况可能是不可表达的,尽管 monad 的许多特殊情况(即许多特定的 monad)是可以表达的。

这里的问题是(缺乏)Java 中的高级泛型;但是,我看到示例 Haskell 代码确实使用https://stackoverflow.com/a/877036/1123502(即public class Fix<F extends Fix<F>>)之类的方法移植到了 Java。

当然,非类型安全的实现(如使用 Object 和向下转换)并不有趣。

更新:有 2 个常见的 monad 定义:join-fmap 和 bind-return。尽管它们(在数学上)是等价的,但它们可能不是等价的,因为一种定义可以用 Java 表达,而另一种则不是(但是,在我看来,不等价的可能性不大)。所以我的问题涉及这两个定义。

底线:是否有人克服了所有障碍并在 Java 6 中编写了“一般情况”单子?或者,或者,请指出一篇论文,或一篇详尽的博客文章,或彻底解释为什么不可能。

4

1 回答 1

5

并非没有肮脏的铸造技巧。正如您已经注意到的那样,Java 不支持类型级别的多态性(在 Scala 领域中也称为“高级类型”)。

这是一种方法:假设您要实现一个仿函数。您想写Functor<F<A>>F例如 aListMaybe,但这是行不通的。但是你可以Base<X,Y>为更高级的东西设置一个“基类”。X必须是您真实班级的“见证人”,例如List. Y是通常的通用参数。现在你的仿函数变成Functor<Base<F,A>>了,但是所有想要与它一起使用的类,都需要实现Base<X,Y>

class List<A> implements Base<List.Witness,A> {
   public class Witness{}
   ...
}

public interface Functor<F> {
    public <A, B> Base<F, B> map(F1<A, B> fn, Base<F, A> nestedA);
}

public class ListFunctor implements Functor<List.Witness> {
    public <A, B> Base<List.Witness, B> map(F1<A, B> fn, Base<List.Witness, A> nestedA) {
       ...
    }  
}

当然要付出的代价是你得到一个Base<List.Witness,B>,而不是一个List<B>。如果您留在那个更高种类的域中,这可能会很好,当然您可以为方便起见使用转换功能,但它仍然不是很好。

有关实现,请参阅我的不太严重的项目highJ。请注意,我正在开发一个更接近上面示例的完全重写且稍微方便的版本。

对于严肃的代码,请考虑用 Scala 编写这样的东西(或使用 Scalaz)。

于 2012-11-25T17:38:33.917 回答