77import com .jnape .palatable .lambda .functions .Fn3 ;
88import com .jnape .palatable .lambda .functions .builtin .fn3 .LiftA2 ;
99import com .jnape .palatable .lambda .functions .builtin .fn4 .LiftA3 ;
10- import com .jnape .palatable .lambda .functor .Applicative ;
1110import com .jnape .palatable .lambda .functor .builtin .Lazy ;
1211import com .jnape .palatable .lambda .io .IO ;
1312import com .jnape .palatable .lambda .traversable .LambdaIterable ;
@@ -40,6 +39,7 @@ public void applicativesZipEmbeddedValuesWithEmbeddedFunctions() {
4039
4140 assertThat (just (9 ).zip (just (inc )), equalTo (just (10 )));
4241 assertThat (just (15 ).zip (just (inc )), equalTo (just (__ )));
42+ assertThat (just (7 ).zip (nothing ()), equalTo (nothing ()));
4343 // Explicit types help the compiler
4444 assertThat (Maybe .<Integer >nothing ().zip (just (inc )), equalTo (__ ));
4545
@@ -50,7 +50,7 @@ public void applicativesZipEmbeddedValuesWithEmbeddedFunctions() {
5050
5151 // Moving on to LambdaIterables, where "zipping" is more obvious
5252 LambdaIterable <Integer > oneThroughThree = LambdaIterable .wrap (asList (1 , 2 , 3 ));
53- Applicative <Fn1 <? super Integer , ? extends Integer >, LambdaIterable <? >> wrappedInc = LambdaIterable .wrap (asList (inc ));
53+ LambdaIterable <Fn1 <? super Integer , ? extends Integer >> wrappedInc = LambdaIterable .wrap (asList (inc ));
5454 assertThat (oneThroughThree .zip (wrappedInc ).unwrap (), iterates (2 , 3 , 4 ));
5555
5656 Fn1 <Integer , Integer > dec = x -> x - 1 ;
@@ -62,6 +62,30 @@ public void applicativesZipEmbeddedValuesWithEmbeddedFunctions() {
6262 assertThat (oneThroughThree .zip (allFunctions ).unwrap (), iterates (__ ()));
6363 }
6464
65+ @ Test
66+ public void functionIsApplicative () {
67+ Fn1 <String , Integer > strLen = String ::length ;
68+ Fn1 <String , String > toUpper = String ::toUpperCase ;
69+
70+ // Result of unary function calls are passed to mapping function as arguments
71+ Fn1 <String , Tuple2 <Integer , String >> lengthAndUppercase = LiftA2 .liftA2 (Tuple2 ::tuple , strLen , toUpper );
72+ assertThat (lengthAndUppercase .apply ("hello world" ), equalTo (tuple (11 , "HELLO WORLD" )));
73+
74+ Fn1 <Integer , Integer > mod3 = i -> i % 3 ;
75+ Fn1 <Integer , Integer > div3 = i -> i / 3 ;
76+
77+ Fn1 <Integer , String > showDivision = LiftA2 .liftA2 ((divided , remainder ) -> String .format ("%d * 3 + %d" , divided , remainder ), div3 , mod3 );
78+ assertThat (showDivision .apply (10 ), equalTo (__ ));
79+
80+
81+ Fn1 <String , Integer > findStart = s -> s .indexOf ('j' );
82+ Fn1 <String , Integer > findEnd = s -> s .indexOf (' ' );
83+ Fn3 <String , Integer , Integer , String > cutString = String ::substring ;
84+
85+ Fn1 <String , String > transformAndCut = LiftA3 .liftA3 (cutString , toUpper , findStart , findEnd );
86+ assertThat (transformAndCut .apply ("hellojava world" ), equalTo (__ ));
87+ }
88+
6589 @ Test
6690 public void lazyApplicatives () {
6791 // Zipping LambdaIterables is lazy because LambdaIterables are lazy
@@ -85,44 +109,21 @@ public void lazyApplicatives() {
85109 Lazy <Maybe <Fn1 <? super Integer , ? extends String >>> lazyGetToString = lazy (() ->
86110 expensiveWayToGetMaybeToString .apply (100_000_000 ));
87111
88- // ...then apply it with lazyZip
112+ // ...then apply it with lazyZip.
89113 Maybe <Integer > nothing = nothing ();
114+ // Note: unlike LambdaIterables, the Maybe inside is not itself lazy
90115 Lazy <Maybe <String >> lazyNothingToString = nothing .lazyZip (lazyGetToString );
91116
92117 assertThat (lazyNothingToString .value (), equalTo (__ ));
93118 assertThat (computed .get (), equalTo (__ ));
94119
95- // zip, however, we've eagerly generated a mapping function
120+ // zip, however, eagerly generates a mapping function
96121 Maybe <String > nothingToString = nothing .zip (expensiveWayToGetMaybeToString .apply (100_000 ));
97122 assertThat (nothingToString , equalTo (__ ));
98123 assertThat (computed .get (), equalTo (__ ));
99124 }
100125
101- @ Test
102- public void functionIsApplicative () {
103- Fn1 <String , Integer > strLen = String ::length ;
104- Fn1 <String , String > toUpper = String ::toUpperCase ;
105-
106- // Result of unary function calls are passed to mapping function as arguments
107- Fn1 <String , Tuple2 <Integer , String >> lengthAndUppercase = LiftA2 .liftA2 (Tuple2 ::tuple , strLen , toUpper );
108- assertThat (lengthAndUppercase .apply ("hello world" ), equalTo (tuple (11 , "HELLO WORLD" )));
109-
110- Fn1 <Integer , Integer > mod3 = i -> i % 3 ;
111- Fn1 <Integer , Integer > div3 = i -> i / 3 ;
112-
113- Fn1 <Integer , String > showDivision = LiftA2 .liftA2 ((divided , remainder ) -> String .format ("%d * 3 + %d" , divided , remainder ), div3 , mod3 );
114- assertThat (showDivision .apply (10 ), equalTo (__ ));
115-
116-
117- Fn1 <String , Integer > findStart = s -> s .indexOf ('j' );
118- Fn1 <String , Integer > findEnd = s -> s .indexOf (' ' );
119- Fn3 <String , Integer , Integer , String > cutString = String ::substring ;
120-
121- Fn1 <String , String > transformAndCut = LiftA3 .liftA3 (cutString , toUpper , findStart , findEnd );
122- assertThat (transformAndCut .apply ("hellojava world" ), equalTo (__ ));
123- }
124-
125- @ Test
126+ @ Test (timeout = 6500 )
126127 public void applicativeRepresentsParallelism () throws ExecutionException , InterruptedException {
127128 IO <Integer > foo = IO .io (() -> {
128129 Thread .sleep (2_000 );
@@ -149,7 +150,8 @@ public void applicativeRepresentsParallelism() throws ExecutionException, Interr
149150
150151 applicativeInIo
151152 .flatMap (result -> IO .io (() -> assertThat (result , equalTo (__ ))))
152- .unsafePerformAsyncIO (Executors .newFixedThreadPool (2 ))
153+ // How many threads should we use?
154+ .unsafePerformAsyncIO (Executors .newFixedThreadPool (__ ()))
153155 .get ();
154156
155157 System .out .printf ("Multiple thread execution took %d seconds%n" , (System .currentTimeMillis () - multipleThreadStart ) / 1000 );
0 commit comments