Chr*_*lor 9 java haskell algebraic-data-types
应用程序可以以两种模式运行 - "实时",它查看对世界状态的每次更新,或"采样",其中它仅每T毫秒查看世界状态.
如果我正在编写Haskell(或任何使用ADT的语言),我会将其建模为
data Mode = RealTime | Sampled Int
Run Code Online (Sandbox Code Playgroud)
可以以类型安全的方式使用如下
case mode of
RealTime -> -- do realtime stuff
Sampled interval -> -- do sample stuff with 'interval'
Run Code Online (Sandbox Code Playgroud)
我说它是"类型安全的",因为如果您在实时模式下运行,则无法尝试访问该interval字段(如果您在采样模式下操作,则会在您需要时提供该字段).
如何以类型安全的方式在Java中对相同的东西进行建模?那就是我想要的
interval在实时模式下禁止访问该字段,以及这在Java中可行吗?如果没有,实现这种类型安全的惯用方法是什么?
在类似Java的语言中模拟封闭代数数据类型的传统方法是访问者模式:只能以类型安全的方式提供开放类(可以随时继承).
abstract class Mode {
public abstract <T> T accept(ModeVisitor<T> visitor);
}
final class RealTime extends Mode {
public RealTime() {}
public <T> T accept(ModeVisitor<T> visitor) {
return visitor.visit(this);
}
}
final class Sampled extends Mode {
private final int interval;
public Sampled(int interval) {
this.interval = interval;
}
public int getInterval() {
return this.interval;
}
public <T> T accept(ModeVisitor<T> visitor) {
return visitor.visit(this);
}
}
// The recursion principle itself
abstract class ModeVisitor<T> {
public abstract T visit(RealTime mode);
public abstract T visit(Sampled mode);
}
// Concrete uses of the recursion principle
final class ModeShow extends ModeVisitor<String> {
private ModeShow() {}
public static String show(Mode mode) {
return mode.accept(new ModeShow());
}
public String visit(RealTime mode) {
return "RealTime";
}
public String visit(Sampled mode) {
return "Sampled " + mode.getInterval();
}
}
Run Code Online (Sandbox Code Playgroud)
正如@ user3237465所说,数据类型的几种编码是可能的,当数据类型不是递归时恰好是一致的:Church编码是一个折叠:它允许你通过Church编码的数据类型的递归来累积值.Scott编码对应于实际模式匹配.无论如何,访问者可以用来实现所有这些编码.感谢你的推动,@ user3237465!