1+ package org .highj .typeclass2 .arrow ;
2+
3+ import org .derive4j .hkt .__2 ;
4+ import org .highj .Hkt ;
5+ import org .highj .data .eq .Eq ;
6+ import org .highj .data .tuple .T2 ;
7+ import org .highj .function .F1 ;
8+ import org .highj .util .Gen ;
9+ import org .highj .util .Law ;
10+
11+ import java .util .function .Function ;
12+
13+ import static org .assertj .core .api .Assertions .assertThat ;
14+
15+ public abstract class ArrowLaw <A > implements Law {
16+
17+ private final Arrow <A > arrow ;
18+
19+ public ArrowLaw (Arrow <A > arrow ) {
20+ this .arrow = arrow ;
21+ }
22+
23+ public abstract <B , C > boolean areEqual (__2 <A , B , C > one , __2 <A , B , C > two , B b , Eq <C > eq );
24+
25+
26+ @ Override
27+ public void test () {
28+ arrowIdentity ();
29+ composition ();
30+ arrFirst ();
31+ firstComposition ();
32+ t2_1 ();
33+ split ();
34+ assoc ();
35+ }
36+
37+ // arr id = id
38+ public void arrowIdentity () {
39+ __2 <A , String , String > arrowOfId = arrow .arr (Function .identity ());
40+ __2 <A , String , String > arrowIdentity = arrow .identity ();
41+ for (String s : Gen .stringGen .get (20 )) {
42+ assertThat (areEqual (arrowOfId , arrowIdentity , s , Eq .fromEquals ())).isTrue ();
43+ }
44+ }
45+
46+ // arr (f >>> g) = arr f >>> arr g
47+ public void composition () {
48+ Function <String , Integer > f1 = String ::length ;
49+ Function <Integer , Integer > f2 = x -> x * x ;
50+ __2 <A , String , Integer > arrOfComposed = arrow .arr (f1 .andThen (f2 ));
51+ __2 <A , String , Integer > composedArr = arrow .then (arrow .arr (f1 ), arrow .arr (f2 ));
52+ for (String s : Gen .stringGen .get (20 )) {
53+ assertThat (areEqual (arrOfComposed , composedArr , s , Eq .fromEquals ())).isTrue ();
54+ }
55+ }
56+
57+ // first (arr f) = arr (first f)
58+ public void arrFirst () {
59+ F1 <String , Integer > fn = String ::length ;
60+ __2 <A , T2 <String , Boolean >, T2 <Integer , Boolean >> firstArr = arrow .first (arrow .arr (fn ));
61+ __2 <A , T2 <String , Boolean >, T2 <Integer , Boolean >> arrFirst = arrow .arr (F1 .arrow .first (fn ));
62+ for (T2 <String , Boolean > t2 : Gen .zip (Gen .stringGen , Gen .boolGen ).get (20 )) {
63+ assertThat (areEqual (firstArr , arrFirst , t2 ,
64+ T2 .eq (Eq .fromEquals (), Eq .fromEquals ()))).isTrue ();
65+ }
66+ }
67+
68+ // first (f >>> g) = first f >>> first g
69+ public void firstComposition () {
70+ __2 <A , String , Integer > f = arrow .arr (String ::length );
71+ __2 <A , Integer , Integer > g = arrow .arr (x -> x * x );
72+ __2 <A , T2 <String , Boolean >, T2 <Integer , Boolean >> firstOfComposed =
73+ arrow .first (arrow .then (f , g ));
74+ __2 <A , T2 <String , Boolean >, T2 <Integer , Boolean >> composedFirst =
75+ arrow .then (arrow .first (f ), arrow .first (g ));
76+ for (T2 <String , Boolean > t2 : Gen .zip (Gen .stringGen , Gen .boolGen ).get (20 )) {
77+ assertThat (areEqual (firstOfComposed , composedFirst , t2 ,
78+ T2 .eq (Eq .fromEquals (), Eq .fromEquals ()))).isTrue ();
79+ }
80+ }
81+
82+ // first f >>> arr fst = arr fst >>> f
83+ public void t2_1 () {
84+ __2 <A , String , Integer > f = arrow .arr (String ::length );
85+
86+ __2 <A , T2 <String , Boolean >, Integer > firstThenT2 = arrow .then (arrow .first (f ), arrow .arr (T2 ::_1 ));
87+ __2 <A , T2 <String , Boolean >, Integer > T2ThenF = arrow .then (arrow .arr (T2 ::_1 ), f );
88+
89+ for (T2 <String , Boolean > t2 : Gen .zip (Gen .stringGen , Gen .boolGen ).get (20 )) {
90+ assertThat (areEqual (firstThenT2 , T2ThenF , t2 , Eq .fromEquals ())).isTrue ();
91+ }
92+ }
93+
94+ // first f >>> arr (id *** g) = arr (id *** g) >>> first f
95+ public void split () {
96+ __2 <A , String , Integer > f = arrow .arr (String ::length );
97+ __2 <F1 .µ , Long , Long > g = (F1 <Long , Long >) x -> x * x ;
98+
99+ __2 <A , T2 <Integer , Long >, T2 <Integer , Long >> g1 = arrow .arr (Hkt .asF1 (F1 .arrow .split (F1 .arrow .identity (), g )));
100+ __2 <A , T2 <String , Long >, T2 <Integer , Long >> firstSplitted = arrow .then (arrow .first (f ), g1 );
101+
102+ __2 <A , T2 <String , Long >, T2 <String , Long >> g2 = arrow .arr (Hkt .asF1 (F1 .arrow .split (F1 .arrow .identity (), g )));
103+ __2 <A , T2 <String , Long >, T2 <Integer , Long >> splittedFirst = arrow .then (g2 , arrow .first (f ));
104+
105+ for (T2 <String , Long > t2 : Gen .zip (Gen .stringGen , Gen .longGen ).get (20 )) {
106+ assertThat (areEqual (firstSplitted , splittedFirst , t2 ,
107+ T2 .eq (Eq .fromEquals (), Eq .fromEquals ()))).isTrue ();
108+ }
109+ }
110+
111+ // first (first f) >>> arr assoc = arr assoc >>> first f -- where assoc ((a,b),c) = (a,(b,c))
112+ public void assoc () {
113+ __2 <A , String , Integer > f = arrow .arr (String ::length );
114+
115+ __2 <A , T2 <T2 <String , Boolean >, Long >, T2 <T2 <Integer , Boolean >, Long >> firstFirst =
116+ arrow .first (arrow .first (f ));
117+ __2 <A , T2 <T2 <Integer , Boolean >, Long >, T2 <Integer , T2 <Boolean , Long >>> arrAssoc1 =
118+ arrow .arr (t2 -> T2 .of (t2 ._1 ()._1 (), T2 .of (t2 ._1 ()._2 (), t2 ._2 ())));
119+ __2 <A , T2 <T2 <String , Boolean >, Long >, T2 <Integer , T2 <Boolean , Long >>> firstAssoc =
120+ arrow .then (firstFirst , arrAssoc1 );
121+
122+ __2 <A , T2 <T2 <String , Boolean >, Long >, T2 <String , T2 <Boolean , Long >>> arrAssoc2 =
123+ arrow .arr (t2 -> T2 .of (t2 ._1 ()._1 (), T2 .of (t2 ._1 ()._2 (), t2 ._2 ())));
124+ __2 <A , T2 <String , T2 <Boolean , Long >>, T2 <Integer , T2 <Boolean , Long >>> first =
125+ arrow .first (f );
126+ __2 <A , T2 <T2 <String , Boolean >, Long >, T2 <Integer , T2 <Boolean , Long >>> assocFirst =
127+ arrow .then (arrAssoc2 , first );
128+
129+ for (T2 <T2 <String , Boolean >, Long > t2 : Gen .zip (Gen .zip (Gen .stringGen , Gen .boolGen ),Gen .longGen ).get (20 )) {
130+ assertThat (areEqual (firstAssoc , assocFirst , t2 ,
131+ T2 .eq (Eq .fromEquals (), T2 .eq (Eq .fromEquals (), Eq .fromEquals ())))).isTrue ();
132+ }
133+ }
134+
135+ }
0 commit comments