package Ġarrow . test . l aws Ċ Ċ import Ġarrow . Kind Ċ import Ġarrow . core . Eval Ċ import Ġarrow . core . Id Ċ import Ġarrow . core . extensions . eq Ċ import Ġarrow . core . extensions . id . com on ad . extract Ċ import Ġarrow . core . extensions . id . mon ad . mon ad Ċ import Ġarrow . core . extensions . mon oid Ċ import Ġarrow . test . concurrency . Side Effect Ċ import Ġarrow . test . generators . Gen K Ċ import Ġarrow . test . generators . function A To B Ċ import Ġarrow . test . generators . int Predicate Ċ import Ġarrow . test . generators . int Small Ċ import Ġarrow . type classes . Eq Ċ import Ġarrow . type classes . Fold able Ċ import Ġio . kot lint est . properties . Gen Ċ import Ġio . kot lint est . properties . for All Ċ Ċ object ĠFold able L aws Ġ{ ĊĊĠ Ġfun Ġ< F > Ġlaws ( FF : ĠFold able < F >, ĠGEN K : ĠGen K < F >): ĠList < Law > Ġ{ ĊĠĠĠ Ġval ĠGEN Ġ= ĠGEN K . gen K ( Gen . int Small ()) ĊĠĠĠ Ġval ĠE Q Ġ= ĠInt . eq () ĊĊĠĠĠ Ġreturn ĠlistOf ( ĊĠĠĠĠĠĠĠ ĠLaw (" Fold able ĠL aws : ĠLeft Ġfold Ġconsistent Ġwith Ġfold Map ") Ġ{ ĠFF . left Fold Cons istent With Fold Map ( GEN , ĠE Q ) Ġ}, ĊĠĠĠĠĠĠĠ ĠLaw (" Fold able ĠL aws : ĠRight Ġfold Ġconsistent Ġwith Ġfold Map ") Ġ{ ĠFF . right Fold Cons istent With Fold Map ( GEN , ĠE Q ) Ġ}, ĊĠĠĠĠĠĠĠ ĠLaw (" Fold able ĠL aws : ĠEx ists Ġis Ġconsistent Ġwith Ġfind ") Ġ{ ĠFF . exists Cons istent With Find ( GEN ) Ġ}, ĊĠĠĠĠĠĠĠ ĠLaw (" Fold able ĠL aws : ĠEx ists Ġis Ġlazy ") Ġ{ ĠFF . exists Is Lazy ( GEN , ĠE Q ) Ġ}, ĊĠĠĠĠĠĠĠ ĠLaw (" Fold able ĠL aws : ĠFor All Ġis Ġlazy ") Ġ{ ĠFF . for All Is Lazy ( GEN , ĠE Q ) Ġ}, ĊĠĠĠĠĠĠĠ ĠLaw (" Fold able ĠL aws : ĠFor All Ġconsistent Ġwith Ġexists ") Ġ{ ĠFF . forall Cons istent With Exists ( GEN ) Ġ}, ĊĠĠĠĠĠĠĠ ĠLaw (" Fold able ĠL aws : ĠFor All Ġreturns Ġtrue Ġif ĠisEmpty ") Ġ{ ĠFF . forall Returns True If Empty ( GEN ) Ġ}, ĊĠĠĠĠĠĠĠ ĠLaw (" Fold able ĠL aws : ĠFirst Option Ġreturns ĠNone Ġif ĠisEmpty ") Ġ{ ĠFF . first Option Returns None If Empty ( GEN ) Ġ}, ĊĠĠĠĠĠĠĠ ĠLaw (" Fold able ĠL aws : ĠFirst Option Ġreturns ĠNone Ġif Ġpredicate Ġfails ") Ġ{ ĠFF . first Option Returns None If Predicate Fails ( GEN ) Ġ}, ĊĠĠĠĠĠĠĠ ĠLaw (" Fold able ĠL aws : ĠFold M Ġfor ĠId Ġis Ġequivalent Ġto Ġfold Ġleft ") Ġ{ ĠFF . fold M Id Is Fold L ( GEN , ĠE Q ) Ġ} ĊĠĠĠĠĠ Ġ) ĊĠ Ġ} ĊĊĠ Ġfun Ġ< F > ĠFold able < F >. left Fold Cons istent With Fold Map ( G : ĠGen < Kind < F , ĠInt >>, ĠE Q : ĠEq < Int >) Ġ= ĊĠĠĠ Ġfor All ( Gen . function A To B < Int , ĠInt >( Gen . int Small ()), ĠG ) Ġ{ Ġf : Ġ( Int ) Ġ-> ĠInt , Ġfa : ĠKind < F , ĠInt > Ġ-> ĊĠĠĠĠĠ Ġwith ( Int . mon oid ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġfa . fold Map ( this , Ġf ). equal Under The Law ( fa . fold Left ( empty ()) Ġ{ Ġacc , Ġa Ġ-> Ġacc . combine ( f ( a )) Ġ}, ĠE Q ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġ< F > ĠFold able < F >. right Fold Cons istent With Fold Map ( G : ĠGen < Kind < F , ĠInt >>, ĠE Q : ĠEq < Int >) Ġ= ĊĠĠĠ Ġfor All ( Gen . function A To B < Int , ĠInt >( Gen . int Small ()), ĠG ) Ġ{ Ġf : Ġ( Int ) Ġ-> ĠInt , Ġfa : ĠKind < F , ĠInt > Ġ-> ĊĠĠĠĠĠ Ġwith ( Int . mon oid ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġfa . fold Map ( this , Ġf ). equal Under The Law ( fa . fold Right ( Eval . later Ġ{ Ġempty () Ġ}) Ġ{ Ġa , Ġlb : ĠEval < Int > Ġ-> Ġlb . map Ġ{ Ġf ( a ). combine ( it ) Ġ} Ġ}. value (), ĠE Q ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġ< F > ĠFold able < F >. exists Cons istent With Find ( G : ĠGen < Kind < F , ĠInt >>) Ġ= ĊĠĠĠ Ġfor All ( Gen . int Predicate (), ĠG ) Ġ{ Ġf : Ġ( Int ) Ġ-> ĠBoolean , Ġfa : ĠKind < F , ĠInt > Ġ-> ĊĠĠĠĠĠ Ġfa . exists ( f ). equal Under The Law ( fa . find ( f ). fold ({ Ġfalse Ġ}, Ġ{ Ġtrue Ġ}), ĠEq . any ()) ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġ< F > ĠFold able < F >. exists Is Lazy ( G : ĠGen < Kind < F , ĠInt >>, ĠE Q : ĠEq < Int >) Ġ= ĊĠĠĠ Ġfor All ( G ) Ġ{ Ġfa : ĠKind < F , ĠInt > Ġ-> ĊĠĠĠĠĠ Ġval Ġside Effect Ġ= ĠSide Effect () ĊĠĠĠĠĠ Ġfa . exists Ġ{ Ġ_ Ġ-> ĊĠĠĠĠĠĠĠ Ġside Effect . increment () ĊĠĠĠĠĠĠĠ Ġtrue ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġval Ġexpected Ġ= Ġif Ġ( fa . isEmpty ()) Ġ 0 Ġelse Ġ 1 ĊĠĠĠĠĠ Ġside Effect . counter . equal Under The Law ( expected , ĠE Q ) ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġ< F > ĠFold able < F >. for All Is Lazy ( G : ĠGen < Kind < F , ĠInt >>, ĠE Q : ĠEq < Int >) Ġ= ĊĠĠĠ Ġfor All ( G ) Ġ{ Ġfa : ĠKind < F , ĠInt > Ġ-> ĊĠĠĠĠĠ Ġval Ġside Effect Ġ= ĠSide Effect () ĊĠĠĠĠĠ Ġfa . for All Ġ{ Ġ_ Ġ-> ĊĠĠĠĠĠĠĠ Ġside Effect . increment () ĊĠĠĠĠĠĠĠ Ġtrue ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġval Ġexpected Ġ= Ġif Ġ( fa . isEmpty ()) Ġ 0 Ġelse Ġfa . size ( Long . mon oid ()) ĊĠĠĠĠĠ Ġside Effect . counter . equal Under The Law ( expected . toInt (), ĠE Q ) ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġ< F > ĠFold able < F >. forall Cons istent With Exists ( G : ĠGen < Kind < F , ĠInt >>) Ġ= ĊĠĠĠ Ġfor All ( Gen . int Predicate (), ĠG ) Ġ{ Ġf : Ġ( Int ) Ġ-> ĠBoolean , Ġfa : ĠKind < F , ĠInt > Ġ-> ĊĠĠĠĠĠ Ġif Ġ( fa . for All ( f )) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġif Ġf Ġis Ġtrue Ġfor Ġall Ġelements , Ġthen Ġthere Ġcannot Ġbe Ġan Ġelement Ġfor Ġwhich ĊĠĠĠĠĠĠĠ Ġ// Ġit Ġdoes Ġnot Ġhold . ĊĠĠĠĠĠĠĠ Ġval Ġneg ation Exists Ġ= Ġfa . exists Ġ{ Ġa Ġ-> Ġ!( f ( a )) Ġ} ĊĠĠĠĠĠĠĠ Ġ// Ġif Ġf Ġis Ġtrue Ġfor Ġall Ġelements , Ġthen Ġeither Ġthere Ġmust Ġbe Ġno Ġelements ĊĠĠĠĠĠĠĠ Ġ// Ġor Ġthere Ġmust Ġexist Ġan Ġelement Ġfor Ġwhich Ġit Ġis Ġtrue . ĊĠĠĠĠĠĠĠ Ġ! neg ation Exists Ġ&& Ġ( fa . isEmpty () Ġ|| Ġfa . exists ( f )) ĊĠĠĠĠĠ Ġ} Ġelse Ġtrue ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġ< F > ĠFold able < F >. forall Returns True If Empty ( G : ĠGen < Kind < F , ĠInt >>) Ġ= ĊĠĠĠ Ġfor All ( Gen . int Predicate (), ĠG ) Ġ{ Ġf : Ġ( Int ) Ġ-> ĠBoolean , Ġfa : ĠKind < F , ĠInt > Ġ-> ĊĠĠĠĠĠ Ġ! fa . isEmpty () Ġ|| Ġfa . for All ( f ) ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġ< F > ĠFold able < F >. first Option Returns None If Empty ( G : ĠGen < Kind < F , ĠInt >>) Ġ= ĊĠĠĠ Ġfor All ( G ) Ġ{ Ġfa : ĠKind < F , ĠInt > Ġ-> ĊĠĠĠĠĠ Ġif Ġ( fa . isEmpty ()) Ġfa . first Option (). isEmpty () ĊĠĠĠĠĠ Ġelse Ġfa . first Option (). isDefined () ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġ< F > ĠFold able < F >. first Option Returns None If Predicate Fails ( G : ĠGen < Kind < F , ĠInt >>) Ġ= ĊĠĠĠ Ġfor All ( G ) Ġ{ Ġfa : ĠKind < F , ĠInt > Ġ-> ĊĠĠĠĠĠ Ġfa . first Option Ġ{ Ġfalse Ġ}. isEmpty () ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġ< F > ĠFold able < F >. fold M Id Is Fold L ( G : ĠGen < Kind < F , ĠInt >>, ĠE Q : ĠEq < Int >) Ġ= ĊĠĠĠ Ġfor All ( Gen . function A To B < Int , ĠInt >( Gen . int Small ()), ĠG ) Ġ{ Ġf : Ġ( Int ) Ġ-> ĠInt , Ġfa : ĠKind < F , ĠInt > Ġ-> ĊĠĠĠĠĠ Ġwith ( Int . mon oid ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfold L : ĠInt Ġ= Ġfa . fold Left ( empty ()) Ġ{ Ġacc , Ġa Ġ-> Ġacc . combine ( f ( a )) Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġfold M : ĠInt Ġ= Ġfa . fold M ( Id . mon ad (), Ġempty ()) Ġ{ Ġacc , Ġa Ġ-> ĠId ( acc . combine ( f ( a ))) Ġ}. extract () ĊĠĠĠĠĠĠĠ Ġfold M . equal Under The Law ( fold L , ĠE Q ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ