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 数据结构具有的一些属性:

  • 它的类型为 Expr和两个构造函数 LitAdd
  • 您不能从“外部”添加或删除构造函数

  • 因此,如果我们希望这些属性在 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 中的静态方法类(class)。我不会将其设为实例方法,因为这与 Haskell 版本相差甚远。

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

    相关文章:

    java - 使用json模板文件和json数据文件构建新的json字符串

    java - Xcode: 'Generics are not supported in -source 1.3' 编译器错误?

    java - 如何从JAVA中的两个集合中获取不匹配的字符串?

    haskell - 余数据类型真的是终端代数吗?

    swift - Monads和AOP相关?

    java - 如何在文件中的某个字符之后读取

    java - validator 无法正常工作

    haskell - 自动重新计算结果

    尽管总内存使用量只有 22Mb,但 Haskell 线程堆溢出?

    parsing - Haskell中Data.ByteString.Lazy.Char8的解析器?