如何在Java中使用访问者模式模拟Haskell的模式匹配

huangapple go评论57阅读模式
英文:

How to simulate Haskell's pattern matching using visitor pattern in Java

问题

// Java代码示例
// 以下是用于模拟Haskell函数和Visitor模式的Java代码。
// 请注意,以下代码仅为示例,您可能需要根据实际需要进行调整和优化。

interface Visitor<T, S> {
    S visitJust(Just<T> j);
    S visitNothing(Nothing<T> n);
}

abstract class Maybe<T> {
    public abstract <S> S accept(Visitor<T, S> v);

    public T getOrDefault(T defaultValue) {
        return this.accept(new Visitor<T, T>() {
            @Override
            public T visitJust(Just<T> j) { return j.value; }

            @Override
            public T visitNothing(Nothing<T> n) { return defaultValue; }
        });
    }

    public abstract int getLength();
}

class Just<T> extends Maybe<T> {
    final T value;

    public Just(T value) {
        this.value = value;
    }

    public <S> S accept(Visitor<T, S> v) {
        return v.visitJust(this);
    }

    public int getLength() {
        // 在这里实现获取长度的逻辑
        // 返回合适的长度值
    }
}

class Nothing<T> extends Maybe<T> {
    public <S> S accept(Visitor<T, S> v) {
        return v.visitNothing(this);
    }

    public int getLength() {
        // 返回表示没有长度的值,比如 -1
        return -1;
    }
}
// 解决泛型问题
// 要解决类型不匹配的问题,您需要将Visitor接口的泛型参数类型设置为List<T>,而不仅仅是T。
// 这样,Visitor中的方法就能正确地匹配Just<List<T>>和Nothing<List<T>>的类型。

public int getLength() {
    return this.accept(new Visitor<List<T>, Integer>() {
        @Override
        public Integer visitJust(Just<List<T>> j) {
            List<T> list = j.value;
            return list.size();
        }

        @Override
        public Integer visitNothing(Nothing<List<T>> n) {
            return -1;
        }
    });
}

请注意,由于这是一个简化的示例,您可能需要根据您的实际需求进行适当的调整和扩展。此代码演示了如何使用Visitor模式在Java中实现类似于Haskell中的模式匹配功能。

英文:

I am new to Java and I am trying to use visitor pattern to simulate pattern matching. For this Haskell function

getOrDefault :: Maybe a -&gt; a -&gt; a
getOrDefault (Just x) = const x
getOrDefault Nothing = id

which returns a value of type a (given a value of type Maybe a and a default value), the following Java codes work.

interface Visitor&lt;T, S&gt; {
    S visitJust(Just&lt;T&gt; j);
    S visitNothing(Nothing&lt;T&gt; n);
}

abstract class Maybe&lt;T&gt; {
    public abstract &lt;S&gt; S accept(Visitor&lt;T, S&gt; v);

    public T getOrDefault(T defaultValue) {
        return this.accept(new Visitor&lt;T, T&gt;() {
            @Override
            public T visitJust(Just&lt;T&gt; j) { return j.value; }

            @Override
            public T visitNothing(Nothing&lt;T&gt; n) { return defaultValue; }
        });
    }
}

class Just&lt;T&gt; extends Maybe&lt;T&gt; {
    final T value;

    public Just(T value) {
        this.value = value;
    }

    public &lt;S&gt; S accept(Visitor&lt;T, S&gt; v) {
        return v.visitJust(this);
    }

}

class Nothing&lt;T&gt; extends Maybe&lt;T&gt; {
    public &lt;S&gt; S accept(Visitor&lt;T, S&gt; v) {
        return v.visitNothing(this);
    }
}

When I try to simulate this function that obtains the "length" of a value of type Maybe [a]

getLength :: Maybe [a] -&gt; Int
getLength (Just x) = length x
getLength Nothing = -1

, the Java-version getLength I write is

public int getLength() {
    return this.accept(new Visitor&lt;List&lt;T&gt;, Integer&gt;() {
        @Override
        public Integer visitJust(Just&lt;List&lt;T&gt;&gt; j) { ... }

        @Override
        public Integer visitNothing(Nothing&lt;List&lt;T&gt;&gt; n) { ... }
    });
}

But it doesn't work, since T and List&lt;T&gt; are incompatible. How to fix this?

答案1

得分: 4

声明 getLength() 作为一个带有自己类型变量的静态方法:

public static <T> int getLength(Maybe<List<T>> maybe) {
  return maybe.accept(new Visitor<List<T>, Integer>() {
    @Override
    public Integer visitJust(Just<List<T>> j) { ... }

    @Override
    public Integer visitNothing(Nothing<List<T>> n) { ... }
  });
}
英文:

Declare getLength() as a static method with its own type variable:

  public static &lt;T&gt; int getLength(Maybe&lt;List&lt;T&gt;&gt; maybe) {
return maybe.accept(new Visitor&lt;List&lt;T&gt;, Integer&gt;() {
@Override
public Integer visitJust(Just&lt;List&lt;T&gt;&gt; j) { ... }
@Override
public Integer visitNothing(Nothing&lt;List&lt;T&gt;&gt; n) { ... }
});
}

huangapple
  • 本文由 发表于 2020年8月4日 16:21:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/63242850.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定