Я новичок в Java и пытаюсь использовать шаблон посетителя для имитации сопоставления с шаблоном. Для этой функции Haskell
getOrDefault :: Maybe a -> a -> a
getOrDefault (Just x) = const x
getOrDefault Nothing = id
, которая возвращает значение типа a
(с учетом значения типа Maybe a
и значения по умолчанию), работают следующие коды 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; }
});
}
}
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);
}
}
class Nothing<T> extends Maybe<T> {
public <S> S accept(Visitor<T, S> v) {
return v.visitNothing(this);
}
}
Когда я пытаюсь смоделировать эту функцию, которая получает «длину» значения типа Maybe [a]
getLength :: Maybe [a] -> Int
getLength (Just x) = length x
getLength Nothing = -1
, Java -версия getLength
я пишу
public int getLength() {
return this.accept(new Visitor<List<T>, Integer>() {
@Override
public Integer visitJust(Just<List<T>> j) { ... }
@Override
public Integer visitNothing(Nothing<List<T>> n) { ... }
});
}
Но это не работает, так как T
и List<T>
несовместимы. Как это исправить?