이것은 Haskell과 C++ 템플릿 메타 프로그래밍을 너무 많이 수행 한 사람의 흥미롭지 만 흥미로운 질문입니다. 나와 함께하시기 바랍니다일반 함수를 캡슐화하기위한 Java 함수 객체를 만드는 올바른 방법
일부 대수적 인 함수 속성을 확인하기 위해 일부 일반적인 Java 코드를 작성 중이며, 일부 함수에 대해 적절한 유형을 찾는 데 어려움이 있습니다. 이 기능은 읽어야
<E, R>
boolean checkCommutative(Binary<E,E,R> f
, Binary<R,R,Boolean> eq
, E a, E b)
{
return eq.ap(f.ap(a,b), f.ap(b, a));
}
: "두 E
's의 소요와 R
이 생산 진 기능 f
작동 예를 들어
a
입력
E
의
b
대한
f
가
(a,b)
인가 가환 경우 (두
R
년대 비교 함수
eq
의해 정의와 같음),
(b,a)
인가
f
같다. "
class Plus implements Binary<Integer, Integer, Integer> {
Integer ap(Integer a, Integer b) { return C.plus(a,b); }
}
class Eq implements Binary<Integer, Integer, Boolean> {
Boolean ap(Integer a, Integer b) { return a.equals(b); }
}
checkCommutative(new Plus(), new Eq(), rand(), rand());
을 모두 잘하고 좋은 :
나는 다음 주어진 함수 C.plus(Integer,Integer)
는 다음을 수행하여 교환 법칙이 성립하는지 테스트 할 수 있습니다.
이제 좀 더 복잡한 것을 구현하고 싶습니다. TheIntegers
및 TheRationals
: 나는 두 가지 구현이
interface Group<E> {
E plus(E,E);
}
하는의 말을하자의 내가 더하기 방법으로 일반적인 인터페이스 Group<E>
있다고 가정 해 봅시다 이제
class TheIntegers implements Group<Integer> { ... }
class TheRationals implements Group<Fraction> { ... }
을, 나는 아이디어를 캡처 할 수 있도록하려는 일반 함수 F
은 정수에서 rationalals까지 과 같은 함수 g
으로 통근합니다.
<E, R>
booleanCheckCommutesWith(Unary<E,R> f
, ?? g
, Binary<R,R,Boolean> eq
, E a, E b)
{
return eq.ap(f.ap(g.ap(a,b)), g.ap(f.ap(a), f.ap(b));
}
class F implements Unary<TheIntegers, TheRationals> {
Fraction ap (Integer x) { ... }
}
checkCommutesWith(new F(), new Plus(), new Eq(), rand(), rand());
여기서 문제는 g
의 형태가 무엇을해야입니다 제 1 컷, 나는 이런 식으로 뭔가를 쓰고 싶어? 문제는 이 E
및 R
의 두 가지 유형에 적용된다는 것입니다. 구체적인 예에서 g
은 Group<Integer>.plus(Integer,Integer)
과 Group<Fraction>.plus(Fraction,Fraction)
을 모두 나타내야합니다.
이제 g.ap
에 대한 두 호출 간의 유일한 구분이 지워지는 제네릭 형식이기 때문에 위의 checkCommutesWith
구현이 작동하지 않을 수 있습니다.
boolean checkCommutesWith(Unary<DE,RE> f
, ?? g
, Binary<RE,RE,Boolean> eq
, S domain, S range
, E x, E y)
{
return eq.ap(f.ap(g.ap(domain, x, y)),
, g.ap(range, f.ap(x), f.ap(y))
);
}
class Plus implements ??
{
<E, G extends Group<E>>
E ap (G gp, E x, E y) { return gp.plus(x,y); }
}
그래서 인터페이스 (??
)이 같아야합니다 : 그래서, 그것은 객체로 도메인과 범위를 추가하여 약간 수정거야? 이 C를했다면 ++ 나는
interface ?? <T> {
<E, S extends T<E>>
E ap(S, E, E);
}
의 상당을 작성하지만, AFAICT 자바는 템플릿 템플릿 매개 변수에 해당이 없습니다. 그게 내가 붙어있는 곳이야.
다른 구조에서도이 코드를 사용할 수 있기를 원하기 때문에 그룹에 checkCommutesWith
의 서명을 포함하고 싶지 않습니다. 일반 정의가 가능해야한다고 생각합니다 ("should"의 정의에 따라).)
업데이트/설명 여기서 중요한 점은 세트 간 맵의 정의 속성은 eq()로 통근한다는 것입니다. 집단 동형어 변성의 특징은 plus()로 통근한다는 것이다. 고리 동형 이형성의 정의 적 특성은 시간()으로 통근한다는 것이다. 이 아이디어를 캡처하는 일반적인 commutesWith 함수를 정의하려고합니다. eq, plus 및 times (및 다른 구조도 캡슐화하는 데 적합한 추상화를 찾고 있습니다.
전략 패턴 – rees
없이 컴파일
https://github.com/rfqu/CodeSamples/blob/master/src/so/SoFun.java
에서 코드를 볼 "문제는 g는 두 가지 유형에 적용된다 : E와 R ". 그렇다면 문제는 Java가 아닌 디자인에 있습니다. 자바는 그렇게 할 수 없을 때 옳다. 그러한 함수 g가 의미가있는 곳에서 더 구체적인 예를 들어 주시겠습니까? –
@AlexeiKaigorodov : plus() 함수를 생각해보십시오. 그룹에 하나의 그룹과 두 그룹의 요소를 제공하면 해당 그룹의 요소를 제공해야합니다. TheRationals에 적용하여 한 쌍의 이성에서 합리적인 것으로 함수를 만들고 TheIntegers로 정수에서 정수로 함수를 가져와야합니다. 마찬가지로, times()는 반지와 함께 제공 될 때, 그리고 그 반지의 두 요소는 저에게 반지의 요소를 제공해야합니다. 따라서 캡슐화하려는 공통 구조는 임의의 T에 대해> E ap (S, E, E) 형식의 함수입니다. –
mdgeorge