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

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

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

问题

  1. // Java代码示例
  2. // 以下是用于模拟Haskell函数和Visitor模式的Java代码。
  3. // 请注意,以下代码仅为示例,您可能需要根据实际需要进行调整和优化。
  4. interface Visitor<T, S> {
  5. S visitJust(Just<T> j);
  6. S visitNothing(Nothing<T> n);
  7. }
  8. abstract class Maybe<T> {
  9. public abstract <S> S accept(Visitor<T, S> v);
  10. public T getOrDefault(T defaultValue) {
  11. return this.accept(new Visitor<T, T>() {
  12. @Override
  13. public T visitJust(Just<T> j) { return j.value; }
  14. @Override
  15. public T visitNothing(Nothing<T> n) { return defaultValue; }
  16. });
  17. }
  18. public abstract int getLength();
  19. }
  20. class Just<T> extends Maybe<T> {
  21. final T value;
  22. public Just(T value) {
  23. this.value = value;
  24. }
  25. public <S> S accept(Visitor<T, S> v) {
  26. return v.visitJust(this);
  27. }
  28. public int getLength() {
  29. // 在这里实现获取长度的逻辑
  30. // 返回合适的长度值
  31. }
  32. }
  33. class Nothing<T> extends Maybe<T> {
  34. public <S> S accept(Visitor<T, S> v) {
  35. return v.visitNothing(this);
  36. }
  37. public int getLength() {
  38. // 返回表示没有长度的值,比如 -1
  39. return -1;
  40. }
  41. }
  1. // 解决泛型问题
  2. // 要解决类型不匹配的问题,您需要将Visitor接口的泛型参数类型设置为List<T>,而不仅仅是T。
  3. // 这样,Visitor中的方法就能正确地匹配Just<List<T>>和Nothing<List<T>>的类型。
  4. public int getLength() {
  5. return this.accept(new Visitor<List<T>, Integer>() {
  6. @Override
  7. public Integer visitJust(Just<List<T>> j) {
  8. List<T> list = j.value;
  9. return list.size();
  10. }
  11. @Override
  12. public Integer visitNothing(Nothing<List<T>> n) {
  13. return -1;
  14. }
  15. });
  16. }

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

英文:

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

  1. getOrDefault :: Maybe a -&gt; a -&gt; a
  2. getOrDefault (Just x) = const x
  3. 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.

  1. interface Visitor&lt;T, S&gt; {
  2. S visitJust(Just&lt;T&gt; j);
  3. S visitNothing(Nothing&lt;T&gt; n);
  4. }
  5. abstract class Maybe&lt;T&gt; {
  6. public abstract &lt;S&gt; S accept(Visitor&lt;T, S&gt; v);
  7. public T getOrDefault(T defaultValue) {
  8. return this.accept(new Visitor&lt;T, T&gt;() {
  9. @Override
  10. public T visitJust(Just&lt;T&gt; j) { return j.value; }
  11. @Override
  12. public T visitNothing(Nothing&lt;T&gt; n) { return defaultValue; }
  13. });
  14. }
  15. }
  16. class Just&lt;T&gt; extends Maybe&lt;T&gt; {
  17. final T value;
  18. public Just(T value) {
  19. this.value = value;
  20. }
  21. public &lt;S&gt; S accept(Visitor&lt;T, S&gt; v) {
  22. return v.visitJust(this);
  23. }
  24. }
  25. class Nothing&lt;T&gt; extends Maybe&lt;T&gt; {
  26. public &lt;S&gt; S accept(Visitor&lt;T, S&gt; v) {
  27. return v.visitNothing(this);
  28. }
  29. }

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

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

, the Java-version getLength I write is

  1. public int getLength() {
  2. return this.accept(new Visitor&lt;List&lt;T&gt;, Integer&gt;() {
  3. @Override
  4. public Integer visitJust(Just&lt;List&lt;T&gt;&gt; j) { ... }
  5. @Override
  6. public Integer visitNothing(Nothing&lt;List&lt;T&gt;&gt; n) { ... }
  7. });
  8. }

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

答案1

得分: 4

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

  1. public static <T> int getLength(Maybe<List<T>> maybe) {
  2. return maybe.accept(new Visitor<List<T>, Integer>() {
  3. @Override
  4. public Integer visitJust(Just<List<T>> j) { ... }
  5. @Override
  6. public Integer visitNothing(Nothing<List<T>> n) { ... }
  7. });
  8. }
英文:

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

  1. public static &lt;T&gt; int getLength(Maybe&lt;List&lt;T&gt;&gt; maybe) {
  2. return maybe.accept(new Visitor&lt;List&lt;T&gt;, Integer&gt;() {
  3. @Override
  4. public Integer visitJust(Just&lt;List&lt;T&gt;&gt; j) { ... }
  5. @Override
  6. public Integer visitNothing(Nothing&lt;List&lt;T&gt;&gt; n) { ... }
  7. });
  8. }

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:

确定