@amon의 제안에서 더 모나 딕 한 답변이 있습니다. 그것은 매우 삶은 버전이며 몇 가지 가정을 받아 들여야합니다.
"unit"또는 "return"함수는 클래스 생성자입니다.
"바인드"작업은 컴파일시 발생하므로 호출에서 숨겨집니다.
"action"함수는 컴파일 타임에 클래스에 바인딩됩니다
클래스는 일반적이며 임의의 클래스 E를 래핑하지만 실제로이 경우 과잉이라고 생각합니다. 그러나 나는 당신이 할 수있는 일의 예로서 그 길을 떠났습니다.
이러한 고려 사항으로 모나드는 유창한 래퍼 클래스로 변환됩니다 (순전히 기능적인 언어로 얻을 수있는 많은 유연성을 포기하더라도).
public class RepositoryLookup<E> {
private String source;
private E answer;
private Exception exception;
public RepositoryLookup<E>(String source) {
this.source = source;
}
public RepositoryLookup<E> fetchElement() {
if (answer != null) return this;
if (! exception instanceOf NotFoundException) return this;
try {
answer = lookup(source);
}
catch (Exception e) {
exception = e;
}
return this;
}
public RepositoryLookup<E> orFetchSimilarElement() {
if (answer != null) return this;
if (! exception instanceOf NotFoundException) return this;
try {
answer = lookupVariation(source);
}
catch (Exception e) {
exception = e;
}
return this;
}
public RepositoryLookup<E> orFetchParentElement() {
if (answer != null) return this;
if (! exception instanceOf NotFoundException) return this;
try {
answer = lookupParent(source);
}
catch (Exception e) {
exception = e;
}
return this;
}
public boolean failed() {
return exception != null;
}
public Exception getException() {
return exception;
}
public E getAnswer() {
// better to check failed() explicitly ;)
if (this.exception != null) {
throw new IllegalArgumentException(exception);
}
// TODO: add a null check here?
return answer;
}
}
(이것은 컴파일되지 않습니다 ... 샘플을 작게 유지하기 위해 특정 세부 사항이 완료되지 않은 상태로 남아 있습니다)
그리고 호출은 다음과 같습니다.
Repository<String> repository = new Repository<String>(x);
repository.fetchElement().orFetchParentElement().orFetchSimilarElement();
if (repository.failed()) {
throw new IllegalArgumentException(repository.getException());
}
System.err.println("Got " + repository.getAnswer());
"가져 오기"작업을 원하는대로 구성 할 수있는 유연성이 있습니다. 찾을 수없는 것 이외의 답변이나 예외를 받으면 중지됩니다.
나는 이것을 정말로 빨리했다; 그것은 옳지 않지만 희망적으로 아이디어를 전달합니다.
NotFoundException
실제로 특별한 무언가는?