簡體   English   中英

如何將 rxjava2 Zip function (從 Single/Observable)的 arity 推廣到 n 可選 arguments 而不會丟失其類型?

[英]How can I generalize the arity of rxjava2 Zip function (from Single/Observable) to n Optional arguments without lose its types?

Related to this question https://stackoverflow.com/questions I want to achieve the same in Java with rxJava2 as in haskell How can I implement generalized "zipn" and "unzipn" 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中:

想象一下,你有一個很長的參數 function:

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;
}

以及使用該接口的 function:

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);

您需要的 arguments 來源如下:

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 function:

    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>>怎么辦?

為了解決這個問題,我使用了另一個答案中的工具:

  1. 柯里化函數
  2. 部分應用
  3. Generics
  4. 應用函子概念
  5. 函子概念

首先,我使用所需的 arguments 創建接口:

導入 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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM