【问题标题】:Haskell style value constructors in JavaJava 中的 Haskell 样式值构造函数
【发布时间】:2016-06-19 12:56:46
【问题描述】:

在 Haskell 中,我们可以定义具有多个互斥值构造函数的类型,例如 Maybe 类型,其定义如下:

data Maybe a = Nothing | Just a

其中“a”是任何现有类型。如果我们可以在 Java 中做类似的事情,那就太好了。例如,如果我们想在 Haskell 中定义一个扩展实数,我们可以这样做

data ExtendedReal = Infinity | Real Double

在 Java 中,我能想到的创建具有类似功能的类的唯一方法是在类中放置一个布尔标志来覆盖双精度。例如,我们可以这样做

public class ExtendedReal {

    private double real;
    private boolean isInfinity;

    public ExtendedReal() {
        isInfinity = true;
    }

    public ExtendedReal(double real) {
        this.real = real;
    }
    ...
    ...
}

然后检查所有方法中的标志。

有没有更规范的方法来实现这一点?

【问题讨论】:

  • 你的结局是什么?
  • Double 已经代表无穷大,而且比这个更好(它区分了正无穷和负无穷);您可以通过Double.isInfinite 进行检查。
  • @AndyTurner 是的,但这是一个比实现双打更普遍的问题。

标签: java haskell


【解决方案1】:

不确定这是否真的回答了你的问题,因为我不熟悉 Haskell,我不确定我是否真的理解这个问题,但是像这样的“特殊情况”可以设计为带有子类的基类,和多态性:

public abstract class Real {
    public abstract Real plus(double value);

    public static Real infinity() {
        return new Infinity();
    }

    public static Real regular(double value) {
        return new RegularReal(value);
    }

    private static class Infinity extends Real {
        @Override
        public void plus(double value) {
            return this;
        }
    }

    private static class RegularReal extends Real {
        private final double value;

        private RegularReal(double value) {
            this.value = value;
        }

        @Override 
        public Real plus(double value) {
            return new RegularReal(this.value + value);
        }
    }
}

【讨论】:

  • 这里唯一缺少的重要东西是一个变态来弥补模式匹配的缺失,在 Java 中你称之为“访问者模式”。
【解决方案2】:

为不可变类实现此目的的一种可能方法是定义表示特殊值的类的公共静态最终实例。使用这种方法不会引入新类型。

【讨论】:

    【解决方案3】:

    AFAIK Java 8 的 Optional 是 somewhat similar to Haskell's Maybe。由于 Java 的 Optional 是使用 if/else 实现的,我想这是在 Java 中实现的方式。当然,也可以用多态来代替它,但原则仍然存在。比如Optional的map函数就是这样实现的:

    public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
        }
    }
    
    public boolean isPresent() {
        return value != null;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-01
      相关资源
      最近更新 更多