Java到Haskell - 计算器

时间:2015-04-07 00:36:35

标签: haskell math types

我需要一些帮助将一些Java代码转换为Haskell。我设法做了一个愚蠢的版本。这个愚蠢的版本如下:

add :: Integer -> Integer -> Integer
add a b = a + b

sub :: Integer -> Integer -> Integer
sub a b = a - b

mult :: Integer -> Integer -> Integer
mult a b = a * b

divi :: Integer -> Integer -> Integer
divi a b = a `div` b

因此,对于上述情况,如果我执行以下示例:

Prelude> add (mult 3 2) (sub 2 1)

它将返回:

Prelude> 7

我知道这有效,但我应该将以下Java代码转换为Haskell,并且我知道上面的代码与Java代码不同:

public class Calculator {
    static interface Expression { < T > T accept(Visitor < T > v);
    }
    static class IntNumber implements Expression {
        int value;
        IntNumber(int value) {
            this.value = value;
        }@Override
        public < T > T accept(Visitor < T > v) {
            return v.visit(this);
        }
    }
    static class Multiply implements Expression {

        Expression a, b;
        Multiply(Expression a, Expression b) {
            this.a = a;
            this.b = b;
        }@Override
        public < T > T accept(Visitor < T > v) {
            return v.visit(this);
        }
    }
    static class Divide implements Expression {
        Expression numerator, denominator;
        Divide(Expression numerator, Expression denominator) {
            this.numerator = numerator;
            this.denominator = denominator;
        }@Override
        public < T > T accept(Visitor < T > v) {
            return v.visit(this);
        }
    }
    static class Add implements Expression {
        Expression a, b;
        Add(Expression a, Expression b) {
            this.a = a;
            this.b = b;
        }@Override
        public < T > T accept(Visitor < T > v) {
            return v.visit(this);
        }
    }
    static class Subtract implements Expression {
        Expression a, b;
        Subtract(Expression a, Expression b) {
            this.a = a;
            this.b = b;
        }@Override
        public < T > T accept(Visitor < T > v) {
            return v.visit(this);
        }
    }
    static interface Visitor < T > {
        public T visit(IntNumber integer);
        public T visit(Add add);
        public T visit(Subtract subtract);
        public T visit(Multiply multiply);
        public T visit(Divide divide);
    }
    static class Evaluate implements Visitor < Integer > {@Override
        //this method will be called and return “3”
        public Integer visit(IntNumber integer) {
            return integer.value;
        }@Override
        public Integer visit(Add add) {
            return add.a.accept(this) + add.b.accept(this);
        }@Override
        public Integer visit(Subtract subtract) {
            return subtract.a.accept(this) - subtract.b.accept(this);
        }@Override
        public Integer visit(Multiply multiply) {
            // “this” means an instance (eval) of Evaluate class
            return multiply.a.accept(this) * multiply.b.accept(this);
        }@Override
        public Integer visit(Divide divide) {
            return divide.numerator.accept(this) / divide.denominator.accept(this);
        }
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        Evaluate eval = new Evaluate();
        System.out.println(eval.visit(
        new Multiply(
        new IntNumber(3),
        new Subtract(new IntNumber(10), new IntNumber(5)))));
    }
}

我真的迷失了,即使Java代码让我感到困惑。我真的需要一些帮助。任何帮助是极大的赞赏!

1 个答案:

答案 0 :(得分:5)

Java代码中精心设计的visitor pattern模拟带有产品的sum typequantification。在Java中,量化采用通用类型的形式。我写了一个更简单的例子(在C#中)using generics to simulate sum types

在Haskell中,我们不需要求助于这样精细的表示,并且可以直接使用和类型

data Expression
     = IntNumber Integer
     | Add      Expression Expression
     | Subtract Expression Expression
     | Multiply Expression Expression
     | Divide   Expression Expression

Evaluate Visitor <Integer>可以在Haskell中编写为类型为Expression -> Integer的简单函数。

evaluate :: Expression     -> Integer
evaluate    (IntNumber x)  =  x
evaluate    (Add      a b) =  evaluate a + evaluate b
evaluate    (Subtract a b) =  evaluate a - evaluate b
evaluate    (Multiply a b) =  evaluate a * evaluate b
evaluate    (Divide   a b) =  evaluate a `div` evaluate b