如何在不丢失其类型的情况下将 rxjava2 Zip 函数的元数(从 Single/Observable)概括为 n 个可选参数?
How can I generalize the arity of rxjava2 Zip function (from Single/Observable) to n Optional arguments without lose its types?
与此问题相关https://whosebug.com/questions I want to achieve the same in Java with rxJava2 as in haskell :
在 haskell 中,我可以使用应用函子实现此目的:
f <$> a1 <*> a2 <*> a3 <*> a4 <*> a5 <*> a6 <*> a7 <*> a8 <*> a9 <*> a10 <*> a11
成为f :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> String -> String -> String -> Int
和a1 .. a11
值对应每种类型
现在 Java
:
假设你有一个 long arity 函数:
import io.reactivex.annotations.NonNull;
public interface Function11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R> {
@NonNull
R apply(@NonNull T1 var1, @NonNull T2 var2, @NonNull T3 var3, @NonNull T4 var4, @NonNull T5 var5, @NonNull T6 var6, @NonNull T7 var7, @NonNull T8 var8, @NonNull T9 var9, @NonNull T10 var10, @NonNull T11 var11) throws Exception;
}
以及使用该接口的函数:
Function11<String, Integer, Optional<Integer>, String, String, String, String, String, String, String, String, String> f = (s, i1, i2, s2, s3, s4, s5, s6, s7, s8, s9) -> "".join("-", s, "i" + i1.toString(), "i" + i2.orElse(5).toString(), s2, s3, s4, s5, s6, s7, s8, s9);
您需要的论据来源如下:
Single<String> singleString1 = Single.just("s1");
Single<Integer> singleOne = Single.just(1);
Optional<Single<Integer>> singleOptionalTwo = Optional.of(Single.just(2));
Single<String> singleString2 = Single.just("s2");
Single<String> singleString3 = Single.just("s3");
Single<String> singleString4 = Single.just("s4");
Single<String> singleString5 = Single.just("s5");
Single<String> singleString6 = Single.just("s6");
Single<String> singleString7 = Single.just("s7");
Single<String> singleString8 = Single.just("s8");
Single<String> singleString9 = Single.just("s9");
然后是 zipArray 函数:
Single.zipArray(
(Object[] array) ->
function11(
(String) array[0],
(Integer) array[0],
(Optional<Integer>) array[0],
(String) array[0],
(String) array[0],
(String) array[0],
(String) array[0],
(String) array[0],
(String) array[0],
(String) array[0],
(String) array[0],
(String) array[0]
)
,
singleString1,
singleOne,
singleString2,
singleString2,
singleString3,
singleString4,
singleString5,
singleString6,
singleString7,
singleString8,
singleString9
);
如您所见,有几个错误:
- 选角不好
- 错误的参数索引
- 运行时输入错误
如何修复这些错误?如果其中之一是 Optiona<Single<String>>
怎么办?
为了解决这个问题,我使用了其他答案中的工具:
- 柯里化函数
- 部分申请
- 泛型
- 应用函子概念
- 函子概念
首先,我使用所需的参数创建接口:
导入io.reactivex.annotations.NonNull;
public interface Function11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R> {
@NonNull
R apply(@NonNull T1 var1, @NonNull T2 var2, @NonNull T3 var3, @NonNull T4 var4, @NonNull T5 var5, @NonNull T6 var6, @NonNull T7 var7, @NonNull T8 var8, @NonNull T9 var9, @NonNull T10 var10, @NonNull T11 var11) throws Exception;
}
然后,我创建扩展 class:
public class SingleExtension {
public static <A, B> Single<B> zipOver(Single<Function<A, B>> applicativeFunctor, Single<A> applicativeValue) {
return Single.zip(
applicativeFunctor,
applicativeValue,
(Function<A, B> f, A a) -> f.apply(a));
}
public static <A, B> Single<B> zipOverOptional(Single<Function<Optional<A>, B>> applicativeFunctor, Optional<Single<A>> applicativeValue) {
if (applicativeValue.isPresent()) {
return Single.zip(
applicativeFunctor,
applicativeValue.get(),
(Function<Optional<A>, B> f, A a) -> f.apply(Optional.of(a))
);
} else {
return applicativeFunctor.map((f) -> f.apply(Optional.empty()));
}
}
}
终于用上了
public static void main(String[] args) {
Function11<String, Integer, Optional<Integer>, String, String, String, String, String, String, String, String, String> function11 = (String s1, Integer i2, Optional<Integer> i3, String s4, String s5, String s6, String s7, String s8, String s9, String s10, String s11) -> "".join("-", s1, "i" + i2.toString(), "i" + i3.orElse(5).toString(), s4, s5, s6, s7, s8, s9, s10, s11);
Function<String, Function<Integer, Function<Optional<Integer>, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>>>>>>> curryF = Curry.curry(function11);
Single<Function<String, Function<Integer, Function<Optional<Integer>, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>>>>>>>> applicativeCurryF = Single.just(curryF);
Single<String> singleString1 = Single.just("s1");
Single<Integer> singleOne = Single.just(1);
Optional<Single<Integer>> singleOptionalTwo = Optional.of(Single.just(2));
Single<String> singleString2 = Single.just("s2");
Single<String> singleString3 = Single.just("s3");
Single<String> singleString4 = Single.just("s4");
Single<String> singleString5 = Single.just("s5");
Single<String> singleString6 = Single.just("s6");
Single<String> singleString7 = Single.just("s7");
Single<String> singleString8 = Single.just("s8");
Single<String> singleString9 = Single.just("s9");
Single<String> singleString10 = Single.just("s10");
Single<Function<Integer, Function<Optional<Integer>, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>>>>>>> applied1 = (SingleExtension.zipOver(applicativeCurryF, singleString1));
Single<Function<Optional<Integer>, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>>>>>> applied2 = (SingleExtension.zipOver(applied1, singleOne));
Single<Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>>>>> applied3 = (SingleExtension.zipOverOptional(applied2, singleOptionalTwo));
Single<Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>>>> applied4 = (SingleExtension.zipOver(applied3, singleString2));
Single<Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>>> applied5 = (SingleExtension.zipOver(applied4, singleString3));
Single<Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>> applied6 = (SingleExtension.zipOver(applied5, singleString4));
Single<Function<String, Function<String, Function<String, Function<String, String>>>>> applied7 = (SingleExtension.zipOver(applied6, singleString5));
Single<Function<String, Function<String, Function<String, String>>>> applied8 = (SingleExtension.zipOver(applied7, singleString6));
Single<Function<String, Function<String, String>>> applied9 = (SingleExtension.zipOver(applied8, singleString7));
Single<Function<String, String>> applied10 = (SingleExtension.zipOver(applied9, singleString8));
Single<String> result = (SingleExtension.zipOver(applied10, singleString9));
result
.test()
.assertValue("s1-i1-i2-s2-s3-s4-s5-s6-s7-s8-s9");
System.out.println("All ok");
}
如果库包含这些方法,那么将它们链接起来就很容易了:
String result = applicativeCurryF
.zipOver(singleString1)
.zipOverOptional(singleOptionalTwo)
.zipOver(singleString2)
.zipOver(singleString3)
.zipOver(singleString4)
.zipOver(singleString5)
.zipOver(singleString6)
.zipOver(singleString7)
.zipOver(singleString8)
.zipOver(singleString9)
与此问题相关https://whosebug.com/questions I want to achieve the same in Java with rxJava2 as in haskell
在 haskell 中,我可以使用应用函子实现此目的:
f <$> a1 <*> a2 <*> a3 <*> a4 <*> a5 <*> a6 <*> a7 <*> a8 <*> a9 <*> a10 <*> a11
成为f :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> String -> String -> String -> Int
和a1 .. a11
值对应每种类型
现在 Java
:
假设你有一个 long arity 函数:
import io.reactivex.annotations.NonNull;
public interface Function11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R> {
@NonNull
R apply(@NonNull T1 var1, @NonNull T2 var2, @NonNull T3 var3, @NonNull T4 var4, @NonNull T5 var5, @NonNull T6 var6, @NonNull T7 var7, @NonNull T8 var8, @NonNull T9 var9, @NonNull T10 var10, @NonNull T11 var11) throws Exception;
}
以及使用该接口的函数:
Function11<String, Integer, Optional<Integer>, String, String, String, String, String, String, String, String, String> f = (s, i1, i2, s2, s3, s4, s5, s6, s7, s8, s9) -> "".join("-", s, "i" + i1.toString(), "i" + i2.orElse(5).toString(), s2, s3, s4, s5, s6, s7, s8, s9);
您需要的论据来源如下:
Single<String> singleString1 = Single.just("s1");
Single<Integer> singleOne = Single.just(1);
Optional<Single<Integer>> singleOptionalTwo = Optional.of(Single.just(2));
Single<String> singleString2 = Single.just("s2");
Single<String> singleString3 = Single.just("s3");
Single<String> singleString4 = Single.just("s4");
Single<String> singleString5 = Single.just("s5");
Single<String> singleString6 = Single.just("s6");
Single<String> singleString7 = Single.just("s7");
Single<String> singleString8 = Single.just("s8");
Single<String> singleString9 = Single.just("s9");
然后是 zipArray 函数:
Single.zipArray(
(Object[] array) ->
function11(
(String) array[0],
(Integer) array[0],
(Optional<Integer>) array[0],
(String) array[0],
(String) array[0],
(String) array[0],
(String) array[0],
(String) array[0],
(String) array[0],
(String) array[0],
(String) array[0],
(String) array[0]
)
,
singleString1,
singleOne,
singleString2,
singleString2,
singleString3,
singleString4,
singleString5,
singleString6,
singleString7,
singleString8,
singleString9
);
如您所见,有几个错误:
- 选角不好
- 错误的参数索引
- 运行时输入错误
如何修复这些错误?如果其中之一是 Optiona<Single<String>>
怎么办?
为了解决这个问题,我使用了其他答案中的工具:
- 柯里化函数
- 部分申请
- 泛型
- 应用函子概念
- 函子概念
首先,我使用所需的参数创建接口:
导入io.reactivex.annotations.NonNull;
public interface Function11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R> {
@NonNull
R apply(@NonNull T1 var1, @NonNull T2 var2, @NonNull T3 var3, @NonNull T4 var4, @NonNull T5 var5, @NonNull T6 var6, @NonNull T7 var7, @NonNull T8 var8, @NonNull T9 var9, @NonNull T10 var10, @NonNull T11 var11) throws Exception;
}
然后,我创建扩展 class:
public class SingleExtension {
public static <A, B> Single<B> zipOver(Single<Function<A, B>> applicativeFunctor, Single<A> applicativeValue) {
return Single.zip(
applicativeFunctor,
applicativeValue,
(Function<A, B> f, A a) -> f.apply(a));
}
public static <A, B> Single<B> zipOverOptional(Single<Function<Optional<A>, B>> applicativeFunctor, Optional<Single<A>> applicativeValue) {
if (applicativeValue.isPresent()) {
return Single.zip(
applicativeFunctor,
applicativeValue.get(),
(Function<Optional<A>, B> f, A a) -> f.apply(Optional.of(a))
);
} else {
return applicativeFunctor.map((f) -> f.apply(Optional.empty()));
}
}
}
终于用上了
public static void main(String[] args) {
Function11<String, Integer, Optional<Integer>, String, String, String, String, String, String, String, String, String> function11 = (String s1, Integer i2, Optional<Integer> i3, String s4, String s5, String s6, String s7, String s8, String s9, String s10, String s11) -> "".join("-", s1, "i" + i2.toString(), "i" + i3.orElse(5).toString(), s4, s5, s6, s7, s8, s9, s10, s11);
Function<String, Function<Integer, Function<Optional<Integer>, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>>>>>>> curryF = Curry.curry(function11);
Single<Function<String, Function<Integer, Function<Optional<Integer>, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>>>>>>>> applicativeCurryF = Single.just(curryF);
Single<String> singleString1 = Single.just("s1");
Single<Integer> singleOne = Single.just(1);
Optional<Single<Integer>> singleOptionalTwo = Optional.of(Single.just(2));
Single<String> singleString2 = Single.just("s2");
Single<String> singleString3 = Single.just("s3");
Single<String> singleString4 = Single.just("s4");
Single<String> singleString5 = Single.just("s5");
Single<String> singleString6 = Single.just("s6");
Single<String> singleString7 = Single.just("s7");
Single<String> singleString8 = Single.just("s8");
Single<String> singleString9 = Single.just("s9");
Single<String> singleString10 = Single.just("s10");
Single<Function<Integer, Function<Optional<Integer>, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>>>>>>> applied1 = (SingleExtension.zipOver(applicativeCurryF, singleString1));
Single<Function<Optional<Integer>, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>>>>>> applied2 = (SingleExtension.zipOver(applied1, singleOne));
Single<Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>>>>> applied3 = (SingleExtension.zipOverOptional(applied2, singleOptionalTwo));
Single<Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>>>> applied4 = (SingleExtension.zipOver(applied3, singleString2));
Single<Function<String, Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>>> applied5 = (SingleExtension.zipOver(applied4, singleString3));
Single<Function<String, Function<String, Function<String, Function<String, Function<String, String>>>>>> applied6 = (SingleExtension.zipOver(applied5, singleString4));
Single<Function<String, Function<String, Function<String, Function<String, String>>>>> applied7 = (SingleExtension.zipOver(applied6, singleString5));
Single<Function<String, Function<String, Function<String, String>>>> applied8 = (SingleExtension.zipOver(applied7, singleString6));
Single<Function<String, Function<String, String>>> applied9 = (SingleExtension.zipOver(applied8, singleString7));
Single<Function<String, String>> applied10 = (SingleExtension.zipOver(applied9, singleString8));
Single<String> result = (SingleExtension.zipOver(applied10, singleString9));
result
.test()
.assertValue("s1-i1-i2-s2-s3-s4-s5-s6-s7-s8-s9");
System.out.println("All ok");
}
如果库包含这些方法,那么将它们链接起来就很容易了:
String result = applicativeCurryF
.zipOver(singleString1)
.zipOverOptional(singleOptionalTwo)
.zipOver(singleString2)
.zipOver(singleString3)
.zipOver(singleString4)
.zipOver(singleString5)
.zipOver(singleString6)
.zipOver(singleString7)
.zipOver(singleString8)
.zipOver(singleString9)