java - Haskell 数据类型到 Java(OO)

标签 java haskell

我正在尝试将一个简单的 Haskell 数据类型和一个函数转换为 OO。 但是我很困惑..

具有以下用于算术计算的Haskell类型:

data Expr = Lit Int | 
      Add Expr Expr |
   deriving Show

--Turn the expr to a nice string
showExpr :: Expr -> String 
showExpr (Lit n) = show n
showExpr (Add e1 e2) = "(" ++ showExpr e1 ++ "+" ++ showExpr e2 ++ ")"

现在我正在尝试转换..

public interface Expr {
  String showExpr(String n);
} 

// Base case
public class Lit implements Expr {
  String n;

  public Lit(String n) {
    this.n = n;
  }

  @Override
  public String ShowExpr() {
    return n;
  }
}

public class Add implements Expr {
  Expr a;
  Expr b;

  public Add(Expr aExpr, Expr bExpr) {
    this.a = aExpr;
    this.b = bExpr;
  }

  public String ShowExpr() {
    return "(" + a.ShowExpr() + "+" + b.ShowExpr() + ")";
  }

  public static void main(String[] args) {
    Lit firstLit  = new Lit("2");
    Lit secLit = new Lit("3");
    Add add = new Add(firstLit,secLit);
    System.out.println(add.ShowExpr());
  }
}

这将导致“(2+3)”,这是正确答案。

但是..我不确定..这是在 OO 中思考和建模的正确方法吗?

Haskell 数据类型不是很好的表示吗?

最佳答案

让我们尽可能地复制代码。

Haskell 数据结构的一些属性如下:

  1. 它有类型 Expr 和两个构造函数 LitAdd
  2. 您不能从“外部”添加或删除构造函数

因此,如果我们希望这些属性在 Java 版本中保持为真,您应该这样做:

public abstract class Expr {
    // So that you can't add more subclasses outside this block
    private Expr() {}

    // Simulate pattern matching:
    // (This CAN be done with instanceof, but that's ugly and not OO)
    public boolean isLit() {
        return false;
    }
    public boolean isAdd() {
        return false;
    }
    public Lit asLit() {
        throw new UnsupportedOperationException("This is not a Lit");
    }
    public Add asAdd() {
        throw new UnsupportedOperationException("This is not an Add");
    }

    public static class Lit extends Expr {
        public final int n;
        public Lit(int n) {
            this.n = n;
        }
        @Override
        public boolean isLit() {
            return true;
        }
        @Override
        public Lit asLit() {
            return this;
        }
    }

    public static class Add extends Expr {
        public final Expr a, b;
        public Lit(Expr a, Expr b) {
            this.a = a;
            this.b = b;
        }
        @Override
        public boolean isAdd() {
            return true;
        }
        @Override
        public Add asAdd() {
            return this;
        }
    }
}

现在,转换showExpr:

public static String showExpr(final Expr expr) {
    if(expr.isLit()) {
        return Integer.toString(expr.asLit().n);
    } else if(expr.isAdd()) {
        return "(" + expr.asAdd().a + "+" + expr.asAdd().b + ")";
    }
}

您可以将showExpr 作为Expr 类中的静态方法。我不会使它成为一个实例方法,因为这与 Haskell 版本相去甚远。

关于java - Haskell 数据类型到 Java(OO),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9504641/

相关文章:

haskell - 神经网络总是为任何输入产生相同/相似的输出

c - Haskell FFI - 你能从 Haskell 数据结构中获取 C 指针吗?

class - Haskell,类中的函数声明

java - 使用 spring boot 对数据库的错误查询

java - 如果我没有与之共享,JRuby 中的 Ruby 脚本可以使用我的 Java 类吗?

list - 如何将函数应用于列表的两个元素 - Haskell

haskell - Haskell 中的并行 monad 映射?像 parMapM 之类的东西?

java - 如何在 Java 中以线程安全的方式通过构造函数传递列表?

java - 找出/计算符号的宽度

java - java Builder 类中的附加方法(lombok 注解)