java - Java 中的 Haskell 风格内存

标签 java haskell memoization

我知道这是异端邪说,但我试着翻译了来自 http://www.haskell.org/haskellwiki/Memoization 的例子到 java 。到目前为止,我有:

public abstract class F<A,B> {
    public abstract B f(A a);
}

...
public static <A, B> F<A, B> memoize(final F<A, B> fn) {
  return new F<A, B>() {

    private final Map<A, B> map = new HashMap<A, B>();

    public B f(A a) {
      B b = map.get(a);
        if (b == null) {
          b = fn.f(a);
          map.put(a, b);
        }
      return b;
    }
  };
}

//usage:
private class Cell<X> {
    public X value = null;
}

...
final Cell<F<Integer, BigInteger>> fibCell = new Cell<F<Integer, BigInteger>>();
fibCell.value = memoize(new F<Integer, BigInteger>() {
  public BigInteger f(Integer a) {
     return a <= 1 ? BigInteger.valueOf(a) : fibCell.value.f(a - 1).add(fibCell.value.f(a - 2));
  }
});
System.out.println(fibCell.value.f(1000));

这很好用。现在我尝试实现 memoFix 组合器定义为

memoFix :: ((a -> b) -> (a -> b)) -> a -> b
memoFix f =
   let mf = memoize (f mf) in mf

但是我卡住了。这在 Java 中是否有意义,尤其是考虑到其固有的懒惰性?

最佳答案

Guava库实际上实现了与其 MapMaker 类似的东西:

final Map<Integer, String> memoizingMap = new MapMaker().makeComputingMap(
    new Function<Integer, String>() {
        @Override
        public String apply(final Integer input) {
            System.out.println("Calculating ...");
            return Integer.toHexString(input.intValue());
        }
    });
System.out.println(memoizingMap.get(1));
System.out.println(memoizingMap.get(100));
System.out.println(memoizingMap.get(100000));
System.out.println("The following should not calculate:");
System.out.println(memoizingMap.get(1));

输出:

Calculating ...
1
Calculating ...
64
Calculating ...
186a0
The following should not calculate:
1

好处是您可以针对过期、并发级别等不同方面微调生成的映射。

关于java - Java 中的 Haskell 风格内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6956555/

相关文章:

PHP:在数据库中查找一组总和为特定数字的数字

recursion - 递归记忆化比递归慢

java - 斐波那契数列为负数

java - 如何从动态代理显式调用默认方法?

Java 映射 Lambda 异常

java - 在 IntelliJ Idea 中删除 .orig 文件

haskell - 获取 ByteString 的子字符串的惯用方式

performance - 在非整数键上有效地实现记忆化

haskell - 使用模板 Haskell 生成 TExp

使用 cryptojs 的 Java 到 JS 和 JS 到 Java 加密