From 15e3c29aa74aabce79d205507c84891a164615f6 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Sun, 19 Oct 2025 14:23:15 +0200 Subject: [PATCH 01/42] wip --- sample100pages.pdf | Bin 2238586 -> 2231030 bytes sofp-src/lyx/sofp-free-type.lyx | 46 +++++++++++---- sofp-src/lyx/sofp-typeclasses.lyx | 92 ++++++++++++++++------------- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-disjunctions.tex | 4 +- sofp-src/tex/sofp-reasoning.tex | 11 ++-- sofp-src/tex/sofp.tex | 6 +- 7 files changed, 94 insertions(+), 65 deletions(-) diff --git a/sample100pages.pdf b/sample100pages.pdf index 6b47fe2fd4cb8a23ec581bb3c54b44df25ba1475..ab250a4dd9f9c160f84944cebd7a79393ee16703 100644 GIT binary patch delta 620008 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�TM;3|YxJm>*dRsbtAw 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%0D>BL$iZ)ei7yQxCt3E;>s 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

ZY$yM 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ℜL;2a=--6gm9e> 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�WV7AA^N8e{$Qs6Y6-@v70?4bk&(b2_`4lMbmA3s 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�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 z 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

+mxv zfo+rrVM@xzfW{|lpsH65hS<>^VhAN@8}&5|kA(XH1rZ?tn&t~bgFou9{xba9;c<<3 za!jr^a|90j1gmE@M$JCo8igSdAVTje@{L?u0MA*gUUe#9mQMOsvHiQNuGgXir}^&K zx00rFjJ-(hNRaJ zdS=34GYFl;dWXdCh17C={L+1Cq_h$>R*QxXQ{SLM`+l$SLD9~=?!I_#7<7E5o_A^Y zbN-HK8}_vpFnDuG@S3$w9`F@ZrCO}iCF_H40_3I4RvHg~$-^&|@brX-(CYN=m=F3E zMQWU;b;{n&j~}`OS{4=EX+cYb5Mo)YzZS(K`Xm6FK1-ZNf*Ed7xr?MWO_3zejGu;CCWm$hCLkNyLz;H>LQ#Bhww;{I>{{A`B;JOMzw$vA z2c}Fi0gYYcI$;Kj7#+l(!UGaH$%F7?^T5CltIo;7P}-r){4b|HrjH3Wo!&UturNvQpY2~Got>TyKG5b9bM#~%8->MPD5 zT^1X-UMAjhdxnf9y%?r*nf=u@z|OPb)k|rAO8eDt9thsOnIu%m`!8*I z+*=91tQyduJ2?vjnhpH+-g40my0A=|{_VzkgBLA^2RV-q4ztxHmA$jvpjP&W*46PE zBzyti-#e5T(?3f3Z#7uNwUHFK<-hXP-@bW%AmDI^2;LS30v`po9pIx70b?A^nC?VZ~0ge^y|*ZV?6M2!R_l&Y|%I|LAw^0 zF1~w>Rm|)HFLq9bMRJSGem7O)k4^7^b`9JX@?q=!NlR-@yENWCWp|KvqzL9 z>otmDp+qMr1hR$~Mr&PS7?AK`?6CG2Bvi~GbEqdCmehtXDgCHLuT>d~($oWl+;x<} z*_I~?DCve$vG+qbqX_ypFNGf}*1^d_vTl4YMB;nwtr0~v)&mvJw6xPlK@dhz^>_tw z5x7$oAKQ>U7(WI0gREmHO=|9Ig8pjXLHje{)3BCp-9gDetU>nKU$@S5;)7J0JKHB-(x~jjjKV z79TDa*lP(k9&`NAaaqa%@TN&Q$OqmcOKfAp_l3o{>Z&`BSP0_4ig&yV10MC<-=pXecpjn3Dq1W! zbROY8xe(D;B>xjhnOd1N!DOoiTLn0UMOgx$sZ5>(F9;UEn0z+x&80Pke31^xNt_Q` zS^rL!A2e{t>?7l%2F@&v;H?lCMW+>%ApU+M;s=%pq6agWmv=&M^ zpe6p*_@shL*f{&FWRx?;MqP>mM;q2zqX7BTqqxRxS#ySU@O0jj+`PdRI2UCE;Xq_-BEO94p7BUkCU~Hc=cMe`6_wX5U0x4 z=P>NBX|RZJ#4)<$wJ)ByBX>2D9zHd>c3?6v=>WYUPIzQhvjkX}c}vS39v!{XOzv*Y zbQyF{2;VR3ItMCx7`lS?g(h1Wdgkh~#aNkaK7e9$ziw)}5%eCpF%X{Lu4b1f*gaw# zjp(Ww;dwsoQe*5goRCSS0t*D2=|%~h%rdo$;WFMlXM^jMU+aqrHH&2 z=m25UE`yX~CIYinH`AcwwCMy5aiX<)Iv$HUTR6JC8U%{=Gb}0CFK|buLh3CYh*#st zy6Zr%gUBA-LoHF1fv2*<5quKvtrO@_;AAOwaDm%; zRSOzqjp+%I#f*CT7|x*mL!6|0eo8{4#TpEeJEDW&{PY!pFslW-pmM;G#HC; zs>#k^uQ*3@66=~Rjyj=3`JqLo`GPCjJH775G?}4hHLZqh>#cisvhtA-LOQQ{>Anw* z=r#dI*rW;IT^Pxq1_9$um_?qt_`AMPU-UrF-aV$HEH@tWK|}oqJS;V*Odu{Afc%k_ z%fO+F4meA9P9X8S4V@itdJ2x3lC+}K!Xs?A#vR9L zNaPwQ;w33p&K*y1#8v*T?k^nz05t0j-L2^1M*Z?>AKhawM}FSPo}@|g3Q`<0p7#56 zFVePQ)$b8>b>W&J833{02>zkEmz@ML#z7r10DQGoC*ISo|DaeJs98G>c51_+eh~px z9J9CGrPA@6)pu27ND8Toc+FFRn7l$On?D5!{GmBKs!ph49>9Nsw73XJFF%9B>lPjN zp4ZBa3(I^FL2h#Z>ebVcz*eOqPp*zYv)AyYir&E6Y^|*9Kpnj6xl!ZJ)ZeN+(Al7n zmEYliTl*y&nyF_Nmv29FEToWOtXF$X7@?k_Kgf9V=h|zmo2H%ZKUaJa{N+`tPVN=R z86dOczoH-nV*dz-pI9VS-D!~eDyZYv1@$k{>0dD2|3s&ML6v`_zl}{(g{?_&p#Ljj zDb>)L1TWQpkC5h%a3v0)TKj+Th5ld5ssEoe)PEtKfkGub8O%9uHekm%_HVLcTe1oL`kFVuaw!lwTL7xybKT#rv z<=QvfNC_&>TG&Jqe_i?q@D<(N)kTEqE`k2tm*uE>4gCb}9Mov`B@?&03`g;VA}cCP z3HFlusDty@a56`L05*=q_s2}RAHN;m`v(Op)W^;$zZ-FoLs*iQ*;-Cf2umlfW=V@$ zoM(Dv1Dpg(!6cf8^d}X#%NDd z3h78vfuq;x^@P`Ht|=9vm&2iR`V5Of_=}YlL!Cn8T%~F!_gW2^*hfPeqS~wn1{7v| zC`BlEpcWzzz)GGI@li|)veU~bwX9tav+-D`XSO{Ji8(u0rFGF`Or%?~YMo?*y=-6G zBZw){jO)9GArs!m%UQ4SDD10^yxZux{Bj)b*9A}(oNZpcJn?;-8Df@{2{TFE%q!1w%=;*p%#X0hjzLJ;5Dd6cexkamU`oVbcY^`;&^^H5VK$MSkl zqBEK;z}wn3#mv&t_L~CsV%hyDY%3?!dX}6Hn|&WM_c9SK-0RL7j!>a68`oK%4?)To zi?7O7Yjk4pq4^QcHZ(r*_HHN?{sHMA%-jX6WvIVLub3vMY`84VUJ_fImrwTEzR&7X zpQ-8F9&|REG%I;q!9Br6Y+cATG4op~wNp%b0p`d2_zFl#M%P09st)6fm!N_p6AI>+ zptP6~rW_7hKD!V^bWE4q4BIZC?sTKEyGf)VAhCesevza!&qLel}T44Y)>rQG9_{PB_PhaRn| zK*wo|W)1vKBVrIj9+SRaN25fO*FYBnm@81@4wCs>wMY=o$2nLb1cWbLXTX@bemnlg zY}b*_^vh#j`3go&Me=02Qv5XCT9Rs0pN3h|6vOHyYQ|x8GYfIHSd+s^sYS21+A(!fjDp@YnSlHS#>zw>PuqJa| z*WQ(`5ibs40A(-SD)}&;JWdHJgu?B(r&orno`XxkZGobn+yKiC#yn$Jk4EK>e2KPM zbt22EqQZ;)1#}FSPfC{E;H1v3U&buO_tOd2nx5O845kCem2?upIr1|CyP{!8TAjp* zQIS2%-kM*4GTO10L*o-fu>Z-#yqiV;n5bg_=w4$R}vmV+rDzb&*DqJ9}RxLR?FQG zUn|F3>Y^OM8bvqW8u-xA*5?#|`uwE{-4xsDuP(VfWV264Mrh5K_=e|e?Y$odUb2rn zUPJ`}W6b3%_N&|275-Y)pR6_O@t?tXMz@L?o=R?h_LFBPxI3uIwu{LpV#Y&`i89{2 z3`yvXM1WO%o6Y5AM|#yWRQ9jmUOTkyGb(z{COaP_tdYf`kG&7|ny=cw@ffbtRUrtk zQ1qr7ft<r$nw;v;ZYFc& zuKWkV>XRnyMKiO`j0kOJ-f5c~e4^mKl2iXu_H)OqD*-=8Ls92tYDGpID2roqu`Td7 zIKxHVhLNQ&8RtaDJdZ@++Q)6gd?Y@`RUEMvq46eoSbYJLUVOofM#Tt z!B`r?ttY30$CU=H_A_?ji*#|p!NcE9n~&rt%mM62jH_%H%w%Q>{>0}rbW4SWICW0g zl!9@FcQ)#G7GUHe_%=LW_8}M2} z!&pgOqBrTBbxss#w(3Ig=6?%t>)rc`*^7SPVbjC%a76%2IGULdL5K&${LU!>dJ#~1}=s1WE>mc^o6vV{)$mK{_25hgjFR;CR``<7I5Iyx|%y^-P^c?w^(s;vmpxcNooZ>Z38^zd7 zwdNI86P`$~+vj-#uKAm5An04_^8*bO^!9Gd+0nzMzt-IV6H@%cu<|1O*E$@lUZVBg z@{-4?7Au_E0t8l0$BES-BZpdGu*Bo;q9s8+12KC7w1g1IbBNP9b_lT$!C5r0KkRA2 z;V9SJe16Jx{7y^1!{7iO0W%s4`Jp6IFR2?R6R!yXW^x%DU?vCtYXHHB2wBp&Migw+ zDqa&9x{Qq}jeyHxJmLd}@wRRW@G2DSY#4VaPvQxZL6DuF{I0&&6YjpBa<0pY2~kg| z^u7IJy4MH@G#`@<_Bed;GguZNDKqU_k8-yV5|@wB{6H1g62u&Dj;;Wlujs(}n)d?$ z9}5@Db2y}(&i2GB||ZTe7tbk($IAn01^Pak4HGtVbmx+>LJa>;eS(A!o} z&l~Lo*Z0XYkx2ADTK0ytJl-}@iJTUIC(InBfxj9xNxG{t$^umudSd<=Hz_H))l_K^ zTNJLQLylk`v=-`TNqnRLDX&Zu3ADnL``CuUbt<52(eklDhq&OWrh41DxNo2-Ol*pno9Y z*F?sRZE(X>K=sTmQ4qi66|}H2F;gU5S0c-(x!+hC_J}slz&=6n$Y}f^`GzO20fDaa z(xG(iGo8{CB2qI!I7`s>Ja^R#Fc&w4klNU7+V3b~`xrvZRt0!@F?+NJQAB&EtJ~i|2S1#Od>n)0Z=CRXs6cBx(}MU zdWyDW7-W%?`_&-@aMW_)F23;Tr|+i568{a2o8_Na)_?L;`rD%PpQzgZRB#r!HvE5F zZBEv|3z+{`d#Jyu*<2)Syg|cvi>G-^DuD$wbH!ozzErZCQv*~yj&cA5rHS6DwCoE zxVe~kfuihxv$4zica8FYL)-peu(to^`a};LI7y&#p7n2w``;yi*nky%|FrP`AJ_fB zw*F%`m>g*P^iKrtHN7=peOy$)y+MwUa|m~h;da_3M~W4d%dz6q)B~S~G#jka_7Ttb z;t1)bPOjIDwg(bgm4s+FGAlM_GVuTq*P1p>20!B0rO*45ojzM_CkqSA`W-zYEPX;M zoxOD@E4Y|6o9v{xWS}W}%oZO!0lS|kd^VmflGh~CSR$~uo<1u!U#!`=rM>dWpLM;o zE;5lja~3V$uXjq^t^aCstX*ZUbx+fM^?r@Xm3YKVmB`k@p`G|@_gyA@DIF$1E7|pR z*XbR~x0-2tE=^cnUl|6TW_0&uOBR(mfD3htu~(eB`JPnqev9udrVSaf9`H4d2i6Ul zO9?Nyjh?_gg8x~5#~o45mbI%6N5noF%sT^pf!fEzfUk? zCI`u+gF&`ecUV{9Bvr;{8`3imV)gS;=s!lc=k&1jjO;DmH*D@l*cz%t78Zjj;WI0n zBBm}^RztQCXR71agA+(Z*#S|~{yd4iE9yFj75nEUY-xTko7 zua)l!QEK{!$@5cjydTk6Crag~1<$)693kd?Wo>8Vxygw?OL;d2-hHz3em{es$rYp9 z9ORQ#U(#dZkNHVWOXmA+1{#rsM9HW&NW7aN!eyI!gZe9~!$UlJ=?uUEWzUc%1dA;ihSszDrn8b~%?{7nOu2*(#&e?-PA`z}&?H1AN0TC3y~eqqWh!aa zQAH6ov3@zv>Sjeq7K@L$Nb>NuVUsZb-YUIZR|EY}m2XC4W_oYqB5I_V?Yk8z4bC&u z3a<}6tk3tu{uIi}#8m){IL&C9AtaQvY~5Lhg4XnO6P@>iJ2qtlLNsMaJOsSB&pFSC z?Gg91s9Pgz<yhF2&|M*@WGP;1z+cZvl$uy z7H1mbp_WS64CCURt9f8=b>H;@*GJbTy-rs>#5kzE6XF7!4K={I@WIR3(||p*^ZOHf zc_yM6`_w%yEJ`FEL#M2bu14&%j;MOP?vhGToz+P zcc-6xrLE9t7-*a7v(kn^B!@M=VKnp>0VHI*i#UsI?O`A?{?@yAXKB&hYF0E5h1hg> z6y~N3Hi8aXlbry*-N5*xc-$n2kNX0LX3jeJ>ybO4M3?*y-q_0`S6SN@9hFg42ZPqC z*w^b4U4lN!Z@*-2-RIwhAp887cw$o6gS+nO@8_qRJDWD-F|Aof=1Zju4KnqyLfuB##>tZn%yx5wn? zw8!M|PGeZ9Y}aj!kUiB{29>+1&p)VH;pp~A4)!u(L_&srw8A_UV-(t@P>1%;=Q>Fx^h3i6XLUX@GB{}w zk7Q&BPTDvOo%_d7Q;~BYP0(D_VVG(I2QcE>g}?nIw7Lj1()ifl`) zIS?w5$W4rD`VrX>X){JBCyznk!6<_2CaU!3zK^E;;Cr7f>E=cqd*gCMb5SL^7Fr*O zXsZNhyJ1(_x6xUzXvx^AieXCxx9L4hVV+>GP{8j{oRvCuHPT2!kN2(7{aD_6z5V&h z(SfHUgGx2i*no)!#oe%Dyy?VPfg$}=Yc2O|k8X7`0o7CA$j@G{d3rmzYSVU7J$z<| zOI>!`SL~v1SPa-kQcn!&Y49~=I5q6;fe-`4?F{8=nOlTL=%t`84yK=~iBDoFLizq+ zcvT`z7ByYoTBd^y9KCPGSqye}3dl!0AQvp4=&JA4GZ;JkXj&p3q_j%&yE83;o%sVa zxA2hML)$WXsbDfD+atE>CP=WV1}B4k$2k zK*h&}e_r>W^p3P-aV%2<9*M=ph1any6*8&w4oSdxC6Jk6(ogSy1Z#OaxdTVs-WTB} zl`OI)0rolLnTd%J^yrk@$6fUFEW8StN?y8$b_E@U8G^Re`;qY<#6o@Qj2aVSW~yUF zif;Wp8V9=dm2E5sX*+f4lRySLOnjv_W<{Ptf~g+nJ?jLY&JLTDP20An$Dvy}s0JOS z@t0*L#i)>;sJCIw#o%dVmMh2)MmG_A0~WmeU7Oc;$WEdTp;(uE-o#N3B`s^8nHs&& zvg(qbUkY){<~|uUwVf66--Rv}N0n^CjJ?%ISpmC0>S$QgoiBWE!bBC2gF?ihC<_^= zO&vx0k=)1-;cG1GC9GtL2o}ew+ND;FN-D@mDGn=EOeEV^iU#c~b+H{~L`n1_t^(8{ z4pYQ}Oh|3*Q@0ZT)}Kn(x^l^!<-H6)Nd&|_mhO17Md6lngqRCaLQN4>5B+`&XkSpk zqJuwzzt0>Bt@4&`T~q`E(4D$X@S3G+@rKnwuT(WB2zKCi0&cQkaulkqG5U*uvYP2d zg^#5=g+Wd0mD>`kBWP-}5YUu$g>jVIJUl@o;U9yt7fP5r+@0(#g7D~msF^#)lQ^Om zG8KqHF#&$f=1loG0A?6k-Lx1?^khP`77wJMIFlQnfles!IL&GRlTSy*Vhy1&Q>WfE z;$&OwI>Q@6!KonBF`eJB5ddBSPJt= zwqrVw)VTR&FS6vrmLb3)m`=mW7<|JR@*|7^m4P*k;pw&jXGc^wa_U;3F->KF4}{Lg z64v=Hq$Poyk7G3qU`g)Z#R<$N zs$(%DrWt!;W|HCQAHA!VSv)aY=-pI@lU0g1iS#9-GD=8ACyM81Tr)4$PcfK`Lx_Cg ziL#6-OSJt+<^Gny1at=I238*L!EM-$HV?~uMd8QDMkDhMzzIyVH8dn-7^;i(dQ#M_ z5iw){;c``3OaHg*<`j4^85y}enqRQ2y9FQLYHKKrP^NzbNY}Yw9y`cemBJ@8LR8ks zAJBS0vGvglc=-fa1o$du$~@v=jvb*^e#<%G$3Uq>(mr@b6osfm)xs&4#{SEkhW1 z+OBH0**eamN|wi{JEjF*vPL9HT%bw-sFufhdo8LpnY`@e76*u5C zAB;(6qmWiqK=E61!ZfM(?Jb|GhUR;r@A(~?1ITI_41cEWeI%(=FrQh?TR%(qWKI;~ zex_p085qPvih%bywaKyE=u4hj0o*Pa6dcXo{M#OX^gEKthIIsO`y}>W7KWPtQ7zrU zdlq~#aG|~kTG>sYijta}aYQEH$*-@=3p$C2e(+`1n}UyJNOr-L91*VB_OVv)BIfcc z2CxcqIRR1Cw{Be{m#YiH4*jGHp^&c2C;#rF(tSld{%&-$(_9U91SFJS&%O|>`lCTV zGrbt@aD*Ozu6`=t9xS66BglR;bC~L1h}V1z4GN?Z;_OL=4ZX6aKp^-*j0^q@e2xos zVy&`5E2dd)wzn5G7eNU))CpFRT(FRq0gE1IbyQ*|D9E5b0;nLzLK?v}0op!7dpY@% zz1?CX!#M6Er7TD{qG`$fr7ZLGp^ppM>-}wNSwm(*T*OQ{Y;K;kWAzO)WfuvG_D=as zejI1yty+q+N}=3=L%nGTjvf!NM5JGz$Ksr~6coxHoiSEvjK4cDE1q?nMGaz%09xV( z)7%Nq$Dj-HFTVHRzVt~2ESO(k?cal&-)*zi|y}9Vb?au0&N*U5qdpeE(U~7&f zn7$!*74Oxxm?wsmit?W+xr{{_1bd( zTBUh`(c4pxXbwyqi2K0A0Tm90ZvcWGoPW{27=bC{we%`S8;G?d)8_vPEyNWZ7*oXl zj<~%H#Y}R{GiYvqMW8SCQ7~ne$MdXy#A`Ce#+pd9o7-&RLOLGK6QB{FZRK<*{mNDT zD*rWn?QAf?7AuMp%%JrrI5%=*%xDzL^p~^q;QRX%=zFt`JQqo218raX$2IN>EZmy6 zZMm8dYjs|qdq~rG*}Jrsm5Of2+}y_aXR2jAnf(@92&)H&U{hYcN zYt$W)7WRuc9O>>@9>B}`05J^&8jE=JguTM&!!i|?%VBP&yIV#E6?DO~zJuRw+Ls#a zMhYN~3#9IiVB|ZgKJNz1y^Tg>C|=&WD)A3#&}HqWv5XbWcRp%0AY(6*8o-eoPWR~f2Jt_z4bW%KqdZ!{GeKx!7=}%HWVl8KkT$QfqMBrQ5XJ4mHyxC zw12DNso8;Ebv(e2{#^~v4)m(yVQ2jdlERuKk^q$D^Rh8`@1auKY*bA zHN@Z20xqCG04K0FfQkoJPN3p|i<5+li;0W%F9CA0{!JS3hY{ibwGjaRVgC<8{JT}+ zzq@=ZB+U&NO^yAOKdc`PJ;?Z>8T+uCy#gv^!qeSa7HOb;Q_3-l z5p%f3=$Y<)^fx@o&G2y^HHm!X0LuH$7`;ReExS6JuWKtMUaU1;bqXj&$Rp+r*39*L zlv6I(AC;jgj4)UtU4;wlNZz=-hw*x3X-RyevuM^4N1XEkmcno(5VR(_91LI`yFJme zs@t7r!4Qgjm3uBIwkjGG93T?9ol35AYN~}JT4+UE@;Rp+z?v?+6$Pn5Fsd*On1ttZ zdI?LZ_I+BlaH={uP*$eJ5*jX5V|@(iEkCfnxg<+?x^`C6fPbEaYkA5_h#zm0DcB7K zbUi%14G=Q}I0m;M6nG#Aw!T(n2P7+)mtnW28-pf)=n;mSljiYo|F!XI!*Q5f*NS*d z&4?iy#%#4okpc0w3m0)z3u>~ZcQqmXoD^h@eI|h~Gbojg^ zqqrAx{MKr`WZrWTf*wYn)MZXT()2OaMd>BgkA{f*R}%1Z4?u?NPXC1|?G6FTsp%1w zyrYxsYi{o{KFo?BZWcL;Zz&UOM>(F1`-K7^{gXkbZ7Kd#Yty98SXVk?xyVcz7R$+$ znles00XJoM(W*9Pfim45BU&OGg&lI~n(Xb9Q4Zr#y3ElTh1qjVs!SsAjxvZqsw`#w zB*>O?mp|1>7@I~oKeY&*KM8qKycv!sb&r2e^>q|Num2|bf%fkMK&p9la1??h05x04 z=L>nCL-RF89XPsir_8*%shD#GXKr~aF?Ou$PZMwn7VUOhTxMosuIWdK}HN_TwG9tks$njGT9f(r^=YI5e%@DpgUKNvJ+wM5O&e<(<^Jqs;EGgA3CRL zCa;V*Q?4p=m5(^*%JMzx@YaIOD=&MwnV}bXD(L}XN>_Gf$y-YyQDc?cjo}y00~5Q5 z^fjbu51FP<8ECE&R(a|G;B{`@96%{gbGfl9K`8SM9ThFDuU^#FKJg?KJt*oBM7oam z-03J-T(_EF+OHU|M|m-X0V~s4huSPkf#f+t@2eXgW*{OX1lv{{Wq~;c!CDimogmRH zcY=re@IhnPE`YkkRge!JxpT}+dUqgqDpGda>>j(|hO9q6bt^9dpbRWU(Zgj?|u!Vh0lGuev zNt_fcAu=7%_j~&40w0+8tq2S@5Y{tV?_VB|!d7XHAu6q}OcbjM1`+x_!BT`vssY&- z-I*de7pX9!xnc?7Qs0DpAdFIcj6R~vN;gADH)BW|w9Tryjtj4W=N@ON@G5i_pjnWz z7Nc8%Lb&IR$;N@DA8>l+dFce#M6e*7?it}v$^+DkQ}Y#JXvq`n^uSjhNVO*LUF4l* zi`oy6KQ>ezDt z>>7=8by7{Sc5koRBeuaM&B5gA8j4y&HN_P?I+gyla`7Q7#3WqDGjNzFPgtjYqMM)8 z5y?S*ITA#WiG$>3Hk*8uOuN6|4|+^wiaYyacVWR~WWE0xs#2CUw(QAPiT{x+%2u0+ zT~aJ6Bez%>H_+p1X(37;1GKsvkLGOxApEO?Cc2hJ6AMb!o)k6So^w(UpHt2w0&{y# zyf2_hzUajabD;NL)Vjke9p)So%l2-XL93#Pi@Nsd){uyjUdPdvzB4Ay z_H!1s<00Pkh_^y4q|Spro8j~K@g-r1%ct;m!baRTfc3UtEoUm zD_lyHY*(Bb$t*&RDNuvp{Y>5o1`wUB_5EW2A)rMgSHh~grxH zKXvJ7UK+J7o--(vA4(CO`b9^k{Z1%pz=T3AxSuT7Jtee-OwgmK0H9WMy0KD1YMVpO zXnM)&a34)%h20(Y0l~!aG`Iv8GdjSd?gQD59Svhc==jZiUkn)>!MP;0Pq0SQcM@WL z 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墿j;Z9rnVq1nc$hEhLe7EGRAD)2qiQM$dwm`Vu_d%T0cK^++81eb zk)8(eIGy|Cdbx>uAgmQ)vmA;v3c5a*l6__%8#kk|YSa&7)uA$JWUyX^#7o$6;3$6>aFs6hyBLW31!{Nk+&K8t`? zU81EE9h`LlA}5bXe?+U&CztRx!%2fCmgeys3o+Su9E8yc_h{8RUn>mRm#_^EG|u`WngICPs*%yH z%>nf=TS}Z(s}Z6B8mA6ecCQGEYe7pBctFr2;S;44;L10X&ZQcu0J8gB-!hJG3Sclt z+^NPAP{0iA<7&Zu@AZh}G&TbNAYo$pT#C<3yKl&HBRHaPh}_2wUJ5QF+Ib)PGD$jUXyf;chkZQfY0PB zh0nUcw1OuvZM+FgXL<>Y46V=!5E!YA1<_k7X(#|umNXiOc`CLj^)RAzhg{z=CXMUU z@z=>k2Nh11D-k;BQ(*cqOVAWqqlV*tlrdETgi2SCwwNP6Aw=@yTnP#rd{n^R!Y6dh zbBZd*A&Ler4afUR;tSqqsn>*PlwN&8T>kTqMT)QE&}bCOl1v!Zlv)!8x^eEw^ zbdkEHY;}|#IJc%Zim*cFRH0Bleo}t z(Ew;$u?<>4zhRw4t~}_pSb=F@jli_8MquIu5G15=swqa#XOZlBf;a{=e(_xzE607N zIH5%0(SKEc!dBo(m31?zsP!v>;mwdxw_YjlJDuI?Sv4bDZX zaSy|!kZP-kpd@#s)J6f5Bxa_M6J5swXn~(ZF$-Wi79jNu*#%6yTBRNuvRWHA{XL7n z9%m(cZ;mv1*pxS|cErl`slXqk`5F;deeagxkXUx+6BgHwEKiM8qF2h6l%yN)osG)J z78qd|Z-)sQ>q~1i!Iz-1$|Zg%P!2^t{7>nEYy&fMgC3E+8Y3jUtF%a(Bqf*2J7y%x zX?DTJl0l&m%VujqOFf%Fm~_*Xj0NQ?AioH;M0bM}R*I|CGdLD7e5aWzxy_5)l9iz5 zf_G>u>a5WPcm~tFSJwv1e zlUyIc)BubbWo6L>^;*+4>B5?^QcvHwleXNr)6;^r1p7;n!8ofntWlp|amMM*!XqiB zqwFtMs&ic{6w|cBa9yxw>Rd3jzWQmEG^mpQwm2FzPo~HBN>(%286&!jWkZ z3l^f$3--Suka*ffS$T1ud(mD-f%*6H^D8q)OvDo^Yv%Qno1c+`ChVCY@>VYXKD`hk z;wqhsuDJ$gEJ+e7^)lhBdJ|n{W!97FHxSl&f{&wXkeZ9G=S@ssrj+2HPMi{$A-aG; zTj7bJ?CZoS+8TaMV99URmJuXc3DR+A(`t(Vbm*0{s zi}vl!#`o=Ov*Pk-SzkBa=E6Q@ydA^A1_j(=>Ff6C?ZnG^_aShU?1SISY9qg~HhA!G qdDn+IOV8I1xVzkY=Er}=xa^MM-qSxaH|OM}drEQfC0AW~%KrlwiH)@Y diff --git a/sofp-src/lyx/sofp-free-type.lyx b/sofp-src/lyx/sofp-free-type.lyx index 6d793155a..0ed095dd0 100644 --- a/sofp-src/lyx/sofp-free-type.lyx +++ b/sofp-src/lyx/sofp-free-type.lyx @@ -33147,6 +33147,11 @@ The monad algebra's laws require a certain kind of compatibility between 's methods. \end_layout +\begin_layout Standard +*** How does a monad algebra impose laws? How to write a law as explicit + equation, given E? give examples. +\end_layout + \begin_layout Standard Note that for any monad \begin_inset Formula $E$ @@ -33231,7 +33236,7 @@ flatten \end_layout \begin_layout Standard -When any type +When \begin_inset Formula $E^{T}$ \end_inset @@ -33239,7 +33244,11 @@ When any type \begin_inset Formula $P$ \end_inset --functor algebra, we have a special relationship between +-functor algebra for all +\begin_inset Formula $T$ +\end_inset + + then one can derive a special relationship between \begin_inset Formula $E$ \end_inset @@ -33355,7 +33364,11 @@ noprefix "false" \begin_inset Formula $P$ \end_inset --algebra. +-algebra that obeys all the laws assured by +\begin_inset Formula $E$ +\end_inset + +. The structure map \begin_inset Formula $s:E^{C}\rightarrow C$ \end_inset @@ -33393,7 +33406,7 @@ noprefix "false" \begin_inset Formula $C$ \end_inset - that satisfies the laws assured by + that satisfies all the laws assured by \begin_inset Formula $E$ \end_inset @@ -33409,15 +33422,23 @@ noprefix "false" \series bold (c) \series default - The + Items +\series bold +(a) +\series default + and +\series bold +(b) +\series default + give a a 1-to-1 correspondence between \begin_inset Formula $P$ \end_inset --algebras and the +-algebras and \begin_inset Formula $E$ \end_inset --monad algebras are in a 1-to-1 correspondence. +-monad algebras. \end_layout \begin_layout Subparagraph @@ -33492,6 +33513,10 @@ P\text{-algebra morphism law~(\ref{eq:P-algebra-morphism-law-of-flatten}) of }\t \end_inset + +\end_layout + +\begin_layout Standard The \family roman \series medium @@ -33531,10 +33556,7 @@ The \end_inset is surjective. -\end_layout - -\begin_layout Standard -By Statement + By Statement \begin_inset space ~ \end_inset @@ -33623,7 +33645,7 @@ We note that this part of the proof does not use the uniqueness property \begin_inset Formula $s:E^{C}\rightarrow C$ \end_inset - by: + by:***rewrite this proof using eval instead of run: \begin_inset Formula \[ s:E^{C}\rightarrow C\quad,\quad\quad s\triangleq\text{eval}_{E}^{C}\quad. diff --git a/sofp-src/lyx/sofp-typeclasses.lyx b/sofp-src/lyx/sofp-typeclasses.lyx index cb81c30ee..e1903a299 100644 --- a/sofp-src/lyx/sofp-typeclasses.lyx +++ b/sofp-src/lyx/sofp-typeclasses.lyx @@ -37837,7 +37837,11 @@ Eq \begin_inset Formula $A\rightarrow P^{A}$ \end_inset -. + (where +\begin_inset Formula $P$ +\end_inset + + must be a covariant functor). \end_layout \begin_layout Subsection @@ -37845,10 +37849,9 @@ Typeclasses, object-oriented interfaces, and algebraic data types \end_layout \begin_layout Standard -Typeclasses can be viewed as a way of managing various sets of methods that - a data type must support. - Scala supports two other features for managing data methods: object-oriented - interfaces +Typeclasses can be viewed as a way of managing the methods that various + data types must support. + Scala has two other features for managing methods: object-oriented interfaces \begin_inset Index idx status open @@ -37871,7 +37874,7 @@ algebraic data types (ADTs). We will now compare the expressive power of all those features. We will find that typeclasses can be seen as a generalization of both OOIs - and ADTs, transcending their specific limitations. + and ADTs, overcoming their specific limitations. \end_layout \begin_layout Standard @@ -38220,7 +38223,7 @@ size: Int \end_inset . - To call that function, we use the syntax + We use that function with the syntax \begin_inset listings inline true status open @@ -38230,6 +38233,14 @@ status open c.isSmallerThan(1000) \end_layout +\end_inset + + to pass the arguments +\begin_inset Formula $c$ +\end_inset + + and +\begin_inset Formula $1000$ \end_inset . @@ -38276,7 +38287,7 @@ this . In some other object-oriented languages, method signatures must have an - explicit first argument called + explicit first argument, usually called \begin_inset listings inline true status open @@ -38303,12 +38314,8 @@ this , or similar. When we analyze OOIs as types, we must make all argument types explicit, even though the Scala syntax does not do that. - For convenience, let us therefore assume that each method in an OOI definition - has an additional -\emph on -first -\emph default - argument (corresponding to Scala's + For this reason, we will view the types of methods in an OOI definition + as having an additional first argument (corresponding to Scala's \begin_inset listings inline true status open @@ -38325,7 +38332,7 @@ this \begin_layout Standard We have expressed the type of an interface as a tuple of some function types. - The first argument of each function is the type of a class that will later + The first argument of each function has the type of a class that will later implement that interface. That type is unknown within the scope of an interface definition, and so we have to denote that type by a type parameter @@ -38347,8 +38354,13 @@ We have expressed the type of an interface as a tuple of some function types. \begin_inset Formula $T$ \end_inset - a curried first argument and we obtain a description of an OOI type as - a tuple of types of the form + a +\emph on +curried +\emph default + first argument. + Then we obtain a description of an OOI type as a tuple of types of the + form \begin_inset Formula $T\rightarrow U_{1}$ \end_inset @@ -38368,7 +38380,7 @@ We have expressed the type of an interface as a tuple of some function types. \begin_inset Formula $U_{n}$ \end_inset - are some type expressions that might also use + are some type expressions that might also depend on \begin_inset Formula $T$ \end_inset @@ -38377,8 +38389,8 @@ We have expressed the type of an interface as a tuple of some function types. \begin_inset Formula $U_{i}$ \end_inset - correspond to the type expressions as seen in the Scala interface definition, - where the first argument of type + exactly correspond to the type expressions specified in the Scala interface + definition, where the first argument of type \begin_inset Formula $T$ \end_inset @@ -38394,11 +38406,7 @@ Using a standard type equivalence such as: \end_inset -and similarly for other -\begin_inset Formula $U_{i}$ -\end_inset - -, we can simplify the type of an OOI to a single function: +we can simplify the type of an OOI to a single function: \begin_inset Formula \[ (T\rightarrow U_{1})\times...\times(T\rightarrow U_{n})\cong T\rightarrow U_{1}\times...\times U_{n}=T\rightarrow U^{T}\quad, @@ -38505,7 +38513,7 @@ isSmallerThan \end_inset - in the interface definition, where the first argument (of type + in the Scala interface definition, where the first argument (of type \begin_inset Formula $T$ \end_inset @@ -38571,7 +38579,7 @@ extension methods \begin_inset Quotes erd \end_inset - whose first argument has type + since their first arguments have type \begin_inset Formula $T$ \end_inset @@ -39092,7 +39100,7 @@ Eq \end_inset with any definition of -\begin_inset Formula $T$ +\begin_inset Formula $P$ \end_inset . @@ -39137,7 +39145,7 @@ A typeclass with signature \begin_inset Formula $Q$ \end_inset - describes the additional methods that the new typeclass has.) So, typeclass + describes all the additional methods that the new typeclass has.) So, typeclass inheritance corresponds to taking products of method signatures. \end_layout @@ -39225,8 +39233,8 @@ Keep in mind that this description is only at the level of method types. \end_layout \begin_layout Itemize -For OOIs, the compiler provides automatic subtyping for interfaces, via - the object-oriented inheritance mechanism. +For OOIs, the compiler provides automatic subtyping for interfaces via the + object-oriented inheritance mechanism. If a class (or an interface) \begin_inset Formula $A$ \end_inset @@ -39287,10 +39295,6 @@ transitive inherits from \begin_inset Formula $B$ -\end_inset - - and -\begin_inset Formula $C$ \end_inset (this needs to be declared together with the definition of @@ -39301,7 +39305,11 @@ transitive \begin_inset Formula $A$ \end_inset - should inherit additionally from some other interface, or that + should inherit additionally from some other interface +\begin_inset Formula $C$ +\end_inset + +; or that \begin_inset Formula $A$ \end_inset @@ -39317,8 +39325,8 @@ transitive inheritance and subtyping. This will make typeclass inheritance behave like object-oriented interface inheritance, with all its benefits and shortcomings. - As we have seen, typeclasses and their inheritance may be also implemented - without using object-oriented interfaces or inheritance. + As we have seen, typeclasses and their inheritance may be implemented with + or without object-oriented inheritance. \end_layout \begin_layout Itemize @@ -39449,7 +39457,7 @@ Either[A, B] to all disjunctive types. In this way, typeclass membership can be provided automatically by the - compiler for a wide range of types, which reduces boilerplate code. + compiler (with no boilerplate code) for a wide range of user-defined types. But there are no comparable facilities for object-oriented \begin_inset Quotes eld \end_inset @@ -39463,9 +39471,9 @@ interface derivation \end_layout \begin_layout Itemize -The compiler's treatment of ADTs in Scala (and in other functional languages) - is significantly different from the treatment of typeclasses and interfaces. - An ADT is not an arbitrary type +The compilers of Scala and other functional languages treat ADTs significantly + differently from typeclasses. + An ADT is not just an arbitrary type \begin_inset Formula $T$ \end_inset diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index ddcb6fb7fb9fd06ccc1963696fe097c6d1d45e82..5745772bdeec77758529d9cf04daf8c66831e671 100644 GIT binary patch delta 166 zcmX?Ra?E7I3K2d-16@P&5Ft(7*_&>7%#=5_hw(#5G1I6Jt{+6IUlAS0_gk3j7%#=5_hw(#5G1IQzru_0~0qRCo=;#QzugsCkr!I6K6A53u6Ow R0}~@lI~zhOCTmMc0|3~MDwO~L diff --git a/sofp-src/tex/sofp-disjunctions.tex b/sofp-src/tex/sofp-disjunctions.tex index e86719a14..feebc9b43 100644 --- a/sofp-src/tex/sofp-disjunctions.tex +++ b/sofp-src/tex/sofp-disjunctions.tex @@ -331,8 +331,8 @@ \subsection{Tuples with one part and with zero parts} Other than that, \lstinline!case class C()! and \lstinline!case object C! have the same meaning: a named tuple with zero parts, which we may also view as a \textsf{``}named \lstinline!Unit!\index{unit type!named}\textsf{''} -type. This book will not use \lstinline!case object!s because \lstinline!case class!es -are sufficient. +type. For this book\textsf{'}s purposes, case classes are sufficient and case +objects are not needed. \subsection{Pattern matching for case classes} diff --git a/sofp-src/tex/sofp-reasoning.tex b/sofp-src/tex/sofp-reasoning.tex index c7a6fa2fe..9f7eb511b 100644 --- a/sofp-src/tex/sofp-reasoning.tex +++ b/sofp-src/tex/sofp-reasoning.tex @@ -248,15 +248,15 @@ \subsection{The nine constructions of fully parametric code} The code notation for this disjunctive function is modeled after the Scala code: \[ -\text{compute}^{:\bbnum 1+\text{Int}\rightarrow\bbnum 1+\text{Int}}\triangleq\,\begin{array}{|c||cc|} +\text{compute}:\bbnum 1+\text{Int}\rightarrow\bbnum 1+\text{Int}\quad,\quad\quad\text{compute}\triangleq\,\begin{array}{|c||cc|} & \bbnum 1 & \text{Int}\\ \hline \bbnum 1 & \bbnum 0 & \_\rightarrow100\\ \text{Int} & \bbnum 0 & x\rightarrow\frac{x}{2} \end{array}\quad. \] -We will use this example to explain how disjunctive functions are -written in the matrix notation\index{matrix notation}\index{disjunctive type!matrix notation}. +We will use this example to explain in detail how disjunctive functions +are written in the matrix notation\index{matrix notation}\index{disjunctive type!matrix notation}. Each row of a matrix corresponds to a part of the disjunctive type matched by one of the \lstinline!case! expressions. The column to @@ -274,9 +274,8 @@ \subsection{The nine constructions of fully parametric code} If the return type is not disjunctive, the matrix will have one column. What are the matrix elements? The idea of the matrix notation is to -translate the \lstinline!case! expressions line by line. Look at -the first \lstinline!case! line as if it were a standalone partial -function: +represent pattern-matching code, line by line. Look at the first \lstinline!case! +line as if it were a standalone partial function: \begin{lstlisting} { case None => Some(100) } \end{lstlisting} diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 8fcf1eabb..1698113ab 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): 78c1bdf371a4a5b26757fc2cbb040109745983d0a5cda174e052a4282b0e33c4}\\ -{\scriptsize{}Git commit: cf9c1ff8f5f6658e5d878b872c200ce75b0655fa}\\ -{\scriptsize{}PDF file built on Fri, 19 Sep 2025 18:48:58 +0200 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): a1dd267f3b9f9e371fbec6af076d72888f2b5bfe6e48f79de1678ff7794c804c}\\ +{\scriptsize{}Git commit: aa93d569770a77db2f159ef8f2024738be422647}\\ +{\scriptsize{}PDF file built on Fri, 17 Oct 2025 21:03:03 +0200 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From cc66740f02415636e8207dd0f7cfee055cbdaf0d Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Sun, 19 Oct 2025 23:10:14 +0200 Subject: [PATCH 02/42] add tables for structural analysis in part 2 --- sofp-src/lyx/sofp-applicative.lyx | 4191 +++++++++++++++++++---------- sofp-src/lyx/sofp-monads.lyx | 617 ++++- sofp-src/lyx/sofp-summary.lyx | 106 +- sofp-src/lyx/sofp-typeclasses.lyx | 8 +- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-applicative.tex | 96 +- sofp-src/tex/sofp-free-type.tex | 31 +- sofp-src/tex/sofp-monads.tex | 64 +- sofp-src/tex/sofp-summary.tex | 24 +- sofp-src/tex/sofp-typeclasses.tex | 113 +- sofp-src/tex/sofp.tex | 6 +- 11 files changed, 3683 insertions(+), 1573 deletions(-) diff --git a/sofp-src/lyx/sofp-applicative.lyx b/sofp-src/lyx/sofp-applicative.lyx index a58465622..3c3366dc7 100644 --- a/sofp-src/lyx/sofp-applicative.lyx +++ b/sofp-src/lyx/sofp-applicative.lyx @@ -16290,505 +16290,484 @@ zip . So, each monad construction gives at least one applicative construction. - We will focus on constructions that produce applicative functors and have - no analogous monad constructions. -\end_layout - -\begin_layout Paragraph -Type parameters -\end_layout - -\begin_layout Standard -Three type constructions are based on using just type parameters: a constant - functor, -\begin_inset Formula $L^{A}\triangleq Z$ + We will focus on constructions that produce applicative functors and do + +\emph on +not +\emph default + come from monad constructions. + The results are summarized in Table +\begin_inset space ~ \end_inset -, the identity functor -\begin_inset Formula $L^{A}\triangleq A$ -\end_inset -, and the functor composition, -\begin_inset Formula $L^{A}\triangleq F^{G^{A}}$ -\end_inset +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Constructions-of-applicative-functors" +plural "false" +caps "false" +noprefix "false" - (also written as -\begin_inset Formula $L\triangleq F\circ G$ \end_inset -). +. \end_layout \begin_layout Standard -Given a fixed -\emph on -monoid -\emph default - type -\begin_inset Formula $Z$ -\end_inset - -, the constant functor -\begin_inset Formula $L^{A}\triangleq Z$ -\end_inset - - is applicative. - To see this, consider the operation -\begin_inset listings -inline true +\begin_inset Float table +wide false +sideways false status open +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + + + +\begin_inset Text + \begin_layout Plain Layout -zip +\series bold +\size small +Construction \end_layout \end_inset + + +\begin_inset Text - of type -\begin_inset Formula $L^{A}\times L^{B}\rightarrow L^{A\times B}$ -\end_inset +\begin_layout Plain Layout -, which in this case becomes just -\begin_inset Formula $Z\times Z\rightarrow Z$ -\end_inset +\series bold +\size small +Type notation +\end_layout -, the monoid -\begin_inset Formula $Z$ \end_inset - -'s -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -combine +\series bold +\size small +Assumptions \end_layout \end_inset - - function. - The value -\begin_inset listings -inline true -status open + + + + +\begin_inset Text \begin_layout Plain Layout -wu +\size footnotesize +fixed type \end_layout \end_inset + + +\begin_inset Text - of type -\begin_inset Formula $L^{\bbnum 1}=Z$ -\end_inset - - is just the monoid -\begin_inset Formula $Z$ -\end_inset +\begin_layout Plain Layout -'s empty value ( -\begin_inset Formula $e_{Z}$ +\size footnotesize +\begin_inset Formula $F^{A}\triangleq Z$ \end_inset -). - The laws of -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout -zip \end_layout \end_inset + + +\begin_inset Text - then reduce to the monoid laws of +\begin_layout Plain Layout + +\size footnotesize \begin_inset Formula $Z$ \end_inset -. - For the same reason, the applicative functor -\begin_inset Formula $L^{A}\triangleq Z$ -\end_inset + is a monoid +\end_layout - will be commutative if the monoid -\begin_inset Formula $Z$ \end_inset + + + + +\begin_inset Text - is commutative. +\begin_layout Plain Layout + +\size footnotesize +identity \end_layout -\begin_layout Standard -Comparing this with the corresponding monad construction, we note that -\begin_inset Formula $L^{A}\triangleq Z$ \end_inset + + +\begin_inset Text - is -\emph on -not -\emph default - a monad unless -\begin_inset Formula $Z=\bbnum 1$ -\end_inset +\begin_layout Plain Layout -. - For an arbitrary monoid type -\begin_inset Formula $Z$ +\size footnotesize +\begin_inset Formula $F^{A}\triangleq A$ \end_inset -, the functor -\begin_inset Formula $L^{A}\triangleq Z$ -\end_inset - is only a semimonad. \end_layout -\begin_layout Standard -The identity functor -\begin_inset Formula $L^{A}\triangleq A$ \end_inset - - is applicative and commutative: the -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -zip -\end_layout - +\size footnotesize +\begin_inset Formula $F$ \end_inset - operation is the identity function of type -\begin_inset Formula $A\times B\rightarrow A\times B$ -\end_inset + is commutative +\end_layout -, and the wrapped unit ( -\begin_inset listings -inline true -status open +\end_inset + + + + +\begin_inset Text \begin_layout Plain Layout -wu +\size footnotesize +composition \end_layout \end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F^{A}\triangleq G^{H^{A}}$ +\end_inset + -) is just the unit value. - All required laws hold for the identity function. \end_layout -\begin_layout Standard -The functor composition -\begin_inset Formula $L\triangleq F\circ G$ \end_inset + + +\begin_inset Text - of two applicative functors -\begin_inset Formula $F$ +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $G$ \end_inset and -\begin_inset Formula $G$ +\begin_inset Formula $H$ \end_inset - is again applicative, unlike the functor composition of monads that often - does not produce a new monad. + are applicative functors \end_layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-applicative-composition" - \end_inset + + + + +\begin_inset Text +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-applicative-composition" -plural "false" -caps "false" -noprefix "false" +\size footnotesize +product +\end_layout \end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F^{A}\triangleq P^{A}\times Q^{A}$ +\end_inset \end_layout -\begin_layout Standard -For any two applicative functors -\begin_inset Formula $F$ -\end_inset - - and -\begin_inset Formula $G$ \end_inset - - with lawful -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -zip -\end_layout - +\size footnotesize +\begin_inset Formula $P$ \end_inset and -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout +\begin_inset Formula $Q$ +\end_inset -pure + are applicative \end_layout \end_inset - - methods, the functor -\begin_inset Formula $L^{A}\triangleq F^{G^{A}}$ -\end_inset - - is also applicative. - Its -\begin_inset listings -inline true -status open + + + + +\begin_inset Text \begin_layout Plain Layout -zip +\size footnotesize +co-product \end_layout \end_inset - - and -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -pure +\size footnotesize +\begin_inset Formula $F^{A}\triangleq Z+P^{A}$ +\end_inset + + \end_layout \end_inset + + +\begin_inset Text - methods are defined by: -\begin_inset Formula -\begin{align*} - & \text{zip}_{L}:F^{G^{A}}\times F^{G^{B}}\rightarrow F^{G^{A\times B}}\quad,\quad\quad\text{zip}_{L}\triangleq\text{zip}_{F}\bef\text{zip}_{G}^{\uparrow F}\quad,\\ - & \text{pu}_{L}:A\rightarrow F^{G^{A}}\quad,\quad\quad\text{pu}_{L}\triangleq\text{pu}_{G}\bef\text{pu}_{F}\quad,\quad\quad\text{wu}_{L}\triangleq\text{pu}_{F}(\text{wu}_{G})\quad. -\end{align*} +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $Z$ \end_inset -If -\begin_inset Formula $F$ + is a monoid and +\begin_inset Formula $P$ \end_inset - and -\begin_inset Formula $G$ -\end_inset + is applicative +\end_layout - are commutative applicative functors, then so is -\begin_inset Formula $L$ \end_inset + + + + +\begin_inset Text -. -\end_layout +\begin_layout Plain Layout -\begin_layout Subparagraph -Proof +\size footnotesize +co-product \end_layout -\begin_layout Standard -We note that the lifting to -\begin_inset Formula $L$ \end_inset + + +\begin_inset Text - is defined by -\begin_inset Formula $f^{\uparrow L}\triangleq f^{\uparrow G\uparrow F}=(f^{\uparrow G})^{\uparrow F}$ +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F^{A}\triangleq P^{A}+Q^{A}$ \end_inset -. + \end_layout -\begin_layout Standard -To verify the left identity law +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +conditions in Statement \begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:zip-left-identity-law" +reference "subsec:Statement-co-product-with-co-pointed-applicative" plural "false" caps "false" noprefix "false" \end_inset -): -\begin_inset Formula -\begin{align*} -\text{expect to equal }p\triangleright\text{ilu}^{\uparrow L}:\quad & \text{zip}_{L}(\text{wu}_{L}\times p^{:F^{G^{A}}})=(\gunderline{\text{pu}_{F}(\text{wu}_{G})}\times p)\triangleright\gunderline{\text{zip}_{F}}\bef\text{zip}_{G}^{\uparrow F}\\ -\text{left identity law of }\text{zip}_{F}:\quad & =p\triangleright(g^{:G^{A}}\rightarrow\gunderline{\text{wu}_{G}\times g)^{\uparrow F}\bef\text{zip}_{G}^{\uparrow F}}\\ -\text{composition under }^{\uparrow F}:\quad & =p\triangleright\big(g^{:G^{A}}\rightarrow\gunderline{\text{zip}_{G}(\text{wu}_{G}\times g)}\big)^{\uparrow F}\\ -\text{left identity law of }\text{zip}_{G}:\quad & =p\triangleright(\gunderline{g\rightarrow g}\triangleright\text{ilu}^{\uparrow G})^{\uparrow F}=p\triangleright(\text{ilu}^{\uparrow G})^{\uparrow F}=p\triangleright\text{ilu}^{\uparrow L}\quad. -\end{align*} + +\end_layout \end_inset + + + + +\begin_inset Text +\begin_layout Plain Layout +\size footnotesize +co-product \end_layout -\begin_layout Standard -To verify the right identity law: -\begin_inset Formula -\begin{align*} -\text{expect to equal }p\triangleright\text{iru}^{\uparrow L}:\quad & \text{zip}_{L}(p^{:F^{G^{A}}}\times\text{wu}_{L})=(p\times\gunderline{\text{pu}_{F}(\text{wu}_{G})})\triangleright\gunderline{\text{zip}_{F}}\bef\text{zip}_{G}^{\uparrow F}\\ -\text{right identity law of }\text{zip}_{F}:\quad & =p\triangleright(g^{:G^{A}}\rightarrow\gunderline{g\times\text{wu}_{G})^{\uparrow F}\bef\text{zip}_{G}^{\uparrow F}}\\ - & =p\triangleright\big(g^{:G^{A}}\rightarrow\gunderline{\text{zip}_{G}(g\times\text{wu}_{G})}\big)^{\uparrow F}\\ -\text{right identity law of }\text{zip}_{G}:\quad & =p\triangleright(\gunderline{g\rightarrow g\,\triangleright}\,\text{iru}^{\uparrow G})^{\uparrow F}=p\triangleright(\text{iru}^{\uparrow G})^{\uparrow F}=p\triangleright\text{iru}^{\uparrow L}\quad. -\end{align*} - \end_inset + + +\begin_inset Text +\begin_layout Plain Layout -\end_layout - -\begin_layout Standard -To verify the associativity law, substitute the definition of -\begin_inset Formula $\text{zip}_{L}$ +\size footnotesize +\begin_inset Formula $F^{A}\triangleq P^{A}+Q^{A}\times R^{A}$ \end_inset - into one side: -\begin_inset Formula -\begin{align*} - & \quad\text{left-hand side}:\quad\\ - & \text{zip}_{L}\big(p\times\text{zip}_{L}(q\times r)\big)\triangleright\varepsilon_{1,23}^{\uparrow L}=\big(p\times\text{zip}_{L}(q\times r)\big)\triangleright\text{zip}_{F}\bef\text{zip}_{G}^{\uparrow F}\bef\gunderline{\varepsilon_{1,23}^{\uparrow L}}\\ - & \quad\text{definition of }^{\uparrow L}:\quad\\ - & =\big(p\times\big(\text{zip}_{F}(q\times r)\triangleright\gunderline{\text{zip}_{G}^{\uparrow F}}\big)\big)\triangleright\gunderline{\text{zip}_{F}}\bef\text{zip}_{G}^{\uparrow F}\bef\varepsilon_{1,23}^{\uparrow G\uparrow F}\\ - & \quad\text{naturality law of }\text{zip}_{F}:\quad\\ - & =\big(p\times\text{zip}_{F}(q\times r)\big)\triangleright\text{zip}_{F}\bef\big(g\times k^{:G^{B}\times G^{C}}\!\rightarrow\gunderline{g\times\text{zip}_{G}(k)\big)^{\uparrow F}\bef\text{zip}_{G}^{\uparrow F}\bef\varepsilon_{1,23}^{\uparrow G\uparrow F}}\\ - & \quad\text{composition under }^{\uparrow F}:\quad\\ - & =\text{zip}_{F}\big(p\times\text{zip}_{F}(q\times r)\big)\triangleright\big(g\times(h\times j)\rightarrow\text{zip}_{G}(g\times\text{zip}_{G}(h\times j))\triangleright\varepsilon_{1,23}^{\uparrow G}\big)^{\uparrow F}\quad. -\end{align*} + +\end_layout \end_inset + + +\begin_inset Text -Now rewrite the other side in a similar way: -\begin_inset Formula -\begin{align*} - & \quad\text{right-hand side}:\quad\\ - & \text{zip}_{L}\big(\text{zip}_{L}(p\times q)\times r\big)\triangleright\varepsilon_{12,3}^{\uparrow L}=\big(\text{zip}_{L}(p\times q)\times r\big)\triangleright\text{zip}_{F}\bef\text{zip}_{G}^{\uparrow F}\bef\varepsilon_{12,3}^{\uparrow L}\\ - & \quad\text{definition of }^{\uparrow L}:\quad\\ - & =\big(\big(\text{zip}_{F}(p\times q)\triangleright\gunderline{\text{zip}_{G}^{\uparrow F}}\big)\times r\big)\triangleright\gunderline{\text{zip}_{F}}\bef\text{zip}_{G}^{\uparrow F}\bef\varepsilon_{12,3}^{\uparrow G\uparrow F}\\ - & \quad\text{naturality law of }\text{zip}_{F}:\quad\\ - & =\big(\text{zip}_{F}(p\times q)\times r\big)\triangleright\text{zip}_{F}\bef\big(k^{:G^{A}\times G^{B}}\!\times j\rightarrow\gunderline{\text{zip}_{G}(k)\times j\big)^{\uparrow F}\bef\text{zip}_{G}^{\uparrow F}\bef\varepsilon_{12,3}^{\uparrow G\uparrow F}}\\ - & \quad\text{composition under }^{\uparrow F}:\quad\\ - & =\text{zip}_{F}\big(\text{zip}_{F}(p\times q)\times r\big)\triangleright\big((g\times h)\times j\rightarrow\text{zip}_{G}(\text{zip}_{G}(g\times h)\times j)\triangleright\varepsilon_{12,3}^{\uparrow G}\big)^{\uparrow F}\quad. -\end{align*} +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $P$ \end_inset -The two sides become equal after using the associativity laws of -\begin_inset Formula $\text{zip}_{F}$ +, +\begin_inset Formula $Q$ \end_inset - and -\begin_inset Formula $\text{zip}_{G}$ + are polynomial and +\begin_inset Formula $R$ \end_inset -: -\begin_inset Formula -\begin{align*} - & \text{zip}_{F}\big(p\times\text{zip}_{F}(q\times r)\big)\triangleright\varepsilon_{1,23}^{\uparrow F}=\text{zip}_{F}\big(\text{zip}_{F}(p\times q)\times r\big)\triangleright\varepsilon_{12,3}^{\uparrow F}\quad,\\ - & \text{zip}_{G}(g\times\text{zip}_{G}(h\times j))\triangleright\varepsilon_{1,23}^{\uparrow G}=\text{zip}_{G}(\text{zip}_{G}(g\times h)\times j)\triangleright\varepsilon_{12,3}^{\uparrow G}\quad. -\end{align*} + is applicative +\end_layout \end_inset + + + + +\begin_inset Text +\begin_layout Plain Layout +\size footnotesize +recursive type \end_layout -\begin_layout Standard -To verify the commutativity law -\begin_inset space ~ \end_inset + + +\begin_inset Text -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:commutativity-law-of-zip" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $F^{A}\triangleq S^{A,F^{P^{A}}}$ \end_inset -) for -\begin_inset Formula $L$ -\end_inset -, we assume that the law holds for -\begin_inset Formula $F$ -\end_inset +\end_layout - and -\begin_inset Formula $G$ \end_inset + + +\begin_inset Text -: -\begin_inset Formula -\begin{align*} -\text{expect to equal }(\text{zip}_{L}\bef\text{swap}^{\uparrow L}):\quad & \text{swap}\bef\text{zip}_{L}=\gunderline{\text{swap}\bef\text{zip}_{F}}\bef\text{zip}_{G}^{\uparrow F}\\ -\text{commutativity law of }F:\quad & =\text{zip}_{F}\bef\gunderline{\text{swap}^{\uparrow F}\bef\text{zip}_{G}^{\uparrow F}}=\text{zip}_{F}\bef(\gunderline{\text{swap}\bef\text{zip}_{G}})^{\uparrow F}\\ -\text{commutativity law of }G\text{ under }^{\uparrow F}:\quad & =\gunderline{\text{zip}_{F}\bef\text{zip}_{G}^{\uparrow F}}\bef\text{swap}^{\gunderline{\uparrow G\uparrow F}}=\text{zip}_{L}\bef\text{swap}^{\uparrow L}\quad. -\end{align*} +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $S$ \end_inset - -\begin_inset Formula $\square$ + and +\begin_inset Formula $P$ \end_inset - -\end_layout - -\begin_layout Paragraph -Products + are polynomial \end_layout -\begin_layout Standard -Similarly to most other typeclasses, the product of applicative functors - is applicative: +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +recursive type \end_layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-applicative-product" +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F^{A}\triangleq P^{A}+Q^{A}\times R^{F^{A}}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\size footnotesize +conditions in Statement +\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-applicative-product" +reference "subsec:Statement-applicative-recursive-type-1" plural "false" caps "false" noprefix "false" @@ -16798,219 +16777,142 @@ noprefix "false" \end_layout -\begin_layout Standard -For any applicative functors -\begin_inset Formula $F$ \end_inset + + + - and -\begin_inset Formula $G$ \end_inset -, the functor -\begin_inset Formula $L^{A}\triangleq F^{A}\times G^{A}$ -\end_inset - is also applicative. - Its -\begin_inset listings -inline true -status open +\end_layout \begin_layout Plain Layout +\begin_inset Caption Standard -zip -\end_layout +\begin_layout Plain Layout +Constructions of applicative functors. +\begin_inset CommandInset label +LatexCommand label +name "tab:Constructions-of-applicative-functors" \end_inset - and -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout -wu \end_layout \end_inset - methods are defined by: -\begin_inset Formula -\begin{align*} - & \text{zip}_{L}:(F^{A}\times G^{A})\times(F^{B}\times G^{B})\rightarrow F^{A\times B}\times G^{A\times B}\quad,\\ - & \text{zip}_{L}\big((m^{:F^{A}}\times n^{:G^{A}})\times(p^{:F^{B}}\times q^{:G^{B}})\big)\triangleq\text{zip}_{F}(m\times p)\times\text{zip}_{G}(n\times q)\quad,\\ - & \text{wu}_{L}:F^{\bbnum 1}\times G^{\bbnum 1}\quad,\quad\quad\text{wu}_{L}\triangleq\text{wu}_{F}\times\text{wu}_{G}\quad. -\end{align*} - -\end_inset -If -\begin_inset Formula $F$ -\end_inset +\end_layout - and -\begin_inset Formula $G$ \end_inset - are commutative applicative functors, then so is -\begin_inset Formula $L$ -\end_inset -. \end_layout -\begin_layout Subparagraph -Proof +\begin_layout Paragraph +Type parameters \end_layout \begin_layout Standard -We note that the lifting to -\begin_inset Formula $L$ +Three type constructions are based on using just type parameters: a constant + functor, +\begin_inset Formula $L^{A}\triangleq Z$ \end_inset - is defined by -\begin_inset Formula $f^{\uparrow L}\triangleq f^{\uparrow F}\boxtimes f^{\uparrow G}$ +, the identity functor +\begin_inset Formula $L^{A}\triangleq A$ \end_inset -. -\end_layout - -\begin_layout Standard -To verify the left identity law of -\begin_inset Formula $\text{zip}_{L}$ +, and the functor composition, +\begin_inset Formula $L^{A}\triangleq F^{G^{A}}$ \end_inset -: -\begin_inset Formula -\begin{align*} -\text{expect to equal }(p\times q)\triangleright\text{ilu}^{\uparrow L}:\quad & \text{zip}_{L}\big(\gunderline{\text{wu}_{L}}\times(p^{:F^{A}}\times q^{:G^{A}})\big)\\ - & =\gunderline{\text{zip}_{L}}((\text{wu}_{F}\times\text{wu}_{G})\times(p\times q))\\ -\text{definition of }\text{zip}_{L}:\quad & =\text{zip}_{F}(\text{wu}_{F}\times p)\times\text{zip}_{G}(\text{wu}_{G}\times q)\\ -\text{left identity laws of }\text{zip}_{F}\text{ and }\text{zip}_{G}:\quad & =(p\triangleright\text{ilu}^{\uparrow F})\times(q\triangleright\text{ilu}^{\uparrow G})\\ - & =(p\times q)\triangleright(\text{ilu}^{\uparrow F}\boxtimes\text{ilu}^{\uparrow G})\\ -\text{definition of }^{\uparrow L}:\quad & =(p\times q)\triangleright\text{ilu}^{\uparrow L}\quad. -\end{align*} - + (also written as +\begin_inset Formula $L\triangleq F\circ G$ \end_inset - +). \end_layout \begin_layout Standard -To verify the right identity law of -\begin_inset Formula $\text{zip}_{L}$ -\end_inset - -: -\begin_inset Formula -\begin{align*} -\text{expect to equal }(p\times q)\triangleright\text{iru}^{\uparrow L}:\quad & \text{zip}_{L}\big((p^{:F^{A}}\times q^{:G^{A}})\times\gunderline{\text{wu}_{L}}\big)\\ - & =\gunderline{\text{zip}_{L}}((p\times q)\times(\text{wu}_{F}\times\text{wu}_{G}))\\ -\text{definition of }\text{zip}_{L}:\quad & =\text{zip}_{F}(p\times\text{wu}_{F})\times\text{zip}_{G}(q\times\text{wu}_{G})\\ -\text{right identity laws of }\text{zip}_{F}\text{ and }\text{zip}_{G}:\quad & =(p\triangleright\text{iru}^{\uparrow F})\times(q\triangleright\text{iru}^{\uparrow G})\\ - & =(p\times q)\triangleright(\text{iru}^{\uparrow F}\boxtimes\text{iru}^{\uparrow G})\\ -\text{definition of }^{\uparrow L}:\quad & =(p\times q)\triangleright\text{iru}^{\uparrow L}\quad. -\end{align*} - +Given a fixed +\emph on +monoid +\emph default + type +\begin_inset Formula $Z$ \end_inset - -\end_layout - -\begin_layout Standard -To verify the associativity law, begin with its left-hand side and use the - definition of -\begin_inset Formula $\text{zip}_{L}$ +, the constant functor +\begin_inset Formula $L^{A}\triangleq Z$ \end_inset -: -\begin_inset Formula -\begin{align*} - & \text{zip}_{L}\big((p_{1}^{:F^{A}}\times p_{2}^{:G^{A}})\times\text{zip}_{L}\big((q_{1}^{:F^{B}}\times q_{2}^{:G^{B}})\times(r_{1}^{:F^{C}}\times r_{2}^{:G^{C}})\big)\big)\triangleright\gunderline{\varepsilon_{1,23}^{\uparrow L}}\\ - & =\text{zip}_{L}\big((p_{1}\times p_{2})\times\big(\text{zip}_{F}(q_{1}\times r_{1})\times\text{zip}_{G}(q_{2}\times r_{2})\big)\big)\triangleright\big(\varepsilon_{1,23}^{\uparrow F}\boxtimes\varepsilon_{1,23}^{\uparrow G}\big)\\ - & =\big(\gunderline{\text{zip}_{F}\big(p_{1}\times\text{zip}_{F}(q_{1}\times r_{1})\big)\triangleright\varepsilon_{1,23}^{\uparrow F}}\big)\times\big(\gunderline{\text{zip}_{G}\big(p_{2}\times\text{zip}_{G}(q_{2}\times r_{2})\big)\triangleright\varepsilon_{1,23}^{\uparrow G}}\big)\quad. -\end{align*} + is applicative. + To see this, consider the operation +\begin_inset listings +inline true +status open -\end_inset +\begin_layout Plain Layout -The right-hand side is rewritten in a similar way: -\begin_inset Formula -\begin{align*} - & \text{zip}_{L}\big(\text{zip}_{L}\big((p_{1}^{:F^{A}}\times p_{2}^{:G^{A}})\times(q_{1}^{:F^{B}}\times q_{2}^{:G^{B}})\big)\times(r_{1}^{:F^{C}}\times r_{2}^{:G^{C}})\big)\triangleright\gunderline{\varepsilon_{12,3}^{\uparrow L}}\\ - & =\text{zip}_{L}\big(\big(\text{zip}_{F}(p_{1}\times q_{1})\times\text{zip}_{G}(p_{2}\times q_{2})\big)\times(r_{1}\times r_{2})\big)\big)\triangleright\big(\varepsilon_{12,3}^{\uparrow F}\boxtimes\varepsilon_{12,3}^{\uparrow G}\big)\\ - & =\big(\gunderline{\text{zip}_{F}\big(\text{zip}_{F}(p_{1}\times q_{1})\times r_{1}\big)\triangleright\varepsilon_{12,3}^{\uparrow F}}\big)\times\big(\gunderline{\text{zip}_{G}\big(\text{zip}_{G}(p_{2}\times q_{2})\times r_{2}\big)\triangleright\varepsilon_{12,3}^{\uparrow G}}\big)\quad. -\end{align*} +zip +\end_layout \end_inset -The underlined expressions in both sides are equal due to associativity - laws of -\begin_inset Formula $\text{zip}_{F}$ + of type +\begin_inset Formula $L^{A}\times L^{B}\rightarrow L^{A\times B}$ \end_inset - and -\begin_inset Formula $\text{zip}_{G}$ +, which in this case becomes just +\begin_inset Formula $Z\times Z\rightarrow Z$ \end_inset -. -\end_layout - -\begin_layout Standard -To verify the commutativity law of -\begin_inset Formula $L$ +, the monoid +\begin_inset Formula $Z$ \end_inset - when it holds for -\begin_inset Formula $F$ -\end_inset +'s +\begin_inset listings +inline true +status open - and -\begin_inset Formula $G$ -\end_inset +\begin_layout Plain Layout -: -\begin_inset Formula -\begin{align*} - & \quad\text{expect to equal }\text{zip}_{L}\big((p\times q)\times(m\times n)\big):\quad\\ - & \text{zip}_{L}\big((m\times n)\times(p\times q)\big)\triangleright\text{swap}^{\uparrow L}\\ - & \quad\text{definitions of }\text{zip}_{L}\text{ and }^{\uparrow L}:\quad\\ - & =\big(\text{zip}_{F}(m\times p)\times\text{zip}_{G}(n\times q)\big)\triangleright(\text{swap}^{\uparrow F}\boxtimes\text{swap}^{\uparrow G})\\ - & \quad\text{definition of }\boxtimes:\quad\\ - & =\big(\text{zip}_{F}(m\times p)\triangleright\text{swap}^{\uparrow F}\big)\times\big(\text{zip}_{G}(n\times q)\triangleright\text{swap}^{\uparrow G}\big)\\ - & \quad\text{commutativity laws of }F\text{ and }G:\quad\\ - & =\text{zip}_{F}(p\times m)\times\text{zip}_{G}(q\times n)=\text{zip}_{L}\big((p\times q)\times(m\times n)\big)\quad. -\end{align*} +combine +\end_layout \end_inset + function. + The value +\begin_inset listings +inline true +status open -\begin_inset Formula $\square$ -\end_inset - +\begin_layout Plain Layout +wu \end_layout -\begin_layout Paragraph -Co-products -\end_layout +\end_inset -\begin_layout Standard -The co-product -\begin_inset Formula $F+G$ + of type +\begin_inset Formula $L^{\bbnum 1}=Z$ \end_inset - of two arbitrary applicative functors -\begin_inset Formula $F$ + is just the monoid +\begin_inset Formula $Z$ \end_inset - and -\begin_inset Formula $G$ +'s empty value ( +\begin_inset Formula $e_{Z}$ \end_inset - is not always applicative (just as with monads). - One case where the +). + The laws of \begin_inset listings inline true status open @@ -17022,34 +16924,90 @@ zip \end_inset - method cannot be implemented for -\begin_inset Formula $F+G$ + then reduce to the monoid laws of +\begin_inset Formula $Z$ \end_inset - was given in Example -\begin_inset space ~ +. + For the same reason, the applicative functor +\begin_inset Formula $L^{A}\triangleq Z$ \end_inset - -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:tc-Example-10" -plural "false" -caps "false" -noprefix "false" - + will be commutative if the monoid +\begin_inset Formula $Z$ \end_inset -(b). - However, the following statements show that the co-product -\begin_inset Formula $F+G$ + is commutative. +\end_layout + +\begin_layout Standard +Comparing this with the corresponding monad construction, we note that +\begin_inset Formula $L^{A}\triangleq Z$ \end_inset - + is \emph on -can +not \emph default - be applicative under certain restrictions on + a monad unless +\begin_inset Formula $Z=\bbnum 1$ +\end_inset + +. + For an arbitrary monoid type +\begin_inset Formula $Z$ +\end_inset + +, the functor +\begin_inset Formula $L^{A}\triangleq Z$ +\end_inset + + is only a semimonad. +\end_layout + +\begin_layout Standard +The identity functor +\begin_inset Formula $L^{A}\triangleq A$ +\end_inset + + is applicative and commutative: the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + operation is the identity function of type +\begin_inset Formula $A\times B\rightarrow A\times B$ +\end_inset + +, and the wrapped unit ( +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +wu +\end_layout + +\end_inset + +) is just the unit value. + All required laws hold for the identity function. +\end_layout + +\begin_layout Standard +The functor composition +\begin_inset Formula $L\triangleq F\circ G$ +\end_inset + + of two applicative functors \begin_inset Formula $F$ \end_inset @@ -17057,21 +17015,22 @@ can \begin_inset Formula $G$ \end_inset -. + is again applicative, unlike the functor composition of monads that often + does not produce a new monad. \end_layout \begin_layout Subsubsection Statement \begin_inset CommandInset label LatexCommand label -name "subsec:Statement-co-product-with-constant-functor-applicative" +name "subsec:Statement-applicative-composition" \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-co-product-with-constant-functor-applicative" +reference "subsec:Statement-applicative-composition" plural "false" caps "false" noprefix "false" @@ -17082,63 +17041,89 @@ noprefix "false" \end_layout \begin_layout Standard -If +For any two applicative functors \begin_inset Formula $F$ \end_inset - is applicative and -\begin_inset Formula $Z$ + and +\begin_inset Formula $G$ \end_inset - is a fixed monoid type then -\begin_inset Formula $L^{A}\triangleq Z+F^{A}$ -\end_inset + with lawful +\begin_inset listings +inline true +status open - is applicative: -\begin_inset Formula -\begin{align*} - & \text{zip}_{L}:(Z+F^{A})\times(Z+F^{B})\rightarrow Z+F^{A\times B}\quad,\\ - & \text{zip}_{L}\triangleq\,\begin{array}{|c||cc|} - & Z & F^{A\times B}\\ -\hline Z\times Z & z_{1}\times z_{2}\rightarrow z_{1}\oplus z_{2} & \bbnum 0\\ -F^{A}\times Z & \_^{:F^{A}}\times z\rightarrow z & \bbnum 0\\ -Z\times F^{B} & z\times\_^{:F^{B}}\rightarrow z & \bbnum 0\\ -F^{A}\times F^{B} & \bbnum 0 & \text{zip}_{F} -\end{array}\quad. -\end{align*} +\begin_layout Plain Layout + +zip +\end_layout \end_inset -The -\begin_inset Quotes eld + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + \end_inset -wrapped unit -\begin_inset Quotes erd + methods, the functor +\begin_inset Formula $L^{A}\triangleq F^{G^{A}}$ \end_inset - ( -\begin_inset Formula $\text{wu}_{L}:Z+F^{\bbnum 1}$ + is also applicative. + Its +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + \end_inset -) is defined as -\begin_inset Formula $\text{wu}_{L}\triangleq\bbnum 0^{:Z}+\text{wu}_{F}$ + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + \end_inset -. - If -\begin_inset Formula $Z$ + methods are defined by: +\begin_inset Formula +\begin{align*} + & \text{zip}_{L}:F^{G^{A}}\times F^{G^{B}}\rightarrow F^{G^{A\times B}}\quad,\quad\quad\text{zip}_{L}\triangleq\text{zip}_{F}\bef\text{zip}_{G}^{\uparrow F}\quad,\\ + & \text{pu}_{L}:A\rightarrow F^{G^{A}}\quad,\quad\quad\text{pu}_{L}\triangleq\text{pu}_{G}\bef\text{pu}_{F}\quad,\quad\quad\text{wu}_{L}\triangleq\text{pu}_{F}(\text{wu}_{G})\quad. +\end{align*} + \end_inset - is a commutative monoid and +If \begin_inset Formula $F$ \end_inset - is commutative then + and +\begin_inset Formula $G$ +\end_inset + + are commutative applicative functors, then so is \begin_inset Formula $L$ \end_inset - is also commutative. +. \end_layout \begin_layout Subparagraph @@ -17146,35 +17131,40 @@ Proof \end_layout \begin_layout Standard -We will verify the laws of -\begin_inset Formula $\text{zip}_{L}$ -\end_inset - - and -\begin_inset Formula $\text{wu}_{L}$ +We note that the lifting to +\begin_inset Formula $L$ \end_inset -, assuming that -\begin_inset Formula $F$ + is defined by +\begin_inset Formula $f^{\uparrow L}\triangleq f^{\uparrow G\uparrow F}=(f^{\uparrow G})^{\uparrow F}$ \end_inset - is a lawful applicative functor. +. \end_layout \begin_layout Standard -The lifting to -\begin_inset Formula $L$ +To verify the left identity law +\begin_inset space ~ \end_inset - is defined in the standard way: +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:zip-left-identity-law" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +): \begin_inset Formula -\[ -(f^{:A\rightarrow B})^{\uparrow L}\triangleq\,\begin{array}{|c||cc|} - & Z & F^{B}\\ -\hline Z & \text{id} & \bbnum 0\\ -F^{A} & \bbnum 0 & f^{\uparrow F} -\end{array}\quad. -\] +\begin{align*} +\text{expect to equal }p\triangleright\text{ilu}^{\uparrow L}:\quad & \text{zip}_{L}(\text{wu}_{L}\times p^{:F^{G^{A}}})=(\gunderline{\text{pu}_{F}(\text{wu}_{G})}\times p)\triangleright\gunderline{\text{zip}_{F}}\bef\text{zip}_{G}^{\uparrow F}\\ +\text{left identity law of }\text{zip}_{F}:\quad & =p\triangleright(g^{:G^{A}}\rightarrow\gunderline{\text{wu}_{G}\times g)^{\uparrow F}\bef\text{zip}_{G}^{\uparrow F}}\\ +\text{composition under }^{\uparrow F}:\quad & =p\triangleright\big(g^{:G^{A}}\rightarrow\gunderline{\text{zip}_{G}(\text{wu}_{G}\times g)}\big)^{\uparrow F}\\ +\text{left identity law of }\text{zip}_{G}:\quad & =p\triangleright(\gunderline{g\rightarrow g}\triangleright\text{ilu}^{\uparrow G})^{\uparrow F}=p\triangleright(\text{ilu}^{\uparrow G})^{\uparrow F}=p\triangleright\text{ilu}^{\uparrow L}\quad. +\end{align*} \end_inset @@ -17182,29 +17172,13 @@ F^{A} & \bbnum 0 & f^{\uparrow F} \end_layout \begin_layout Standard -To verify the left identity law, we use the left identity law of -\begin_inset Formula $\text{zip}_{F}$ -\end_inset - -: +To verify the right identity law: \begin_inset Formula \begin{align*} - & \text{zip}_{L}(\text{wu}_{L}\times p^{:Z+F^{B}})=\text{zip}_{L}((\bbnum 0+\text{wu}_{F})\times p)\\ - & =(\text{wu}_{F}\times p)\triangleright\,\begin{array}{|c||cc|} - & Z & F^{\bbnum 1\times B}\\ -\hline F^{\bbnum 1}\times Z & \_^{:F^{\bbnum 1}}\times z\rightarrow z & \bbnum 0\\ -F^{\bbnum 1}\times F^{B} & \bbnum 0 & \text{zip}_{F} -\end{array}\\ - & =p\triangleright\,\begin{array}{|c||cc|} - & Z & F^{\bbnum 1\times B}\\ -\hline Z & \text{id} & \bbnum 0\\ -F^{B} & \bbnum 0 & k^{:F^{B}}\rightarrow\gunderline{\text{zip}_{F}(\text{wu}_{F}\times k)} -\end{array}\,=p\triangleright\,\begin{array}{|c||cc|} - & Z & F^{\bbnum 1\times B}\\ -\hline Z & \text{id} & \bbnum 0\\ -F^{B} & \bbnum 0 & k\rightarrow k\triangleright\text{ilu}^{\uparrow F} -\end{array}\\ - & =p\triangleright\text{ilu}^{\uparrow L}\quad. +\text{expect to equal }p\triangleright\text{iru}^{\uparrow L}:\quad & \text{zip}_{L}(p^{:F^{G^{A}}}\times\text{wu}_{L})=(p\times\gunderline{\text{pu}_{F}(\text{wu}_{G})})\triangleright\gunderline{\text{zip}_{F}}\bef\text{zip}_{G}^{\uparrow F}\\ +\text{right identity law of }\text{zip}_{F}:\quad & =p\triangleright(g^{:G^{A}}\rightarrow\gunderline{g\times\text{wu}_{G})^{\uparrow F}\bef\text{zip}_{G}^{\uparrow F}}\\ + & =p\triangleright\big(g^{:G^{A}}\rightarrow\gunderline{\text{zip}_{G}(g\times\text{wu}_{G})}\big)^{\uparrow F}\\ +\text{right identity law of }\text{zip}_{G}:\quad & =p\triangleright(\gunderline{g\rightarrow g\,\triangleright}\,\text{iru}^{\uparrow G})^{\uparrow F}=p\triangleright(\text{iru}^{\uparrow G})^{\uparrow F}=p\triangleright\text{iru}^{\uparrow L}\quad. \end{align*} \end_inset @@ -17213,9 +17187,552 @@ F^{B} & \bbnum 0 & k\rightarrow k\triangleright\text{ilu}^{\uparrow F} \end_layout \begin_layout Standard -To verify the right identity law, we write a similar calculation: -\begin_inset Formula -\begin{align*} +To verify the associativity law, substitute the definition of +\begin_inset Formula $\text{zip}_{L}$ +\end_inset + + into one side: +\begin_inset Formula +\begin{align*} + & \quad\text{left-hand side}:\quad\\ + & \text{zip}_{L}\big(p\times\text{zip}_{L}(q\times r)\big)\triangleright\varepsilon_{1,23}^{\uparrow L}=\big(p\times\text{zip}_{L}(q\times r)\big)\triangleright\text{zip}_{F}\bef\text{zip}_{G}^{\uparrow F}\bef\gunderline{\varepsilon_{1,23}^{\uparrow L}}\\ + & \quad\text{definition of }^{\uparrow L}:\quad\\ + & =\big(p\times\big(\text{zip}_{F}(q\times r)\triangleright\gunderline{\text{zip}_{G}^{\uparrow F}}\big)\big)\triangleright\gunderline{\text{zip}_{F}}\bef\text{zip}_{G}^{\uparrow F}\bef\varepsilon_{1,23}^{\uparrow G\uparrow F}\\ + & \quad\text{naturality law of }\text{zip}_{F}:\quad\\ + & =\big(p\times\text{zip}_{F}(q\times r)\big)\triangleright\text{zip}_{F}\bef\big(g\times k^{:G^{B}\times G^{C}}\!\rightarrow\gunderline{g\times\text{zip}_{G}(k)\big)^{\uparrow F}\bef\text{zip}_{G}^{\uparrow F}\bef\varepsilon_{1,23}^{\uparrow G\uparrow F}}\\ + & \quad\text{composition under }^{\uparrow F}:\quad\\ + & =\text{zip}_{F}\big(p\times\text{zip}_{F}(q\times r)\big)\triangleright\big(g\times(h\times j)\rightarrow\text{zip}_{G}(g\times\text{zip}_{G}(h\times j))\triangleright\varepsilon_{1,23}^{\uparrow G}\big)^{\uparrow F}\quad. +\end{align*} + +\end_inset + +Now rewrite the other side in a similar way: +\begin_inset Formula +\begin{align*} + & \quad\text{right-hand side}:\quad\\ + & \text{zip}_{L}\big(\text{zip}_{L}(p\times q)\times r\big)\triangleright\varepsilon_{12,3}^{\uparrow L}=\big(\text{zip}_{L}(p\times q)\times r\big)\triangleright\text{zip}_{F}\bef\text{zip}_{G}^{\uparrow F}\bef\varepsilon_{12,3}^{\uparrow L}\\ + & \quad\text{definition of }^{\uparrow L}:\quad\\ + & =\big(\big(\text{zip}_{F}(p\times q)\triangleright\gunderline{\text{zip}_{G}^{\uparrow F}}\big)\times r\big)\triangleright\gunderline{\text{zip}_{F}}\bef\text{zip}_{G}^{\uparrow F}\bef\varepsilon_{12,3}^{\uparrow G\uparrow F}\\ + & \quad\text{naturality law of }\text{zip}_{F}:\quad\\ + & =\big(\text{zip}_{F}(p\times q)\times r\big)\triangleright\text{zip}_{F}\bef\big(k^{:G^{A}\times G^{B}}\!\times j\rightarrow\gunderline{\text{zip}_{G}(k)\times j\big)^{\uparrow F}\bef\text{zip}_{G}^{\uparrow F}\bef\varepsilon_{12,3}^{\uparrow G\uparrow F}}\\ + & \quad\text{composition under }^{\uparrow F}:\quad\\ + & =\text{zip}_{F}\big(\text{zip}_{F}(p\times q)\times r\big)\triangleright\big((g\times h)\times j\rightarrow\text{zip}_{G}(\text{zip}_{G}(g\times h)\times j)\triangleright\varepsilon_{12,3}^{\uparrow G}\big)^{\uparrow F}\quad. +\end{align*} + +\end_inset + +The two sides become equal after using the associativity laws of +\begin_inset Formula $\text{zip}_{F}$ +\end_inset + + and +\begin_inset Formula $\text{zip}_{G}$ +\end_inset + +: +\begin_inset Formula +\begin{align*} + & \text{zip}_{F}\big(p\times\text{zip}_{F}(q\times r)\big)\triangleright\varepsilon_{1,23}^{\uparrow F}=\text{zip}_{F}\big(\text{zip}_{F}(p\times q)\times r\big)\triangleright\varepsilon_{12,3}^{\uparrow F}\quad,\\ + & \text{zip}_{G}(g\times\text{zip}_{G}(h\times j))\triangleright\varepsilon_{1,23}^{\uparrow G}=\text{zip}_{G}(\text{zip}_{G}(g\times h)\times j)\triangleright\varepsilon_{12,3}^{\uparrow G}\quad. +\end{align*} + +\end_inset + + +\end_layout + +\begin_layout Standard +To verify the commutativity law +\begin_inset space ~ +\end_inset + +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:commutativity-law-of-zip" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +) for +\begin_inset Formula $L$ +\end_inset + +, we assume that the law holds for +\begin_inset Formula $F$ +\end_inset + + and +\begin_inset Formula $G$ +\end_inset + +: +\begin_inset Formula +\begin{align*} +\text{expect to equal }(\text{zip}_{L}\bef\text{swap}^{\uparrow L}):\quad & \text{swap}\bef\text{zip}_{L}=\gunderline{\text{swap}\bef\text{zip}_{F}}\bef\text{zip}_{G}^{\uparrow F}\\ +\text{commutativity law of }F:\quad & =\text{zip}_{F}\bef\gunderline{\text{swap}^{\uparrow F}\bef\text{zip}_{G}^{\uparrow F}}=\text{zip}_{F}\bef(\gunderline{\text{swap}\bef\text{zip}_{G}})^{\uparrow F}\\ +\text{commutativity law of }G\text{ under }^{\uparrow F}:\quad & =\gunderline{\text{zip}_{F}\bef\text{zip}_{G}^{\uparrow F}}\bef\text{swap}^{\gunderline{\uparrow G\uparrow F}}=\text{zip}_{L}\bef\text{swap}^{\uparrow L}\quad. +\end{align*} + +\end_inset + + +\begin_inset Formula $\square$ +\end_inset + + +\end_layout + +\begin_layout Paragraph +Products +\end_layout + +\begin_layout Standard +Similarly to most other typeclasses, the product of applicative functors + is applicative: +\end_layout + +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-applicative-product" + +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-applicative-product" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\begin_layout Standard +For any applicative functors +\begin_inset Formula $F$ +\end_inset + + and +\begin_inset Formula $G$ +\end_inset + +, the functor +\begin_inset Formula $L^{A}\triangleq F^{A}\times G^{A}$ +\end_inset + + is also applicative. + Its +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +wu +\end_layout + +\end_inset + + methods are defined by: +\begin_inset Formula +\begin{align*} + & \text{zip}_{L}:(F^{A}\times G^{A})\times(F^{B}\times G^{B})\rightarrow F^{A\times B}\times G^{A\times B}\quad,\\ + & \text{zip}_{L}\big((m^{:F^{A}}\times n^{:G^{A}})\times(p^{:F^{B}}\times q^{:G^{B}})\big)\triangleq\text{zip}_{F}(m\times p)\times\text{zip}_{G}(n\times q)\quad,\\ + & \text{wu}_{L}:F^{\bbnum 1}\times G^{\bbnum 1}\quad,\quad\quad\text{wu}_{L}\triangleq\text{wu}_{F}\times\text{wu}_{G}\quad. +\end{align*} + +\end_inset + +If +\begin_inset Formula $F$ +\end_inset + + and +\begin_inset Formula $G$ +\end_inset + + are commutative applicative functors, then so is +\begin_inset Formula $L$ +\end_inset + +. +\end_layout + +\begin_layout Subparagraph +Proof +\end_layout + +\begin_layout Standard +We note that the lifting to +\begin_inset Formula $L$ +\end_inset + + is defined by +\begin_inset Formula $f^{\uparrow L}\triangleq f^{\uparrow F}\boxtimes f^{\uparrow G}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +To verify the left identity law of +\begin_inset Formula $\text{zip}_{L}$ +\end_inset + +: +\begin_inset Formula +\begin{align*} +\text{expect to equal }(p\times q)\triangleright\text{ilu}^{\uparrow L}:\quad & \text{zip}_{L}\big(\gunderline{\text{wu}_{L}}\times(p^{:F^{A}}\times q^{:G^{A}})\big)\\ + & =\gunderline{\text{zip}_{L}}((\text{wu}_{F}\times\text{wu}_{G})\times(p\times q))\\ +\text{definition of }\text{zip}_{L}:\quad & =\text{zip}_{F}(\text{wu}_{F}\times p)\times\text{zip}_{G}(\text{wu}_{G}\times q)\\ +\text{left identity laws of }\text{zip}_{F}\text{ and }\text{zip}_{G}:\quad & =(p\triangleright\text{ilu}^{\uparrow F})\times(q\triangleright\text{ilu}^{\uparrow G})\\ + & =(p\times q)\triangleright(\text{ilu}^{\uparrow F}\boxtimes\text{ilu}^{\uparrow G})\\ +\text{definition of }^{\uparrow L}:\quad & =(p\times q)\triangleright\text{ilu}^{\uparrow L}\quad. +\end{align*} + +\end_inset + + +\end_layout + +\begin_layout Standard +To verify the right identity law of +\begin_inset Formula $\text{zip}_{L}$ +\end_inset + +: +\begin_inset Formula +\begin{align*} +\text{expect to equal }(p\times q)\triangleright\text{iru}^{\uparrow L}:\quad & \text{zip}_{L}\big((p^{:F^{A}}\times q^{:G^{A}})\times\gunderline{\text{wu}_{L}}\big)\\ + & =\gunderline{\text{zip}_{L}}((p\times q)\times(\text{wu}_{F}\times\text{wu}_{G}))\\ +\text{definition of }\text{zip}_{L}:\quad & =\text{zip}_{F}(p\times\text{wu}_{F})\times\text{zip}_{G}(q\times\text{wu}_{G})\\ +\text{right identity laws of }\text{zip}_{F}\text{ and }\text{zip}_{G}:\quad & =(p\triangleright\text{iru}^{\uparrow F})\times(q\triangleright\text{iru}^{\uparrow G})\\ + & =(p\times q)\triangleright(\text{iru}^{\uparrow F}\boxtimes\text{iru}^{\uparrow G})\\ +\text{definition of }^{\uparrow L}:\quad & =(p\times q)\triangleright\text{iru}^{\uparrow L}\quad. +\end{align*} + +\end_inset + + +\end_layout + +\begin_layout Standard +To verify the associativity law, begin with its left-hand side and use the + definition of +\begin_inset Formula $\text{zip}_{L}$ +\end_inset + +: +\begin_inset Formula +\begin{align*} + & \text{zip}_{L}\big((p_{1}^{:F^{A}}\times p_{2}^{:G^{A}})\times\text{zip}_{L}\big((q_{1}^{:F^{B}}\times q_{2}^{:G^{B}})\times(r_{1}^{:F^{C}}\times r_{2}^{:G^{C}})\big)\big)\triangleright\gunderline{\varepsilon_{1,23}^{\uparrow L}}\\ + & =\text{zip}_{L}\big((p_{1}\times p_{2})\times\big(\text{zip}_{F}(q_{1}\times r_{1})\times\text{zip}_{G}(q_{2}\times r_{2})\big)\big)\triangleright\big(\varepsilon_{1,23}^{\uparrow F}\boxtimes\varepsilon_{1,23}^{\uparrow G}\big)\\ + & =\big(\gunderline{\text{zip}_{F}\big(p_{1}\times\text{zip}_{F}(q_{1}\times r_{1})\big)\triangleright\varepsilon_{1,23}^{\uparrow F}}\big)\times\big(\gunderline{\text{zip}_{G}\big(p_{2}\times\text{zip}_{G}(q_{2}\times r_{2})\big)\triangleright\varepsilon_{1,23}^{\uparrow G}}\big)\quad. +\end{align*} + +\end_inset + +The right-hand side is rewritten in a similar way: +\begin_inset Formula +\begin{align*} + & \text{zip}_{L}\big(\text{zip}_{L}\big((p_{1}^{:F^{A}}\times p_{2}^{:G^{A}})\times(q_{1}^{:F^{B}}\times q_{2}^{:G^{B}})\big)\times(r_{1}^{:F^{C}}\times r_{2}^{:G^{C}})\big)\triangleright\gunderline{\varepsilon_{12,3}^{\uparrow L}}\\ + & =\text{zip}_{L}\big(\big(\text{zip}_{F}(p_{1}\times q_{1})\times\text{zip}_{G}(p_{2}\times q_{2})\big)\times(r_{1}\times r_{2})\big)\big)\triangleright\big(\varepsilon_{12,3}^{\uparrow F}\boxtimes\varepsilon_{12,3}^{\uparrow G}\big)\\ + & =\big(\gunderline{\text{zip}_{F}\big(\text{zip}_{F}(p_{1}\times q_{1})\times r_{1}\big)\triangleright\varepsilon_{12,3}^{\uparrow F}}\big)\times\big(\gunderline{\text{zip}_{G}\big(\text{zip}_{G}(p_{2}\times q_{2})\times r_{2}\big)\triangleright\varepsilon_{12,3}^{\uparrow G}}\big)\quad. +\end{align*} + +\end_inset + +The underlined expressions in both sides are equal due to associativity + laws of +\begin_inset Formula $\text{zip}_{F}$ +\end_inset + + and +\begin_inset Formula $\text{zip}_{G}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +To verify the commutativity law of +\begin_inset Formula $L$ +\end_inset + + when it holds for +\begin_inset Formula $F$ +\end_inset + + and +\begin_inset Formula $G$ +\end_inset + +: +\begin_inset Formula +\begin{align*} + & \quad\text{expect to equal }\text{zip}_{L}\big((p\times q)\times(m\times n)\big):\quad\\ + & \text{zip}_{L}\big((m\times n)\times(p\times q)\big)\triangleright\text{swap}^{\uparrow L}\\ + & \quad\text{definitions of }\text{zip}_{L}\text{ and }^{\uparrow L}:\quad\\ + & =\big(\text{zip}_{F}(m\times p)\times\text{zip}_{G}(n\times q)\big)\triangleright(\text{swap}^{\uparrow F}\boxtimes\text{swap}^{\uparrow G})\\ + & \quad\text{definition of }\boxtimes:\quad\\ + & =\big(\text{zip}_{F}(m\times p)\triangleright\text{swap}^{\uparrow F}\big)\times\big(\text{zip}_{G}(n\times q)\triangleright\text{swap}^{\uparrow G}\big)\\ + & \quad\text{commutativity laws of }F\text{ and }G:\quad\\ + & =\text{zip}_{F}(p\times m)\times\text{zip}_{G}(q\times n)=\text{zip}_{L}\big((p\times q)\times(m\times n)\big)\quad. +\end{align*} + +\end_inset + + +\begin_inset Formula $\square$ +\end_inset + + +\end_layout + +\begin_layout Paragraph +Co-products +\end_layout + +\begin_layout Standard +The co-product +\begin_inset Formula $F+G$ +\end_inset + + of two arbitrary applicative functors +\begin_inset Formula $F$ +\end_inset + + and +\begin_inset Formula $G$ +\end_inset + + is not always applicative (just as with monads). + One case where the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + method cannot be implemented for +\begin_inset Formula $F+G$ +\end_inset + + was given in Example +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:tc-Example-10" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +(b). + However, the following statements show that the co-product +\begin_inset Formula $F+G$ +\end_inset + + +\emph on +can +\emph default + be applicative under certain restrictions on +\begin_inset Formula $F$ +\end_inset + + and +\begin_inset Formula $G$ +\end_inset + +. +\end_layout + +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-co-product-with-constant-functor-applicative" + +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-co-product-with-constant-functor-applicative" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\begin_layout Standard +If +\begin_inset Formula $F$ +\end_inset + + is applicative and +\begin_inset Formula $Z$ +\end_inset + + is a fixed monoid type then +\begin_inset Formula $L^{A}\triangleq Z+F^{A}$ +\end_inset + + is applicative: +\begin_inset Formula +\begin{align*} + & \text{zip}_{L}:(Z+F^{A})\times(Z+F^{B})\rightarrow Z+F^{A\times B}\quad,\\ + & \text{zip}_{L}\triangleq\,\begin{array}{|c||cc|} + & Z & F^{A\times B}\\ +\hline Z\times Z & z_{1}\times z_{2}\rightarrow z_{1}\oplus z_{2} & \bbnum 0\\ +F^{A}\times Z & \_^{:F^{A}}\times z\rightarrow z & \bbnum 0\\ +Z\times F^{B} & z\times\_^{:F^{B}}\rightarrow z & \bbnum 0\\ +F^{A}\times F^{B} & \bbnum 0 & \text{zip}_{F} +\end{array}\quad. +\end{align*} + +\end_inset + +The +\begin_inset Quotes eld +\end_inset + +wrapped unit +\begin_inset Quotes erd +\end_inset + + ( +\begin_inset Formula $\text{wu}_{L}:Z+F^{\bbnum 1}$ +\end_inset + +) is defined as +\begin_inset Formula $\text{wu}_{L}\triangleq\bbnum 0^{:Z}+\text{wu}_{F}$ +\end_inset + +. + If +\begin_inset Formula $Z$ +\end_inset + + is a commutative monoid and +\begin_inset Formula $F$ +\end_inset + + is commutative then +\begin_inset Formula $L$ +\end_inset + + is also commutative. +\end_layout + +\begin_layout Subparagraph +Proof +\end_layout + +\begin_layout Standard +We will verify the laws of +\begin_inset Formula $\text{zip}_{L}$ +\end_inset + + and +\begin_inset Formula $\text{wu}_{L}$ +\end_inset + +, assuming that +\begin_inset Formula $F$ +\end_inset + + is a lawful applicative functor. +\end_layout + +\begin_layout Standard +The lifting to +\begin_inset Formula $L$ +\end_inset + + is defined in the standard way: +\begin_inset Formula +\[ +(f^{:A\rightarrow B})^{\uparrow L}\triangleq\,\begin{array}{|c||cc|} + & Z & F^{B}\\ +\hline Z & \text{id} & \bbnum 0\\ +F^{A} & \bbnum 0 & f^{\uparrow F} +\end{array}\quad. +\] + +\end_inset + + +\end_layout + +\begin_layout Standard +To verify the left identity law, we use the left identity law of +\begin_inset Formula $\text{zip}_{F}$ +\end_inset + +: +\begin_inset Formula +\begin{align*} + & \text{zip}_{L}(\text{wu}_{L}\times p^{:Z+F^{B}})=\text{zip}_{L}((\bbnum 0+\text{wu}_{F})\times p)\\ + & =(\text{wu}_{F}\times p)\triangleright\,\begin{array}{|c||cc|} + & Z & F^{\bbnum 1\times B}\\ +\hline F^{\bbnum 1}\times Z & \_^{:F^{\bbnum 1}}\times z\rightarrow z & \bbnum 0\\ +F^{\bbnum 1}\times F^{B} & \bbnum 0 & \text{zip}_{F} +\end{array}\\ + & =p\triangleright\,\begin{array}{|c||cc|} + & Z & F^{\bbnum 1\times B}\\ +\hline Z & \text{id} & \bbnum 0\\ +F^{B} & \bbnum 0 & k^{:F^{B}}\rightarrow\gunderline{\text{zip}_{F}(\text{wu}_{F}\times k)} +\end{array}\,=p\triangleright\,\begin{array}{|c||cc|} + & Z & F^{\bbnum 1\times B}\\ +\hline Z & \text{id} & \bbnum 0\\ +F^{B} & \bbnum 0 & k\rightarrow k\triangleright\text{ilu}^{\uparrow F} +\end{array}\\ + & =p\triangleright\text{ilu}^{\uparrow L}\quad. +\end{align*} + +\end_inset + + +\end_layout + +\begin_layout Standard +To verify the right identity law, we write a similar calculation: +\begin_inset Formula +\begin{align*} & \text{zip}_{L}(p^{:Z+F^{A}}\times\text{wu}_{L})=\text{zip}_{L}(p\times(\bbnum 0+\text{wu}_{F}))\\ & =(p\times\text{wu}_{F})\triangleright\,\begin{array}{|c||cc|} & Z & F^{A\times\bbnum 1}\\ @@ -22097,52 +22614,272 @@ plural "false" caps "false" noprefix "false" -\end_inset +\end_inset + + below, where we need to set +\begin_inset Formula $R\triangleq F$ +\end_inset + +, +\begin_inset Formula $S^{T}\triangleq G^{A}+H^{A}\times T$ +\end_inset + +, +\begin_inset Formula $U\triangleq P^{A}$ +\end_inset + +, and +\begin_inset Formula $V\triangleq L^{A}$ +\end_inset + +. + +\begin_inset Formula $\square$ +\end_inset + + +\end_layout + +\begin_layout Standard +Note that the construction shown in Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-applicative-recursive-type-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + needs to define +\emph on +both +\emph default + +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +wu +\end_layout + +\end_inset + + recursively. + This leads to a problem in case +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +wu +\end_layout + +\end_inset + + does not have the type of a function. + A simple example when this problem occurs is with the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +List +\end_layout + +\end_inset + + functor. + The value +\begin_inset Formula $\text{wu}_{\text{List}}$ +\end_inset + + is then defined as: +\begin_inset Formula +\[ +\text{wu}_{\text{List}}:\text{List}^{\bbnum 1}\cong\bbnum 1+\bbnum 1\times\text{List}^{\bbnum 1}\quad,\quad\quad\text{wu}_{\text{List}}\triangleq\bbnum 0+1^{:\bbnum 1}\times\text{wu}_{\text{List}}\quad. +\] + +\end_inset + +This value apparently represents an +\emph on +infinite +\emph default + list of unit values: +\begin_inset Formula +\[ +\text{wu}_{L}=\bbnum 0+1\times\left(\bbnum 0+1\times\left(\bbnum 0+1\times\left(...\right)\right)\right)\quad\quad??? +\] + +\end_inset + +We need a +\begin_inset Quotes eld +\end_inset + +lazy list +\begin_inset Index idx +status open + +\begin_layout Plain Layout +lazy collection +\end_layout + +\end_inset + + +\begin_inset Quotes erd +\end_inset + + (or another non-eager collection) if we want to define +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +wu +\end_layout + +\end_inset + + recursively by the code shown above. + However, the data structure +\begin_inset Formula $\text{List}^{A}$ +\end_inset + + is eagerly evaluated and can only hold a finite number of values. + So, we must conclude that +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +wu +\end_layout + +\end_inset + + is undefined for the eager functor +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +List +\end_layout + +\end_inset + +, which then cannot be considered a lawful applicative functor if the standard + definition of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + is used. + Nevertheless, the associativity and the commutativity laws hold for +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + +. + The absence of a well-defined value +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +wu +\end_layout - below, where we need to set -\begin_inset Formula $R\triangleq F$ \end_inset -, -\begin_inset Formula $S^{T}\triangleq G^{A}+H^{A}\times T$ + does not lead to practical disadvantages when working with finite lists. + +\end_layout + +\begin_layout Standard +For certain choices of +\begin_inset Formula $F$ \end_inset , -\begin_inset Formula $U\triangleq P^{A}$ +\begin_inset Formula $G$ \end_inset , and -\begin_inset Formula $V\triangleq L^{A}$ +\begin_inset Formula $H$ \end_inset -. - -\begin_inset Formula $\square$ +, the functor +\begin_inset Formula $L$ \end_inset + will be a monad. + It is important that the implementation of applicative methods +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +pure \end_layout -\begin_layout Standard -Note that the construction shown in Statement -\begin_inset space ~ \end_inset +, +\begin_inset listings +inline true +status open -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-applicative-recursive-type-1" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout + +map2 +\end_layout \end_inset - needs to define -\emph on -both -\emph default - +, and \begin_inset listings inline true status open @@ -22154,33 +22891,34 @@ zip \end_inset - and + for this functor will be, in general, incompatible with its monad methods. + The \begin_inset listings inline true status open \begin_layout Plain Layout -wu +List \end_layout \end_inset - recursively. - This leads to a problem in case + functor again gives an example where the monad is not commutative while + the applicative functor is. + So, the commutative \begin_inset listings inline true status open \begin_layout Plain Layout -wu +zip \end_layout \end_inset - does not have the type of a function. - A simple example when this problem occurs is with the + method of \begin_inset listings inline true status open @@ -22192,378 +22930,465 @@ List \end_inset - functor. - The value -\begin_inset Formula $\text{wu}_{\text{List}}$ -\end_inset - - is then defined as: -\begin_inset Formula -\[ -\text{wu}_{\text{List}}:\text{List}^{\bbnum 1}\cong\bbnum 1+\bbnum 1\times\text{List}^{\bbnum 1}\quad,\quad\quad\text{wu}_{\text{List}}\triangleq\bbnum 0+1^{:\bbnum 1}\times\text{wu}_{\text{List}}\quad. -\] - -\end_inset + cannot be defined via its +\begin_inset listings +inline true +status open -This value apparently represents an -\emph on -infinite -\emph default - list of unit values: -\begin_inset Formula -\[ -\text{wu}_{L}=\bbnum 0+1\times\left(\bbnum 0+1\times\left(\bbnum 0+1\times\left(...\right)\right)\right)\quad\quad??? -\] +\begin_layout Plain Layout -\end_inset +map +\end_layout -We need a -\begin_inset Quotes eld \end_inset -lazy list -\begin_inset Index idx + and +\begin_inset listings +inline true status open \begin_layout Plain Layout -lazy collection -\end_layout - -\end_inset +flatMap +\end_layout -\begin_inset Quotes erd \end_inset - (or another non-eager collection) if we want to define + methods. + Also, the \begin_inset listings inline true status open \begin_layout Plain Layout -wu +List \end_layout \end_inset - recursively by the code shown above. - However, the data structure -\begin_inset Formula $\text{List}^{A}$ -\end_inset - - is eagerly evaluated and can only hold a finite number of values. - So, we must conclude that + monad's \begin_inset listings inline true status open \begin_layout Plain Layout -wu +pure \end_layout \end_inset - is undefined for the eager functor + method (returning a list with a single value) differs from the applicative + \begin_inset listings inline true status open \begin_layout Plain Layout -List +pure \end_layout \end_inset -, which then cannot be considered a lawful applicative functor if the standard - definition of + method (returning an infinite list of values, as we just saw). +\end_layout + +\begin_layout Standard +There exist other recursive constructions that produce lawful applicative + functors. + For instance, one could assume an +\begin_inset Quotes eld +\end_inset + +biapplicative bifunctor +\begin_inset Quotes erd +\end_inset + + +\begin_inset Formula $P$ +\end_inset + + having a \begin_inset listings inline true status open \begin_layout Plain Layout -zip +bizip \end_layout \end_inset - is used. - Nevertheless, the associativity and the commutativity laws hold for + method with this type signature: +\begin_inset Formula +\[ +\text{bizip}_{P}^{A,B,F}:P^{A,F^{A}}\times P^{B,F^{B}}\rightarrow P^{A\times B,F^{A}\times F^{B}}\quad(\text{for all functors }F)\quad. +\] + +\end_inset + +The bifunctor +\begin_inset Formula $P$ +\end_inset + + should also have a designated +\begin_inset Quotes eld +\end_inset + +wrapped unit +\begin_inset Quotes erd +\end_inset + + value, +\begin_inset Formula $\text{wu}_{P}:P^{\bbnum 1,\bbnum 1}$ +\end_inset + +. + Then the functor +\begin_inset Formula $L$ +\end_inset + + defined via the recursive type equation +\begin_inset Formula $L^{A}\triangleq P^{A,L^{A}}$ +\end_inset + + will be applicative when suitable laws are imposed on \begin_inset listings inline true status open \begin_layout Plain Layout -zip +bizip \end_layout \end_inset . - The absence of a well-defined value -\begin_inset listings -inline true -status open + The methods +\begin_inset Formula $\text{wu}_{L}$ +\end_inset + + and +\begin_inset Formula $\text{zip}_{L}$ +\end_inset + + will be defined recursively by: +\begin_inset Formula +\begin{align*} +\text{wu}_{L}:L^{\bbnum 1}\cong P^{\bbnum 1,L^{\bbnum 1}}\quad, & \quad\quad\text{wu}_{L}\triangleq\text{wu}_{P}\triangleright(\_\rightarrow\overline{\text{wu}_{L}})^{\uparrow P^{\bbnum 1,\bullet}}\quad,\\ +\text{zip}_{L}:P^{A,L^{A}}\times P^{B,L^{B}}\rightarrow P^{A\times B,L^{A\times B}}\quad, & \quad\quad\text{zip}_{L}=\text{bizip}_{P}^{A,B,L^{\bullet}}\bef\overline{\text{zip}_{L}}^{\uparrow P^{A\times B,\bullet}}\quad. +\end{align*} + +\end_inset -\begin_layout Plain Layout -wu \end_layout +\begin_layout Standard +To find what biapplicative bifunctors +\begin_inset Formula $P$ +\end_inset + + exist, one could continue with structural analysis (considering products + +\begin_inset Formula $P_{1}\times P_{2}$ +\end_inset + +, co-products +\begin_inset Formula $P_{1}+P_{2}$ +\end_inset + +, and so on). + This book will not pursue that analysis further, because we already found + sufficiently many type constructions required for practical applications. +\begin_inset Note Note +status collapsed + +\begin_layout Plain Layout +Note that any functor defined via a recursive type equation +\begin_inset Formula $L^{A}\triangleq S^{A,L^{\bullet}}$ +\end_inset + + will be applicative if +\begin_inset Formula $S^{A,R^{\bullet}}$ +\end_inset + + produces an applicative functor whenever +\begin_inset Formula $R^{\bullet}$ +\end_inset + + is applicative. + Statements +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-applicative-recursive-type" +plural "false" +caps "false" +noprefix "false" + \end_inset - does not lead to practical disadvantages when working with finite lists. - -\end_layout +– +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-applicative-recursive-type-1" +plural "false" +caps "false" +noprefix "false" -\begin_layout Standard -For certain choices of -\begin_inset Formula $F$ \end_inset -, -\begin_inset Formula $G$ + are obtained with +\begin_inset Formula $S^{A,R^{\bullet}}\triangleq A+H^{A}\times F^{R^{A}}$ \end_inset -, and -\begin_inset Formula $H$ + and +\begin_inset Formula $S^{A,R^{\bullet}}\triangleq G^{A}+H^{A}\times F^{R^{A}}$ \end_inset -, the functor -\begin_inset Formula $L$ +. + Other examples of such +\begin_inset Formula $S^{\bullet,\bullet}$ \end_inset - will be a monad. - It is important that the implementation of applicative methods -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -pure + can be found by combining some type constructions that are known to produce + applicative functors. \end_layout \end_inset -, -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout -map2 \end_layout +\begin_layout Standard +We conclude this section with a proof of one version of the +\begin_inset Quotes eld \end_inset -, and -\begin_inset listings -inline true -status open +unrolling trick +\begin_inset Quotes erd +\end_inset -\begin_layout Plain Layout + for recursive types: +\begin_inset Index idx +status collapsed -zip +\begin_layout Plain Layout +unrolling trick for recursive types!proof \end_layout \end_inset - for this functor will be, in general, incompatible with its monad methods. - The -\begin_inset listings -inline true -status open -\begin_layout Plain Layout +\begin_inset Index idx +status collapsed -List +\begin_layout Plain Layout +recursive types!unrolling trick!proof \end_layout \end_inset - functor again gives an example where the monad is not commutative while - the applicative functor is. - So, the commutative -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout -zip \end_layout -\end_inset +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-unrolling-trick" - method of -\begin_inset listings -inline true -status open +\end_inset -\begin_layout Plain Layout -List -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-unrolling-trick" +plural "false" +caps "false" +noprefix "false" \end_inset - cannot be defined via its -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout -map \end_layout +\begin_layout Standard +Given two functors +\begin_inset Formula $R$ \end_inset and -\begin_inset listings -inline true -status open +\begin_inset Formula $S$ +\end_inset -\begin_layout Plain Layout +, define two recursive types +\begin_inset Formula $U$ +\end_inset -flatMap -\end_layout + and +\begin_inset Formula $V$ +\end_inset + by +\begin_inset Formula $U\triangleq R^{S^{U}}$ \end_inset - methods. - Also, the -\begin_inset listings -inline true -status open + and +\begin_inset Formula $V\triangleq S^{R^{V}}$ +\end_inset -\begin_layout Plain Layout +. + The +\begin_inset Quotes eld +\end_inset -List -\end_layout +unrolling trick +\begin_inset Quotes erd +\end_inset + writes (non-rigorously) +\begin_inset Formula $U=R^{S^{R^{S^{\iddots}}}}\!$ \end_inset - monad's -\begin_inset listings -inline true -status open + and +\begin_inset Formula $V=S^{R^{S^{R^{\iddots}}}}\!$ +\end_inset -\begin_layout Plain Layout +, which suggests that +\begin_inset Formula $U$ +\end_inset -pure -\end_layout + and +\begin_inset Formula $R^{V}$ +\end_inset + are the same type. + In fact, the type +\begin_inset Formula $U$ \end_inset - method (returning a list with a single value) differs from the applicative - -\begin_inset listings -inline true -status open + is rigorously equivalent to the type +\begin_inset Formula $R^{V}$ +\end_inset -\begin_layout Plain Layout +. +\end_layout -pure +\begin_layout Subparagraph +Proof \end_layout +\begin_layout Standard +We will show that +\begin_inset Formula $U\cong R^{V}$ \end_inset - method (returning an infinite list of values, as we just saw). + by implementing the isomorphisms in two directions. + \end_layout \begin_layout Standard -There exist other recursive constructions that produce lawful applicative - functors. - For instance, one could assume an -\begin_inset Quotes eld +By definition of the type +\begin_inset Formula $U$ \end_inset -biapplicative bifunctor -\begin_inset Quotes erd +, we must have some isomorphisms (called +\begin_inset Formula $\text{fix}_{U}$ \end_inset - -\begin_inset Formula $P$ + and +\begin_inset Formula $\text{unfix}_{U}$ \end_inset - having a -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout +) between types +\begin_inset Formula $U$ +\end_inset -bizip -\end_layout + and +\begin_inset Formula $R^{S^{U}}$ +\end_inset +, and similarly for the type +\begin_inset Formula $V$ \end_inset - method with this type signature: +. + So, we assume that the following functions are known and satisfy the properties + of isomorphisms: \begin_inset Formula -\[ -\text{bizip}_{P}^{A,B,F}:P^{A,F^{A}}\times P^{B,F^{B}}\rightarrow P^{A\times B,F^{A}\times F^{B}}\quad(\text{for all functors }F)\quad. -\] +\begin{align*} + & \text{fix}_{U}:R^{S^{U}}\rightarrow U\quad,\quad\text{unfix}_{U}:U\rightarrow R^{S^{U}}\quad,\quad\text{fix}_{U}\bef\text{unfix}_{U}=\text{id}\quad,\quad\text{unfix}_{U}\bef\text{fix}_{U}=\text{id}\quad;\\ + & \text{fix}_{V}:S^{R^{V}}\rightarrow V\quad,\quad\text{unfix}_{V}:V\rightarrow S^{R^{V}}\quad,\quad\text{fix}_{V}\bef\text{unfix}_{V}=\text{id}\quad,\quad\text{unfix}_{V}\bef\text{fix}_{V}=\text{id}\quad. +\end{align*} \end_inset -The bifunctor -\begin_inset Formula $P$ -\end_inset - should also have a designated -\begin_inset Quotes eld -\end_inset +\end_layout -wrapped unit -\begin_inset Quotes erd -\end_inset +\begin_layout Standard +We implement the isomorphism functions (called +\begin_inset listings +inline true +status open - value, -\begin_inset Formula $\text{wu}_{P}:P^{\bbnum 1,\bbnum 1}$ -\end_inset +\begin_layout Plain Layout -. - Then the functor -\begin_inset Formula $L$ -\end_inset +toU +\end_layout - defined via the recursive type equation -\begin_inset Formula $L^{A}\triangleq P^{A,L^{A}}$ \end_inset - will be applicative when suitable laws are imposed on + and \begin_inset listings inline true status open \begin_layout Plain Layout -bizip +toRV \end_layout \end_inset -. - The methods -\begin_inset Formula $\text{wu}_{L}$ +) recursively: +\begin_inset Formula +\begin{align*} + & \text{toU}:R^{V}\rightarrow U\quad,\quad\quad\text{toU}\triangleq\text{unfix}_{V}^{\uparrow R}\bef\overline{\text{toU}}^{\uparrow S\uparrow R}\bef\text{fix}_{U}\quad;\\ + & \text{toRV}:U\rightarrow R^{V}\quad,\quad\quad\text{toRV}\triangleq\text{unfix}_{U}\bef\overline{\text{toRV}}^{\uparrow S\uparrow R}\bef\text{fix}_{V}^{\uparrow R}\quad. +\end{align*} + +\end_inset + + +\end_layout + +\begin_layout Standard +To verify the isomorphism properties ( +\begin_inset Formula $\text{toU}\bef\text{toRV}=\text{id}$ \end_inset and -\begin_inset Formula $\text{zip}_{L}$ +\begin_inset Formula $\text{toRV}\bef\text{toU}=\text{id}$ \end_inset - will be defined recursively by: +), we use the inductive assumption that those properties already hold for + any recursive calls of these functions: \begin_inset Formula \begin{align*} -\text{wu}_{L}:L^{\bbnum 1}\cong P^{\bbnum 1,L^{\bbnum 1}}\quad, & \quad\quad\text{wu}_{L}\triangleq\text{wu}_{P}\triangleright(\_\rightarrow\overline{\text{wu}_{L}})^{\uparrow P^{\bbnum 1,\bullet}}\quad,\\ -\text{zip}_{L}:P^{A,L^{A}}\times P^{B,L^{B}}\rightarrow P^{A\times B,L^{A\times B}}\quad, & \quad\quad\text{zip}_{L}=\text{bizip}_{P}^{A,B,L^{\bullet}}\bef\overline{\text{zip}_{L}}^{\uparrow P^{A\times B,\bullet}}\quad. + & \text{toU}\bef\text{toRV}=\text{unfix}_{V}^{\uparrow R}\bef\overline{\text{toU}}^{\uparrow S\uparrow R}\bef\gunderline{\text{fix}_{U}\bef\text{unfix}_{U}}\bef\overline{\text{toRV}}^{\uparrow S\uparrow R}\bef\text{fix}_{V}^{\uparrow R}\\ + & \quad=\text{unfix}_{V}^{\uparrow R}\bef\gunderline{\overline{\text{toU}}^{\uparrow S\uparrow R}\bef\overline{\text{toRV}}^{\uparrow S\uparrow R}}\bef\text{fix}_{V}^{\uparrow R}=\text{unfix}_{V}^{\uparrow R}\bef\text{fix}_{V}^{\uparrow R}=\text{id}\quad,\\ + & \text{toRV}\bef\text{toU}=\text{unfix}_{U}\bef\overline{\text{toRV}}^{\uparrow S\uparrow R}\bef\gunderline{\text{fix}_{V}^{\uparrow R}\bef\text{unfix}_{V}^{\uparrow R}}\bef\overline{\text{toU}}^{\uparrow S\uparrow R}\bef\text{fix}_{U}\\ + & \quad=\text{unfix}_{U}\bef\gunderline{\overline{\text{toRV}}^{\uparrow S\uparrow R}\bef\overline{\text{toU}}^{\uparrow S\uparrow R}}\bef\text{fix}_{U}=\text{unfix}_{U}\bef\text{fix}_{U}=\text{id}\quad. \end{align*} \end_inset @@ -22571,130 +23396,182 @@ bizip \end_layout -\begin_layout Standard -To find what biapplicative bifunctors -\begin_inset Formula $P$ +\begin_layout Section +Applicative contrafunctors and profunctors +\begin_inset CommandInset label +LatexCommand label +name "sec:Applicative-contrafunctors-and-profunctors" + \end_inset - exist, one could continue with structural analysis (considering products - -\begin_inset Formula $P_{1}\times P_{2}$ + +\end_layout + +\begin_layout Standard +We have seen in Example +\begin_inset space ~ \end_inset -, co-products -\begin_inset Formula $P_{1}+P_{2}$ + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-applicative-profunctor" +plural "false" +caps "false" +noprefix "false" + \end_inset -, and so on). - This book will not pursue that analysis further, because we already found - sufficiently many type constructions required for practical applications. -\begin_inset Note Note + that a +\begin_inset listings +inline true status open \begin_layout Plain Layout -Note that any functor defined via a recursive type equation -\begin_inset Formula $L^{A}\triangleq S^{A,L^{\bullet}}$ -\end_inset - will be applicative if -\begin_inset Formula $S^{A,R^{\bullet}}$ +zip +\end_layout + \end_inset - produces an applicative functor whenever -\begin_inset Formula $R^{\bullet}$ + method can be implemented for some type constructors that are not covariant. + In this section, we will apply structural analysis systematically to discover + the non-covariant type constructors (contrafunctors and profunctors) that + admit a lawful +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + \end_inset - is applicative. - Statements + method. +\end_layout + +\begin_layout Subsection +Applicative contrafunctors: Laws and constructions +\end_layout + +\begin_layout Standard +Contrafunctors (see Section \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-applicative-recursive-type" +reference "subsec:Contrafunctors" plural "false" caps "false" noprefix "false" \end_inset -– -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-applicative-recursive-type-1" -plural "false" -caps "false" -noprefix "false" +) support a +\begin_inset listings +inline true +status open -\end_inset +\begin_layout Plain Layout + +contramap +\end_layout - are obtained with -\begin_inset Formula $S^{A,R^{\bullet}}\triangleq A+H^{A}\times F^{R^{A}}$ \end_inset - and -\begin_inset Formula $S^{A,R^{\bullet}}\triangleq G^{A}+H^{A}\times F^{R^{A}}$ + method instead of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map +\end_layout + \end_inset . - Other examples of such -\begin_inset Formula $S^{\bullet,\bullet}$ -\end_inset + So, contrafunctors cannot have the +\begin_inset listings +inline true +status open - can be found by combining some type constructions that are known to produce - applicative functors. +\begin_layout Plain Layout + +map2 \end_layout \end_inset + or +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +ap \end_layout -\begin_layout Standard -We conclude this section with a proof of one version of the -\begin_inset Quotes eld \end_inset -unrolling trick -\begin_inset Quotes erd + methods. + Nevertheless, the applicative laws can be formulated via +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + \end_inset - for recursive types: -\begin_inset Index idx -status collapsed + and +\begin_inset listings +inline true +status open \begin_layout Plain Layout -unrolling trick for recursive types!proof + +wu \end_layout \end_inset - -\begin_inset Index idx -status collapsed + methods using +\begin_inset listings +inline true +status open \begin_layout Plain Layout -recursive types!unrolling trick!proof + +contramap \end_layout \end_inset - +: \end_layout \begin_layout Subsubsection -Statement +Definition \begin_inset CommandInset label LatexCommand label -name "subsec:Statement-unrolling-trick" +name "subsec:Definition-applicative-contrafunctor" \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-unrolling-trick" +reference "subsec:Definition-applicative-contrafunctor" plural "false" caps "false" noprefix "false" @@ -22705,776 +23582,881 @@ noprefix "false" \end_layout \begin_layout Standard -Given two functors -\begin_inset Formula $R$ +A contrafunctor +\begin_inset Formula $C$ +\end_inset + + is +\series bold +applicative +\series default + if there exist methods +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + \end_inset and -\begin_inset Formula $S$ +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +wu +\end_layout + \end_inset -, define two recursive types -\begin_inset Formula $U$ + such that: +\begin_inset Formula +\begin{align} + & \text{zip}_{C}:C^{A}\times C^{B}\rightarrow C^{A\times B}\quad,\quad\quad\text{wu}_{C}:C^{\bbnum 1}\quad,\nonumber \\ + & \quad\text{associativity law}:\quad\nonumber \\ + & \text{zip}_{C}(p\times\text{zip}_{C}(q\times r))\triangleright\tilde{\varepsilon}_{1,23}^{\downarrow C}=\text{zip}_{C}(\text{zip}_{C}(p\times q)\times r)\triangleright\tilde{\varepsilon}_{12,3}^{\downarrow C}\quad,\label{eq:applicative-contrafunctor-associativity-law}\\ + & \quad\text{left and right identity laws}:\quad\nonumber \\ + & \text{zip}_{C}(\text{wu}_{C}\times p)\triangleright\text{ilu}^{\downarrow C}=p\quad,\quad\quad\text{zip}_{C}(p\times\text{wu}_{C})\triangleright\text{iru}^{\downarrow C}=p\quad.\label{eq:applicative-contrafunctor-identity-laws} +\end{align} + \end_inset - and -\begin_inset Formula $V$ +Here the tuple-rearranging isomorphisms +\begin_inset Formula $\tilde{\varepsilon}_{1,23}$ +\end_inset + +, +\begin_inset Formula $\tilde{\varepsilon}_{12,3}$ \end_inset - by -\begin_inset Formula $U\triangleq R^{S^{U}}$ -\end_inset +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout - and -\begin_inset Formula $V\triangleq S^{R^{V}}$ -\end_inset +ilu +\end_layout -. - The -\begin_inset Quotes eld \end_inset -unrolling trick -\begin_inset Quotes erd -\end_inset +, and +\begin_inset listings +inline true +status open - writes (non-rigorously) -\begin_inset Formula $U=R^{S^{R^{S^{\iddots}}}}\!$ -\end_inset +\begin_layout Plain Layout - and -\begin_inset Formula $V=S^{R^{S^{R^{\iddots}}}}\!$ -\end_inset +iru +\end_layout -, which suggests that -\begin_inset Formula $U$ \end_inset - and -\begin_inset Formula $R^{V}$ -\end_inset + are defined by: +\begin_inset Formula +\begin{align*} + & \tilde{\varepsilon}_{1,23}\triangleq a\times b\times c\rightarrow a\times\left(b\times c\right)\quad,\quad\quad\tilde{\varepsilon}_{12,3}\triangleq a\times b\times c\rightarrow\left(a\times b\right)\times c\quad,\\ + & \text{ilu}\triangleq a\rightarrow1\times a\quad,\quad\quad\text{iru}=a\rightarrow a\times1\quad. +\end{align*} - are the same type. - In fact, the type -\begin_inset Formula $U$ \end_inset - is rigorously equivalent to the type -\begin_inset Formula $R^{V}$ + +\begin_inset Formula $\square$ \end_inset -. -\end_layout -\begin_layout Subparagraph -Proof \end_layout \begin_layout Standard -We will show that -\begin_inset Formula $U\cong R^{V}$ -\end_inset +An example of an applicative contrafunctor is the equality comparison typeclass + ( +\begin_inset listings +inline true +status open - by implementing the isomorphisms in two directions. - +\begin_layout Plain Layout + +Eq \end_layout -\begin_layout Standard -By definition of the type -\begin_inset Formula $U$ \end_inset -, we must have some isomorphisms (called -\begin_inset Formula $\text{fix}_{U}$ +, defined in Section +\begin_inset space ~ \end_inset - and -\begin_inset Formula $\text{unfix}_{U}$ -\end_inset -) between types -\begin_inset Formula $U$ -\end_inset +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:The-Eq-typeclass" +plural "false" +caps "false" +noprefix "false" - and -\begin_inset Formula $R^{S^{U}}$ \end_inset -, and similarly for the type -\begin_inset Formula $V$ +) viewed as a type constructor +\begin_inset Formula $\text{Eq}^{A}\triangleq A\times A\rightarrow\bbnum 2$ \end_inset . - So, we assume that the following functions are known and satisfy the properties - of isomorphisms: + This type constructor supports a +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + method: \begin_inset Formula \begin{align*} - & \text{fix}_{U}:R^{S^{U}}\rightarrow U\quad,\quad\text{unfix}_{U}:U\rightarrow R^{S^{U}}\quad,\quad\text{fix}_{U}\bef\text{unfix}_{U}=\text{id}\quad,\quad\text{unfix}_{U}\bef\text{fix}_{U}=\text{id}\quad;\\ - & \text{fix}_{V}:S^{R^{V}}\rightarrow V\quad,\quad\text{unfix}_{V}:V\rightarrow S^{R^{V}}\quad,\quad\text{fix}_{V}\bef\text{unfix}_{V}=\text{id}\quad,\quad\text{unfix}_{V}\bef\text{fix}_{V}=\text{id}\quad. + & \text{zip}:\text{Eq}^{A}\times\text{Eq}^{B}\rightarrow\text{Eq}^{A\times B}\quad,\\ + & \text{zip}\,(p^{:\text{Eq}^{A}}\times q^{:\text{Eq}^{B}})\triangleq(a_{1}^{:A}\times b_{1}^{:B})\times(a_{2}^{:A}\times b_{2}^{:B})\rightarrow p(a_{1}\times a_{2})\,\wedge\,q(b_{1}\times b_{2})\quad. \end{align*} \end_inset +Note that we are using the Boolean +\begin_inset Quotes eld +\end_inset -\end_layout +and +\begin_inset Quotes erd +\end_inset -\begin_layout Standard -We implement the isomorphism functions (called + operation ( +\begin_inset Formula $\wedge$ +\end_inset + +) because two pairs are equal when both the first parts and the second parts + are equal separately. + This \begin_inset listings inline true status open \begin_layout Plain Layout -toU +zip \end_layout \end_inset - and + method allows us to derive \begin_inset listings inline true status open \begin_layout Plain Layout -toRV +Eq \end_layout \end_inset -) recursively: -\begin_inset Formula -\begin{align*} - & \text{toU}:R^{V}\rightarrow U\quad,\quad\quad\text{toU}\triangleq\text{unfix}_{V}^{\uparrow R}\bef\overline{\text{toU}}^{\uparrow S\uparrow R}\bef\text{fix}_{U}\quad;\\ - & \text{toRV}:U\rightarrow R^{V}\quad,\quad\quad\text{toRV}\triangleq\text{unfix}_{U}\bef\overline{\text{toRV}}^{\uparrow S\uparrow R}\bef\text{fix}_{V}^{\uparrow R}\quad. -\end{align*} + typeclass instances for product types (e.g., for case classes) automatically. +\end_layout -\end_inset +\begin_layout Standard +It is important to require the laws to hold for +\begin_inset listings +inline true +status open +\begin_layout Plain Layout +zip \end_layout -\begin_layout Standard -To verify the isomorphism properties ( -\begin_inset Formula $\text{toU}\bef\text{toRV}=\text{id}$ \end_inset - and -\begin_inset Formula $\text{toRV}\bef\text{toU}=\text{id}$ -\end_inset +. + Otherwise, a function with the type signature of +\begin_inset listings +inline true +status open -), we use the inductive assumption that those properties already hold for - any recursive calls of these functions: -\begin_inset Formula -\begin{align*} - & \text{toU}\bef\text{toRV}=\text{unfix}_{V}^{\uparrow R}\bef\overline{\text{toU}}^{\uparrow S\uparrow R}\bef\gunderline{\text{fix}_{U}\bef\text{unfix}_{U}}\bef\overline{\text{toRV}}^{\uparrow S\uparrow R}\bef\text{fix}_{V}^{\uparrow R}\\ - & \quad=\text{unfix}_{V}^{\uparrow R}\bef\gunderline{\overline{\text{toU}}^{\uparrow S\uparrow R}\bef\overline{\text{toRV}}^{\uparrow S\uparrow R}}\bef\text{fix}_{V}^{\uparrow R}=\text{unfix}_{V}^{\uparrow R}\bef\text{fix}_{V}^{\uparrow R}=\text{id}\quad,\\ - & \text{toRV}\bef\text{toU}=\text{unfix}_{U}\bef\overline{\text{toRV}}^{\uparrow S\uparrow R}\bef\gunderline{\text{fix}_{V}^{\uparrow R}\bef\text{unfix}_{V}^{\uparrow R}}\bef\overline{\text{toU}}^{\uparrow S\uparrow R}\bef\text{fix}_{U}\\ - & \quad=\text{unfix}_{U}\bef\gunderline{\overline{\text{toRV}}^{\uparrow S\uparrow R}\bef\overline{\text{toU}}^{\uparrow S\uparrow R}}\bef\text{fix}_{U}=\text{unfix}_{U}\bef\text{fix}_{U}=\text{id}\quad. -\end{align*} +\begin_layout Plain Layout -\end_inset +zip +\end_layout +\end_inset -\end_layout + could be implemented for any contrafunctor +\begin_inset Formula $C$ +\end_inset -\begin_layout Section -Applicative contrafunctors and profunctors -\begin_inset CommandInset label -LatexCommand label -name "sec:Applicative-contrafunctors-and-profunctors" +: +\begin_inset Formula +\[ +\text{badZip}:C^{A}\times C^{B}\rightarrow C^{A\times B}\quad,\quad\quad\text{badZip}\triangleq(p^{:C^{A}}\times\_^{:C^{B}})\rightarrow p\triangleright(a\times b\rightarrow a)^{\downarrow C}\quad. +\] \end_inset +This function loses information because it ignores one of its arguments. + Intuitively, we expect that some laws will fail for this function. + Indeed, the left identity law cannot hold: +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +badZip(wu, p) \end_layout -\begin_layout Standard -We have seen in Example -\begin_inset space ~ \end_inset + ignores +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Example-applicative-profunctor" -plural "false" -caps "false" -noprefix "false" +p +\end_layout \end_inset - that a +, so \begin_inset listings inline true status open \begin_layout Plain Layout -zip +badZip(wu, p).contramap(ilu) \end_layout \end_inset - method can be implemented for some type constructors that are not covariant. - In this section, we will apply structural analysis systematically to discover - the non-covariant type constructors (contrafunctors and profunctors) that - admit a lawful + cannot be equal to \begin_inset listings inline true status open \begin_layout Plain Layout -zip +p \end_layout \end_inset - method. -\end_layout - -\begin_layout Subsection -Applicative contrafunctors: Laws and constructions +. \end_layout \begin_layout Standard -Contrafunctors (see Section -\begin_inset space ~ -\end_inset +The laws of +\begin_inset listings +inline true +status open +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Contrafunctors" -plural "false" -caps "false" -noprefix "false" +zip +\end_layout \end_inset -) support a + describe a programmer's expectations about how a function should be distributed + over pairs of arguments. + In the example of the \begin_inset listings inline true status open \begin_layout Plain Layout -contramap +zip \end_layout \end_inset - method instead of + method for \begin_inset listings inline true status open \begin_layout Plain Layout -map +Eq \end_layout \end_inset -. - So, contrafunctors cannot have the +, a violation of the laws of \begin_inset listings inline true status open \begin_layout Plain Layout -map2 +zip \end_layout \end_inset - or + would mean that comparisons of pairs give wrong results. +\end_layout + +\begin_layout Standard +Once the \begin_inset listings inline true status open \begin_layout Plain Layout -ap +zip \end_layout \end_inset - methods. - Nevertheless, the applicative laws can be formulated via + and \begin_inset listings inline true status open \begin_layout Plain Layout -zip +wu \end_layout \end_inset - and + methods are known, we can define \begin_inset listings inline true status open \begin_layout Plain Layout -wu +cpure \end_layout \end_inset - methods using + and \begin_inset listings inline true status open \begin_layout Plain Layout -contramap +cmap2 \end_layout \end_inset : +\begin_inset Formula +\begin{align*} + & \text{cpu}_{C}:\forall A.\,C^{A}\quad,\quad\quad\text{cpu}_{C}\triangleq\text{wu}_{C}\triangleright(\_^{:A}\rightarrow1)^{\downarrow C}\quad,\\ + & \text{cmap}_{2}:(D\rightarrow A\times B)\rightarrow C^{A}\times C^{B}\rightarrow C^{D}\quad,\quad\quad\text{cmap}_{2}(f^{:D\rightarrow A\times B})\triangleq\text{zip}_{C}\bef f^{\downarrow C}\quad. +\end{align*} + +\end_inset + + \end_layout -\begin_layout Subsubsection -Definition -\begin_inset CommandInset label -LatexCommand label -name "subsec:Definition-applicative-contrafunctor" +\begin_layout Standard +The commutativity law is formulated for applicative contrafunctors like + this: +\begin_inset Formula +\begin{align*} + & \text{zip}_{C}(q\times p)=\text{zip}_{C}(p\times q)\triangleright\text{swap}^{\downarrow C}\quad,\\ +\text{or equivalently}:\quad & \text{swap}\bef\text{zip}_{C}=\text{zip}_{C}\bef\text{swap}^{\downarrow C}\quad. +\end{align*} + +\end_inset + +\end_layout + +\begin_layout Standard +The rest of this section proves some constructions that produce lawful applicati +ve contrafunctors. + The results are summarized in Table +\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Definition-applicative-contrafunctor" +reference "tab:Constructions-of-applicative-contrafunctors" plural "false" caps "false" noprefix "false" \end_inset - +. \end_layout \begin_layout Standard -A contrafunctor -\begin_inset Formula $C$ -\end_inset - - is -\series bold -applicative -\series default - if there exist methods -\begin_inset listings -inline true +\begin_inset Float table +wide false +sideways false status open +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + + + +\begin_inset Text + \begin_layout Plain Layout -zip +\series bold +\size small +Construction \end_layout \end_inset - - and -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -wu +\series bold +\size small +Type notation \end_layout \end_inset + + +\begin_inset Text - such that: -\begin_inset Formula -\begin{align} - & \text{zip}_{C}:C^{A}\times C^{B}\rightarrow C^{A\times B}\quad,\quad\quad\text{wu}_{C}:C^{\bbnum 1}\quad,\nonumber \\ - & \quad\text{associativity law}:\quad\nonumber \\ - & \text{zip}_{C}(p\times\text{zip}_{C}(q\times r))\triangleright\tilde{\varepsilon}_{1,23}^{\downarrow C}=\text{zip}_{C}(\text{zip}_{C}(p\times q)\times r)\triangleright\tilde{\varepsilon}_{12,3}^{\downarrow C}\quad,\label{eq:applicative-contrafunctor-associativity-law}\\ - & \quad\text{left and right identity laws}:\quad\nonumber \\ - & \text{zip}_{C}(\text{wu}_{C}\times p)\triangleright\text{ilu}^{\downarrow C}=p\quad,\quad\quad\text{zip}_{C}(p\times\text{wu}_{C})\triangleright\text{iru}^{\downarrow C}=p\quad.\label{eq:applicative-contrafunctor-identity-laws} -\end{align} - -\end_inset +\begin_layout Plain Layout -Here the tuple-rearranging isomorphisms -\begin_inset Formula $\tilde{\varepsilon}_{1,23}$ -\end_inset +\series bold +\size small +Assumptions +\end_layout -, -\begin_inset Formula $\tilde{\varepsilon}_{12,3}$ \end_inset - -, -\begin_inset listings -inline true -status open + + + + +\begin_inset Text \begin_layout Plain Layout -ilu +\size footnotesize +fixed type \end_layout \end_inset - -, and -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -iru +\size footnotesize +\begin_inset Formula $F^{A}\triangleq Z$ +\end_inset + + \end_layout \end_inset + + +\begin_inset Text - are defined by: -\begin_inset Formula -\begin{align*} - & \tilde{\varepsilon}_{1,23}\triangleq a\times b\times c\rightarrow a\times\left(b\times c\right)\quad,\quad\quad\tilde{\varepsilon}_{12,3}\triangleq a\times b\times c\rightarrow\left(a\times b\right)\times c\quad,\\ - & \text{ilu}\triangleq a\rightarrow1\times a\quad,\quad\quad\text{iru}=a\rightarrow a\times1\quad. -\end{align*} +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $Z$ \end_inset + is a monoid +\end_layout -\begin_inset Formula $\square$ \end_inset + + + + +\begin_inset Text +\begin_layout Plain Layout +\size footnotesize +identity \end_layout -\begin_layout Standard -An example of an applicative contrafunctor is the equality comparison typeclass - ( -\begin_inset listings -inline true -status open +\end_inset + + +\begin_inset Text \begin_layout Plain Layout -Eq +\size footnotesize +\begin_inset Formula $F^{A}\triangleq A$ +\end_inset + + \end_layout \end_inset + + +\begin_inset Text -, defined in Section -\begin_inset space ~ -\end_inset +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $F$ +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:The-Eq-typeclass" -plural "false" -caps "false" -noprefix "false" + is commutative +\end_layout \end_inset + + + + +\begin_inset Text -) viewed as a type constructor -\begin_inset Formula $\text{Eq}^{A}\triangleq A\times A\rightarrow\bbnum 2$ -\end_inset +\begin_layout Plain Layout -. - This type constructor supports a -\begin_inset listings -inline true -status open +\size footnotesize +composition +\end_layout + +\end_inset + + +\begin_inset Text \begin_layout Plain Layout -zip +\size footnotesize +\begin_inset Formula $F^{A}\triangleq G^{H^{A}}$ +\end_inset + + \end_layout \end_inset + + +\begin_inset Text - method: -\begin_inset Formula -\begin{align*} - & \text{zip}:\text{Eq}^{A}\times\text{Eq}^{B}\rightarrow\text{Eq}^{A\times B}\quad,\\ - & \text{zip}\,(p^{:\text{Eq}^{A}}\times q^{:\text{Eq}^{B}})\triangleq(a_{1}^{:A}\times b_{1}^{:B})\times(a_{2}^{:A}\times b_{2}^{:B})\rightarrow p(a_{1}\times a_{2})\,\wedge\,q(b_{1}\times b_{2})\quad. -\end{align*} +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $G$ \end_inset -Note that we are using the Boolean -\begin_inset Quotes eld + is an appl. +\begin_inset space ~ \end_inset -and -\begin_inset Quotes erd +functor, +\begin_inset Formula $H$ \end_inset - operation ( -\begin_inset Formula $\wedge$ + is an appl. +\begin_inset space ~ \end_inset -) because two pairs are equal when both the first parts and the second parts - are equal separately. - This -\begin_inset listings -inline true -status open +contrafunctor +\end_layout + +\end_inset + + + + +\begin_inset Text \begin_layout Plain Layout -zip +\size footnotesize +product \end_layout \end_inset - - method allows us to derive -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -Eq -\end_layout - +\size footnotesize +\begin_inset Formula $F^{A}\triangleq P^{A}\times Q^{A}$ \end_inset - typeclass instances for product types (e.g., for case classes) automatically. + \end_layout -\begin_layout Standard -It is important to require the laws to hold for -\begin_inset listings -inline true -status open +\end_inset + + +\begin_inset Text \begin_layout Plain Layout -zip -\end_layout +\size footnotesize +\begin_inset Formula $P$ +\end_inset + and +\begin_inset Formula $Q$ \end_inset -. - Otherwise, a function with the type signature of -\begin_inset listings -inline true -status open + are applicative contrafunctors +\end_layout + +\end_inset + + + + +\begin_inset Text \begin_layout Plain Layout -zip +\size footnotesize +co-product \end_layout \end_inset + + +\begin_inset Text - could be implemented for any contrafunctor -\begin_inset Formula $C$ +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F^{A}\triangleq P^{A}+Q^{A}$ \end_inset -: -\begin_inset Formula -\[ -\text{badZip}:C^{A}\times C^{B}\rightarrow C^{A\times B}\quad,\quad\quad\text{badZip}\triangleq(p^{:C^{A}}\times\_^{:C^{B}})\rightarrow p\triangleright(a\times b\rightarrow a)^{\downarrow C}\quad. -\] -\end_inset +\end_layout -This function loses information because it ignores one of its arguments. - Intuitively, we expect that some laws will fail for this function. - Indeed, the left identity law cannot hold: -\begin_inset listings -inline true -status open +\end_inset + + +\begin_inset Text \begin_layout Plain Layout -badZip(wu, p) -\end_layout +\size footnotesize +\begin_inset Formula $P$ +\end_inset + and +\begin_inset Formula $Q$ \end_inset - ignores -\begin_inset listings -inline true -status open + are applicative contrafunctors +\end_layout + +\end_inset + + + + +\begin_inset Text \begin_layout Plain Layout -p +\size footnotesize +function type \end_layout \end_inset - -, so -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -badZip(wu, p).contramap(ilu) +\size footnotesize +\begin_inset Formula $F^{A}\triangleq P^{A}\rightarrow Q^{A}$ +\end_inset + + \end_layout \end_inset - - cannot be equal to -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -p -\end_layout +\size footnotesize +\begin_inset Formula $P$ +\end_inset + is any functor, +\begin_inset Formula $Q$ \end_inset -. + is an applicative contrafunctor \end_layout -\begin_layout Standard -The laws of -\begin_inset listings -inline true -status open +\end_inset + + + + +\begin_inset Text \begin_layout Plain Layout -zip +\size footnotesize +recursive type \end_layout \end_inset - - describe a programmer's expectations about how a function should be distributed - over pairs of arguments. - In the example of the -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -zip -\end_layout - +\size footnotesize +\begin_inset Formula $F^{A}\triangleq S^{A,F^{P^{A}}}$ \end_inset - method for -\begin_inset listings -inline true -status open -\begin_layout Plain Layout - -Eq \end_layout \end_inset - -, a violation of the laws of -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -zip -\end_layout +\size footnotesize +\begin_inset Formula $S$ +\end_inset + and +\begin_inset Formula $P$ \end_inset - would mean that comparisons of pairs give wrong results. + are polynomial \end_layout -\begin_layout Standard -Once the -\begin_inset listings -inline true -status open +\end_inset + + + + +\begin_inset Text \begin_layout Plain Layout -zip +\size footnotesize +recursive type \end_layout \end_inset - - and -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -wu +\size footnotesize +\begin_inset Formula $F^{A}\triangleq P^{A}+Q^{A}\times R^{F^{A}}$ +\end_inset + + \end_layout \end_inset - - methods are known, we can define -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -cpure -\end_layout - +\size footnotesize +conditions in Statement +\begin_inset space ~ \end_inset - and -\begin_inset listings -inline true -status open -\begin_layout Plain Layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-applicative-recursive-type-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + -cmap2 \end_layout \end_inset - -: -\begin_inset Formula -\begin{align*} - & \text{cpu}_{C}:\forall A.\,C^{A}\quad,\quad\quad\text{cpu}_{C}\triangleq\text{wu}_{C}\triangleright(\_^{:A}\rightarrow1)^{\downarrow C}\quad,\\ - & \text{cmap}_{2}:(D\rightarrow A\times B)\rightarrow C^{A}\times C^{B}\rightarrow C^{D}\quad,\quad\quad\text{cmap}_{2}(f^{:D\rightarrow A\times B})\triangleq\text{zip}_{C}\bef f^{\downarrow C}\quad. -\end{align*} + + + \end_inset \end_layout -\begin_layout Standard -The commutativity law is formulated for applicative contrafunctors like - this: -\begin_inset Formula -\begin{align*} - & \text{zip}_{C}(q\times p)=\text{zip}_{C}(p\times q)\triangleright\text{swap}^{\downarrow C}\quad,\\ -\text{or equivalently}:\quad & \text{swap}\bef\text{zip}_{C}=\text{zip}_{C}\bef\text{swap}^{\downarrow C}\quad. -\end{align*} +\begin_layout Plain Layout +\begin_inset Caption Standard + +\begin_layout Plain Layout +Constructions of applicative contrafunctors. +\begin_inset CommandInset label +LatexCommand label +name "tab:Constructions-of-applicative-contrafunctors" + +\end_inset + + +\end_layout \end_inset \end_layout -\begin_layout Standard -The rest of this section proves some constructions that produce lawful applicati -ve contrafunctors. +\end_inset + + \end_layout \begin_layout Paragraph @@ -25334,106 +26316,395 @@ Here we imply tuple-rearranging isomorphisms \begin_inset Formula $\tilde{\varepsilon}_{12,3}$ \end_inset -, -\begin_inset listings -inline true +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +ilu +\end_layout + +\end_inset + +, and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +iru +\end_layout + +\end_inset + +: +\begin_inset Formula +\begin{align*} + & \text{zip}_{P}(p\times\text{zip}_{P}(q\times r))\triangleright\varepsilon_{1,23}^{\uparrow P}\tilde{\varepsilon}_{1,23}^{\downarrow P}=\text{zip}_{P}(\text{zip}_{P}(p\times q)\times r)\triangleright\varepsilon_{12,3}^{\uparrow P}\tilde{\varepsilon}_{12,3}^{\downarrow P}\quad,\\ + & \text{zip}_{P}(\text{wu}_{P}\times p)=p\triangleright\text{ilu}^{\uparrow P}\pi_{2}^{\downarrow P}\quad,\quad\quad\text{zip}_{P}(p\times\text{wu}_{P})=p\triangleright\text{iru}^{\uparrow P}\pi_{1}^{\downarrow P}\quad. +\end{align*} + +\end_inset + + +\end_layout + +\begin_layout Standard +Once the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +wu +\end_layout + +\end_inset + + methods are known, we can define +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +xmap2 +\end_layout + +\end_inset + +: +\begin_inset Formula +\begin{align*} + & \text{pu}_{P}:A\rightarrow P^{A}\quad,\quad\quad\text{pu}_{P}(a^{:A})\triangleq\text{wu}_{P}\triangleright(\_^{:A}\rightarrow1)^{\downarrow P}(\_^{:\bbnum 1}\rightarrow a)^{\uparrow P}\quad,\\ + & \text{xmap}_{2}:(A\times B\rightarrow D)\times(D\rightarrow A\times B)\rightarrow P^{A}\times P^{B}\rightarrow P^{D}\quad,\\ + & \text{xmap}_{2}(f^{:A\times B\rightarrow D}\times g^{:D\rightarrow A\times B})\triangleq\text{zip}_{P}\bef(g^{\downarrow P}f^{\uparrow P})\quad. +\end{align*} + +\end_inset + + +\end_layout + +\begin_layout Standard +It is important that the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + +\end_inset + + method ( +\begin_inset Formula $\text{pu}_{P}$ +\end_inset + +) for profunctors is defined via the wrapped unit ( +\begin_inset Formula $\text{wu}_{P}$ +\end_inset + +). + The presence of a value +\begin_inset Formula $\text{wu}_{P}:P^{\bbnum 1}$ +\end_inset + + means that the profunctor +\begin_inset Formula $P$ +\end_inset + + is pointed +\begin_inset Index idx +status open + +\begin_layout Plain Layout +profunctor!pointed +\end_layout + +\end_inset + + (see Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Pointed-functors-motivation-equivalence" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). + For functors and contrafunctors, the naturality law of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + +\end_inset + + is enough to enforce the equivalence of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +wu +\end_layout + +\end_inset + +. + For profunctors, however, the value +\begin_inset Formula $\text{wu}_{P}:P^{\bbnum 1}$ +\end_inset + + is +\emph on +not +\emph default + equivalent to the type of fully parametric functions with the type signature + of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + +\end_inset + +. + The following example illustrates this (see also Exercise +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Exercise-profunctor-pure-not-equivalent-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). +\end_layout + +\begin_layout Subsubsection +Example +\begin_inset CommandInset label +LatexCommand label +name "subsec:Example-profunctor-pure-not-equivalent" + +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-profunctor-pure-not-equivalent" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\begin_inset Index idx status open \begin_layout Plain Layout - -ilu +examples \end_layout \end_inset -, and -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout -iru \end_layout +\begin_layout Standard +For the profunctor +\begin_inset Formula $P^{A}\triangleq\left(A\rightarrow A\right)\rightarrow A$ \end_inset -: -\begin_inset Formula -\begin{align*} - & \text{zip}_{P}(p\times\text{zip}_{P}(q\times r))\triangleright\varepsilon_{1,23}^{\uparrow P}\tilde{\varepsilon}_{1,23}^{\downarrow P}=\text{zip}_{P}(\text{zip}_{P}(p\times q)\times r)\triangleright\varepsilon_{12,3}^{\uparrow P}\tilde{\varepsilon}_{12,3}^{\downarrow P}\quad,\\ - & \text{zip}_{P}(\text{wu}_{P}\times p)=p\triangleright\text{ilu}^{\uparrow P}\pi_{2}^{\downarrow P}\quad,\quad\quad\text{zip}_{P}(p\times\text{wu}_{P})=p\triangleright\text{iru}^{\uparrow P}\pi_{1}^{\downarrow P}\quad. -\end{align*} +, show that the type +\begin_inset Formula $P^{\bbnum 1}$ +\end_inset + is +\emph on +not +\emph default + equivalent to the type of fully parametric functions +\begin_inset Formula $\text{pu}_{P}:A\rightarrow P^{A}$ \end_inset +. +\end_layout +\begin_layout Subparagraph +Solution \end_layout \begin_layout Standard -Once the +We can rewrite the type of +\begin_inset Formula $\text{wu}_{P}$ +\end_inset + + equivalently as +\begin_inset Formula $P^{\bbnum 1}=\left(\bbnum 1\rightarrow\bbnum 1\right)\rightarrow\bbnum 1\cong\bbnum 1$ +\end_inset + +. + So, there is only one value of this type (a function that ignores its argument + and always returns the unit value +\begin_inset Formula $1$ +\end_inset + +). + The corresponding \begin_inset listings inline true status open \begin_layout Plain Layout -zip +pure \end_layout \end_inset - and -\begin_inset listings -inline true -status open + method is a function that ignores its argument and always returns the given + value: +\begin_inset Formula +\[ +\text{pu}_{P}\triangleq a^{:A}\rightarrow\_^{:A\rightarrow A}\rightarrow a\quad. +\] -\begin_layout Plain Layout +\end_inset -wu -\end_layout +But there are many more functions with the same type signature as +\begin_inset Formula $\text{pu}_{P}$ +\end_inset +. + To see this, we swap the curried arguments of +\begin_inset Formula $\text{pu}_{P}$ \end_inset - methods are known, we can define -\begin_inset listings -inline true -status open + and obtain an equivalent type: +\begin_inset Formula +\[ +A\rightarrow P^{A}=A\rightarrow\left(A\rightarrow A\right)\rightarrow A\cong\left(A\rightarrow A\right)\rightarrow A\rightarrow A\quad. +\] -\begin_layout Plain Layout +\end_inset -pure -\end_layout +Examples of functions of this type are: +\begin_inset Formula +\[ +f_{1}\triangleq k^{:A\rightarrow A}\rightarrow k\quad,\quad\quad f_{2}\triangleq k^{:A\rightarrow A}\rightarrow(k\bef k)\quad, +\] \end_inset - and -\begin_inset listings -inline true -status open +and so on. + For any non-negative integer +\begin_inset Formula $n=0,1,2,...$ +\end_inset -\begin_layout Plain Layout +, we can define the function +\begin_inset Formula $f_{n}$ +\end_inset -xmap2 -\end_layout + that applies its argument +\begin_inset Formula $n$ +\end_inset + times (similar functions were defined in Example +\begin_inset space ~ \end_inset -: -\begin_inset Formula -\begin{align*} - & \text{pu}_{P}:A\rightarrow P^{A}\quad,\quad\quad\text{pu}_{P}(a^{:A})\triangleq\text{wu}_{P}\triangleright(\_^{:A}\rightarrow1)^{\downarrow P}(\_^{:\bbnum 1}\rightarrow a)^{\uparrow P}\quad,\\ - & \text{xmap}_{2}:(A\times B\rightarrow D)\times(D\rightarrow A\times B)\rightarrow P^{A}\times P^{B}\rightarrow P^{D}\quad,\\ - & \text{xmap}_{2}(f^{:A\times B\rightarrow D}\times g^{:D\rightarrow A\times B})\triangleq\text{zip}_{P}\bef(g^{\downarrow P}f^{\uparrow P})\quad. -\end{align*} +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-hof-derive-types-2" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + and Exercise +\begin_inset space ~ \end_inset -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Exercise-hof-simple-4" +plural "false" +caps "false" +noprefix "false" -\begin_layout Standard -It is important that the +\end_inset + +). + The function \begin_inset listings inline true status open @@ -25445,336 +26716,374 @@ pure \end_inset - method ( -\begin_inset Formula $\text{pu}_{P}$ + defined above is the same as +\begin_inset Formula $f_{0}$ \end_inset -) for profunctors is defined via the wrapped unit ( -\begin_inset Formula $\text{wu}_{P}$ +. + All functions +\begin_inset Formula $f_{n}$ \end_inset -). - The presence of a value -\begin_inset Formula $\text{wu}_{P}:P^{\bbnum 1}$ + are fully parametric. + So, the type of fully parametric functions with type signature +\begin_inset Formula $A\rightarrow P^{A}$ \end_inset - means that the profunctor -\begin_inset Formula $P$ + contains many more values than the type +\begin_inset Formula $P^{\bbnum 1}$ +\end_inset + +. + +\begin_inset Formula $\square$ \end_inset - is pointed -\begin_inset Index idx -status open -\begin_layout Plain Layout -profunctor!pointed \end_layout +\begin_layout Standard +The commutativity law of applicative profunctors is written like this: +\begin_inset Formula +\[ +\text{zip}_{P}(q\times p)\triangleright\text{swap}^{\downarrow P}\text{swap}^{\uparrow P}=\text{zip}_{P}(p\times q)\quad. +\] + \end_inset - (see Section + +\end_layout + +\begin_layout Standard +The rest of this section proves some constructions that produce lawful applicati +ve profunctors and are not equivalent to previously shown constructions + of applicative functors or contrafunctors. + The results are summarized in Table \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Pointed-functors-motivation-equivalence" +reference "tab:Constructions-of-applicative-profunctors" plural "false" caps "false" noprefix "false" \end_inset -). - For functors and contrafunctors, the naturality law of -\begin_inset listings -inline true +. +\end_layout + +\begin_layout Standard +\begin_inset Float table +wide false +sideways false status open \begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + + + +\begin_inset Text -pure +\begin_layout Plain Layout + +\series bold +\size small +Construction \end_layout \end_inset - - is enough to enforce the equivalence of -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -pure +\series bold +\size small +Type notation \end_layout \end_inset - - and -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -wu +\series bold +\size small +Assumptions \end_layout \end_inset + + + + +\begin_inset Text -. - For profunctors, however, the value -\begin_inset Formula $\text{wu}_{P}:P^{\bbnum 1}$ -\end_inset +\begin_layout Plain Layout - is -\emph on -not -\emph default - equivalent to the type of fully parametric functions with the type signature - of -\begin_inset listings -inline true -status open +\size footnotesize +composition +\end_layout + +\end_inset + + +\begin_inset Text \begin_layout Plain Layout -pure -\end_layout - +\size footnotesize +\begin_inset Formula $F^{A}\triangleq G^{H^{A}}$ \end_inset -. - The following example illustrates this (see also Exercise -\begin_inset space ~ + +\end_layout + \end_inset + + +\begin_inset Text +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Exercise-profunctor-pure-not-equivalent-1" -plural "false" -caps "false" -noprefix "false" +\size footnotesize +\begin_inset Formula $G$ +\end_inset + is an applicative functor, +\begin_inset Formula $H$ \end_inset -). + is an applicative profunctor \end_layout -\begin_layout Subsubsection -Example -\begin_inset CommandInset label -LatexCommand label -name "subsec:Example-profunctor-pure-not-equivalent" - \end_inset + + + + +\begin_inset Text +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Example-profunctor-pure-not-equivalent" -plural "false" -caps "false" -noprefix "false" +\size footnotesize +product +\end_layout \end_inset - - -\begin_inset Index idx -status open + + +\begin_inset Text \begin_layout Plain Layout -examples -\end_layout +\size footnotesize +\begin_inset Formula $F^{A}\triangleq P^{A}\times Q^{A}$ \end_inset \end_layout -\begin_layout Standard -For the profunctor -\begin_inset Formula $P^{A}\triangleq\left(A\rightarrow A\right)\rightarrow A$ \end_inset + + +\begin_inset Text -, show that the type -\begin_inset Formula $P^{\bbnum 1}$ +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $P$ \end_inset - is -\emph on -not -\emph default - equivalent to the type of fully parametric functions -\begin_inset Formula $\text{pu}_{P}:A\rightarrow P^{A}$ + and +\begin_inset Formula $Q$ \end_inset -. + are applicative profunctors \end_layout -\begin_layout Subparagraph -Solution +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +co-product \end_layout -\begin_layout Standard -We can rewrite the type of -\begin_inset Formula $\text{wu}_{P}$ \end_inset + + +\begin_inset Text - equivalently as -\begin_inset Formula $P^{\bbnum 1}=\left(\bbnum 1\rightarrow\bbnum 1\right)\rightarrow\bbnum 1\cong\bbnum 1$ -\end_inset +\begin_layout Plain Layout -. - So, there is only one value of this type (a function that ignores its argument - and always returns the unit value -\begin_inset Formula $1$ +\size footnotesize +\begin_inset Formula $F^{A}\triangleq Z+Q^{A}$ \end_inset -). - The corresponding -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout -pure \end_layout \end_inset + + +\begin_inset Text - method is a function that ignores its argument and always returns the given - value: -\begin_inset Formula -\[ -\text{pu}_{P}\triangleq a^{:A}\rightarrow\_^{:A\rightarrow A}\rightarrow a\quad. -\] +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $Z$ \end_inset -But there are many more functions with the same type signature as -\begin_inset Formula $\text{pu}_{P}$ -\end_inset + is a monoid type +\end_layout -. - To see this, we swap the curried arguments of -\begin_inset Formula $\text{pu}_{P}$ \end_inset + + + + +\begin_inset Text - and obtain an equivalent type: -\begin_inset Formula -\[ -A\rightarrow P^{A}=A\rightarrow\left(A\rightarrow A\right)\rightarrow A\cong\left(A\rightarrow A\right)\rightarrow A\rightarrow A\quad. -\] +\begin_layout Plain Layout + +\size footnotesize +co-product +\end_layout \end_inset + + +\begin_inset Text -Examples of functions of this type are: -\begin_inset Formula -\[ -f_{1}\triangleq k^{:A\rightarrow A}\rightarrow k\quad,\quad\quad f_{2}\triangleq k^{:A\rightarrow A}\rightarrow(k\bef k)\quad, -\] +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $F^{A}\triangleq P^{A}+Q^{A}$ \end_inset -and so on. - For any non-negative integer -\begin_inset Formula $n=0,1,2,...$ -\end_inset -, we can define the function -\begin_inset Formula $f_{n}$ -\end_inset +\end_layout - that applies its argument -\begin_inset Formula $n$ \end_inset + + +\begin_inset Text - times (similar functions were defined in Example +\begin_layout Plain Layout + +\size footnotesize +conditions of Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Example-hof-derive-types-2" +reference "subsec:Statement-applicative-profunctor-co-product-2" plural "false" caps "false" noprefix "false" \end_inset - and Exercise -\begin_inset space ~ + +\end_layout + \end_inset + + + + +\begin_inset Text +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Exercise-hof-simple-4" -plural "false" -caps "false" -noprefix "false" +\size footnotesize +function type +\end_layout \end_inset - -). - The function -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -pure +\size footnotesize +\begin_inset Formula $F^{A}\triangleq P^{A}\rightarrow Q^{A}$ +\end_inset + + \end_layout \end_inset + + +\begin_inset Text - defined above is the same as -\begin_inset Formula $f_{0}$ -\end_inset +\begin_layout Plain Layout -. - All functions -\begin_inset Formula $f_{n}$ +\size footnotesize +\begin_inset Formula $P$ \end_inset - are fully parametric. - So, the type of fully parametric functions with type signature -\begin_inset Formula $A\rightarrow P^{A}$ + is any functor, +\begin_inset Formula $Q$ \end_inset - contains many more values than the type -\begin_inset Formula $P^{\bbnum 1}$ + is an applicative profunctor +\end_layout + \end_inset + + + -. - -\begin_inset Formula $\square$ \end_inset \end_layout -\begin_layout Standard -The commutativity law of applicative profunctors is written like this: -\begin_inset Formula -\[ -\text{zip}_{P}(q\times p)\triangleright\text{swap}^{\downarrow P}\text{swap}^{\uparrow P}=\text{zip}_{P}(p\times q)\quad. -\] +\begin_layout Plain Layout +\begin_inset Caption Standard + +\begin_layout Plain Layout +Constructions of applicative profunctors. +\begin_inset CommandInset label +LatexCommand label +name "tab:Constructions-of-applicative-profunctors" \end_inset \end_layout -\begin_layout Standard -The rest of this section proves some constructions that produce lawful applicati -ve profunctors. +\end_inset + + +\end_layout + +\end_inset + + \end_layout \begin_layout Subsubsection @@ -33594,7 +34903,7 @@ pure (b) \series default Show that the type of fully parametric functions -\begin_inset Formula $\text{pu}_{P}:A\rightarrow P^{A}$ +\begin_inset Formula $\text{pu}_{P}:\forall A.\,A\rightarrow P^{A}$ \end_inset is diff --git a/sofp-src/lyx/sofp-monads.lyx b/sofp-src/lyx/sofp-monads.lyx index 6b52ddddc..9467a3bdc 100644 --- a/sofp-src/lyx/sofp-monads.lyx +++ b/sofp-src/lyx/sofp-monads.lyx @@ -24357,6 +24357,558 @@ We have seen different examples of well-known monads that were discovered analysis to semi-monads and monads. For each type construction, we will prove rigorously that the monad laws hold. + The results are summarized in Table +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Constructions-of-monads" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size small +Construction +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size small +Type notation +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size small +Assumptions, results +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +fixed type +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F^{A}\triangleq Z$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is a monad if +\begin_inset Formula $Z=\bbnum 1$ +\end_inset + +; +\begin_inset Formula $F$ +\end_inset + + is a semi-monad for +\begin_inset Formula $Z\neq\bbnum 1$ +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +identity +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F^{A}\triangleq A$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is a full monad +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +product +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F^{A}\triangleq P^{A}\times Q^{A}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $P$ +\end_inset + + and +\begin_inset Formula $Q$ +\end_inset + + are (semi-)monads +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +product +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F^{A}\triangleq A\times P^{A}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is a semi-monad when +\begin_inset Formula $P$ +\end_inset + + is any functor +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +free pointed +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F^{A}\triangleq A+P^{A}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is a monad when +\begin_inset Formula $P$ +\end_inset + + is a monad +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +function type +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F^{A}\triangleq Z\rightarrow P^{A}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $Z$ +\end_inset + + is a fixed type, +\begin_inset Formula $P$ +\end_inset + + is a (semi-)monad +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +function type +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F^{A}\triangleq H^{A}\rightarrow A$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is a monad when +\begin_inset Formula $H$ +\end_inset + + is any contrafunctor +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +function type +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F^{A}\triangleq H^{A}\rightarrow G^{A}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $G$ +\end_inset + + is a (semi-)monad, +\begin_inset Formula $H$ +\end_inset + + is a +\begin_inset Formula $G$ +\end_inset + +-filterable contrafunctor +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +free monad +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F^{A}\triangleq A+L^{F^{A}}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $L$ +\end_inset + + is any functor +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +tree semi-monad +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F^{A}\triangleq L^{A}+L^{F^{A}}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is a semi-monad if +\begin_inset Formula $L$ +\end_inset + + is any functor +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption Standard + +\begin_layout Plain Layout +Constructions of semi-monads and monads. +\begin_inset CommandInset label +LatexCommand label +name "tab:Constructions-of-monads" + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + \end_layout \begin_layout Paragraph @@ -26366,7 +26918,14 @@ F^{L^{A}} & \bbnum 0 & \gamma^{\uparrow F}\bef\text{ftn}_{F} & A & F^{A}\\ \hline A & \text{id} & \bbnum 0\\ F^{A} & \bbnum 0 & \text{id} -\end{array}\,=\text{id}\quad,\\ +\end{array}\,=\text{id}\quad, +\end{align*} + +\end_inset + + +\begin_inset Formula +\begin{align*} & \text{pu}_{L}^{\uparrow L}\bef\text{ftn}_{L}=\,\begin{array}{|c||ccc|} & A & F^{A} & F^{L^{A}}\\ \hline A & \text{id} & \bbnum 0 & \bbnum 0\\ @@ -26519,8 +27078,7 @@ F^{L^{L^{A}}} & \bbnum 0 & \bbnum 0 & \gamma^{\uparrow F}\bef\text{ftn}_{F} \end_inset -We are ready to verify the associativity law. - Simplify both sides using matrix compositions: +We are ready to verify the associativity law: \begin_inset Formula \begin{align*} & \text{ftn}_{L}^{\uparrow L}\bef\text{ftn}_{L}=\,\begin{array}{|c||ccc|} @@ -26534,14 +27092,7 @@ F^{L^{L^{A}}} & \bbnum 0 & \bbnum 0 & \text{ftn}_{L}^{\uparrow F} \hline A & \text{id} & \bbnum 0\\ F^{A} & \bbnum 0 & \text{id}\\ F^{L^{A}} & \bbnum 0 & \gamma^{\uparrow F}\bef\text{ftn}_{F} -\end{array} -\end{align*} - -\end_inset - - -\begin_inset Formula -\begin{align*} +\end{array}\\ & \quad=\,\begin{array}{|c||cc|} & A & F^{A}\\ \hline A & \text{id} & \bbnum 0\\ @@ -26753,7 +27304,7 @@ F^{L^{A}} & \gamma^{\uparrow F}\bef\text{ftn}_{F} \begin_inset Note Note -status open +status collapsed \begin_layout Plain Layout \begin_inset Formula @@ -27055,8 +27606,11 @@ f^{:Z\rightarrow A\rightarrow F^{B}}\tilde{\diamond}_{_{L}}g^{:Z\rightarrow B\ri \end_inset +\end_layout + +\begin_layout Standard \begin_inset Note Note -status open +status collapsed \begin_layout Plain Layout \begin_inset Formula @@ -27072,10 +27626,6 @@ f^{:Z\rightarrow A\rightarrow F^{B}}\tilde{\diamond}_{_{L}}g^{:Z\rightarrow B\ri \end_inset - -\end_layout - -\begin_layout Standard To verify the laws, it is convenient to substitute an arbitrary \begin_inset Formula $z^{:Z}$ \end_inset @@ -28678,9 +29228,7 @@ def flatMap_L[A, B](la: L[A])(f: A => L[B]): L[B] = la match { \begin_layout Plain Layout - case Right(fla) => Right(fla.map { (x: L[A]) => flatMap_L(x)(f) }) // - Recursive call of flatMap_L. - + case Right(fla) => Right(fla.map { (x: L[A]) => flatMap_L(x)(f) }) \end_layout \begin_layout Plain Layout @@ -28706,8 +29254,7 @@ def flatten_L[A]: L[L[A]] => L[A] = { // Match on L[L[A]] = Either[Either[A, \begin_layout Plain Layout - case Right(Right(flla)) => Right(flla.map(x => flatten_L(x))) // - Recursive call of flatten_L. + case Right(Right(flla)) => Right(flla.map(x => flatten_L(x))) \end_layout \begin_layout Plain Layout @@ -28852,7 +29399,7 @@ F^{L^{L^{L^{A}}}} & \bbnum 0 & \bbnum 0 & \big(\text{ftn}_{L}^{\overline{\uparro \end_inset -We can now verify the identity and associativity laws of +We can now verify the laws of \begin_inset Formula $\text{pu}_{L}$ \end_inset @@ -28863,7 +29410,7 @@ We can now verify the identity and associativity laws of . Identity laws: \begin_inset Note Note -status collapsed +status open \begin_layout Plain Layout \begin_inset Formula @@ -30283,7 +30830,15 @@ pure status open \begin_layout Plain Layout -There are several implementations of +Functors of the form +\begin_inset Formula $F^{A}\triangleq\bbnum 1+A\times...\times A$ +\end_inset + + are not monads: +\emph on +none +\emph default + of the possible implementations of \begin_inset listings inline true status open @@ -30307,16 +30862,8 @@ flatten \end_inset - for -\begin_inset Formula $D^{A}\triangleq\bbnum 1+A\times A$ -\end_inset - -, but -\emph on -none -\emph default - of them obey the monad laws (Hew Wolff, private communication). - For details, see + obey the monad laws (Hew Wolff, private communication). + For some details, see \family typewriter \begin_inset CommandInset href diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 0199abad8..3f88757d7 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -2699,6 +2699,24 @@ noprefix "false" *** \end_layout +\begin_layout Standard +The results of structural analysis are shown in Table +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Constructions-of-monads" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +. +\end_layout + \begin_layout Subsection Chapter \begin_inset space ~ @@ -2718,7 +2736,49 @@ noprefix "false" \end_layout \begin_layout Standard -*** +***The results for applicative functors are shown in Table +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Constructions-of-applicative-functors" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +, for applicative contrafunctors in Table +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Constructions-of-applicative-contrafunctors" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +, and for applicative profunctors in Table +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Constructions-of-applicative-profunctors" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +. \end_layout \begin_layout Subsection @@ -3834,6 +3894,50 @@ literal "false" will gain wide use. \end_layout +\begin_layout Subsection +Programming language theory +\end_layout + +\begin_layout Standard +Certain theoretical questions are of interest to designers of programming + languages but not to users of those languages. + Here are some examples of such questions: +\end_layout + +\begin_layout Itemize +Proving that type inference and type checking are terminating procedures. +\end_layout + +\begin_layout Itemize +Proving that evaluation will be always error-free once an expression has + been type-checked. + ( +\begin_inset Quotes eld +\end_inset + +Soundness +\begin_inset Quotes erd +\end_inset + + of the type system.) +\end_layout + +\begin_layout Itemize +Proving that evaluating an expression will always give the same results + regardless of which part of the expression is evaluated first; or providing + precise conditions for that to be true. +\end_layout + +\begin_layout Itemize +Proving that composition of functions is associative by a rigorous description + of what it means for functions to be equal without involving an evaluation + of those functions. +\end_layout + +\begin_layout Standard +This book does not pursue those topics. +\end_layout + \begin_layout Section Additional exercises and open problems \begin_inset CommandInset label diff --git a/sofp-src/lyx/sofp-typeclasses.lyx b/sofp-src/lyx/sofp-typeclasses.lyx index e1903a299..93b492f44 100644 --- a/sofp-src/lyx/sofp-typeclasses.lyx +++ b/sofp-src/lyx/sofp-typeclasses.lyx @@ -39297,7 +39297,7 @@ transitive \begin_inset Formula $B$ \end_inset - (this needs to be declared together with the definition of + (this must be declared together with the definition of \begin_inset Formula $A$ \end_inset @@ -39471,8 +39471,8 @@ interface derivation \end_layout \begin_layout Itemize -The compilers of Scala and other functional languages treat ADTs significantly - differently from typeclasses. +The compilers of Scala and other functional languages treat ADTs and typeclasses + in rather different ways. An ADT is not just an arbitrary type \begin_inset Formula $T$ \end_inset @@ -39482,7 +39482,7 @@ The compilers of Scala and other functional languages treat ADTs significantly \end_inset . - Instead, the Scala compiler interprets an ADT as the + In fact, the Scala compiler interprets an ADT as the \emph on smallest unique \emph default diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 5745772bdeec77758529d9cf04daf8c66831e671..9edb6ebad0889aecdaa1e43ddac5a15f844ede5f 100644 GIT binary patch delta 152 zcmX?Ra?E7I8WAqb5F=wN0~0G#^U2#p43W7XMV|1c7#f?I8mF1*rka{0ZGI%m!NhK9 zWNcspRQ*w08phr%EOCv|$<4yR($Ubx#mU^*$HjrWz+&Y L[B]): L[B] = la match { case Left(a) => f(a) - case Right(fla) => Right(fla.map { (x: L[A]) => flatMap_L(x)(f) }) // Recursive call of flatMap_L. + case Right(fla) => Right(fla.map { (x: L[A]) => flatMap_L(x)(f) }) } def flatten_L[A]: L[L[A]] => L[A] = { // Match on L[L[A]] = Either[Either[A, F[L[A]]], F[L[L[A]]]]. case Left(a) => Left(a) case Left(Right(fla)) => Right(fla) - case Right(Right(flla)) => Right(flla.map(x => flatten_L(x))) // Recursive call of flatten_L. + case Right(Right(flla)) => Right(flla.map(x => flatten_L(x))) } \end{lstlisting} \[ @@ -6406,8 +6440,8 @@ \subsubsection{Statement \label{subsec:Statement-monad-construction-4-free-monad F^{L^{L^{L^{A}}}} & \bbnum 0 & \bbnum 0 & \big(\text{ftn}_{L}^{\overline{\uparrow L}}\big)^{\uparrow F} \end{array}\quad. \end{align*} -We can now verify the identity and associativity laws of $\text{pu}_{L}$ -and $\text{ftn}_{L}$. Identity laws: +We can now verify the laws of $\text{pu}_{L}$ and $\text{ftn}_{L}$. +Identity laws: \[ \text{pu}_{L}^{L^{A}}\bef\text{ftn}_{L}=\,\begin{array}{|c||ccc|} & A & F^{L^{A}} & F^{L^{L^{A}}}\\ @@ -6689,10 +6723,10 @@ \subsubsection{Exercise \label{subsec:Exercise-1-monads-7-not-a-monad}\ref{subse this is defined by \lstinline!type D[A] = Option[(A, A)]!). Implement the \lstinline!flatten! and \lstinline!pure! methods for $D$ in at least two different ways. Show that some of the monad laws fail -to hold for every implementation.\footnote{There are several implementations of \lstinline!pure! and \lstinline!flatten! -for $D^{A}\triangleq\bbnum 1+A\times A$, but \emph{none} of them -obey the monad laws (Hew Wolff, private communication). For details, -see \texttt{\href{https://stackoverflow.com/questions/49742377/}{https://stackoverflow.com/questions/49742377/}}} +to hold for every implementation.\footnote{Functors of the form $F^{A}\triangleq\bbnum 1+A\times...\times A$ +are not monads: \emph{none} of the possible implementations of \lstinline!pure! +and \lstinline!flatten! obey the monad laws (Hew Wolff, private communication). +For some details, see \texttt{\href{https://stackoverflow.com/questions/49742377/}{https://stackoverflow.com/questions/49742377/}}} \subsubsection{Exercise \label{subsec:Exercise-1-monads-8}\ref{subsec:Exercise-1-monads-8}} diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index 5380d1b2a..05c2b032d 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -399,9 +399,13 @@ \subsection{Chapter~\ref{chap:Semimonads-and-monads}} {*}{*}{*} +The results of structural analysis are shown in Table~\ref{tab:Constructions-of-monads}. + \subsection{Chapter~\ref{chap:8-Applicative-functors,-contrafunctors}} -{*}{*}{*} +{*}{*}{*}The results for applicative functors are shown in Table~\ref{tab:Constructions-of-applicative-functors}, +for applicative contrafunctors in Table~\ref{tab:Constructions-of-applicative-contrafunctors}, +and for applicative profunctors in Table~\ref{tab:Constructions-of-applicative-profunctors}. \subsection{Chapter~\ref{chap:9-Traversable-functors-and}} @@ -605,6 +609,24 @@ \subsection{Effect systems} have been created recently. It is perhaps too early to say what form of effect-oriented programming will gain wide use. +\subsection{Programming language theory} + +Certain theoretical questions are of interest to designers of programming +languages but not to users of those languages. Here are some examples +of such questions: +\begin{itemize} +\item Proving that type inference and type checking are terminating procedures. +\item Proving that evaluation will be always error-free once an expression +has been type-checked. (\textsf{``}Soundness\textsf{''} of the type system.) +\item Proving that evaluating an expression will always give the same results +regardless of which part of the expression is evaluated first; or +providing precise conditions for that to be true. +\item Proving that composition of functions is associative by a rigorous +description of what it means for functions to be equal without involving +an evaluation of those functions. +\end{itemize} +This book does not pursue those topics. + \section{Additional exercises and open problems\label{chap:Exercises-in-AFTT}} The following is a sample set of problems that can be solved using diff --git a/sofp-src/tex/sofp-typeclasses.tex b/sofp-src/tex/sofp-typeclasses.tex index 8463b0f6b..99ee27d4d 100644 --- a/sofp-src/tex/sofp-typeclasses.tex +++ b/sofp-src/tex/sofp-typeclasses.tex @@ -5840,17 +5840,18 @@ \subsection{$P$-typeclasses, their laws and structure\label{subsec:P-typeclasses An example of a typeclass to which neither description applies is the \lstinline!Eq! typeclass. Its evidence values have type $A\times A\rightarrow\bbnum 2$, -which is neither of the form $P^{A}\rightarrow A$ nor $A\rightarrow P^{A}$. +which is neither of the form $P^{A}\rightarrow A$ nor $A\rightarrow P^{A}$ +(where $P$ must be a covariant functor). \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} -Typeclasses can be viewed as a way of managing various sets of methods -that a data type must support. Scala supports two other features for -managing data methods: object-oriented interfaces\index{object-oriented interfaces} +Typeclasses can be viewed as a way of managing the methods that various +data types must support. Scala has two other features for managing +methods: object-oriented interfaces\index{object-oriented interfaces} (OOIs) and algebraic data types\index{algebraic data types} (ADTs). We will now compare the expressive power of all those features. We will find that typeclasses can be seen as a generalization of both -OOIs and ADTs, transcending their specific limitations. +OOIs and ADTs, overcoming their specific limitations. We begin by formulating typeclasses, OOIs, and ADTs purely in terms of types. @@ -5898,41 +5899,42 @@ \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} use the information from the value itself. So, the type-centric view must consider \lstinline!isSmallerThan! as a function of \emph{two} arguments: an argument denoted by \lstinline!this! and an argument -\lstinline!size: Int!. To call that function, we use the syntax \lstinline!c.isSmallerThan(1000)!. -Similarly, we must consider \lstinline!isEmpty! as a function of -one argument (\lstinline!this!), even though it is declared without -any arguments in the interface code. +\lstinline!size: Int!. We use that function with the syntax \lstinline!c.isSmallerThan(1000)! +to pass the arguments $c$ and $1000$. Similarly, we must consider +\lstinline!isEmpty! as a function of one argument (\lstinline!this!), +even though it is declared without any arguments in the interface +code. Methods in an OOI may use an automatically defined value denoted by the keyword \lstinline!this!. In some other object-oriented languages, -method signatures must have an explicit first argument called \lstinline!self!, -\lstinline!this!, or similar. When we analyze OOIs as types, we must -make all argument types explicit, even though the Scala syntax does -not do that. For convenience, let us therefore assume that each method -in an OOI definition has an additional \emph{first} argument (corresponding -to Scala\textsf{'}s \lstinline!this! keyword). +method signatures must have an explicit first argument, usually called +\lstinline!self!, \lstinline!this!, or similar. When we analyze +OOIs as types, we must make all argument types explicit, even though +the Scala syntax does not do that. For this reason, we will view the +types of methods in an OOI definition as having an additional first +argument (corresponding to Scala\textsf{'}s \lstinline!this! keyword). We have expressed the type of an interface as a tuple of some function -types. The first argument of each function is the type of a class +types. The first argument of each function has the type of a class that will later implement that interface. That type is unknown within the scope of an interface definition, and so we have to denote that type by a type parameter $T$. Then all functions in an interface will have types of the form $T\times(...)\rightarrow(...)$, with a first argument of type $T$. Using curried function types equivalent -to those type signatures, we can make $T$ a curried first argument -and we obtain a description of an OOI type as a tuple of types of -the form $T\rightarrow U_{1}$, $T\rightarrow U_{2}$, ..., $T\rightarrow U_{n}$, -where $U_{1}$, ..., $U_{n}$ are some type expressions that might -also use $T$. Note that the $U_{i}$ correspond to the type expressions -as seen in the Scala interface definition, where the first argument -of type $T$ is not written out. +to those type signatures, we can make $T$ a \emph{curried} first +argument. Then we obtain a description of an OOI type as a tuple of +types of the form $T\rightarrow U_{1}$, $T\rightarrow U_{2}$, ..., +$T\rightarrow U_{n}$, where $U_{1}$, ..., $U_{n}$ are some type +expressions that might also depend on $T$. Note that the $U_{i}$ +exactly correspond to the type expressions specified in the Scala +interface definition, where the first argument of type $T$ is not +written out. Using a standard type equivalence such as: \[ (T\rightarrow U_{1})\times(T\rightarrow U_{2})\cong T\rightarrow U_{1}\times U_{2}\quad, \] -and similarly for other $U_{i}$, we can simplify the type of an OOI -to a single function: +we can simplify the type of an OOI to a single function: \[ (T\rightarrow U_{1})\times...\times(T\rightarrow U_{n})\cong T\rightarrow U_{1}\times...\times U_{n}=T\rightarrow U^{T}\quad, \] @@ -5953,8 +5955,8 @@ \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} The types $\bbnum 2$ and $\text{Int}\rightarrow\bbnum 2$ exactly correspond to the type signatures of the methods \lstinline!isEmpty! -and \lstinline!isSmallerThan! in the interface definition, where -the first argument (of type $T$) is not written. +and \lstinline!isSmallerThan! in the Scala interface definition, +where the first argument (of type $T$) is not written. Now we can see the similarity between OOIs and typeclasses. If a type $T$ belongs to a typeclass with method signature $\text{Sig}$ then @@ -5966,8 +5968,8 @@ \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} of type $T\rightarrow U^{T}$. In this way, we find that an OOI is similar to a special case of a typeclass whose method signature has the form $\text{Sig}^{T}=T\rightarrow U^{T}$. In such a typeclass, -all methods are \textsf{``}extension methods\textsf{''} whose first argument has type -$T$. +all methods are \textsf{``}extension methods\textsf{''} since their first arguments +have type $T$. Not all typeclasses have signatures of that form. As we have just seen, the \lstinline!Monoid! typeclass has this signature: @@ -6047,7 +6049,7 @@ \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} Not all typeclasses have signatures of this form. For example, the equality typeclass (\lstinline!Eq!) has the method signature $\text{Sig}_{\text{Eq}}^{T}=T\times T\rightarrow\bbnum 2$, which is not equivalent to $P^{T}\rightarrow T$ with any definition -of $T$. +of $P$. \paragraph{Summary} @@ -6061,7 +6063,7 @@ \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} A typeclass with signature $\text{Sig}_{1}$ inherits from a typeclass with signature $\text{Sig}_{2}$ if $\text{Sig}_{1}^{T}=\text{Sig}_{2}^{T}\times Q^{T}$ -for some $Q$. (The type constructor $Q$ describes the additional +for some $Q$. (The type constructor $Q$ describes all the additional methods that the new typeclass has.) So, typeclass inheritance corresponds to taking products of method signatures. @@ -6096,7 +6098,7 @@ \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} types. There are other important differences in how the Scala compiler works with typeclasses, OOIs, and ADTs: \begin{itemize} -\item For OOIs, the compiler provides automatic subtyping for interfaces, +\item For OOIs, the compiler provides automatic subtyping for interfaces via the object-oriented inheritance mechanism. If a class (or an interface) $A$ inherits an interface $B$ then the compiler will automatically consider $A$ as a subtype of $B$. Subtyping and inheritance are @@ -6106,18 +6108,18 @@ \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} tree automatically, extending the tree each time a new interface or class is defined. However, one cannot add or remove inherited interfaces once a class definition is given. For example, if it is declared that -$A$ inherits from $B$ and $C$ (this needs to be declared together -with the definition of $A$) then the programmer cannot declare in -another scope that $A$ should inherit additionally from some other -interface, or that $A$ should no longer inherit from $B$. Typeclasses -are more flexible in this respect: additional evidence values for -typeclass membership can be defined in any scope, not necessarily -together with the declaration of a type. Typeclasses may be implemented -via OOIs, which will enable features of inheritance and subtyping. -This will make typeclass inheritance behave like object-oriented interface -inheritance, with all its benefits and shortcomings. As we have seen, -typeclasses and their inheritance may be also implemented without -using object-oriented interfaces or inheritance. +$A$ inherits from $B$ (this must be declared together with the definition +of $A$) then the programmer cannot declare in another scope that +$A$ should inherit additionally from some other interface $C$; or +that $A$ should no longer inherit from $B$. Typeclasses are more +flexible in this respect: additional evidence values for typeclass +membership can be defined in any scope, not necessarily together with +the declaration of a type. Typeclasses may be implemented via OOIs, +which will enable features of inheritance and subtyping. This will +make typeclass inheritance behave like object-oriented interface inheritance, +with all its benefits and shortcomings. As we have seen, typeclasses +and their inheritance may be implemented with or without object-oriented +inheritance. \item For typeclasses, the compiler provides rich features for automatic computation of typeclass evidence values via the mechanism of implicit values and implicit functions. These features enable automatic typeclass @@ -6135,17 +6137,18 @@ \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} pairs \lstinline!(A, B)! to all case classes, and from the disjunctive type \lstinline!Either[A, B]! to all disjunctive types. In this way, typeclass membership can be provided automatically by the compiler -for a wide range of types, which reduces boilerplate code. But there -are no comparable facilities for object-oriented \textsf{``}interface derivation\textsf{''}. -\item The compiler\textsf{'}s treatment of ADTs in Scala (and in other functional -languages) is significantly different from the treatment of typeclasses -and interfaces. An ADT is not an arbitrary type $T$ that happens -to support functions of type $P^{T}\rightarrow T$. Instead, the Scala -compiler interprets an ADT as the \emph{smallest unique} type generated -by the given constructors while using no other information or constraints. -In mathematical terminology, the type $T$ is the least fixpoint\index{least fixpoint} -of the pattern functor $P$. Rigorous definitions and the necessary -theory will be developed in Chapter~\ref{chap:Free-type-constructions}. +(with no boilerplate code) for a wide range of user-defined types. +But there are no comparable facilities for object-oriented \textsf{``}interface +derivation\textsf{''}. +\item The compilers of Scala and other functional languages treat ADTs and +typeclasses in rather different ways. An ADT is not just an arbitrary +type $T$ that happens to support functions of type $P^{T}\rightarrow T$. +In fact, the Scala compiler interprets an ADT as the \emph{smallest +unique} type generated by the given constructors while using no other +information or constraints. In mathematical terminology, the type +$T$ is the least fixpoint\index{least fixpoint} of the pattern functor +$P$. Rigorous definitions and the necessary theory will be developed +in Chapter~\ref{chap:Free-type-constructions}. \end{itemize} \begin{comment} this tutorial is about typeclasses and type level functions to motivate diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 1698113ab..225b5b7a5 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): a1dd267f3b9f9e371fbec6af076d72888f2b5bfe6e48f79de1678ff7794c804c}\\ -{\scriptsize{}Git commit: aa93d569770a77db2f159ef8f2024738be422647}\\ -{\scriptsize{}PDF file built on Fri, 17 Oct 2025 21:03:03 +0200 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 42aae4f730ec25befea827aec99bc15e81c4dac683de7eaf2ea2ab134a87d5c0}\\ +{\scriptsize{}Git commit: 15e3c29aa74aabce79d205507c84891a164615f6}\\ +{\scriptsize{}PDF file built on Sun, 19 Oct 2025 23:05:14 +0200 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From f43a66de5b66e61a1609866ac1a39319513fffb5 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Mon, 20 Oct 2025 12:14:44 +0200 Subject: [PATCH 03/42] wip --- sofp-src/lyx/sofp-applicative.lyx | 24 ++++++++++++++++++++---- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-applicative.tex | 23 +++++++++++------------ sofp-src/tex/sofp.tex | 6 +++--- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/sofp-src/lyx/sofp-applicative.lyx b/sofp-src/lyx/sofp-applicative.lyx index 3c3366dc7..da1179af6 100644 --- a/sofp-src/lyx/sofp-applicative.lyx +++ b/sofp-src/lyx/sofp-applicative.lyx @@ -28904,7 +28904,7 @@ Discussion and further developments \end_layout \begin_layout Subsection -Equivalence of typeclass methods with laws +Equivalence of lawful typeclass methods \end_layout \begin_layout Standard @@ -29146,8 +29146,16 @@ noprefix "false" \end_layout \begin_layout Standard -After seeing those detailed proofs, we can now clarify the meaning of equivalenc -e of typeclass methods when we require some laws to hold. +After seeing those detailed proofs, we can now clarify what it means for + two typeclass methods to be +\begin_inset Quotes eld +\end_inset + +equivalent +\begin_inset Quotes erd +\end_inset + + when we require some laws to hold. The goal of this subsection is to find a rigorous formulation of that equivalen ce. \end_layout @@ -29213,7 +29221,15 @@ pure[A]: A => F[A] \end_inset . - In Scala code, this law is written as + In Scala code, this law is written as the +\begin_inset Quotes eld +\end_inset + +code equation +\begin_inset Quotes erd +\end_inset + + \begin_inset listings inline true status open diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 9edb6ebad0889aecdaa1e43ddac5a15f844ede5f..4453040feac9b613d620e6a2bc433d85cb0809a1 100644 GIT binary patch delta 136 zcmX?Ra?E7IMiEv+BP&zm$=gKCpsbG~Pk2+4Q&WvB(~@*kO-+(FKN96;VlgxVs`@A{ z2WD&*mbk{~WNc<;;N;|J>TF`+XkqAT>SAJQ;B0APVq|P#VrXvQW@kf4#bj+MX#lsx BBu4-M delta 136 zcmX?Ra?E7IMiEv66Dw2m$=gKCpsbG~Pk2)djm=Dr)68^JO-+(EKN96;VlglQs`@A{ z2WD&*mbk{~1gQU;$&{@Waw(_Z0KlUU~XVwY3bx_?Cfl2Zf8SC#bj+MX#joL BBmn>b diff --git a/sofp-src/tex/sofp-applicative.tex b/sofp-src/tex/sofp-applicative.tex index 14ff59b0e..f0edffcf1 100644 --- a/sofp-src/tex/sofp-applicative.tex +++ b/sofp-src/tex/sofp-applicative.tex @@ -2211,7 +2211,7 @@ \subsection{Constructions of applicative functors\label{subsec:Constructions-of- \begin{centering} \begin{tabular}{|c|c|c|} \hline -\textbf{\small{}Construction} & \textbf{\small{}Type notation} & \textbf{\small{}Assumptions, results}\tabularnewline +\textbf{\small{}Construction} & \textbf{\small{}Type notation} & \textbf{\small{}Assumptions}\tabularnewline \hline \hline {\footnotesize{}fixed type} & {\footnotesize{}$F^{A}\triangleq Z$} & {\footnotesize{}$Z$ is a monoid}\tabularnewline @@ -3510,15 +3510,14 @@ \subsubsection{Definition \label{subsec:Definition-applicative-contrafunctor}\re \begin{centering} \begin{tabular}{|c|c|c|} \hline -\textbf{\small{}Construction} & \textbf{\small{}Type notation} & \textbf{\small{}Assumptions, results}\tabularnewline +\textbf{\small{}Construction} & \textbf{\small{}Type notation} & \textbf{\small{}Assumptions}\tabularnewline \hline \hline {\footnotesize{}fixed type} & {\footnotesize{}$F^{A}\triangleq Z$} & {\footnotesize{}$Z$ is a monoid}\tabularnewline \hline {\footnotesize{}identity} & {\footnotesize{}$F^{A}\triangleq A$} & {\footnotesize{}$F$ is commutative}\tabularnewline \hline -{\footnotesize{}composition} & {\footnotesize{}$F^{A}\triangleq G^{H^{A}}$} & {\footnotesize{}$G$ is an applicative functor, $H$ is an applicative -contrafunctor}\tabularnewline +{\footnotesize{}composition} & {\footnotesize{}$F^{A}\triangleq G^{H^{A}}$} & {\footnotesize{}$G$ is an appl.~functor, $H$ is an appl.~contrafunctor}\tabularnewline \hline {\footnotesize{}product} & {\footnotesize{}$F^{A}\triangleq P^{A}\times Q^{A}$} & {\footnotesize{}$P$ and $Q$ are applicative contrafunctors}\tabularnewline \hline @@ -3532,7 +3531,7 @@ \subsubsection{Definition \label{subsec:Definition-applicative-contrafunctor}\re \hline \end{tabular} \par\end{centering} -\caption{Constructions of applicative functors.\label{tab:Constructions-of-applicative-contrafunctors}} +\caption{Constructions of applicative contrafunctors.\label{tab:Constructions-of-applicative-contrafunctors}} \end{table} @@ -4083,7 +4082,7 @@ \subsubsection{Example \label{subsec:Example-profunctor-pure-not-equivalent}\ref \begin{centering} \begin{tabular}{|c|c|c|} \hline -\textbf{\small{}Construction} & \textbf{\small{}Type notation} & \textbf{\small{}Assumptions, results}\tabularnewline +\textbf{\small{}Construction} & \textbf{\small{}Type notation} & \textbf{\small{}Assumptions}\tabularnewline \hline \hline {\footnotesize{}composition} & {\footnotesize{}$F^{A}\triangleq G^{H^{A}}$} & {\footnotesize{}$G$ is an applicative functor, $H$ is an applicative @@ -4649,7 +4648,7 @@ \subsubsection{Statement \label{subsec:Statement-applicative-profunctor-exponent \section{Discussion and further developments} -\subsection{Equivalence of typeclass methods with laws} +\subsection{Equivalence of lawful typeclass methods} In this and the previous chapters, we have seen that certain typeclass methods are equivalent. The equivalence of \lstinline!map2!, \lstinline!zip!, @@ -4669,10 +4668,10 @@ \subsection{Equivalence of typeclass methods with laws} A function $\text{pu}_{F}:A\rightarrow F^{A}$ satisfying a naturality law is equivalent to a value $\text{wu}_{F}:F^{\bbnum 1}$. -After seeing those detailed proofs, we can now clarify the meaning -of equivalence of typeclass methods when we require some laws to hold. -The goal of this subsection is to find a rigorous formulation of that -equivalence. +After seeing those detailed proofs, we can now clarify what it means +for two typeclass methods to be \textsf{``}equivalent\textsf{''} when we require some +laws to hold. The goal of this subsection is to find a rigorous formulation +of that equivalence. In each case seen so far, we have two functions with two different type signatures (usually with type parameters), and we assume that @@ -4685,7 +4684,7 @@ \subsection{Equivalence of typeclass methods with laws} example, the type signature \lstinline!pure[A]: A => F[A]! (in the type notation, $\text{pu}_{F}:\forall A.\,A\rightarrow F^{A}$) gives rise to the naturality law $f\bef\text{pu}_{F}=\text{pu}_{F}\bef f^{\uparrow F}$. -In Scala code, this law is written as \lstinline!pure(f(x)) == pure(x).map(f)!. +In Scala code, this law is written as the \textsf{``}code equation\textsf{''} \lstinline!pure(f(x)) == pure(x).map(f)!. What we have proved in Section~\ref{subsec:Pointed-functors-motivation-equivalence} is a one-to-one correspondence between two \emph{sets}: the set of diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 225b5b7a5..a8abb45a1 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): 42aae4f730ec25befea827aec99bc15e81c4dac683de7eaf2ea2ab134a87d5c0}\\ -{\scriptsize{}Git commit: 15e3c29aa74aabce79d205507c84891a164615f6}\\ -{\scriptsize{}PDF file built on Sun, 19 Oct 2025 23:05:14 +0200 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 5c9e7771f1fcf498d0544f4be34d8efcab688f18ee3fe969b583a1010d3562c3}\\ +{\scriptsize{}Git commit: cc66740f02415636e8207dd0f7cfee055cbdaf0d}\\ +{\scriptsize{}PDF file built on Sun, 19 Oct 2025 23:13:10 +0200 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From 736c3f85b0a3ccbcf2b6a1b60a3b6a6232efd548 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Wed, 22 Oct 2025 09:39:30 +0200 Subject: [PATCH 04/42] wip summary of monads chapter --- sofp-src/lyx/sofp-applicative.lyx | 2 +- sofp-src/lyx/sofp-summary.lyx | 65 ++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/sofp-src/lyx/sofp-applicative.lyx b/sofp-src/lyx/sofp-applicative.lyx index da1179af6..8142ed9b4 100644 --- a/sofp-src/lyx/sofp-applicative.lyx +++ b/sofp-src/lyx/sofp-applicative.lyx @@ -28891,7 +28891,7 @@ covariant \begin_inset Formula $P$ \end_inset - will not be applicative even in simple cases such as + is not guaranteed to be applicative even in simple cases such as \begin_inset Formula $P^{A}\triangleq H^{A}\rightarrow A$ \end_inset diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 3f88757d7..50c4ac32e 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -335,7 +335,7 @@ The book has been written in a tutorial format, motivating and deriving \end_layout \begin_layout Section -Main points and results by chapter +Main ideas and results by chapter \end_layout \begin_layout Standard @@ -2696,7 +2696,68 @@ noprefix "false" \end_layout \begin_layout Standard -*** +The chapter introduces +\begin_inset Quotes eld +\end_inset + +semi-monads +\begin_inset Quotes erd +\end_inset + + as functors with a +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + + method. + This is motivated by considering how functional programming can represent + nested loops. + Simple loops are translated into an application of a +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map +\end_layout + +\end_inset + + function to sequences; similarly, nested loops are translated into applications + of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map +\end_layout + +\end_inset + + functions. + *** \end_layout \begin_layout Standard From 6c0cc7644fe0ea80b2ddcfb05417e57ef1337d92 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Thu, 23 Oct 2025 22:40:33 +0200 Subject: [PATCH 05/42] wip overview of the monad chapter --- sofp-src/lyx/sofp-monads.lyx | 45 +- sofp-src/lyx/sofp-summary.lyx | 795 +++++++++++++++++++++++++++++++++- 2 files changed, 787 insertions(+), 53 deletions(-) diff --git a/sofp-src/lyx/sofp-monads.lyx b/sofp-src/lyx/sofp-monads.lyx index 9467a3bdc..35a03cb48 100644 --- a/sofp-src/lyx/sofp-monads.lyx +++ b/sofp-src/lyx/sofp-monads.lyx @@ -380,7 +380,8 @@ flatMap \end_inset method. - This chapter begins by developing an intuition for the behavior of + This chapter begins by developing a motivation and an intuition for the + use of \begin_inset listings inline true status open @@ -604,7 +605,7 @@ flatten \end_inset -, and its combination with +, and its composition with \begin_inset listings inline true status open @@ -616,7 +617,7 @@ map \end_inset - can be replaced by + is known as \begin_inset listings inline true status open @@ -10340,8 +10341,9 @@ flatMap \end_inset - method can be supported by many other type constructors useful for various - programming tasks not necessarily related to nested iteration. + method is supported by many other type constructors (not just containers) + and may be used for various programming tasks not necessarily related to + nested iteration. \end_layout \begin_layout Standard @@ -10358,7 +10360,7 @@ A general (semi)monad type constructor \begin_inset Formula $A$ \end_inset - wrapped in a special + wrapped in type constructor representing a special \begin_inset Quotes eld \end_inset @@ -10367,7 +10369,7 @@ computational effect \end_inset . - We view + By \begin_inset Quotes eld \end_inset @@ -10379,7 +10381,7 @@ computations with an \begin_inset Quotes erd \end_inset - as functions of type + we simply mean functions of type \begin_inset Formula $A\rightarrow L^{B}$ \end_inset @@ -10398,29 +10400,6 @@ flatMap 's argument type). In this view, different monads — such as list-like, pass/fail, or tree-like — implement different kinds of effects. - -\begin_inset Note Note -status open - -\begin_layout Plain Layout -An ordinary function of type -\begin_inset Formula $A\rightarrow B$ -\end_inset - - is a computation with a -\begin_inset Quotes eld -\end_inset - -trivial effect -\begin_inset Quotes erd -\end_inset - -. -\end_layout - -\end_inset - - \end_layout \begin_layout Standard @@ -10474,7 +10453,7 @@ value-like behavior \begin_inset Quotes erd \end_inset - describes the information computed by a function of type + describes whatever else is computed by a function of type \begin_inset Formula $A\rightarrow L^{B}$ \end_inset @@ -10634,7 +10613,7 @@ which has the form \end_inset if we define -\begin_inset Formula $L^{A}\triangleq Z\rightarrow A$ +\begin_inset Formula $L^{B}\triangleq Z\rightarrow B$ \end_inset . diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 50c4ac32e..2d519b1d2 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -1148,7 +1148,7 @@ noprefix "false" \begin_layout Standard This chapter begins the second part of the book, which is devoted to a systemati c analysis of various type constructions that produce data structures with - different properties. + certain useful properties. The first kind of data structure to be analysed is \begin_inset Quotes eld \end_inset @@ -1169,8 +1169,58 @@ wrappers \begin_inset Quotes erd \end_inset - of data. - Those containers should have a + of data; a first example is a sequence type such as Scala's +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Seq[A] +\end_layout + +\end_inset + +. + A typical operation for sequences is a loop over elements of the sequence. + In functional programming, those loops are implemented by the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map +\end_layout + +\end_inset + + method. + Generalizing from +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Seq +\end_layout + +\end_inset + + to an arbitrary container +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +F +\end_layout + +\end_inset + +, we find that the \begin_inset listings inline true status open @@ -1249,8 +1299,15 @@ map \end_inset must obey. - In this way, we arrive at the functor laws: the identity law and the compositio -n law. + In this way, we arrive at the +\begin_inset Quotes eld +\end_inset + +functor laws +\begin_inset Quotes erd +\end_inset + +: the identity law and the composition law. \end_layout \begin_layout Standard @@ -1279,8 +1336,31 @@ yield \end_inset syntax for chains of functor operations. - In later chapters, we will see how this syntax extends to conditionals - and nested loops. + (In later chapters, we will see how the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +for +\end_layout + +\end_inset + +/ +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +yield +\end_layout + +\end_inset + + syntax can also support conditionals and nested loops.) \end_layout \begin_layout Standard @@ -1301,7 +1381,21 @@ contramap \end_inset method can be implemented. - This motivates the concept of a contrafunctor (short for + This motivates the concept of a +\series bold +contrafunctor +\series default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout +contrafunctor +\end_layout + +\end_inset + + (short for \begin_inset Quotes eld \end_inset @@ -1524,7 +1618,7 @@ noprefix "false" \end_layout \begin_layout Standard -This book uses certain non-standard notation to write types and code more +This book uses certain non-standard notations to write types and code more concisely. For instance, type parameters are written as superscripts ( \begin_inset Formula $F^{A}$ @@ -1614,7 +1708,7 @@ noprefix "false" \end_layout \begin_layout Standard -A +The concept of \begin_inset Quotes eld \end_inset @@ -1622,7 +1716,8 @@ typeclass \begin_inset Quotes erd \end_inset - is a mechanism for constraining type parameters in generic functions. + is motivated as a mechanism for constraining type parameters in generic + functions. We show how a typeclass can be implemented by passing evidence values in extra arguments. We show how to define functions whose type parameters are constrained to @@ -2665,16 +2760,17 @@ This chapter studies filterable functors by following a pattern that all \begin_inset space ~ \end_inset -II will also follow. +II also follow. Beginning with working Scala code involving some operation, we formulate - a typeclass whose members support that operation. - Then we motivate and derive the mathematical laws that describe a programmer's - expectations about that operation's behavior. + a typeclass whose member types support that operation. + Then we motivate a programmer's expectations about that operation's behavior, + and derive the corresponding mathematical laws. To make the reasoning easier, we simplify those laws by introducing other, equivalent operations that have simpler laws. We proceed to structural analysis and discover what type constructions can support the given operation and its laws. - As a result, we obtain many examples of types that belong to the typeclass. + As a result, we obtain many examples of types that belong to the typeclass + (as well as examples of types that do not). \end_layout \begin_layout Subsection @@ -2696,15 +2792,14 @@ noprefix "false" \end_layout \begin_layout Standard -The chapter introduces \begin_inset Quotes eld \end_inset -semi-monads +Semi-monads \begin_inset Quotes erd \end_inset - as functors with a + are introduced as functors that support a \begin_inset listings inline true status open @@ -2757,7 +2852,667 @@ map \end_inset functions. - *** + +\end_layout + +\begin_layout Standard +Scala's +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +for +\end_layout + +\end_inset + + / +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +yield +\end_layout + +\end_inset + + syntax (which is itself modeled on a mathematical notation) is equivalent + to nested +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + + calls. + We give examples for using these functions (either directly or via the + +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +for +\end_layout + +\end_inset + + / +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +yield +\end_layout + +\end_inset + + syntax) for implementing various iterative computations with sequences + and other +\begin_inset Quotes eld +\end_inset + +list-like +\begin_inset Quotes erd +\end_inset + + monads such as +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Array +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Set +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Standard +Computations with sequences and other list-like types is the first step + towards generalizing the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + + functions to other data structures. + The next step is to consider +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Option +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Either +\end_layout + +\end_inset + + types (the +\begin_inset Quotes eld +\end_inset + +pass/fail +\begin_inset Quotes erd +\end_inset + + monads). + Computations with those types are also expressible via +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + + calls, and can benefit from using the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +for +\end_layout + +\end_inset + + / +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +yield +\end_layout + +\end_inset + + syntax. +\end_layout + +\begin_layout Standard +We then turn to tree-like monads and show how computations with binary trees + and abstract syntax trees are naturally expressed via a special implementation + of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Standard +Further generalization is motivated by the idea of viewing functions of + type +\begin_inset Formula $A\rightarrow L^{B}$ +\end_inset + + a +\begin_inset Quotes eld +\end_inset + +computation with an +\begin_inset Formula $L$ +\end_inset + +-effect +\begin_inset Quotes erd +\end_inset + +. + By that we mean not a side effect, but any extra computational work that + is done in a function of type +\begin_inset Formula $A\rightarrow L^{B}$ +\end_inset + + other than computing a result value of type +\begin_inset Formula $B$ +\end_inset + +. +\end_layout + +\begin_layout Standard +With this picture in mind, we are able to derive the monad types that represent + certain special computational situations: computing a value while reading + another given value (the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Reader +\end_layout + +\end_inset + + monad); computing a value while writing out another value (the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Writer +\end_layout + +\end_inset + + monad); computing a value while updating another value (the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +State +\end_layout + +\end_inset + + monad); and computing a value but passing it to a given callback function + ( +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Cont +\end_layout + +\end_inset + +, the continuation monad). + Finally, the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Eval +\end_layout + +\end_inset + + monad represents the possibilities of computing a result eagerly or lazily. + We look at code examples to illustrate the practical use of all those well-know +n monads. + +\end_layout + +\begin_layout Standard +Next, we consider the laws that the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + + operation should obey. + To derive those laws, we look at several code patterns that a programmer + would intuitively expect to behave in certain ways. + Each of those code patterns gives rise to a specific law of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + +. + In this way, we derive an associativity law and two naturality laws for + +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + +. + Analogous laws for the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map +\end_layout + +\end_inset + + operation were derived in Chapter +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "chap:Functors,-contrafunctors,-and" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +, where we defined functors as type constructors with a lawful +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map +\end_layout + +\end_inset + + method. + Functors with a lawful +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + + method are +\series bold +semi-monads +\series default +. + In this way, we find that the functor type involved in a +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +for +\end_layout + +\end_inset + + / +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +yield +\end_layout + +\end_inset + + block (in this book, we call them +\series bold +functor blocks +\series default +) must be in general a semi-monad. +\end_layout + +\begin_layout Standard +The three laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + + are equivalent to just two laws if we pass to a simpler function known + in Scala as +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatten +\end_layout + +\end_inset + +. + We derive the laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatten +\end_layout + +\end_inset + + and prove that they are equivalent to the laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + +. + A formal proof of type equivalence between +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatten +\end_layout + +\end_inset + + (Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-flatten-equivalent-to-flatMap" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +) requires assuming one naturality law of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + +. + +\end_layout + +\begin_layout Standard +We show how to verify the associativity law of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatten +\end_layout + +\end_inset + + for the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Either +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Reader +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +List +\end_layout + +\end_inset + +, and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Writer +\end_layout + +\end_inset + + monads. + +\end_layout + +\begin_layout Standard +A full monad has an additional operation called +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + +\end_inset + +. \end_layout \begin_layout Standard From 3e6341610bccf73e9456432a6ca4af9d7d5915e1 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Fri, 24 Oct 2025 11:18:03 +0200 Subject: [PATCH 06/42] finish summary of monad chapter --- sofp-src/lyx/sofp-monads.lyx | 133 ++++++++-- sofp-src/lyx/sofp-summary.lyx | 428 +++++++++++++++++++++++++++++- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-applicative.tex | 5 +- sofp-src/tex/sofp-monads.tex | 96 +++---- sofp-src/tex/sofp-summary.tex | 200 +++++++++++--- sofp-src/tex/sofp.tex | 6 +- 7 files changed, 743 insertions(+), 125 deletions(-) diff --git a/sofp-src/lyx/sofp-monads.lyx b/sofp-src/lyx/sofp-monads.lyx index 35a03cb48..5ff337fd4 100644 --- a/sofp-src/lyx/sofp-monads.lyx +++ b/sofp-src/lyx/sofp-monads.lyx @@ -12349,8 +12349,12 @@ Logs \end_inset - is not a monoid because its binary operation discards some of the input - data, so we cannot define an + is +\emph on +not +\emph default + a monoid because its binary operation discards some of the input data, + so we cannot define an \begin_inset Quotes eld \end_inset @@ -21421,7 +21425,11 @@ empty effect \end_inset , such that merging the empty effect leaves other effects unchanged. - A monad + A +\series bold +monad +\series default + \begin_inset Formula $M$ \end_inset @@ -21509,7 +21517,7 @@ def pure[A](a: A): M[A] \end_layout \begin_layout Standard -To get intuition about the properties of a vaguely defined +To get intuition about the behavior of what we called an \begin_inset Quotes eld \end_inset @@ -21517,7 +21525,7 @@ empty effect \begin_inset Quotes erd \end_inset -, consider nested iteration over arrays. +, consider nested iteration over lists. The \begin_inset Quotes eld \end_inset @@ -21526,33 +21534,35 @@ empty effect \begin_inset Quotes erd \end_inset - is an array containing + should correspond to trivial iterations; that is, an iteration through + a list containing \emph on one \emph default element. - An iteration over such an array will just need to process that single value. - In a functor block using arrays, a source line with an -\begin_inset Quotes eld -\end_inset + +\begin_inset Note Note +status collapsed + +\begin_layout Plain Layout +An iteration over such a list will just need to process that one element. +\end_layout -empty effect -\begin_inset Quotes erd \end_inset - ( + Indeed, in a functor block using lists, a source line \begin_inset listings inline true status open \begin_layout Plain Layout -y <- pure(x) +y <- List(x) \end_layout \end_inset -) will be equivalent to just + is equivalent to just \begin_inset listings inline true status open @@ -21564,10 +21574,27 @@ y = x \end_inset - with no iteration. + with no extra iterations. +\end_layout + +\begin_layout Standard +To understand the properties of empty effects more formally, consider a + functor block with a source line +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +y <- pure(x) +\end_layout + +\end_inset + +. That line may occur either before or after another source line. - So, we need to examine two situations: first, when an empty effect comes - before another source line: + When an empty effect comes before another source line, the code can be + simplified like this: \end_layout \begin_layout Standard @@ -22093,7 +22120,7 @@ noprefix "false" \end_inset ). - So, we could say that a monad is a pointed semi-monad whose + So, a monad is a pointed semi-monad whose \begin_inset listings inline true status open @@ -22209,7 +22236,7 @@ noprefix "false" \end_inset ). - A full monad's + For the same reason, a monad's \begin_inset listings inline true status open @@ -22221,8 +22248,8 @@ pure \end_inset - method must also satisfy that naturality law, in addition to the two identity - laws. + method must also satisfy that naturality law (in addition to the two identity + laws). \end_layout \begin_layout Standard @@ -22263,6 +22290,7 @@ noprefix "false" \end_inset ). + We will see other examples later in this chapter. \end_layout \begin_layout Subsection @@ -22512,6 +22540,13 @@ In the next section, we will give reasons for the names of these laws. \begin_layout Subsection Monad laws in terms of Kleisli functions +\begin_inset CommandInset label +LatexCommand label +name "subsec:Monad-laws-in-Kleisli" + +\end_inset + + \end_layout \begin_layout Standard @@ -23831,6 +23866,13 @@ flatMap \begin_layout Subsection Verifying the monad laws using Kleisli functions +\begin_inset CommandInset label +LatexCommand label +name "subsec:Verifying-the-monad-via-Kleisli-trick" + +\end_inset + + \end_layout \begin_layout Standard @@ -23906,8 +23948,31 @@ flipped Kleisli flipped Kleisli \series default makes direct proofs of laws shorter. - That trick applies to monads of a function type, such as the continuation - and the state monads. + That trick applies to monads of a function type, such as +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Cont +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +State +\end_layout + +\end_inset + +, and some other monads that we will discover later. \end_layout \begin_layout Subsubsection @@ -34047,7 +34112,7 @@ monadic program \begin_inset Formula $A$ \end_inset - and is a result of nested iterations. +. For a pass/fail monad \begin_inset Formula $M$ \end_inset @@ -37376,7 +37441,7 @@ noprefix "false" \end_inset ). - One can also show that + One can show that \begin_inset Formula $F$ \end_inset @@ -37412,12 +37477,22 @@ By the same logic, we can conclude that \end_inset cannot be obtained through monad constructions. - It is likely (although this book does not have a proof) that -\begin_inset Formula $F^{A}\triangleq\bbnum 1+A\times A\times A$ + It is known +\begin_inset Foot +status open + +\begin_layout Plain Layout +Hew Wolff, private communication (2024). +\end_layout + +\end_inset + + that +\begin_inset Formula $F^{A}\triangleq\bbnum 1+A\times A$ \end_inset , -\begin_inset Formula $F^{A}\triangleq\bbnum 1+A\times A\times A\times A$ +\begin_inset Formula $F^{A}\triangleq\bbnum 1+A\times A\times A$ \end_inset , and all other similarly constructed functors are diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 2d519b1d2..28cc357d6 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -2745,7 +2745,7 @@ Kleisli functions \begin_layout Itemize We notice the similarity between the laws of several typeclasses and the standard functor laws, which invites us to take a first glance at category - theory and its more general definition of functors. + theory that provides a more general definition of a functor. We show that the laws of typeclasses can be derived from the laws of categories and of categorical functors. This gives us assurance that the typeclass laws are chosen in a consistent @@ -3500,7 +3500,157 @@ Writer \end_layout \begin_layout Standard -A full monad has an additional operation called +Almost all semi-monads we considered are in fact +\begin_inset Quotes eld +\end_inset + +full monads +\begin_inset Quotes erd +\end_inset + +, as they support an additional operation called +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + +\end_inset + +. + We motivate this operation by considering an +\begin_inset Quotes eld +\end_inset + +empty effect +\begin_inset Quotes erd +\end_inset + +; for instance, an iteration over a list of length +\begin_inset Formula $1$ +\end_inset + +. + Then we derive the laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + +\end_inset + + by looking at how we expect functor block code to behave when using +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + +\end_inset + +. + The laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + +\end_inset + + have a simpler form when written using +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatten +\end_layout + +\end_inset + + instead of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + +. + As we derive those simpler forms, we introduce Kleisli functions (of type + +\begin_inset Formula $A\rightarrow M^{B}$ +\end_inset + +) and the Kleisli composition operation ( +\begin_inset Formula $\diamond_{_{M}}$ +\end_inset + +) for a given monad +\begin_inset Formula $M$ +\end_inset + +. + Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Monad-laws-in-Kleisli" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + derives the laws of the Kleisli composition operation from the laws of + +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatten +\end_layout + +\end_inset + + and also proves a full formal equivalence between the formulations of the + monad operations and laws via Kleisli functions and via \begin_inset listings inline true status open @@ -3510,13 +3660,55 @@ status open pure \end_layout +\end_inset + + / +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatten +\end_layout + \end_inset . \end_layout \begin_layout Standard -The results of structural analysis are shown in Table +Formulating monads via Kleisli functions has certain advantages when verifying + laws of monads involving function types. + Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Verifying-the-monad-via-Kleisli-trick" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + shows how the +\begin_inset Quotes eld +\end_inset + +flipped / curried Kleisli +\begin_inset Quotes erd +\end_inset + + trick makes the proofs of monad laws shorter and clearer for the continuation + monad and the state monad. +\end_layout + +\begin_layout Standard +We pass on to structural analysis of semi-monads and monads. + The resulting type constructions are shown in Table \begin_inset space ~ \end_inset @@ -3531,6 +3723,226 @@ noprefix "false" \end_inset . + Some constructions only give semi-monads, but most create full monads. +\end_layout + +\begin_layout Standard +The chapter concludes by some further theoretical developments: +\end_layout + +\begin_layout Itemize +Monads must be functors: it is impossible to define nontrivial monads that + are contrafunctors. +\end_layout + +\begin_layout Itemize +In this and the previous chapters, we proved the type isomorphisms between + +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +wu +\end_layout + +\end_inset + + (for pointed functors), between +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +liftOpt +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +deflate +\end_layout + +\end_inset + + (for filterable functors), and between +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatten +\end_layout + +\end_inset + + (for semi-monads). + It turns out that all those isomorphisms are special cases of more general + type isomorphisms, known as the Yoneda identities. +\end_layout + +\begin_layout Itemize +For monads that are not containers, a +\begin_inset Quotes eld +\end_inset + +runner +\begin_inset Quotes erd +\end_inset + + is needed to extract result values. + It turns out that +\begin_inset Quotes eld +\end_inset + +runners +\begin_inset Quotes erd +\end_inset + + are functions that need to satisfy certain laws, known as the laws of +\begin_inset Quotes eld +\end_inset + +monad morphisms +\begin_inset Quotes erd +\end_inset + +. +\end_layout + +\begin_layout Itemize +Monad morphisms and their laws are known in category theory; they are the + morphisms in the category of monads. + Monad morphisms are natural transformations between monads that map one + monad's +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatten +\end_layout + +\end_inset + + operations onto the same operations of another monad. + We show some examples to build up intuition about monad morphisms. +\end_layout + +\begin_layout Itemize +Each monad gives rise to a category we denote by +\begin_inset Quotes eld +\end_inset + + +\begin_inset Formula $M$ +\end_inset + +-Kleisli +\begin_inset Quotes erd +\end_inset + +; morphisms in that category are Kleisli functions. +\end_layout + +\begin_layout Itemize +Polynomial functors are sometimes monads (but sometimes not; one example + is +\begin_inset Formula $F^{A}\triangleq\bbnum 1+A\times A\times...\times A$ +\end_inset + +). + We list the known type constructions that build up polynomial monads. +\end_layout + +\begin_layout Itemize +One of the monad constructions involves the notion of an +\begin_inset Formula $M$ +\end_inset + +-filterable contrafunctor. + They can be motivated as generalizations of filterable contrafunctors when + we replace the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Option +\end_layout + +\end_inset + + monad in the type signature of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +filter +\end_layout + +\end_inset + + by an arbitrary monad +\begin_inset Formula $M$ +\end_inset + +. + We show formal definitions of +\begin_inset Formula $M$ +\end_inset + +-filterable functors and contrafunctors, and briefly explore their structural + analysis. \end_layout \begin_layout Subsection @@ -4040,11 +4452,11 @@ Functional programming in Scala \end_inset . - Stack-safe implementations of standard monads have better performance but - are mathematically equivalent to the same monads implemented via simple, - non-stack-safe code. - There is no new theory to be developed and no new laws to be proved about - code that is specially engineered to be stack-safe. + Stack-safe implementations of standard monads are complicated but are mathemati +cally equivalent to the same monads implemented via simple, non-stack-safe + code. + There is no new theory to be found and no new laws to be proved about code + that is specially engineered to be stack-safe. \end_layout \begin_layout Subsection diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 4453040feac9b613d620e6a2bc433d85cb0809a1..ddb2ee3472d8f0ecf40ffe405836a4e4881054fe 100644 GIT binary patch delta 156 zcmX?Ra?E7IY7uTDlMq7#D`QhDW3$QIL<~^)A4Q(ZV$x7;Jtd%Fe`L zWMXJwYzkEWQCten*(@w^jnT=))yc`s(Z$8w+0oL((9PJ=#L>ja)ZE$3$lTb>#oXA= LhLDQM+EUU0Z*nNs delta 156 zcmX?Ra?E7IY7uTj%Mc@DD?=kIQ{&0oL<~^)A4Q(86^RByWBs%Fe`L zXlZ0@XarRMQCten*(@w^jnT>2%*?>a$ (1 to 4).map(i => (1 to i).map(j => i * j)).flatten res1: IndexedSeq[Int] = Vector(1, 2, 4, 3, 6, 9, 4, 8, 12, 16) @@ -1485,22 +1485,23 @@ \subsection{The \texttt{Reader} monad\label{subsec:The-Reader-monad}} with the list-like monads whose \lstinline!flatMap! method is motivated by the requirements of nested iteration. We then looked at tree-like monads whose \lstinline!flatMap! methods work via tree grafting. -It turns out that the \lstinline!flatMap! method can be supported -by many other type constructors useful for various programming tasks -not necessarily related to nested iteration. +It turns out that the \lstinline!flatMap! method is supported by +many other type constructors (not just containers) and may be used +for various programming tasks not necessarily related to nested iteration. A general (semi)monad type constructor $L$ no longer represents a collection of data items. Instead, we regard $L^{A}$ informally as -a value of type $A$ wrapped in a special \textsf{``}computational effect\textsf{''}. -We view \textsf{``}computations with an $L$-effect\textsf{''} as functions of type -$A\rightarrow L^{B}$ (as in \lstinline!flatMap!\textsf{'}s argument type). -In this view, different monads \textemdash{} such as list-like, pass/fail, -or tree-like \textemdash{} implement different kinds of effects. +a value of type $A$ wrapped in type constructor representing a special +\textsf{``}computational effect\textsf{''}. By \textsf{``}computations with an $L$-effect\textsf{''} +we simply mean functions of type $A\rightarrow L^{B}$ (as in \lstinline!flatMap!\textsf{'}s +argument type). In this view, different monads \textemdash{} such +as list-like, pass/fail, or tree-like \textemdash{} implement different +kinds of effects. In this sense, monadic effects are \emph{not} side effects.\index{side effect} Functions of type $A\rightarrow L^{B}$ are referentially transparent\index{referential transparency} and behave as values.\index{value-like behavior} Informally, an \textsf{``}$L$-effect\textsf{''} -describes the information computed by a function of type $A\rightarrow L^{B}$ +describes whatever else is computed by a function of type $A\rightarrow L^{B}$ in addition to a value of type $B$. To make the vague idea of \textsf{``}effect\textsf{''} concrete, we write the required type of the computation in the form $A\rightarrow L^{B}$ with a specific type constructor $L$. In this @@ -1519,7 +1520,7 @@ \subsection{The \texttt{Reader} monad\label{subsec:The-Reader-monad}} \[ (A\times Z\rightarrow B)\cong(A\rightarrow Z\rightarrow B)\quad, \] -which has the form $A\rightarrow L^{B}$ if we define $L^{A}\triangleq Z\rightarrow A$. +which has the form $A\rightarrow L^{B}$ if we define $L^{B}\triangleq Z\rightarrow B$. This type constructor is known as the \lstinline!Reader! monad\index{monads!Reader monad@\texttt{Reader} monad} and is denoted by $\text{Reader}^{Z,A}\triangleq Z\rightarrow A$. The Scala definition is: \lstinline!type Reader[Z, A] = Z => A!. @@ -1765,9 +1766,9 @@ \subsection{The \texttt{Writer} monad} def |+|(other: Logs): Logs = Logs(begin, other.end, message + "\n" + other.message) } // We assume that timestamps will be monotonically increasing. \end{lstlisting} -The type \lstinline!Logs! is not a monoid because its binary operation -discards some of the input data, so we cannot define an \textsf{``}empty\textsf{''} -value satisfying the identity laws (see Eq.~(\ref{eq:identity-laws-of-monoid}) +The type \lstinline!Logs! is \emph{not} a monoid because its binary +operation discards some of the input data, so we cannot define an +\textsf{``}empty\textsf{''} value satisfying the identity laws (see Eq.~(\ref{eq:identity-laws-of-monoid}) in Example~\ref{subsec:tc-Example-Monoids}). We can now use the semi-monad \lstinline!Writer[A, Logs]!. Here is @@ -4855,8 +4856,8 @@ \subsection{From semi-monads to monads: The identity laws} \lstinline!flatMap! method, which will \textsf{``}merge\textsf{''} the effects. It is generally useful to be able to create values with an \textsf{``}empty effect\textsf{''}, such that merging the empty effect leaves other effects unchanged. -A monad $M$ is a semi-monad that has a method for creating values -with an \textsf{``}empty effect\textsf{''}. That method is called \lstinline!pure! +A \textbf{monad} $M$ is a semi-monad that has a method for creating +values with an \textsf{``}empty effect\textsf{''}. That method is called \lstinline!pure! (notation $\text{pu}_{M}$): \begin{wrapfigure}{l}{0.475\columnwidth}% @@ -4872,15 +4873,18 @@ \subsection{From semi-monads to monads: The identity laws} \text{pu}_{M}^{A}:A\rightarrow M^{A}\quad. \] -To get intuition about the properties of a vaguely defined \textsf{``}empty -effect\textsf{''}, consider nested iteration over arrays. The \textsf{``}empty effect\textsf{''} -is an array containing \emph{one} element. An iteration over such -an array will just need to process that single value. In a functor -block using arrays, a source line with an \textsf{``}empty effect\textsf{''} (\lstinline!y <- pure(x)!) -will be equivalent to just \lstinline!y = x! with no iteration. That -line may occur either before or after another source line. So, we -need to examine two situations: first, when an empty effect comes -before another source line: +To get intuition about the behavior of what we called an \textsf{``}empty +effect\textsf{''}, consider nested iteration over lists. The \textsf{``}empty effect\textsf{''} +should correspond to trivial iterations; that is, an iteration through +a list containing \emph{one} element. Indeed, in a functor block +using lists, a source line \lstinline!y <- List(x)! is equivalent +to just \lstinline!y = x! with no extra iterations. + +To understand the properties of empty effects more formally, consider +a functor block with a source line \lstinline!y <- pure(x)!. That +line may occur either before or after another source line. When an +empty effect comes before another source line, the code can be simplified +like this: \noindent \texttt{\textcolor{blue}{\footnotesize{}}}% \begin{minipage}[c]{0.475\columnwidth}% @@ -4973,21 +4977,22 @@ \subsection{From semi-monads to monads: The identity laws} In fact, \lstinline!pure! is the same method as in the \lstinline!Pointed! typeclass (Sections~\ref{subsec:Pointed-functors-motivation-equivalence}\textendash \ref{subsec:Pointed-functors:-structural-analysis}). -So, we could say that a monad is a pointed semi-monad whose \lstinline!pure! -method obeys the two identity laws~(\ref{eq:monad-left-identity-law-for-flatMap})\textendash (\ref{eq:monad-right-identity-law-for-flatMap}). +So, a monad is a pointed semi-monad whose \lstinline!pure! method +obeys the two identity laws~(\ref{eq:monad-left-identity-law-for-flatMap})\textendash (\ref{eq:monad-right-identity-law-for-flatMap}). Although the \lstinline!pure! method can be replaced by a simpler \textsf{``}wrapped unit\textsf{''} value ($\text{wu}_{M}$), derivations are easier when using \lstinline!pure!. The \lstinline!Pointed! typeclass requires the \lstinline!pure! method to satisfy the naturality law~(\ref{eq:naturality-law-of-pure}). -A full monad\textsf{'}s \lstinline!pure! method must also satisfy that naturality -law, in addition to the two identity laws. +For the same reason, a monad\textsf{'}s \lstinline!pure! method must also +satisfy that naturality law (in addition to the two identity laws). Just as some useful semigroups are not monoids, there exist some useful semi-monads that are not full monads. A simple example is the \lstinline!Writer! semi-monad $F^{A}\triangleq A\times W$ whose type $W$ is a semigroup but not a monoid (see Exercise~\ref{subsec:Exercise-semimonad-not-monad}). +We will see other examples later in this chapter. \subsection{The monad identity laws in terms of \texttt{pure} and \texttt{flatten}} @@ -5037,7 +5042,7 @@ \subsection{The monad identity laws in terms of \texttt{pure} and \texttt{flatte In the next section, we will give reasons for the names of these laws. -\subsection{Monad laws in terms of Kleisli functions} +\subsection{Monad laws in terms of Kleisli functions\label{subsec:Monad-laws-in-Kleisli}} A \textbf{Kleisli function}\index{Kleisli!functions|textit} is a function with type signature $A\rightarrow M^{B}$, where $M$ is @@ -5283,7 +5288,7 @@ \subsubsection{Statement \label{subsec:Statement-equivalence-kleisli-laws-and-fl The two naturality laws of \lstinline!flatMap! are equivalent to the three naturality laws of $\diamond_{_{M}}$. We omit those derivations. -\subsection{Verifying the monad laws using Kleisli functions} +\subsection{Verifying the monad laws using Kleisli functions\label{subsec:Verifying-the-monad-via-Kleisli-trick}} When the monad laws are formulated via Kleisli composition, the intuition behind the laws becomes clearer: they are analogous to the identity @@ -5294,8 +5299,8 @@ \subsection{Verifying the monad laws using Kleisli functions} for \lstinline!flatten! has only one. For certain monads, however, a trick called \index{flipped@\textsf{``}flipped Kleisli\textsf{''} technique|textit}\textbf{flipped Kleisli} makes direct proofs of laws shorter. That trick applies to -monads of a function type, such as the continuation and the state -monads. +monads of a function type, such as \lstinline!Cont!, \lstinline!State!, +and some other monads that we will discover later. \subsubsection{Statement \label{subsec:Statement-continuation-monad-is-lawful}\ref{subsec:Statement-continuation-monad-is-lawful}} @@ -7189,12 +7194,12 @@ \subsection{Monads, effects, and runners} Monads allow us to compose \textsf{``}monadic programs\index{monadic program}\textsf{''} (i.e., values of type $M^{A}$ for some monad $M$). For list-like and tree-like monads $M$, a value of type $M^{A}$ represents a collection -of values of type $A$ and is a result of nested iterations. For a -pass/fail monad $M$, a value of type $M^{A}$ holds either a result -of type $A$ or information about a failure. For other monads $M$, -a monadic program $m:M^{A}$ represents a single value of type $A$ -wrapped by an \textsf{``}effectful wrapper\textsf{''} of some sort. In an application, -we usually need to extract that value of type $A$ from the \textsf{``}wrapper\textsf{''}. +of values of type $A$. For a pass/fail monad $M$, a value of type +$M^{A}$ holds either a result of type $A$ or information about a +failure. For other monads $M$, a monadic program $m:M^{A}$ represents +a single value of type $A$ wrapped by an \textsf{``}effectful wrapper\textsf{''} +of some sort. In an application, we usually need to extract that value +of type $A$ from the \textsf{``}wrapper\textsf{''}. To see how this works, consider monads of function type (such as \lstinline!Reader!, \lstinline!State!, and \lstinline!Cont!). These monads delay their @@ -7786,7 +7791,7 @@ \subsection{Constructions of polynomial monads\label{subsec:Constructions-of-pol As an example, consider t the polynomial functor $F^{A}\triangleq\bbnum 1+A\times A$ that \emph{cannot} be made into a monad (Exercise~\ref{subsec:Exercise-1-monads-6}). -One can also show that $F$ cannot be obtained through the monad constructions +One can show that $F$ cannot be obtained through the monad constructions listed above. Indeed, the corresponding polynomial $f(x)=1+x^{2}$ does not contain any first powers of $x$. However, all constructions either start with a polynomial containing $x$, or add $x$, or take @@ -7795,10 +7800,9 @@ \subsection{Constructions of polynomial monads\label{subsec:Constructions-of-pol be subtracted to zero. By the same logic, we can conclude that $F^{A}\triangleq\bbnum 1+A\times A\times A$ -cannot be obtained through monad constructions. It is likely (although -this book does not have a proof) that $F^{A}\triangleq\bbnum 1+A\times A\times A$, -$F^{A}\triangleq\bbnum 1+A\times A\times A\times A$, and all other -similarly constructed functors are \emph{not} monads. +cannot be obtained through monad constructions. It is known\footnote{Hew Wolff, private communication (2024).} +that $F^{A}\triangleq\bbnum 1+A\times A$, $F^{A}\triangleq\bbnum 1+A\times A\times A$, +and all other similarly constructed functors are \emph{not} monads. On the other hand, some polynomial functors can be obtained via the monad constructions in more than one way. A simple example is: diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index 05c2b032d..1a65c2cb1 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -12,7 +12,7 @@ \chapter{Summary of the book\label{chap:Summary-of-the}} detailed explanations or proofs, referring to the places of the book where more detail is found. -\section{Main points and results by chapter} +\section{Main ideas and results by chapter} \setcounter{secnumdepth}{1}% \begin{comment} @@ -177,26 +177,30 @@ \subsection{Chapter~\ref{chap:Functors,-contrafunctors,-and}} This chapter begins the second part of the book, which is devoted to a systematic analysis of various type constructions that produce -data structures with different properties. The first kind of data -structure to be analysed is \textsf{``}functors\textsf{''}. +data structures with certain useful properties. The first kind of +data structure to be analysed is \textsf{``}functors\textsf{''}. We begin with a motivation for functors as containers or \textsf{``}wrappers\textsf{''} -of data. Those containers should have a \lstinline!map! method that -\textsf{``}lifts\textsf{''} functions of type \lstinline!A => B! into functions of -type \lstinline!F[A] => F[B]!. We examine a programmer\textsf{'}s expectations -for the behavior of the \lstinline!map! method for typical containers. -Those expectations are formulated as mathematical equations (or \textsf{``}laws\textsf{''}) -that an implementation of \lstinline!map! must obey. In this way, -we arrive at the functor laws: the identity law and the composition -law. +of data; a first example is a sequence type such as Scala\textsf{'}s \lstinline!Seq[A]!. +A typical operation for sequences is a loop over elements of the sequence. +In functional programming, those loops are implemented by the \lstinline!map! +method. Generalizing from \lstinline!Seq! to an arbitrary container +\lstinline!F!, we find that the \lstinline!map! method that \textsf{``}lifts\textsf{''} +functions of type \lstinline!A => B! into functions of type \lstinline!F[A] => F[B]!. +We examine a programmer\textsf{'}s expectations for the behavior of the \lstinline!map! +method for typical containers. Those expectations are formulated as +mathematical equations (or \textsf{``}laws\textsf{''}) that an implementation of \lstinline!map! +must obey. In this way, we arrive at the \textsf{``}functor laws\textsf{''}: the identity +law and the composition law. Scala supports a special \lstinline!for!/\lstinline!yield! syntax -for chains of functor operations. In later chapters, we will see how -this syntax extends to conditionals and nested loops. +for chains of functor operations. (In later chapters, we will see +how the \lstinline!for!/\lstinline!yield! syntax can also support +conditionals and nested loops.) Looking at examples of some type constructors that \emph{cannot} have the map method, we find that in certain cases a \lstinline!contramap! -method can be implemented. This motivates the concept of a contrafunctor +method can be implemented. This motivates the concept of a \textbf{contrafunctor}\index{contrafunctor} (short for \textsf{``}contravariant functor\textsf{''}). We show examples where we implement the \lstinline!map! or the \lstinline!contramap! method for different type constructors. @@ -234,7 +238,7 @@ \subsection{Chapter~\ref{chap:Functors,-contrafunctors,-and}} \subsection{Chapter~\ref{chap:Reasoning-about-code}} -This book uses certain non-standard notation to write types and code +This book uses certain non-standard notations to write types and code more concisely. For instance, type parameters are written as superscripts ($F^{A}$ corresponds to the Scala syntax \lstinline!F[A]!). Functions lifted via \lstinline!fmap! are denoted by arrows such as $f^{\uparrow F}$. @@ -254,12 +258,12 @@ \subsection{Chapter~\ref{chap:Reasoning-about-code}} \subsection{Chapter~\ref{chap:Typeclasses-and-functions}} -A \textsf{``}typeclass\textsf{''} is a mechanism for constraining type parameters -in generic functions. We show how a typeclass can be implemented by -passing evidence values in extra arguments. We show how to define -functions whose type parameters are constrained to belong to specific -typeclasses. While the function body is able to use the typeclass -methods, the types remain arbitrary and unspecified. +The concept of \textsf{``}typeclass\textsf{''} is motivated as a mechanism for constraining +type parameters in generic functions. We show how a typeclass can +be implemented by passing evidence values in extra arguments. We show +how to define functions whose type parameters are constrained to belong +to specific typeclasses. While the function body is able to use the +typeclass methods, the types remain arbitrary and unspecified. The verbosity of this implementation is reduced if one employs Scala\textsf{'}s \textsf{``}implicit argument\textsf{''} feature. Another Scala feature is the \textsf{``}extension @@ -377,29 +381,151 @@ \subsection{Chapter~\ref{chap:Filterable-functors}} functors to $M$-filterable functors (where $M$ is any monad). \item We notice the similarity between the laws of several typeclasses and the standard functor laws, which invites us to take a first glance -at category theory and its more general definition of functors. We -show that the laws of typeclasses can be derived from the laws of -categories and of categorical functors. This gives us assurance that -the typeclass laws are chosen in a consistent and useful way. We finish -with a summary of issues for which category theory has been either -helpful or not helpful in the context of functional programming. +at category theory that provides a more general definition of a functor. +We show that the laws of typeclasses can be derived from the laws +of categories and of categorical functors. This gives us assurance +that the typeclass laws are chosen in a consistent and useful way. +We finish with a summary of issues for which category theory has been +either helpful or not helpful in the context of functional programming. \end{itemize} This chapter studies filterable functors by following a pattern that -all further chapters in Part~II will also follow. Beginning with -working Scala code involving some operation, we formulate a typeclass -whose members support that operation. Then we motivate and derive -the mathematical laws that describe a programmer\textsf{'}s expectations about -that operation\textsf{'}s behavior. To make the reasoning easier, we simplify -those laws by introducing other, equivalent operations that have simpler +all further chapters in Part~II also follow. Beginning with working +Scala code involving some operation, we formulate a typeclass whose +member types support that operation. Then we motivate a programmer\textsf{'}s +expectations about that operation\textsf{'}s behavior, and derive the corresponding +mathematical laws. To make the reasoning easier, we simplify those +laws by introducing other, equivalent operations that have simpler laws. We proceed to structural analysis and discover what type constructions can support the given operation and its laws. As a result, we obtain -many examples of types that belong to the typeclass. +many examples of types that belong to the typeclass (as well as examples +of types that do not). \subsection{Chapter~\ref{chap:Semimonads-and-monads}} -{*}{*}{*} - -The results of structural analysis are shown in Table~\ref{tab:Constructions-of-monads}. +\textsf{``}Semi-monads\textsf{''} are introduced as functors that support a \lstinline!flatMap! +method. This is motivated by considering how functional programming +can represent nested loops. Simple loops are translated into an application +of a \lstinline!map! function to sequences; similarly, nested loops +are translated into applications of \lstinline!flatMap! and \lstinline!map! +functions. + +Scala\textsf{'}s \lstinline!for! / \lstinline!yield! syntax (which is itself +modeled on a mathematical notation) is equivalent to nested \lstinline!map! +and \lstinline!flatMap! calls. We give examples for using these functions +(either directly or via the \lstinline!for! / \lstinline!yield! +syntax) for implementing various iterative computations with sequences +and other \textsf{``}list-like\textsf{''} monads such as \lstinline!Array! and \lstinline!Set!. + +Computations with sequences and other list-like types is the first +step towards generalizing the \lstinline!map! and \lstinline!flatMap! +functions to other data structures. The next step is to consider \lstinline!Option! +and \lstinline!Either! types (the \textsf{``}pass/fail\textsf{''} monads). Computations +with those types are also expressible via \lstinline!map! and \lstinline!flatMap! +calls, and can benefit from using the \lstinline!for! / \lstinline!yield! +syntax. + +We then turn to tree-like monads and show how computations with binary +trees and abstract syntax trees are naturally expressed via a special +implementation of \lstinline!flatMap!. + +Further generalization is motivated by the idea of viewing functions +of type $A\rightarrow L^{B}$ a \textsf{``}computation with an $L$-effect\textsf{''}. +By that we mean not a side effect, but any extra computational work +that is done in a function of type $A\rightarrow L^{B}$ other than +computing a result value of type $B$. + +With this picture in mind, we are able to derive the monad types that +represent certain special computational situations: computing a value +while reading another given value (the \lstinline!Reader! monad); +computing a value while writing out another value (the \lstinline!Writer! +monad); computing a value while updating another value (the \lstinline!State! +monad); and computing a value but passing it to a given callback function +(\lstinline!Cont!, the continuation monad). Finally, the \lstinline!Eval! +monad represents the possibilities of computing a result eagerly or +lazily. We look at code examples to illustrate the practical use of +all those well-known monads. + +Next, we consider the laws that the \lstinline!flatMap! operation +should obey. To derive those laws, we look at several code patterns +that a programmer would intuitively expect to behave in certain ways. +Each of those code patterns gives rise to a specific law of \lstinline!flatMap!. +In this way, we derive an associativity law and two naturality laws +for \lstinline!flatMap!. Analogous laws for the \lstinline!map! +operation were derived in Chapter~\ref{chap:Functors,-contrafunctors,-and}, +where we defined functors as type constructors with a lawful \lstinline!map! +method. Functors with a lawful \lstinline!flatMap! method are \textbf{semi-monads}. +In this way, we find that the functor type involved in a \lstinline!for! +/ \lstinline!yield! block (in this book, we call them \textbf{functor +blocks}) must be in general a semi-monad. + +The three laws of \lstinline!flatMap! are equivalent to just two +laws if we pass to a simpler function known in Scala as \lstinline!flatten!. +We derive the laws of \lstinline!flatten! and prove that they are +equivalent to the laws of \lstinline!flatMap!. A formal proof of +type equivalence between \lstinline!flatMap! and \lstinline!flatten! +(Statement~\ref{subsec:Statement-flatten-equivalent-to-flatMap}) +requires assuming one naturality law of \lstinline!flatMap!. + +We show how to verify the associativity law of \lstinline!flatten! +for the \lstinline!Either!, \lstinline!Reader!, \lstinline!List!, +and \lstinline!Writer! monads. + +Almost all semi-monads we considered are in fact \textsf{``}full monads\textsf{''}, +as they support an additional operation called \lstinline!pure!. +We motivate this operation by considering an \textsf{``}empty effect\textsf{''}; for +instance, an iteration over a list of length $1$. Then we derive +the laws of \lstinline!pure! by looking at how we expect functor +block code to behave when using \lstinline!pure!. The laws of \lstinline!pure! +have a simpler form when written using \lstinline!flatten! instead +of \lstinline!flatMap!. As we derive those simpler forms, we introduce +Kleisli functions (of type $A\rightarrow M^{B}$) and the Kleisli +composition operation ($\diamond_{_{M}}$) for a given monad $M$. +Section~\ref{subsec:Monad-laws-in-Kleisli} derives the laws of the +Kleisli composition operation from the laws of \lstinline!pure! and +\lstinline!flatten! and also proves a full formal equivalence between +the formulations of the monad operations and laws via Kleisli functions +and via \lstinline!pure! / \lstinline!flatten!. + +Formulating monads via Kleisli functions has certain advantages when +verifying laws of monads involving function types. Section~\ref{subsec:Verifying-the-monad-via-Kleisli-trick} +shows how the \textsf{``}flipped / curried Kleisli\textsf{''} trick makes the proofs +of monad laws shorter and clearer for the continuation monad and the +state monad. + +We pass on to structural analysis of semi-monads and monads. The resulting +type constructions are shown in Table~\ref{tab:Constructions-of-monads}. +Some constructions only give semi-monads, but most create full monads. + +The chapter concludes by some further theoretical developments: +\begin{itemize} +\item Monads must be functors: it is impossible to define nontrivial monads +that are contrafunctors. +\item In this and the previous chapters, we proved the type isomorphisms +between \lstinline!pure! and \lstinline!wu! (for pointed functors), +between \lstinline!liftOpt! and \lstinline!deflate! (for filterable +functors), and between \lstinline!flatMap! and \lstinline!flatten! +(for semi-monads). It turns out that all those isomorphisms are special +cases of more general type isomorphisms, known as the Yoneda identities. +\item For monads that are not containers, a \textsf{``}runner\textsf{''} is needed to extract +result values. It turns out that \textsf{``}runners\textsf{''} are functions that +need to satisfy certain laws, known as the laws of \textsf{``}monad morphisms\textsf{''}. +\item Monad morphisms and their laws are known in category theory; they +are the morphisms in the category of monads. Monad morphisms are natural +transformations between monads that map one monad\textsf{'}s \lstinline!pure! +and \lstinline!flatten! operations onto the same operations of another +monad. We show some examples to build up intuition about monad morphisms. +\item Each monad gives rise to a category we denote by \textsf{``}$M$-Kleisli\textsf{''}; +morphisms in that category are Kleisli functions. +\item Polynomial functors are sometimes monads (but sometimes not; one example +is $F^{A}\triangleq\bbnum 1+A\times A\times...\times A$). We list +the known type constructions that build up polynomial monads. +\item One of the monad constructions involves the notion of an $M$-filterable +contrafunctor. They can be motivated as generalizations of filterable +contrafunctors when we replace the \lstinline!Option! monad in the +type signature of \lstinline!filter! by an arbitrary monad $M$. +We show formal definitions of $M$-filterable functors and contrafunctors, +and briefly explore their structural analysis. +\end{itemize} \subsection{Chapter~\ref{chap:8-Applicative-functors,-contrafunctors}} diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index a8abb45a1..8907a8c0e 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): 5c9e7771f1fcf498d0544f4be34d8efcab688f18ee3fe969b583a1010d3562c3}\\ -{\scriptsize{}Git commit: cc66740f02415636e8207dd0f7cfee055cbdaf0d}\\ -{\scriptsize{}PDF file built on Sun, 19 Oct 2025 23:13:10 +0200 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): d8c68554f73306a1f23c556ebf530af3a6b78944ab5470dbc737ecc53dee5bb8}\\ +{\scriptsize{}Git commit: 6c0cc7644fe0ea80b2ddcfb05417e57ef1337d92}\\ +{\scriptsize{}PDF file built on Fri, 24 Oct 2025 10:35:54 +0200 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From e2c74870c3682c198d79d61fdded40ba63834a9d Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Fri, 24 Oct 2025 16:01:16 +0200 Subject: [PATCH 07/42] wip overview of applicative chapter --- sofp-src/lyx/sofp-applicative.lyx | 13 +- sofp-src/lyx/sofp-summary.lyx | 300 +++++++++++++++++++++++++++++- sofp-src/lyx/sofp-traversable.lyx | 2 +- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-applicative.tex | 8 +- sofp-src/tex/sofp-summary.tex | 38 +++- sofp-src/tex/sofp.tex | 6 +- 7 files changed, 349 insertions(+), 18 deletions(-) diff --git a/sofp-src/lyx/sofp-applicative.lyx b/sofp-src/lyx/sofp-applicative.lyx index 8142ed9b4..7630ab0a7 100644 --- a/sofp-src/lyx/sofp-applicative.lyx +++ b/sofp-src/lyx/sofp-applicative.lyx @@ -6339,7 +6339,7 @@ zipFold \end_inset - (shown above) follows unambiguously from its type signature. + can be derived unambiguously from its type signature. So, let us use the \begin_inset Index idx status open @@ -6386,7 +6386,7 @@ literal "false" \end_inset - to generate the code automatically: + to generate the code automatically (equivalent code is shown above): \begin_inset listings inline false status open @@ -8336,7 +8336,7 @@ combinators \end_layout \begin_layout Standard -We will apply these parsing techniques to some toy +We will now apply these parsing techniques to some toy \begin_inset Quotes eld \end_inset @@ -9744,6 +9744,13 @@ e, monoidal, and other functionality for building up large parsers from \begin_layout Subsection Functor block syntax for applicative functors +\begin_inset CommandInset label +LatexCommand label +name "subsec:Functor-block-syntax-for-applicative" + +\end_inset + + \end_layout \begin_layout Standard diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 28cc357d6..f7ad4cbed 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -3963,6 +3963,302 @@ noprefix "false" \end_layout +\begin_layout Standard +We begin by looking at the familiar +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + operation for sequences (which are functors). + It turns out that +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + can be generalized to work with many other types. + Type constructors that support a +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + method satisfying suitable laws are called +\begin_inset Quotes eld +\end_inset + +applicative +\begin_inset Quotes erd +\end_inset + +. + This chapter will develop a rigorous description of applicative functors, + contrafunctors, and profunctors. + +\end_layout + +\begin_layout Standard +We begin with examples of practical use of the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + method, showing how +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + can be used to combine polynomial data types, binary trees, and even some + non-covariant type constructors. + Other uses of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + include gathering multiple errors while validating data; performing multiple + computations in parallel; and transposing matrices. + We arrive at an intuition that applicative functors express combination + of effects that are independent of previously computed values. + For that reason, effects can be sometimes evaluated and combined in parallel. + The condition for that is called +\begin_inset Quotes eld +\end_inset + +commutativity +\begin_inset Quotes erd +\end_inset + + of applicative functors. + This property will be formally defined and studied later in this chapter. +\end_layout + +\begin_layout Standard +Another practically useful function is +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map2 +\end_layout + +\end_inset + +. + We show that +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map2 +\end_layout + +\end_inset + + can be expressed via +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + +, and that analogous methods +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map3 +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map4 +\end_layout + +\end_inset + +, etc., may be defined via +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip3 +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip4 +\end_layout + +\end_inset + +, etc. + We can avoid having to implement all those functions via boilerplate code + if we instead implement a method known as +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +ap +\end_layout + +\end_inset + +. + However, this trick works only for covariant functors. + Non-covariant functors must define methods such as +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +xmap2 +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +xmap3 +\end_layout + +\end_inset + +, etc., separately. +\end_layout + +\begin_layout Standard +Other applications of applicative functors are the applicative +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Reader +\end_layout + +\end_inset + + functor; +\begin_inset Quotes eld +\end_inset + +fusion +\begin_inset Quotes erd +\end_inset + + of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +fold +\end_layout + +\end_inset + +-like operations into single traversals; and parsing via parsing combinators. + To build up intuition, we show code that contrasts the applicative and + the monadic approaches to fold fusion and to parsing. +\end_layout + +\begin_layout Standard +We show how to use applicative operations in functor blocks. + Scala does not have a widely accepted special syntax for applicative functor + blocks, although some proposals exist (Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Functor-block-syntax-for-applicative" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). +\end_layout + \begin_layout Standard ***The results for applicative functors are shown in Table \begin_inset space ~ @@ -4550,7 +4846,7 @@ status open \begin_layout Plain Layout -Filterable +Monad \end_layout \end_inset @@ -4562,7 +4858,7 @@ status open \begin_layout Plain Layout -Monad +Filterable \end_layout \end_inset diff --git a/sofp-src/lyx/sofp-traversable.lyx b/sofp-src/lyx/sofp-traversable.lyx index dcb58bd2f..35293f4e2 100644 --- a/sofp-src/lyx/sofp-traversable.lyx +++ b/sofp-src/lyx/sofp-traversable.lyx @@ -445,7 +445,7 @@ traversable functors \end_inset . - In this way, we will complete a theoretical study of the + In this way, we complete a theoretical study of the \begin_inset listings inline true status open diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index ddb2ee3472d8f0ecf40ffe405836a4e4881054fe..16ce4faecaa3ff0d6fb1fa288e32464fe069a4b3 100644 GIT binary patch delta 142 zcmX?Ra?E7IdJ%S0D^p`DBjd^2L`>l9k0MWaO_NLvOp;SfbW<(TQZ_#ll9k0MWa)6C3L(~>PsbyF=;3^qR!121!, \lstinline!10000!, and \lstinline!123!. diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index 1a65c2cb1..54ee9d51a 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -529,6 +529,34 @@ \subsection{Chapter~\ref{chap:Semimonads-and-monads}} \subsection{Chapter~\ref{chap:8-Applicative-functors,-contrafunctors}} +We begin by looking at the familiar \lstinline!zip! operation for +sequences (which are functors). It turns out that \lstinline!zip! +can be generalized to work with many other types. Type constructors +that support a \lstinline!zip! method satisfying suitable laws are +called \textsf{``}applicative\textsf{''}. This chapter will develop a rigorous description +of applicative functors, contrafunctors, and profunctors. + +We begin with examples of practical use of the \lstinline!zip! method, +showing how \lstinline!zip! can be used to combine polynomial data +types, binary trees, and even some non-covariant type constructors. +Other uses of \lstinline!zip! include gathering multiple errors while +validating data; performing multiple computations in parallel; and +transposing matrices. We arrive at an intuition that applicative functors +express combination of effects that are independent of previously +computed values. For that reason, effects can be sometimes evaluated +and combined in parallel. The condition for that is called \textsf{``}commutativity\textsf{''} +of applicative functors. + +Another practically useful function is \lstinline!map2!. We show +that \lstinline!map2! can be expressed via \lstinline!zip!, and +that analogous methods \lstinline!map3!, \lstinline!map4!, etc., +may be defined via \lstinline!zip3!, \lstinline!zip4!, etc. We can +avoid having to implement all those functions via boilerplate code +if we instead implement a method known as \lstinline!ap!. However, +this trick works only for covariant functors. Non-covariant functors +must define methods such as \lstinline!xmap2!, \lstinline!xmap3!, +etc., separately. + {*}{*}{*}The results for applicative functors are shown in Table~\ref{tab:Constructions-of-applicative-functors}, for applicative contrafunctors in Table~\ref{tab:Constructions-of-applicative-contrafunctors}, and for applicative profunctors in Table~\ref{tab:Constructions-of-applicative-profunctors}. @@ -609,10 +637,10 @@ \subsection{Trampolines and stack-safe recursion in functor blocks} Despite the practical significance of those techniques, this book does not discuss them in detail. Trampolines are already well described in the book \textsf{``}Functional programming in Scala\textsf{''}. Stack-safe implementations -of standard monads have better performance but are mathematically -equivalent to the same monads implemented via simple, non-stack-safe -code. There is no new theory to be developed and no new laws to be -proved about code that is specially engineered to be stack-safe. +of standard monads are complicated but are mathematically equivalent +to the same monads implemented via simple, non-stack-safe code. There +is no new theory to be found and no new laws to be proved about code +that is specially engineered to be stack-safe. \subsection{Strictness and laziness} @@ -635,7 +663,7 @@ \subsection{Combined typeclasses and their laws} Sequences and trees are perhaps the most frequently used data structures. Those data structures have at once the properties of several typeclasses: -\lstinline!Functor!, \lstinline!Filterable!, \lstinline!Monad!, +\lstinline!Functor!, \lstinline!Monad!, \lstinline!Filterable!, \lstinline!Applicative!, and \lstinline!Traversable!. It turns out that the methods of various typeclasses satisfy not only the laws of their own typeclass but also additional laws that express a kind diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 8907a8c0e..e96b1792b 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): d8c68554f73306a1f23c556ebf530af3a6b78944ab5470dbc737ecc53dee5bb8}\\ -{\scriptsize{}Git commit: 6c0cc7644fe0ea80b2ddcfb05417e57ef1337d92}\\ -{\scriptsize{}PDF file built on Fri, 24 Oct 2025 10:35:54 +0200 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 6b57a6cd325e85a693ebd3527731d8de56c7901caeca6e1e8c8dcaa58f39d97f}\\ +{\scriptsize{}Git commit: 3e6341610bccf73e9456432a6ca4af9d7d5915e1}\\ +{\scriptsize{}PDF file built on Fri, 24 Oct 2025 15:53:41 +0200 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From a62d9e04bd382238123f5eebcac355e113966af3 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Fri, 24 Oct 2025 16:45:18 +0200 Subject: [PATCH 08/42] overview of the applicative chapter --- sofp-src/lyx/sofp-applicative.lyx | 8 +- sofp-src/lyx/sofp-summary.lyx | 426 +++++++++++++++++++++++++++++- 2 files changed, 425 insertions(+), 9 deletions(-) diff --git a/sofp-src/lyx/sofp-applicative.lyx b/sofp-src/lyx/sofp-applicative.lyx index 7630ab0a7..d5bef3d20 100644 --- a/sofp-src/lyx/sofp-applicative.lyx +++ b/sofp-src/lyx/sofp-applicative.lyx @@ -33205,14 +33205,14 @@ comonad \begin_layout Plain Layout Some typeclasses that follow the functorial pattern. -\end_layout +\begin_inset CommandInset label +LatexCommand label +name "tab:functorial-typeclasses" \end_inset -\begin_inset CommandInset label -LatexCommand label -name "tab:functorial-typeclasses" +\end_layout \end_inset diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index f7ad4cbed..87f972c5a 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -4202,7 +4202,7 @@ xmap3 \end_layout \begin_layout Standard -Other applications of applicative functors are the applicative +We show further use cases for applicative functors: the applicative \begin_inset listings inline true status open @@ -4236,13 +4236,25 @@ fold -like operations into single traversals; and parsing via parsing combinators. To build up intuition, we show code that contrasts the applicative and - the monadic approaches to fold fusion and to parsing. + the monadic approaches to fold fusion and to parsing combinators. \end_layout \begin_layout Standard -We show how to use applicative operations in functor blocks. +Applicative operations may be used in functor blocks as explicit +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + operations. Scala does not have a widely accepted special syntax for applicative functor - blocks, although some proposals exist (Section + blocks, although some experimental proposals exist (Section \begin_inset space ~ \end_inset @@ -4260,7 +4272,188 @@ noprefix "false" \end_layout \begin_layout Standard -***The results for applicative functors are shown in Table +We turn to the derivation of the laws for +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + +. + First, we show that the methods +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +ap +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map2 +\end_layout + +\end_inset + +, and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + are equivalent as types if we assume suitable naturality laws. + We prefer to define the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Zippable +\end_layout + +\end_inset + + typeclass via the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + method, for the reason that the same typeclass will be usable with non-covarian +t functors. +\end_layout + +\begin_layout Standard +The laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map2 +\end_layout + +\end_inset + + follow from the monad laws if we implement +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map2 +\end_layout + +\end_inset + + through +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + +. + Of course, applicative functors do not necessary have +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + +; but this derivation allows us to motivate a reasonable set of laws for + +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map2 +\end_layout + +\end_inset + +. + These are the associativity law and the two identity laws. + We then derive the corresponding laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Standard +We formally define the property of commutativity for applicative functors + and show how it simplifies the other laws. + Most applicative functors used in practice are commutative and are suitable + for parallel evaluation. + +\end_layout + +\begin_layout Standard +Having derived the laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + +, the next step is to perform structural analysis and to discover type construct +ions that create new applicative type constructors. + The results for applicative functors are shown in Table \begin_inset space ~ \end_inset @@ -4303,6 +4496,229 @@ noprefix "false" \end_inset . + +\end_layout + +\begin_layout Standard +Usually, there will be several inequivalent but lawful implementations for + the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + method; so, the applicative typeclass instances are not unique. + Another consequence of structural analysis is that all exponential-polynomial + +\emph on +contravariant +\emph default + functors are applicative. + It is perhaps surprizing that a lawful +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + method can be defined for a wide range of profunctors that are neither + covariant nor contravariant. + One practical use case for this property is shown in Example +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-applicative-profunctor" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +. +\end_layout + +\begin_layout Standard +Further theoretical developments at the end of this chapter include: +\end_layout + +\begin_layout Itemize +We have previously seen several examples of methods that are equivalent + as types: +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatten +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map2 +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + +, and so on. + Now we clarify and formulate rigorously what it means that two typeclass + methods are +\begin_inset Quotes eld +\end_inset + +isomorphic as types assuming some laws hold +\begin_inset Quotes erd +\end_inset + +. +\end_layout + +\begin_layout Itemize +All monads are applicative at least in one way (but not all applicative + functors are monads). + In many cases, the applicative instance derived from the monad instance + is not as useful in applications as a different, inequivalent applicative + instance for the same type constructor. + We show some examples illustrating this. +\end_layout + +\begin_layout Itemize +We motivate and define the concept of +\begin_inset Quotes eld +\end_inset + +applicative morphism +\begin_inset Quotes erd +\end_inset + +: a mapping between two applicative functors that preserves the applicative + methods. +\end_layout + +\begin_layout Itemize +The laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +ap +\end_layout + +\end_inset + + are easier to derive if we get some help from category theory. + For an applicative functor +\begin_inset Formula $L$ +\end_inset + +, we define the +\begin_inset Quotes eld +\end_inset + + +\begin_inset Formula $L$ +\end_inset + +-ap +\begin_inset Quotes erd +\end_inset + + category whose morphisms have type +\begin_inset Formula $L^{A\rightarrow B}$ +\end_inset + + and are composed using the special operation ( +\begin_inset Formula $\odot$ +\end_inset + +). + In this formulation, the laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +ap +\end_layout + +\end_inset + + follow from the category laws of +\begin_inset Formula $L$ +\end_inset + +-ap. +\end_layout + +\begin_layout Itemize +We look back on various typeclass methods and laws defined in this and the + previous chapter, and generalize the patterns we find (see Table +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:functorial-typeclasses" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). + The laws of each typeclass are equivalent to the standard laws of a certain + categorical functor defined in a suitable way for that typeclass. + This provides a general and abstract picture justifying the choice of typeclass + laws in those cases. \end_layout \begin_layout Subsection From abf57a040d32bd5ee24e168d6b375a55f92424f2 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Fri, 24 Oct 2025 23:10:05 +0200 Subject: [PATCH 09/42] summary for traversable chapter --- sofp-src/lyx/sofp-summary.lyx | 876 +++++++++++++++++++++++++++++- sofp-src/lyx/sofp-traversable.lyx | 34 +- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-applicative.tex | 5 +- sofp-src/tex/sofp-summary.tex | 77 ++- sofp-src/tex/sofp-traversable.tex | 4 +- sofp-src/tex/sofp.tex | 6 +- 7 files changed, 977 insertions(+), 25 deletions(-) diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 87f972c5a..2b1b6ff2c 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -4699,8 +4699,9 @@ ap \end_layout \begin_layout Itemize -We look back on various typeclass methods and laws defined in this and the - previous chapter, and generalize the patterns we find (see Table +We summarize various typeclass methods and laws defined in this and the + previous chapter and examine the patterns in their type signatures (see + Table \begin_inset space ~ \end_inset @@ -4715,10 +4716,11 @@ noprefix "false" \end_inset ). - The laws of each typeclass are equivalent to the standard laws of a certain - categorical functor defined in a suitable way for that typeclass. + It turns out that the laws of each typeclass are equivalent to the standard + functor laws, if we consider a certain categorical functor defined in a + suitable way for that typeclass. This provides a general and abstract picture justifying the choice of typeclass - laws in those cases. + laws. \end_layout \begin_layout Subsection @@ -4740,7 +4742,869 @@ noprefix "false" \end_layout \begin_layout Standard -*** +We begin by considering the standard +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +reduce +\end_layout + +\end_inset + + method for sequences. + Traversable functors are found by a generalization that we motivate in + several steps. + As a first step, we pass from +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +reduce +\end_layout + +\end_inset + + to +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +foldMap +\end_layout + +\end_inset + +, which is parameterized by an arbitrary monoid +\begin_inset Formula $M$ +\end_inset + +. + The next step generalizes from sequences to functors that support an analogous + +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +foldMap +\end_layout + +\end_inset + + method. + The final step is to replace the monoid +\begin_inset Formula $M$ +\end_inset + + by an arbitrary applicative functor with a type parameter. + The result is a powerful operation known as +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +traverse +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Standard +The +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +traverse +\end_layout + +\end_inset + + function can be implemented for any polynomial functor (we will prove that + rigorously later in that chapter). + To build up intuition, we show several examples of implementing +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +traverse +\end_layout + +\end_inset + + for different data types, such as lists and trees. +\end_layout + +\begin_layout Standard +Another useful function equivalent to +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +foldMap +\end_layout + +\end_inset + + is +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +toList +\end_layout + +\end_inset + +: it extracts all data from a functor in a certain fixed order into a +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +List +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Standard +We illustrate the usage of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +foldMap +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +toList +\end_layout + +\end_inset + +, and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +traverse +\end_layout + +\end_inset + + for tasks such as depth-first or breadth-first aggregations and +\begin_inset Quotes eld +\end_inset + +decorations +\begin_inset Quotes erd +\end_inset + + on trees. + A typical +\begin_inset Quotes eld +\end_inset + +decoration +\begin_inset Quotes erd +\end_inset + + function is +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zipWithIndex +\end_layout + +\end_inset + +: it adds integer labels to data according to the traversal order. + We show how +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +traverse +\end_layout + +\end_inset + + makes implementing +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zipWithIndex +\end_layout + +\end_inset + + simpler. + Different traversal orders correspond to different implementations of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +traverse +\end_layout + +\end_inset + +, while the +\begin_inset Quotes eld +\end_inset + +decoration +\begin_inset Quotes erd +\end_inset + + logic remains the same. +\end_layout + +\begin_layout Standard +Defining the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Traversable +\end_layout + +\end_inset + + typeclass via the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +traverse +\end_layout + +\end_inset + + method, we show how to implement various traversal-like operations such + as +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zipWithIndex +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +scanLeft +\end_layout + +\end_inset + + using that typeclass. +\end_layout + +\begin_layout Standard +Then we give examples of tasks that cannot be performed via +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +traverse +\end_layout + +\end_inset + + because it cannot obtain certain required information while traversing + the data structure. + To overcome this difficulty, we introduce a generalized +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +fold +\end_layout + +\end_inset + + operation that depends on the pattern functor of a recursive type. + The +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +fold +\end_layout + +\end_inset + + operation is a +\series bold +recursion scheme +\series default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout +recursion scheme +\end_layout + +\end_inset + +: a higher-order function that supplies recursive behavior and is parameterized + by a calculation that needs to be performed repeatedly. + We give some examples of using +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +fold +\end_layout + +\end_inset + + for implementing tasks such as depth labeling ( +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zipWithDepth +\end_layout + +\end_inset + +) and pretty-printing. +\end_layout + +\begin_layout Standard +A recursion scheme opposite to +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +fold +\end_layout + +\end_inset + + is +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +unfold +\end_layout + +\end_inset + +: it creates a new recursive structure by following specified logic. + We give examples of using unfold for creating lists and trees of specified + shape. +\end_layout + +\begin_layout Standard +Unlike +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +fold +\end_layout + +\end_inset + + that always terminates, the termination of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +unfold +\end_layout + +\end_inset + + is not guaranteed, as it can go on indefinitely creating new parts of recursive + structures. + This problem can be avoided by using lazy data structures that delay evaluation + of recursive parts. + We show how to define a +\begin_inset Quotes eld +\end_inset + +lazy +\begin_inset Quotes erd +\end_inset + + binary tree that can simulate trees of unbounded depth. +\end_layout + +\begin_layout Standard +We turn to investigating the laws and formal properties of folding and traversal + operations. + First, we show formally that +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +reduce +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +foldLeft +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +foldMap +\end_layout + +\end_inset + +, and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +toList +\end_layout + +\end_inset + + are isomorphic as types if we assume suitable naturality laws. + When formulating those laws, we find it necessary to introduce +\begin_inset Quotes eld +\end_inset + +monoid morphisms +\begin_inset Quotes erd +\end_inset + +: functions mapping one monoid to another such that the monoid operations + are preserved. +\end_layout + +\begin_layout Standard +In Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:The-missing-laws-of-foldMap-and-reduce" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + we discuss the problem that the naturality laws alone do not guarantee + useful behavior of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +reduce +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +foldMap +\end_layout + +\end_inset + +, and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +toList +\end_layout + +\end_inset + +. + However, it does not appear possible to formulate any new laws. + Instead, we will formulate a law for +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +traverse +\end_layout + +\end_inset + + and derive the folding operations from +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +traverse +\end_layout + +\end_inset + +. + +\end_layout + +\begin_layout Standard +The lack of laws is not a serious issue since foldable functors can be character +ized in a simple way: they are just all polynomial functors. + We show that all polynomial functors support a +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +toList +\end_layout + +\end_inset + + operation (and therefore all the other equivalent operations). +\end_layout + +\begin_layout Standard +We now turn to studying the laws of the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +traverse +\end_layout + +\end_inset + + operation. + First, we note that an equivalent simpler operation is +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +sequence +\end_layout + +\end_inset + +. + Then we formulate several laws of traverse: the applicative naturality + law, the identity law, and the composition law. + We motivate those laws by formal considerations and also show that these + laws do not hold for certain incorrect implementations of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +traverse +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Standard +Then we derive the corresponding simpler laws for +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +sequence +\end_layout + +\end_inset + +. + Using those laws, we perform structural analysis and prove that all polynomial + functors are traversable. + (We also explain why non-polynomial functors are not traversable.) +\end_layout + +\begin_layout Standard +In that proof, we needed a notion of +\begin_inset Quotes eld +\end_inset + +bitraversable +\begin_inset Quotes erd +\end_inset + + bifunctors. + We define that property formally and show that all polynomial bifunctors + are bitraversable. +\end_layout + +\begin_layout Standard +In the last section of the chapter, we explore some further questions: +\end_layout + +\begin_layout Itemize +The recursion schemes +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +fold +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +unfold +\end_layout + +\end_inset + + generate +\begin_inset Quotes eld +\end_inset + +structure-preserving +\begin_inset Quotes erd +\end_inset + + maps between types. + We define formally the notions of functor algebras and functor co-algebras + to show how the property of being +\begin_inset Quotes eld +\end_inset + +structure-preserving +\begin_inset Quotes erd +\end_inset + + can be formulated via equations. +\end_layout + +\begin_layout Itemize +Some laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +traverse +\end_layout + +\end_inset + + are still missing, as we are not able to use the existing laws for proving + certain expected properties of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zipWithIndex +\end_layout + +\end_inset + +. + One needs a +\begin_inset Quotes eld +\end_inset + +representation theorem +\begin_inset Quotes erd +\end_inset + + for +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +traverse +\end_layout + +\end_inset + + (Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-Bird-representation-theorem-for-traversal" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). + A detailed proof of that theorem is beyond the scope of this book. + Using that theorem, we can prove the required properties of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zipWithIndex +\end_layout + +\end_inset + +. + We also show that a traversable functor always allows us to write an explicit + indexed table for all the data it contains (Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-polynomial-functors-Int-A" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). +\end_layout + +\begin_layout Itemize +We show that nontrivial traversable contrafunctors and profunctors do not + exist. +\end_layout + +\begin_layout Itemize +We show how to implement traversals for nested recursive types, and illustrate + with an example implementation of square-shaped nested lists. \end_layout \begin_layout Subsection diff --git a/sofp-src/lyx/sofp-traversable.lyx b/sofp-src/lyx/sofp-traversable.lyx index 35293f4e2..19e386c8d 100644 --- a/sofp-src/lyx/sofp-traversable.lyx +++ b/sofp-src/lyx/sofp-traversable.lyx @@ -17487,7 +17487,7 @@ noprefix "false" \end_inset -We need to choose +We will now choose \begin_inset Formula $A$ \end_inset @@ -17499,7 +17499,7 @@ We need to choose \begin_inset Formula $f$ \end_inset - appropriately in order to be able to derive Eq. + in this equation appropriately, in order to derive Eq. \begin_inset space ~ \end_inset @@ -17514,15 +17514,17 @@ noprefix "false" \end_inset ). - After some guessing and trying, one finds that a good choice is + After some guessing and trying, one finds that a useful choice is to define + \begin_inset Formula $B\triangleq A\rightarrow A$ \end_inset - and +. + Then we choose \begin_inset Formula $f^{:B\rightarrow A}$ \end_inset - defined by: + as the following function: \begin_inset Formula \begin{equation} f:(A\rightarrow A)\rightarrow A\quad,\quad\quad f\triangleq k^{:A\rightarrow A}\rightarrow k(a_{0})\quad\text{with a fixed }a_{0}:A\quad.\label{eq:f-for-relational-law-of-foldFn-derivation1} @@ -17530,7 +17532,7 @@ f:(A\rightarrow A)\rightarrow A\quad,\quad\quad f\triangleq k^{:A\rightarrow A}\ \end_inset -Each value +Here, we assume that a value \begin_inset Formula $a_{0}$ \end_inset @@ -17538,7 +17540,16 @@ Each value \begin_inset Formula $A$ \end_inset - gives us a function + is given (and +\begin_inset Formula $A\neq\bbnum 0$ +\end_inset + +). + Each +\begin_inset Formula $a_{0}$ +\end_inset + + specifies a different function \begin_inset Formula $f_{a_{0}}:(A\rightarrow A)\rightarrow A$ \end_inset @@ -18915,7 +18926,14 @@ The two sides are now equal. \end_layout \begin_layout Subsection -The missing laws of +The +\begin_inset CommandInset label +LatexCommand label +name "subsec:The-missing-laws-of-foldMap-and-reduce" + +\end_inset + + missing laws of \family typewriter foldMap \family default diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 16ce4faecaa3ff0d6fb1fa288e32464fe069a4b3..cd3d39bb12e3f86ab3cbd5be6f4b2c27b0101f8e 100644 GIT binary patch delta 142 zcmX?Ra?E7IdJ%RrD-#PVBa6w~L`>l9k0MWa4N{EKOw7$qbyF=3OgBFg4HWYH46$VPIrv=;-WbVrppOXzJ!->}+V@Z0KfgXG2KEWNj&F E04&cWl9k0MWaO_NLvOp;SfbW<(TQZ_#l Date: Fri, 24 Oct 2025 23:25:03 +0200 Subject: [PATCH 10/42] update pdf --- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-summary.tex | 127 ++++++++++++++++++++++++++++-- sofp-src/tex/sofp-traversable.tex | 15 ++-- sofp-src/tex/sofp.tex | 6 +- 4 files changed, 131 insertions(+), 17 deletions(-) diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index cd3d39bb12e3f86ab3cbd5be6f4b2c27b0101f8e..99938870aa00e08b849f30d64ee76e443f7f0cf8 100644 GIT binary patch delta 146 zcmX?Ra?E7IIuQ;dV=F@=D?{VS+eC~JoR1<;coQv+%+1YGl5|rojT1LN66IuKGcq}FzWXyRz<=3?w@Xy9z Date: Sat, 25 Oct 2025 22:40:10 +0200 Subject: [PATCH 11/42] wip summary of the appendix --- sofp-src/lyx/sofp-appendices.lyx | 49 +++-- sofp-src/lyx/sofp-applicative.lyx | 2 +- sofp-src/lyx/sofp-essay3.lyx | 22 +- sofp-src/lyx/sofp-summary.lyx | 353 +++++++++++++++++++++++++----- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-appendices.tex | 30 +-- sofp-src/tex/sofp-applicative.tex | 4 +- sofp-src/tex/sofp-essay3.tex | 13 +- sofp-src/tex/sofp-summary.tex | 92 +++++--- sofp-src/tex/sofp.tex | 6 +- 10 files changed, 432 insertions(+), 139 deletions(-) diff --git a/sofp-src/lyx/sofp-appendices.lyx b/sofp-src/lyx/sofp-appendices.lyx index de87d0524..1dde6830c 100644 --- a/sofp-src/lyx/sofp-appendices.lyx +++ b/sofp-src/lyx/sofp-appendices.lyx @@ -11156,8 +11156,7 @@ This concludes the proof of the profunctor commutativity law. \end_inset -Similarly, we can prove the commutativity laws for bifunctors and bi-contrafunct -ors. +Similarly, we can prove the commutativity laws for bifunctors: \end_layout \begin_layout Subsubsection @@ -11304,8 +11303,9 @@ noprefix "false" . That naturality law holds by assumption. + \begin_inset Note Note -status open +status collapsed \begin_layout Plain Layout The proofs that do not use naturality laws will need to repeat the same @@ -23361,7 +23361,8 @@ Strong dinaturality does \emph on not \emph default - hold when the type signature involves deeply nested functions such as + hold when the type contains deeply nested higher-order functions such as + \begin_inset Formula $F^{R}\triangleq\forall A.\,(\left(A\rightarrow R\right)\rightarrow A)\rightarrow A$ \end_inset @@ -23385,8 +23386,7 @@ noprefix "false" \end_inset ). - To prove that, one needs to use more advanced techniques that use the relationa -l naturality law in its full generality. + To prove that, one needs to use more advanced techniques. The wedge law still holds for functions of type \begin_inset Formula $F^{R}$ \end_inset @@ -28603,8 +28603,8 @@ We will now do structural analysis to describe the profunctors with the status open \begin_layout Plain Layout -The following derivations are adapted from these unpublished talk slides - by V. +The following derivations are adapted from the following unpublished talk + slides by V. \begin_inset space ~ \end_inset @@ -32065,6 +32065,13 @@ noprefix "false" Universal type quantifiers. Notation. Using Yoneda identities +\begin_inset CommandInset label +LatexCommand label +name "subsec:Universal-type-quantifiers" + +\end_inset + + \end_layout \begin_layout Standard @@ -33083,9 +33090,6 @@ Simplify the type \begin_layout Subparagraph Solution -\end_layout - -\begin_layout Standard \begin_inset Foot status collapsed @@ -33118,6 +33122,10 @@ Dan Doel \end_inset + +\end_layout + +\begin_layout Standard Swap the curried arguments in the given type and get: \begin_inset Formula \begin{align*} @@ -49102,7 +49110,7 @@ noprefix "false" \end_inset -(co-Fubini theorem) + (co-Fubini theorem) \end_layout \begin_layout Standard @@ -58405,7 +58413,14 @@ M^{N^{A}} & \gamma_{M}^{\uparrow M}\bef\text{ftn}_{M} \hline A & \text{pu}_{M}\\ M^{A} & \text{id}\\ M^{N^{A}} & \gamma_{M}^{\uparrow M}\bef\text{ftn}_{M} -\end{array}\quad,\\ +\end{array}\quad, +\end{align*} + +\end_inset + + +\begin_inset Formula +\begin{align*} \text{right-hand side}:\quad & \text{ftn}_{N}\bef\gamma_{M}=\,\begin{array}{|c||cc|} & A & M^{A}\\ \hline A & \text{id} & \bbnum 0\\ @@ -59658,8 +59673,12 @@ status open \begin_layout Plain Layout -def flatten[A](p: List[List[A]]): List[A] = p.takeWhile(_.nonEmpty).flatten - // $ +def flatten[A](p: List[List[A]]): List[A] = +\end_layout + +\begin_layout Plain Layout + + p.takeWhile(_.nonEmpty).flatten // $ \backslash color{dkgreen} \backslash diff --git a/sofp-src/lyx/sofp-applicative.lyx b/sofp-src/lyx/sofp-applicative.lyx index d5bef3d20..584dc3481 100644 --- a/sofp-src/lyx/sofp-applicative.lyx +++ b/sofp-src/lyx/sofp-applicative.lyx @@ -23005,7 +23005,7 @@ pure \begin_layout Standard There exist other recursive constructions that produce lawful applicative functors. - For instance, one could assume an + For instance, assume a \begin_inset Quotes eld \end_inset diff --git a/sofp-src/lyx/sofp-essay3.lyx b/sofp-src/lyx/sofp-essay3.lyx index 12dc299ad..8bbb2c67a 100644 --- a/sofp-src/lyx/sofp-essay3.lyx +++ b/sofp-src/lyx/sofp-essay3.lyx @@ -672,7 +672,15 @@ target "https://www.amazon.com/dp/0262660717" \family default - or + or the manuscript +\begin_inset Quotes eld +\end_inset + +Basic category theory for computing science +\begin_inset Quotes erd +\end_inset + +: \family typewriter \begin_inset CommandInset href @@ -719,7 +727,7 @@ monoidal \begin_inset Quotes erd \end_inset -: +: for example, see \family typewriter \begin_inset CommandInset href @@ -2563,7 +2571,7 @@ Academically minded computer scientists say that this definition of a \begin_inset Quotes eld \end_inset -types/functions +types and functions \begin_inset Quotes erd \end_inset @@ -2584,15 +2592,15 @@ literal "false" \end_inset - a + a category of \begin_inset Quotes eld \end_inset -types/functions +types and functions \begin_inset Quotes erd \end_inset - category: +: \end_layout \begin_layout Itemize @@ -4511,7 +4519,7 @@ flatMap \end_inset . - An example of usage is: + An example of usage: \begin_inset listings inline false status open diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 2b1b6ff2c..26f7bb218 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -5827,13 +5827,87 @@ relations \end_inset . - The chapter explains how relations are defined and what operations are - available for relations, and shows the proof of the relational naturality - law. + The chapter explains how relations are defined and introduces certain combinato +rs that manipulate relations: the relational product, co-product, and the + +\begin_inset Quotes eld +\end_inset + +pair mapper +\begin_inset Quotes erd +\end_inset + + combinators. + Using those combinators and an important technical tool we call +\begin_inset Quotes eld +\end_inset + +simultaneous relational lifting +\begin_inset Quotes erd +\end_inset + + (Definition +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Definition-simultaneous-relational-lifting" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +), we obtain an inductive proof of the relational naturality law (Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Relational-parametricity-theorem" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). + This is a central theorem from which all applications of parametricity + will follow. +\end_layout + +\begin_layout Standard +Because the relational naturality law is formulated in terms of relations, + it is often hard to use directly. + Programmers are more interested in finding some equation that the expression + +\begin_inset Formula $t$ +\end_inset + + satisfies. + Several shortcuts are available that, in most cases, straightforwardly + give such equations. \end_layout \begin_layout Standard -All fully parametric functions of type +One shortcut is the dinaturality law +\begin_inset space ~ +\end_inset + +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:dinaturality-law-for-profunctors" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +) obeyed by all fully parametric functions of type \begin_inset Formula $P^{A,A}\rightarrow Q^{A,A}$ \end_inset @@ -5845,14 +5919,47 @@ All fully parametric functions of type \begin_inset Formula $Q$ \end_inset - are profunctors) obey the dinaturality law + are profunctors). + The form of the law depends only on the function's type signature and applies + to all fully parametric implementations of that type signature. + The dinaturality law is a generalization of the naturality law from type + signatures of the form +\begin_inset Formula $F^{A}\rightarrow G^{A}$ +\end_inset + + (where +\begin_inset Formula $F$ +\end_inset + + and +\begin_inset Formula $G$ +\end_inset + + are both covariant or both contravariant) to arbitrary type signatures + of the form +\begin_inset Formula $P^{A,A}\rightarrow Q^{A,A}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +Another useful shortcut the +\begin_inset Quotes eld +\end_inset + +strong dinaturality +\begin_inset Quotes erd +\end_inset + + law \begin_inset space ~ \end_inset ( \begin_inset CommandInset ref LatexCommand ref -reference "eq:dinaturality-law-for-profunctors" +reference "eq:strong-dinaturality-law" plural "false" caps "false" noprefix "false" @@ -5860,12 +5967,7 @@ noprefix "false" \end_inset ). - The form of the law depends only on the function's type signature and applies - to all fully parametric implementations of that type signature. -\end_layout - -\begin_layout Standard -If the type signature of + That law holds whenever the type signature of \begin_inset Formula $t$ \end_inset @@ -5897,49 +5999,98 @@ noprefix "false" \end_inset -, the function -\begin_inset Formula $t$ +. + Strong dinaturality gives more information than the ordinary dinaturality + law and is simpler to use than the general relational naturality law +\begin_inset space ~ \end_inset - satisfies the -\begin_inset Quotes eld -\end_inset +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:relational-naturality-law-1" +plural "false" +caps "false" +noprefix "false" -strong dinaturality -\begin_inset Quotes erd \end_inset - law +). +\end_layout + +\begin_layout Standard +The strong dinaturality law is the first of the parametricity techniques + that go beyond Yoneda identities. + Section \begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:strong-dinaturality-law" +reference "subsec:Strong-dinaturality.-General-properties" plural "false" caps "false" noprefix "false" \end_inset -). - Strong dinaturality gives more information than the ordinary dinaturality - law and is simpler to use than the general relational naturality law + is an in-depth study of strongly dinatural transformations. + We use structural analysis to look for possible function types +\begin_inset Formula $P^{A,A}\rightarrow Q^{A,A}$ +\end_inset + + for which the strong dinaturality law will hold. + The results of this analysis are used for proving properties of Church + encodings as well as in the proof of the type isomorphism between +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +foldMap +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +reduce +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Standard +Section \begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:relational-naturality-law-1" +reference "subsec:Universal-type-quantifiers" plural "false" caps "false" noprefix "false" \end_inset -). + begins the study of techniques for simplifying types that contain universal + quantifiers. + The Yoneda identities provide such simplifications for a wide range of + such types, of which we show a number of examples. + We also show how the universal quantifier and the function types can encode + other type constructions (void type, unit type, products, co-products, + existentially quantified types, and recursive types). \end_layout \begin_layout Standard @@ -6353,7 +6504,7 @@ duplicate \end_inset The type signatures of those methods are similar to the type signatures - of the monads' methods + of the monadic methods \begin_inset listings inline true status open @@ -6377,7 +6528,7 @@ flatten \end_inset - except that the function arrows point in the opposite direction: +, except that the function arrows point in the opposite direction: \begin_inset Formula \[ \text{pu}_{F}:\forall A.\,A\rightarrow F^{A}\quad,\quad\quad\text{ftn}_{F}:\forall A.\,F^{F^{A}}\rightarrow F^{A}\quad. @@ -6385,16 +6536,39 @@ flatten \end_inset -The comonad's methods must also satisfy the appropriate laws. - Similarly to monads, two comonads can be combined via +The \begin_inset Quotes eld \end_inset -comonad transformers +co-Kleisli \begin_inset Quotes erd \end_inset - into a larger comonad. + functions have type +\begin_inset Formula $F^{A}\rightarrow B$ +\end_inset + + and are composed via the +\begin_inset Quotes eld +\end_inset + +co-Kleisli composition +\begin_inset Quotes erd +\end_inset + + operation that has the type signature: +\begin_inset Formula +\[ +(F^{A}\rightarrow B)\rightarrow(F^{B}\rightarrow C)\rightarrow F^{A}\rightarrow C\quad. +\] + +\end_inset + + +\end_layout + +\begin_layout Standard +The comonad's methods must also satisfy the appropriate laws. An example of a comonad is the non-empty list ( \begin_inset listings inline true @@ -6408,6 +6582,51 @@ NEL \end_inset ). + Some comonads are analogous to known monads: for instance, there is a +\begin_inset Quotes eld +\end_inset + +reader comonad +\begin_inset Quotes erd +\end_inset + + +\begin_inset Formula $F^{A}=R\rightarrow A$ +\end_inset + + (where +\begin_inset Formula $R$ +\end_inset + + needs to be a monoid), the +\begin_inset Quotes eld +\end_inset + +writer comonad +\begin_inset Quotes erd +\end_inset + + +\begin_inset Formula $F^{A}\triangleq A\times W$ +\end_inset + + (this time, +\begin_inset Formula $W$ +\end_inset + + does not need to be a monoid), and the +\begin_inset Quotes eld +\end_inset + +store comonad +\begin_inset Quotes erd +\end_inset + + +\begin_inset Formula $F^{A}\triangleq S\times(S\rightarrow A)$ +\end_inset + +. There is also a \begin_inset Quotes eld \end_inset @@ -6416,7 +6635,16 @@ co-free comonad \begin_inset Quotes erd \end_inset - construction, similar to the free monad. + construction, similarly to the free monad construction. + Similarly to monads, two comonads can be combined via +\begin_inset Quotes eld +\end_inset + +comonad transformers +\begin_inset Quotes erd +\end_inset + + into a larger comonad. \end_layout \begin_layout Standard @@ -9080,14 +9308,15 @@ noprefix "false" \end_layout \begin_layout Standard -Prove the following type equivalences (assuming a fixed type +Prove the following type equivalences (here \begin_inset Formula $P$ \end_inset -): + is a fixed type): \end_layout \begin_layout Standard +\align center \begin_inset Tabular @@ -10115,7 +10344,8 @@ such that that suitable laws hold: \begin_inset Formula \begin{align*} \text{naturality-identity law}:\quad & \text{liftE}_{S}^{A,B,R}(f^{:A\rightarrow B}\bef\text{pu}_{\text{Opt}}^{B})=f^{\uparrow S^{\bullet,R}}\bef(s^{:S^{B,R}}\rightarrow\bbnum 0^{:R}+s)\quad,\\ -\text{composition law}:\quad & \text{liftE}_{S}^{A,B,R}(f^{:A\rightarrow\bbnum 1+B})\bef\,???\,\bef\text{liftE}_{S}^{B,C,R}(g^{:B\rightarrow\bbnum 1+C})=\text{liftE}_{S}^{A,C,R}(f\diamond_{_{\text{Opt}}}g)\quad,\\ +\text{composition law}:\quad & \text{liftE}_{S}^{A,B,R}(f^{:A\rightarrow\bbnum 1+B})\bef\,???\,\bef\text{liftE}_{S}^{B,C,R}(g^{:B\rightarrow\bbnum 1+C})\\ + & \quad=\text{liftE}_{S}^{A,C,R}(f\diamond_{_{\text{Opt}}}g)\quad,\\ \text{naturality law in }R:\quad & (g^{:Q\rightarrow R})^{\uparrow S^{A,\bullet}}\bef\text{liftE}_{S}^{A,B,R}(f)=\text{liftE}_{S}^{A,B,Q}(f)\bef g^{\uparrow U^{B,\bullet}}\quad. \end{align*} @@ -11723,7 +11953,7 @@ ListT \end_inset - (here denoted just by + (here denoted by \begin_inset Formula $T$ \end_inset @@ -11849,13 +12079,14 @@ brunE (which is also a monoid type): \begin_inset Formula -\[ -\text{brunE}:M^{L^{R}}\rightarrow M^{R}\quad,\quad\quad\text{brunE}\triangleq\text{flm}_{M}\bigg(\,\begin{array}{|c||c|} +\begin{align*} + & \text{brunE}:M^{L^{R}}\rightarrow M^{R}\quad,\\ + & \text{brunE}\triangleq\text{flm}_{M}\bigg(\,\begin{array}{|c||c|} & M^{R}\\ \hline \bbnum 1 & 1\rightarrow\text{pu}_{M}(e_{R})\\ R\times M^{L^{R}} & h\times t\rightarrow\text{pu}_{M}(h)\oplus_{M}\overline{\text{brunE}}\,(t) \end{array}\,\bigg)\quad. -\] +\end{align*} \end_inset @@ -11953,21 +12184,7 @@ brunE \end_inset -(If so, Exercise -\begin_inset space ~ -\end_inset - - -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Exercise-traversables-10-1" -plural "false" -caps "false" -noprefix "false" - -\end_inset - - would show that +(If so, \begin_inset listings inline true status open @@ -11979,12 +12196,26 @@ brunE \end_inset - is also a + will be also a \emph on monoid \emph default morphism \begin_inset Formula $M^{L^{A}}\rightarrow M^{A}$ +\end_inset + + by Exercise +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Exercise-traversables-10-1" +plural "false" +caps "false" +noprefix "false" + \end_inset .) @@ -12223,8 +12454,10 @@ shift are defined by: \begin_inset Formula \begin{align*} - & \text{reset}:\forall S.\,\text{Cont}^{R,R}\rightarrow\text{Cont}^{S,R}\quad,\quad\quad\text{reset}\triangleq c^{:\left(R\rightarrow R\right)\rightarrow R}\rightarrow k^{:R\rightarrow S}\rightarrow k(c(\text{id}))\quad,\\ - & \text{shift}:\forall A.\,((A\rightarrow R)\rightarrow\text{Cont}^{R,R})\rightarrow\text{Cont}^{R,A}\quad,\quad\quad\text{shift}\triangleq g^{:\left(A\rightarrow R\right)\rightarrow\text{Cont}^{R,R}}\rightarrow k^{:A\rightarrow R}\rightarrow g(k)(\text{id})\quad. + & \text{reset}:\forall S.\,\text{Cont}^{R,R}\rightarrow\text{Cont}^{S,R}\quad,\\ + & \text{reset}\triangleq c^{:\left(R\rightarrow R\right)\rightarrow R}\rightarrow k^{:R\rightarrow S}\rightarrow k(c(\text{id}))\quad,\\ + & \text{shift}:\forall A.\,((A\rightarrow R)\rightarrow\text{Cont}^{R,R})\rightarrow\text{Cont}^{R,A}\quad,\\ + & \text{shift}\triangleq g^{:\left(A\rightarrow R\right)\rightarrow\text{Cont}^{R,R}}\rightarrow k^{:A\rightarrow R}\rightarrow g(k)(\text{id})\quad. \end{align*} \end_inset diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 99938870aa00e08b849f30d64ee76e443f7f0cf8..a0c6bdd401e1f0435c0fbd76de4db4483acc64d8 100644 GIT binary patch delta 152 zcmX?Ra?E7I8WAqj5F;ZiLsKgw)5+UJ43W7XMV|1cni!`f85vsYrdp;YZGI%m!NhKA zWMpUxRQ*w08phr%EOCv|$;8yez{SnY+1bs-(cH&Zhj=n!NhK2 zWNc^zRQ*w08phr%EOCv|$<^Gz$iT?d!otzQ(Zt!p(aqe^(%jh6z{u6o+|9|*+0KTL Jipkni(g3a;Cy4+6 diff --git a/sofp-src/tex/sofp-appendices.tex b/sofp-src/tex/sofp-appendices.tex index f8af1db96..9660c04d0 100644 --- a/sofp-src/tex/sofp-appendices.tex +++ b/sofp-src/tex/sofp-appendices.tex @@ -1448,8 +1448,7 @@ \subsubsection{Statement \label{subsec:Proof-of-the-profunctor-commutativity-law This equation is exactly the same as the commutativity law~(\ref{eq:profunctor-commutativity-law}) that we need to prove. $\square$ -Similarly, we can prove the commutativity laws for bifunctors and -bi-contrafunctors. +Similarly, we can prove the commutativity laws for bifunctors: \subsubsection{Statement \label{subsec:Proofs-of-commutativity-for-bifunctor}\ref{subsec:Proofs-of-commutativity-for-bifunctor}} @@ -3314,13 +3313,13 @@ \subsection{Strong dinaturality: definition and general properties\label{subsec: \paragraph{Remark} -Strong dinaturality does \emph{not} hold when the type signature involves -deeply nested functions such as $F^{R}\triangleq\forall A.\,(\left(A\rightarrow R\right)\rightarrow A)\rightarrow A$. +Strong dinaturality does \emph{not} hold when the type contains deeply +nested higher-order functions such as $F^{R}\triangleq\forall A.\,(\left(A\rightarrow R\right)\rightarrow A)\rightarrow A$. It turns out that $F^{R}\cong R$ (see Exercise~\ref{par:Problem-Peirce-law}). -To prove that, one needs to use more advanced techniques that use -the relational naturality law in its full generality. The wedge law -still holds for functions of type $F^{R}$ but does not provide enough -information for proving the type equivalence $F^{R}\cong R$. $\square$ +To prove that, one needs to use more advanced techniques. The wedge +law still holds for functions of type $F^{R}$ but does not provide +enough information for proving the type equivalence $F^{R}\cong R$. +$\square$ As motivation, we begin by looking at the wedge law~(\ref{eq:wedge-law-for-profunctors}) in more detail. @@ -4317,8 +4316,8 @@ \subsubsection{Statement \label{subsec:Statement-post-wedge-entails-strong-dinat This is the strong dinaturality law of $t$. $\square$ We will now do structural analysis to describe the profunctors with -the post-wedge property.\footnote{The following derivations are adapted from these unpublished talk -slides by V.~Vene:\index{Varmo Vene} \texttt{\href{https://www.ioc.ee/~tarmo/tday-voore/vene-slides.pdf}{https://www.ioc.ee/$\sim$tarmo/tday-voore/vene-slides.pdf}}} +the post-wedge property.\footnote{The following derivations are adapted from the following unpublished +talk slides by V.~Vene:\index{Varmo Vene} \texttt{\href{https://www.ioc.ee/~tarmo/tday-voore/vene-slides.pdf}{https://www.ioc.ee/$\sim$tarmo/tday-voore/vene-slides.pdf}}} \subsubsection{Statement \label{subsec:Statement-post-wedge}\ref{subsec:Statement-post-wedge}} @@ -8262,8 +8261,8 @@ \subsubsection{Example \label{subsec:Example-simple-existential-derivation-1-1}\ \end{align*} The last type is not equivalent to $R\rightarrow Q$. $\square$ -\subsubsection{Statement \label{subsec:Statement-commute-existential}\ref{subsec:Statement-commute-existential}(co-Fubini -theorem)} +\subsubsection{Statement \label{subsec:Statement-commute-existential}\ref{subsec:Statement-commute-existential} +(co-Fubini theorem)} For any type constructor $P$ with two parameters (not necessarily covariant or contravariant): @@ -10382,7 +10381,9 @@ \subsubsection*{Exercise \ref{par:Exercise-mt-3-1}} \hline A & \text{pu}_{M}\\ M^{A} & \text{id}\\ M^{N^{A}} & \gamma_{M}^{\uparrow M}\bef\text{ftn}_{M} -\end{array}\quad,\\ +\end{array}\quad, +\end{align*} +\begin{align*} {\color{greenunder}\text{right-hand side}:}\quad & \text{ftn}_{N}\bef\gamma_{M}=\,\begin{array}{|c||cc|} & A & M^{A}\\ \hline A & \text{id} & \bbnum 0\\ @@ -10831,7 +10832,8 @@ \subsubsection*{Exercise \ref{subsec:Exercise-effectful-list-not-monad}} \textbf{(b)} The code for the non-standard \lstinline!flatten! function is: \begin{lstlisting}[mathescape=true] -def flatten[A](p: List[List[A]]): List[A] = p.takeWhile(_.nonEmpty).flatten // $\color{dkgreen}\textrm{ftn}_L$ +def flatten[A](p: List[List[A]]): List[A] = + p.takeWhile(_.nonEmpty).flatten // $\color{dkgreen}\textrm{ftn}_L$ \end{lstlisting} The new \lstinline!flatten! function gives the same results as \lstinline!List!\textsf{'}s standard \lstinline!flatten! method, except if one of the nested diff --git a/sofp-src/tex/sofp-applicative.tex b/sofp-src/tex/sofp-applicative.tex index ff6914743..fb3fba275 100644 --- a/sofp-src/tex/sofp-applicative.tex +++ b/sofp-src/tex/sofp-applicative.tex @@ -3353,8 +3353,8 @@ \subsubsection{Statement \label{subsec:Statement-applicative-recursive-type-1}\r method (returning an infinite list of values, as we just saw). There exist other recursive constructions that produce lawful applicative -functors. For instance, one could assume an \textsf{``}biapplicative bifunctor\textsf{''} -$P$ having a \lstinline!bizip! method with this type signature: +functors. For instance, assume a \textsf{``}biapplicative bifunctor\textsf{''} $P$ +having a \lstinline!bizip! method with this type signature: \[ \text{bizip}_{P}^{A,B,F}:P^{A,F^{A}}\times P^{B,F^{B}}\rightarrow P^{A\times B,F^{A}\times F^{B}}\quad(\text{for all functors }F)\quad. \] diff --git a/sofp-src/tex/sofp-essay3.tex b/sofp-src/tex/sofp-essay3.tex index 072a3ae3a..288a05bd5 100644 --- a/sofp-src/tex/sofp-essay3.tex +++ b/sofp-src/tex/sofp-essay3.tex @@ -109,10 +109,11 @@ There exist books intended as presentations of category theory for computer scientists\footnote{See, e.g., \texttt{\href{https://www.amazon.com/dp/0262660717}{https://www.amazon.com/dp/0262660717}} -or \texttt{\href{https://www.math.mcgill.ca/triples/Barr-Wells-ctcs.pdf}{https://www.math.mcgill.ca/triples/Barr-Wells-ctcs.pdf}}} or for programmers.\footnote{\texttt{\href{https://github.com/hmemcpy/milewski-ctfp-pdf}{https://github.com/hmemcpy/milewski-ctfp-pdf}}} +or the manuscript \textsf{``}Basic category theory for computing science\textsf{''}: +\texttt{\href{https://www.math.mcgill.ca/triples/Barr-Wells-ctcs.pdf}{https://www.math.mcgill.ca/triples/Barr-Wells-ctcs.pdf}}} or for programmers.\footnote{\texttt{\href{https://github.com/hmemcpy/milewski-ctfp-pdf}{https://github.com/hmemcpy/milewski-ctfp-pdf}}} However, those books do not cover certain concepts relevant to programming, -such as applicative\footnote{Applicative functors are known in mathematics as \textsf{``}monoidal\textsf{''}: \texttt{\href{https://en.wikipedia.org/wiki/Monoidal_functor}{https://en.wikipedia.org/wiki/Monoidal\_functor}}} -or traversable functors. Instead, those books dwell on concepts (e.g., +such as applicative\footnote{Applicative functors are known in mathematics as \textsf{``}monoidal\textsf{''}: for +example, see \texttt{\href{https://en.wikipedia.org/wiki/Monoidal_functor}{https://en.wikipedia.org/wiki/Monoidal\_functor}}} or traversable functors. Instead, those books dwell on concepts (e.g., limits, enriched categories, topoi) that have no applications in practical functional programming today. @@ -364,8 +365,8 @@ correct types, and also that all return values have the expected types. To each programming language of that kind, there corresponds\footnote{Academically minded computer scientists say that this definition of -a \textsf{``}types/functions\textsf{''} category is insufficiently rigorous. See the -discussion in \texttt{\href{https://math.andrej.com/2016/08/06/hask-is-not-a-category/}{https://math.andrej.com/2016/08/06/hask-is-not-a-category/}}} a \textsf{``}types/functions\textsf{''} category: +a \textsf{``}types and functions\textsf{''} category is insufficiently rigorous. See +the discussion in \texttt{\href{https://math.andrej.com/2016/08/06/hask-is-not-a-category/}{https://math.andrej.com/2016/08/06/hask-is-not-a-category/}}} a category of \textsf{``}types and functions\textsf{''}: \begin{itemize} \item The objects of the category are all the data types supported by the language (including user-defined data types). As an example, for Scala @@ -667,7 +668,7 @@ \subsection*{Monadic endofunctors} array of $25$ values. The Scala library contains such a function, named \lstinline!flatMap!. -An example of usage is: +An example of usage: \begin{lstlisting} scala> (1 to 10).toArray.flatMap(x => 1 to x / 2) res0: Array[Int] = Array(1, 1, 1, 2, 1, 2, 1, 2, 3, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 5) diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index 63277d81d..00c60a702 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -779,19 +779,33 @@ \subsection{Appendix~\ref{app:Proofs-of-naturality-parametricity}} In general, the relational naturality law expresses a property of \emph{relations} rather than functions and is not equivalent to any equation satisfied by $t$. The chapter explains how relations are -defined and what operations are available for relations, and shows -the proof of the relational naturality law. - -All fully parametric functions of type $P^{A,A}\rightarrow Q^{A,A}$ -(where $P$, $Q$ are profunctors) obey the dinaturality law~(\ref{eq:dinaturality-law-for-profunctors}). -The form of the law depends only on the function\textsf{'}s type signature -and applies to all fully parametric implementations of that type signature. - -If the type signature of $t$ satisfies the conditions of Statements~\ref{subsec:Statement-post-wedge-entails-strong-dinaturality} -or~\ref{subsec:Statement-functor-post-pre-wedge}, the function $t$ -satisfies the \textsf{``}strong dinaturality\textsf{''} law~(\ref{eq:strong-dinaturality-law}). -Strong dinaturality gives more information than the ordinary dinaturality -law and is simpler to use than the general relational naturality law~(\ref{eq:relational-naturality-law-1}). +defined and introduces certain combinators that manipulate relations. +Using those combinators, we obtain an inductive proof of the relational +naturality law (Section~\ref{subsec:Relational-parametricity-theorem}). +This is a central theorem from which all applications of parametricity +will follow. + +Because the relational naturality law is formulated in terms of relations, +it is often hard to use directly. Programmers are more interested +in finding some equation that the expression $t$ satisfies. Several +shortcuts are available that, in most cases, straightforwardly give +such equations. + +One shortcut is the dinaturality law~(\ref{eq:dinaturality-law-for-profunctors}) +obeyed by all fully parametric functions of type $P^{A,A}\rightarrow Q^{A,A}$ +(where $P$, $Q$ are profunctors). The form of the law depends only +on the function\textsf{'}s type signature and applies to all fully parametric +implementations of that type signature. The dinaturality law is a +generalization of the naturality law from type signatures of the form +$F^{A}\rightarrow G^{A}$ (where $F$ and $G$ are both covariant +or both contravariant) to arbitrary type signatures of the form $P^{A,A}\rightarrow Q^{A,A}$. + +Another useful shortcut the \textsf{``}strong dinaturality\textsf{''} law~(\ref{eq:strong-dinaturality-law}). +That law holds whenever the type signature of $t$ satisfies the conditions +of Statements~\ref{subsec:Statement-post-wedge-entails-strong-dinaturality} +or~\ref{subsec:Statement-functor-post-pre-wedge}. Strong dinaturality +gives more information than the ordinary dinaturality law and is simpler +to use than the general relational naturality law~(\ref{eq:relational-naturality-law-1}). {*}{*}{*} @@ -879,16 +893,27 @@ \subsection{Comonads and comonad transformers} \text{ex}_{F}:\forall A.\,F^{A}\rightarrow A\quad,\quad\quad\text{dupl}_{F}:\forall A.\,F^{A}\rightarrow F^{F^{A}}\quad. \] The type signatures of those methods are similar to the type signatures -of the monads\textsf{'} methods \lstinline!pure! and \lstinline!flatten! +of the monadic methods \lstinline!pure! and \lstinline!flatten!, except that the function arrows point in the opposite direction: \[ \text{pu}_{F}:\forall A.\,A\rightarrow F^{A}\quad,\quad\quad\text{ftn}_{F}:\forall A.\,F^{F^{A}}\rightarrow F^{A}\quad. \] -The comonad\textsf{'}s methods must also satisfy the appropriate laws. Similarly -to monads, two comonads can be combined via \textsf{``}comonad transformers\textsf{''} -into a larger comonad. An example of a comonad is the non-empty list -(\lstinline!NEL!). There is also a \textsf{``}co-free comonad\textsf{''} construction, -similar to the free monad. +The \textsf{``}co-Kleisli\textsf{''} functions have type $F^{A}\rightarrow B$ and +are composed via the \textsf{``}co-Kleisli composition\textsf{''} operation that has +the type signature: +\[ +(F^{A}\rightarrow B)\rightarrow(F^{B}\rightarrow C)\rightarrow F^{A}\rightarrow C\quad. +\] + +The comonad\textsf{'}s methods must also satisfy the appropriate laws. An example +of a comonad is the non-empty list (\lstinline!NEL!). Some comonads +are analogous to known monads: for instance, there is a \textsf{``}reader +comonad\textsf{''} $F^{A}=R\rightarrow A$ (where $R$ needs to be a monoid), +the \textsf{``}writer comonad\textsf{''} $F^{A}\triangleq A\times W$ (this time, +$W$ does not need to be a monoid), and the \textsf{``}store comonad\textsf{''} $F^{A}\triangleq S\times(S\rightarrow A)$. +There is also a \textsf{``}co-free comonad\textsf{''} construction, similarly to the +free monad construction. Similarly to monads, two comonads can be +combined via \textsf{``}comonad transformers\textsf{''} into a larger comonad. Although the properties of comonads have many similarities to those of monads, this book does not develop the corresponding theory because @@ -1268,8 +1293,8 @@ \subsubsection{Exercise \label{par:Problem-Peirce-law}\ref{par:Problem-Peirce-la \subsubsection{Exercise \label{par:Problem-Peirce-law-2}\ref{par:Problem-Peirce-law-2}} -Prove the following type equivalences (assuming a fixed type $P$): - +Prove the following type equivalences (here $P$ is a fixed type): +\begin{center} \begin{tabular}{|c|c|} \hline \textbf{\footnotesize{}Quantified type} & \textbf{\footnotesize{}Equivalent type}\tabularnewline @@ -1284,6 +1309,7 @@ \subsubsection{Exercise \label{par:Problem-Peirce-law-2}\ref{par:Problem-Peirce- $\forall A.\,((A\rightarrow A)\rightarrow A)\rightarrow P$ & $P$\tabularnewline \hline \end{tabular} +\par\end{center} \subsubsection{Exercise \label{par:Exercise-additional-16-2}\ref{par:Exercise-additional-16-2}} @@ -1404,7 +1430,8 @@ \subsubsection{Problem \label{subsec:Statement-filtering-recursive-type-church}\ such that that suitable laws hold: \begin{align*} {\color{greenunder}\text{naturality-identity law}:}\quad & \text{liftE}_{S}^{A,B,R}(f^{:A\rightarrow B}\bef\text{pu}_{\text{Opt}}^{B})=f^{\uparrow S^{\bullet,R}}\bef(s^{:S^{B,R}}\rightarrow\bbnum 0^{:R}+s)\quad,\\ -{\color{greenunder}\text{composition law}:}\quad & \text{liftE}_{S}^{A,B,R}(f^{:A\rightarrow\bbnum 1+B})\bef\,???\,\bef\text{liftE}_{S}^{B,C,R}(g^{:B\rightarrow\bbnum 1+C})=\text{liftE}_{S}^{A,C,R}(f\diamond_{_{\text{Opt}}}g)\quad,\\ +{\color{greenunder}\text{composition law}:}\quad & \text{liftE}_{S}^{A,B,R}(f^{:A\rightarrow\bbnum 1+B})\bef\,???\,\bef\text{liftE}_{S}^{B,C,R}(g^{:B\rightarrow\bbnum 1+C})\\ + & \quad=\text{liftE}_{S}^{A,C,R}(f\diamond_{_{\text{Opt}}}g)\quad,\\ {\color{greenunder}\text{naturality law in }R:}\quad & (g^{:Q\rightarrow R})^{\uparrow S^{A,\bullet}}\bef\text{liftE}_{S}^{A,B,R}(f)=\text{liftE}_{S}^{A,B,Q}(f)\bef g^{\uparrow U^{B,\bullet}}\quad. \end{align*} Here, the bifunctor $U$ is defined by: @@ -1574,8 +1601,8 @@ \subsubsection{Problem \label{par:Problem-monads-5-2}\ref{par:Problem-monads-5-2 \subsubsection{Problem \label{par:Problem-monads-5-2-1}\ref{par:Problem-monads-5-2-1}} -Consider the monad transformer \lstinline!ListT! (here denoted just -by $T$): +Consider the monad transformer \lstinline!ListT! (here denoted by +$T$): \[ T^{A}\triangleq M^{L^{A}}\quad,\quad\quad L^{A}\triangleq\bbnum 1+A\times M^{L^{A}}\quad, \] @@ -1600,13 +1627,14 @@ \subsubsection{Problem \label{par:Problem-monads-5-2-1}\ref{par:Problem-monads-5 type signature $M^{L^{R}}\rightarrow M^{R}$ aggregates all elements of the effectful list into a single value of type $M^{R}$ (which is also a monoid type): -\[ -\text{brunE}:M^{L^{R}}\rightarrow M^{R}\quad,\quad\quad\text{brunE}\triangleq\text{flm}_{M}\bigg(\,\begin{array}{|c||c|} +\begin{align*} + & \text{brunE}:M^{L^{R}}\rightarrow M^{R}\quad,\\ + & \text{brunE}\triangleq\text{flm}_{M}\bigg(\,\begin{array}{|c||c|} & M^{R}\\ \hline \bbnum 1 & 1\rightarrow\text{pu}_{M}(e_{R})\\ R\times M^{L^{R}} & h\times t\rightarrow\text{pu}_{M}(h)\oplus_{M}\overline{\text{brunE}}\,(t) \end{array}\,\bigg)\quad. -\] +\end{align*} Here, we use the binary operation $\oplus_{M}$ of the monoid $M^{R}$, which is defined by: \[ @@ -1624,8 +1652,8 @@ \subsubsection{Problem \label{par:Problem-monads-5-2-1}\ref{par:Problem-monads-5 {\color{greenunder}\text{for all monoid types }A:}\quad & a^{:A}\triangleright\text{pu}_{T}\bef\text{brunE}=a^{:A}\triangleright\text{pu}_{M}\quad,\\ {\color{greenunder}\text{composition law}:}\quad & p^{:T^{T^{A}}}\triangleright\text{ftn}_{T}\bef\text{brunE }=p^{:T^{T^{A}}}\triangleright\text{brunE}\bef\text{brunE}^{\uparrow M}\bef\text{ftn}_{M}\quad. \end{align*} -(If so, Exercise~\ref{subsec:Exercise-traversables-10-1} would show -that \lstinline!brunE! is also a \emph{monoid} morphism $M^{L^{A}}\rightarrow M^{A}$.) +(If so, \lstinline!brunE! will be also a \emph{monoid} morphism $M^{L^{A}}\rightarrow M^{A}$ +by Exercise~\ref{subsec:Exercise-traversables-10-1}.) % \begin{comment} Failed attempts to verify the composition law: @@ -1724,8 +1752,10 @@ \subsubsection{Problem \label{subsec:Problem-monatron-lift-reset-and-shift}\ref{ The continuation monad\textsf{'}s operations \lstinline!reset! and \lstinline!shift! are defined by: \begin{align*} - & \text{reset}:\forall S.\,\text{Cont}^{R,R}\rightarrow\text{Cont}^{S,R}\quad,\quad\quad\text{reset}\triangleq c^{:\left(R\rightarrow R\right)\rightarrow R}\rightarrow k^{:R\rightarrow S}\rightarrow k(c(\text{id}))\quad,\\ - & \text{shift}:\forall A.\,((A\rightarrow R)\rightarrow\text{Cont}^{R,R})\rightarrow\text{Cont}^{R,A}\quad,\quad\quad\text{shift}\triangleq g^{:\left(A\rightarrow R\right)\rightarrow\text{Cont}^{R,R}}\rightarrow k^{:A\rightarrow R}\rightarrow g(k)(\text{id})\quad. + & \text{reset}:\forall S.\,\text{Cont}^{R,R}\rightarrow\text{Cont}^{S,R}\quad,\\ + & \text{reset}\triangleq c^{:\left(R\rightarrow R\right)\rightarrow R}\rightarrow k^{:R\rightarrow S}\rightarrow k(c(\text{id}))\quad,\\ + & \text{shift}:\forall A.\,((A\rightarrow R)\rightarrow\text{Cont}^{R,R})\rightarrow\text{Cont}^{R,A}\quad,\\ + & \text{shift}\triangleq g^{:\left(A\rightarrow R\right)\rightarrow\text{Cont}^{R,R}}\rightarrow k^{:A\rightarrow R}\rightarrow g(k)(\text{id})\quad. \end{align*} How to lift these operations to an arbitrary monad stack $P$ that contains a continuation monad?\footnote{See \texttt{\href{https://github.com/renormalist/pugs/blob/master/src/Pugs/AST/Eval.hs}{https://github.com/renormalist/pugs/blob/master/src/Pugs/AST/Eval.hs}} diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 0a2ce23df..89f5525a8 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): a94f7e1c3e302acf39ba8599aa77151fbd7b8a7f9c6e2c669b65340e5ecbff66}\\ -{\scriptsize{}Git commit: abf57a040d32bd5ee24e168d6b375a55f92424f2}\\ -{\scriptsize{}PDF file built on Fri, 24 Oct 2025 23:12:32 +0200 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 16cf89e2cfef216f06713d61d0dfcada2688de9d709b9393c62520ea4fde7c87}\\ +{\scriptsize{}Git commit: c9ddd5d1803ec24b427361309548deed37c915b3}\\ +{\scriptsize{}PDF file built on Sat, 25 Oct 2025 22:15:44 +0200 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From 334368472874f4f9b066f5146aad480bf7ea4045 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Mon, 27 Oct 2025 10:22:08 +0100 Subject: [PATCH 12/42] fix formatting in tables with tall equation arrays --- sofp-src/lyx/sofp-appendices.lyx | 2620 +++++++++++++++++++++++- sofp-src/lyx/sofp-summary.lyx | 236 ++- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-appendices.tex | 210 +- sofp-src/tex/sofp-back-cover-no-bg.tex | 4 +- sofp-src/tex/sofp-summary.tex | 88 +- sofp-src/tex/sofp.tex | 10 +- 7 files changed, 2981 insertions(+), 187 deletions(-) diff --git a/sofp-src/lyx/sofp-appendices.lyx b/sofp-src/lyx/sofp-appendices.lyx index 1dde6830c..af3ceff26 100644 --- a/sofp-src/lyx/sofp-appendices.lyx +++ b/sofp-src/lyx/sofp-appendices.lyx @@ -34128,7 +34128,7 @@ higher-order functor \begin_inset Formula $P\leadsto F$ \end_inset - the type + the function type \begin_inset Formula $\forall A.\,P^{A}\rightarrow F^{A}$ \end_inset @@ -34741,7 +34741,7 @@ noprefix "false" \end_layout \begin_layout Standard -Note that the Yoneda lemma cannot be used to prove Eq. +Note that the Yoneda identities cannot be used to prove Eq. \begin_inset space ~ \end_inset @@ -34756,7 +34756,7 @@ noprefix "false" \end_inset ). - The Yoneda lemma only applies to types of the form + The covariant Yoneda identity only applies to types of the form \begin_inset Formula $\forall X.\,(A\rightarrow X)\rightarrow F^{X}$ \end_inset @@ -34881,7 +34881,7 @@ Proof \begin_inset Formula $F^{\bbnum 0}\neq\bbnum 0$ \end_inset -, it is sufficient to implement any function +, it is sufficient to produce a function \begin_inset Formula $f$ \end_inset @@ -34890,7 +34890,7 @@ Proof \end_inset . - The code for that function is: + Such a function exists: \begin_inset Formula \[ f:F^{\bbnum 0}\rightarrow T\quad,\quad\quad f(p^{:F^{\bbnum 0}})\triangleq\forall X.\,q^{:F^{X}\rightarrow X}\rightarrow q(p\triangleright\text{absurd}^{\uparrow F})\quad. @@ -34957,7 +34957,7 @@ noprefix "false" \series bold (b) \series default - if we implement any function + if we implement a function \begin_inset Formula $g$ \end_inset @@ -37296,7 +37296,7 @@ noprefix "false" \end_inset -(nested fixpoint lemma) + (nested fixpoint lemma) \end_layout \begin_layout Standard @@ -40623,7 +40623,7 @@ noprefix "false" \end_inset are non-disjunctive. - Then it follows that, for any type constructors + Then, for any type constructors \begin_inset Formula $F$ \end_inset @@ -41135,7 +41135,7 @@ Suppose \end_inset is any lifting-to-full type constructor that is not identically void ( -\begin_inset Formula $F^{A}\neq0$ +\begin_inset Formula $F^{A}\neq\bbnum 0$ \end_inset for some @@ -41868,7 +41868,7 @@ Under assumptions of parametricity: \end_inset - The +The \begin_inset Quotes eld \end_inset @@ -41931,6 +41931,26 @@ t_{n,k}^{A}\triangleq p^{:(A\rightarrow A)\rightarrow A}\rightarrow p(a_{1}^{:A} \begin_layout Subparagraph Proof +\begin_inset Foot +status open + +\begin_layout Plain Layout +See +\family typewriter + +\begin_inset CommandInset href +LatexCommand href +target "https://cstheory.stackexchange.com/questions/53855/" +literal "false" + +\end_inset + + +\end_layout + +\end_inset + + \end_layout \begin_layout Standard @@ -42568,8 +42588,20 @@ status open \end_inset . - If we imagine that [X] were an ordinary argument (not a type parameter), - we would apply the standard type identities: + If we imagine that +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +[X] +\end_layout + +\end_inset + + were an ordinary argument (not a type parameter), we would apply the standard + type identities: \begin_inset Formula \begin{align*} & A\rightarrow B\times C\cong(A\rightarrow B)\times(A\rightarrow C)\quad,\\ @@ -42669,7 +42701,7 @@ X \end_inset - is a type parameter, not a value parameter, so it is invalid to use ordinary + is a type parameter, not a value parameter, and it is invalid to use ordinary type identities such as \begin_inset Formula $A\rightarrow R\rightarrow B\cong R\rightarrow A\rightarrow B$ \end_inset @@ -42704,7 +42736,7 @@ Proof \series bold (a) \series default - This isomorphism is shown in Example + This isomorphism is proved in Example \begin_inset space ~ \end_inset @@ -42719,7 +42751,11 @@ noprefix "false" \end_inset (e). - It is a + +\end_layout + +\begin_layout Standard +It is a \begin_inset Quotes eld \end_inset @@ -43403,7 +43439,7 @@ For any strictly positive bifunctor , we have: \begin_inset Formula \[ -\forall A.\,S^{P^{A},Q^{A}}\cong S^{\forall A.\,P^{A},\forall A.\,Q^{A}}\quad. +\forall A.\,S^{P^{A},\,Q^{A}}\cong S^{\forall A.\,P^{A},\,\forall A.\,Q^{A}}\quad. \] \end_inset @@ -43568,9 +43604,9 @@ The functor .) We get: \begin_inset Formula \begin{align*} - & \forall A.\,F^{P^{A}}=\forall A.\,S^{P^{A},F^{P^{A}}}\\ -\text{inductive assumption}:\quad & \cong S^{\forall A.\,P^{A},\gunderline{\forall A.\,F^{P^{A}}}}\\ -\text{inductive assumption}:\quad & \cong S^{\forall A.\,P^{A},F^{\forall A.\,P^{A}}}=F^{\forall A.\,P^{A}}\quad. + & \forall A.\,F^{P^{A}}=\forall A.\,S^{P^{A},\,F^{P^{A}}}\\ +\text{inductive assumption}:\quad & \cong S^{\forall A.\,P^{A},\,\gunderline{\forall A.\,F^{P^{A}}}}\\ +\text{inductive assumption}:\quad & \cong S^{\forall A.\,P^{A},\,F^{\forall A.\,P^{A}}}=F^{\forall A.\,P^{A}}\quad. \end{align*} \end_inset @@ -43614,7 +43650,7 @@ noprefix "false" \end_inset - + \end_layout \begin_layout Standard @@ -44280,6 +44316,39 @@ noprefix "false" \begin_inset Formula $F$ \end_inset +. + (See Definition +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Definition-strictly-positive-functor" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +.) It is unknown if this holds for covariant functors +\begin_inset Formula $F$ +\end_inset + + that are not strictly positive; see Problem +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "par:Problem-Peirce-law-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + . \end_layout @@ -50101,7 +50170,7 @@ We have seen that the least fixpoints of functors are expressed via the status open \begin_layout Plain Layout -This section follows the logic shown in P. +This section follows the logic given in P. \begin_inset space ~ \end_inset @@ -50113,7 +50182,11 @@ Recursive types for free \begin_inset Quotes erd \end_inset - except that the existential types are defined by Eq. +, except that we +\emph on +define +\emph default + existential types by Eq. \begin_inset space ~ \end_inset @@ -51337,7 +51410,7 @@ For any \begin_inset Formula $\psi_{u}^{A}$ \end_inset - is known as the + is known as an \series bold anamorphism \series default @@ -52226,10 +52299,2509 @@ T\cong\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B}) \end_inset +\end_layout + +\begin_layout Subsection +Summary of type isomorphisms +\end_layout + +\begin_layout Standard +This Appendix has developed various parametricity techniques to prove a + number of type isomorphisms. + The results are summarized in Tables +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Type-identities-proved-by-Yoneda" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +– +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Type-identities-for-existential-types" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +. +\end_layout + +\begin_layout Standard +\begin_inset Float table +placement h +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size footnotesize +Identity +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size footnotesize +Assumptions +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,A\rightarrow A\cong\bbnum 1$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,A\rightarrow F^{A}\cong F^{\bbnum 1}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is any functor +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,A\times A\rightarrow F^{A}\cong F^{\bbnum 2}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is any functor +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,A\cong\bbnum 0$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,F^{A}\cong F^{\bbnum 0}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is any functor +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,H^{A}\cong H^{\bbnum 1}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $H$ +\end_inset + + is any contrafunctor +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,(A\rightarrow P)\rightarrow A\rightarrow Q\cong P\rightarrow Q$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $P$ +\end_inset + +, +\begin_inset Formula $Q$ +\end_inset + + are fixed types +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,(P\rightarrow A)\rightarrow Q\rightarrow A\cong Q\rightarrow P$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $P$ +\end_inset + +, +\begin_inset Formula $Q$ +\end_inset + + are fixed types +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,((A\rightarrow P)\rightarrow Q)\rightarrow(A\rightarrow S)\rightarrow R\cong((S\rightarrow P)\rightarrow Q)\rightarrow R$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $P$ +\end_inset + +, +\begin_inset Formula $Q$ +\end_inset + +, +\begin_inset Formula $R$ +\end_inset + +, +\begin_inset Formula $S$ +\end_inset + + are fixed types +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,(P\rightarrow A\times Q)\rightarrow(A+R)\times S\cong$ +\end_inset + + +\begin_inset Formula $(P\rightarrow Q)\rightarrow(P+R)\times S$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $P$ +\end_inset + +, +\begin_inset Formula $Q$ +\end_inset + +, +\begin_inset Formula $R$ +\end_inset + +, +\begin_inset Formula $S$ +\end_inset + + are fixed types +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption Standard + +\begin_layout Plain Layout +Type isomorphisms proved via Yoneda identities. +\begin_inset CommandInset label +LatexCommand label +name "tab:Type-identities-proved-by-Yoneda" + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset Float table +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size footnotesize +Identity +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size footnotesize +Assumptions +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size footnotesize +Source +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,(F^{A}\rightarrow A)\rightarrow A\cong\mu A.\,F^{A}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is any functor +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:The-Church-encoding-of-recursive-types" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,(H^{A}\rightarrow A)\rightarrow A\cong H^{\bbnum 1}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $H$ +\end_inset + + is any contrafunctor +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-simplify-quantifier-1-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,(F^{A}\rightarrow A)\rightarrow G^{A}\cong G^{\mu A.\,F^{A}}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + +, +\begin_inset Formula $G$ +\end_inset + + are any functors +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-Church-Yoneda-identity" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\mu A.\,\mu B.\,F^{A,B}\cong\mu B.\,F^{B,B}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is any bifunctor +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-nested-fixpoints" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Note Note +status collapsed + +\begin_layout Plain Layout + +\size footnotesize +See +\family typewriter +\size default + +\begin_inset CommandInset href +LatexCommand href +target "https://tex.stackexchange.com/questions/50332/vertical-spacing-of-a-table-cell" +literal "false" + +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Box Frameless +position "c" +hor_pos "c" +has_inner_box 1 +inner_pos "t" +use_parbox 0 +use_makebox 0 +width "0.1mm" +special "none" +height "12mm" +height_special "none" +thickness "0.4pt" +separation "3pt" +shadowsize "4pt" +framecolor "black" +backgroundcolor "none" +status collapsed + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Box Frameless +position "c" +hor_pos "c" +has_inner_box 1 +inner_pos "c" +use_parbox 0 +use_makebox 0 +width "43col%" +special "none" +height "1in" +height_special "totalheight" +thickness "0.4pt" +separation "3pt" +shadowsize "4pt" +framecolor "black" +backgroundcolor "none" +status open + +\begin_layout Plain Layout +\align center + +\size footnotesize +\begin_inset Formula $\mu A.\,P^{A,\,\mu B.\,Q^{A,B}}\cong$ +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Formula $\forall A.\,\forall B.\,(P^{A,B}\rightarrow A)\times(Q^{A,B}\rightarrow B)\rightarrow A$ +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $P$ +\end_inset + +, +\begin_inset Formula $Q$ +\end_inset + + are any bifunctors +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-nested-fixpoint-under-functor" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,F^{A}\rightarrow P\cong P$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +If +\begin_inset Formula $F^{A}\neq\bbnum 0$ +\end_inset + + for some +\begin_inset Formula $A$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-application-full-relation" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +(a) +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,((A\rightarrow A)\rightarrow A)\rightarrow A\cong\bbnum 1+\bbnum 2+\bbnum 3+...$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset space ~ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-advanced-type-equivalence" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Box Frameless +position "c" +hor_pos "c" +has_inner_box 1 +inner_pos "t" +use_parbox 0 +use_makebox 0 +width "0.1mm" +special "none" +height "17mm" +height_special "none" +thickness "0.4pt" +separation "3pt" +shadowsize "4pt" +framecolor "black" +backgroundcolor "none" +status open + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Box Frameless +position "c" +hor_pos "c" +has_inner_box 1 +inner_pos "c" +use_parbox 0 +use_makebox 0 +width "43col%" +special "none" +height "1in" +height_special "totalheight" +thickness "0.4pt" +separation "3pt" +shadowsize "4pt" +framecolor "black" +backgroundcolor "none" +status collapsed + +\begin_layout Plain Layout +\align center + +\size footnotesize +\begin_inset Formula $\forall A.\,(H^{A}\rightarrow A)\rightarrow F^{A}+G^{A}\cong$ +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Formula $(\forall A.\:(H^{A}\rightarrow A)\rightarrow F^{A})+$ +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Formula $(\forall A.\:(H^{A}\rightarrow A)\rightarrow G^{A})$ +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +For any +\begin_inset Formula $F$ +\end_inset + +, +\begin_inset Formula $G$ +\end_inset + +, +\begin_inset Formula $H$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Example +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-undisjunctive-type-constructors" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +(c) +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,\forall B.\,F^{A,B}\cong\forall B.\,\forall A.\,F^{A,B}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +For any +\begin_inset Formula $F$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-Fubini-theorem-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,(F^{A}+G^{A})\cong(\forall A.\,F^{A})+(\forall A.\,G^{A})$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +For any +\begin_inset Formula $F$ +\end_inset + +, +\begin_inset Formula $G$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-general-identities-forall" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +(a) +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,(F^{A}\times G^{A})\cong(\forall A.\,F^{A})\times(\forall A.\,G^{A})$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +For any +\begin_inset Formula $F$ +\end_inset + +, +\begin_inset Formula $G$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-general-identities-forall" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +(b) +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,R\rightarrow F^{A}\cong R\rightarrow(\forall A.\,F^{A})$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +For any +\begin_inset Formula $F$ +\end_inset + +, +\begin_inset Formula $G$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-general-identities-forall" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +(c) +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,F^{P^{A}}\cong F^{\forall A.\,P^{A}}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is strictly positive +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-quantifier-across-functor" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,F^{A}\cong\bbnum 0$ +\end_inset + + when +\begin_inset Formula $F^{\bbnum 0}\cong\bbnum 0$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is such that +\begin_inset Formula $F^{\bbnum 0}\cong\bbnum 0$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-Fubini-theorem-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,F^{A\rightarrow A}\cong F^{\bbnum 1}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is strictly positive +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Example +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-simplify-quantifier-A-A" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +(a) +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,H^{A\rightarrow A}\cong H^{\bbnum 1}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $H$ +\end_inset + + is a contrafunctor +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Example +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-simplify-quantifier-A-A" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +(b) +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,((A\rightarrow P)\rightarrow A\rightarrow A\cong P$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $P$ +\end_inset + + is a fixed type +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Exercise +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "par:Problem-Peirce-law" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption Standard + +\begin_layout Plain Layout +Type identities proved by other parametricity techniques. +\begin_inset CommandInset label +LatexCommand label +name "tab:Type-identities-proved-by-parametricity" + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset Float table +placement h +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size footnotesize +Identity +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size footnotesize +Assumptions +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size footnotesize +Source +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\exists C.\,F^{C}\cong\forall D.\,\big(\forall C.\,(F^{C}\rightarrow D)\big)\rightarrow D$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +For any +\begin_inset Formula $F$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Equation +\begin_inset space ~ +\end_inset + +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:existential-via-universal-Yoneda" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +) +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $(\exists C.\,F^{C})\rightarrow R\cong\forall C.\,(F^{C}\rightarrow R)$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +For any +\begin_inset Formula $F$ +\end_inset + +, +\begin_inset Formula $R$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-function-extension-rule" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\exists A.\,F^{A}\cong F^{\bbnum 1}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is any functor +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-co-Yoneda-two-identities-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +(a) +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\exists A.\,H^{A}\cong H^{\bbnum 0}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $H$ +\end_inset + + is any contrafunctor +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-co-Yoneda-two-identities-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +(b) +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\exists A.\,F^{A}\rightarrow A\cong\bbnum 1$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +For any +\begin_inset Formula $F$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Example +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-simple-existential-derivation" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\exists A.\,(F^{A}+G^{A})\cong(\exists A.\,F^{A})+(\exists A.\,G^{A})$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +For any +\begin_inset Formula $F$ +\end_inset + +, +\begin_inset Formula $G$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Example +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-simple-existential-derivation-1-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +(b) +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\exists A.\,\exists B.\,F^{A,B}\cong\exists B.\,\exists A.\,F^{A,B}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +For any +\begin_inset Formula $F$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-commute-existential" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\exists A.\,(A\rightarrow F^{A})\times A\cong\nu A.\,F^{A}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is any functor +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:The-greatest-fixpoints-and-Church-co-Yoneda" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\exists A.\,(A\rightarrow F^{A})\times G^{A}\cong G^{\nu A.\,F^{A}}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + +, +\begin_inset Formula $G$ +\end_inset + + are any functors +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-Church-co-Yoneda" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\nu A.\,\nu B.\,F^{A,B}\cong\nu B.\,F^{B,B}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + + is any bifunctor +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-nested-greatest-fixpoints" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Note Note +status collapsed + +\begin_layout Plain Layout + +\size footnotesize +See +\family typewriter +\size default + +\begin_inset CommandInset href +LatexCommand href +target "https://tex.stackexchange.com/questions/50332/vertical-spacing-of-a-table-cell" +literal "false" + +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Box Frameless +position "c" +hor_pos "c" +has_inner_box 1 +inner_pos "t" +use_parbox 0 +use_makebox 0 +width "0.1mm" +special "none" +height "12mm" +height_special "none" +thickness "0.4pt" +separation "3pt" +shadowsize "4pt" +framecolor "black" +backgroundcolor "none" +status collapsed + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Box Frameless +position "c" +hor_pos "c" +has_inner_box 1 +inner_pos "c" +use_parbox 0 +use_makebox 0 +width "43col%" +special "none" +height "1in" +height_special "totalheight" +thickness "0.4pt" +separation "3pt" +shadowsize "4pt" +framecolor "black" +backgroundcolor "none" +status collapsed + +\begin_layout Plain Layout +\align center + +\size footnotesize +\begin_inset Formula $\nu A.\,F^{A,\,\nu B.\,G^{A,B}}\cong$ +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Formula $\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times A$ +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset + +, +\begin_inset Formula $G$ +\end_inset + + are any bifunctors +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-mutually-recursive-greatest-fixpoints" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $G^{\exists C.\,F^{C}}\cong\forall D.\,(\forall C.\,F^{C}\rightarrow D)\rightarrow G^{D}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Any +\begin_inset Formula $F$ +\end_inset + +, any functor +\begin_inset Formula $G$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Exercise +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "par:Exercise-additional-16-3" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\begin_layout Plain Layout +\begin_inset Caption Standard + +\begin_layout Plain Layout +Type isomorphisms for existential types. +\begin_inset CommandInset label +LatexCommand label +name "tab:Type-identities-for-existential-types" + +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + \end_layout \begin_layout Chapter -Solutions of some exercises +Solutions for selected exercises \end_layout \begin_layout Addsec diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 26f7bb218..35921f42e 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -5689,13 +5689,13 @@ in the same way \end_inset for all types. - This appendix develops the necessary theory and technique in order and - proves the following results: + This appendix develops the necessary theory and technique to prove a number + of results used in other parts of the book. \end_layout \begin_layout Standard -A given type constructor may have one fully parametric and lawful implementation - of the +We show that a given type constructor may have at most one fully parametric + and lawful implementation of the \begin_inset listings inline true status open @@ -5798,11 +5798,12 @@ noprefix "false" \end_layout \begin_layout Standard -Any fully parametric expression +The a central theorem from which all applications of parametricity will + follow says that any fully parametric expression \begin_inset Formula $t:\forall A.\,Q^{A}$ \end_inset - satisfies the relational naturality law + satisfies a relational naturality law \begin_inset space ~ \end_inset @@ -5875,19 +5876,22 @@ noprefix "false" \end_inset ). - This is a central theorem from which all applications of parametricity - will follow. + \end_layout \begin_layout Standard -Because the relational naturality law is formulated in terms of relations, - it is often hard to use directly. - Programmers are more interested in finding some equation that the expression - -\begin_inset Formula $t$ +Because the relational naturality law is formulated in terms of relations + rather than functions, it is often hard to use directly. + Programmers are more interested in proving that a fully parametric function + satisfies some equation (a +\begin_inset Quotes eld \end_inset - satisfies. +law +\begin_inset Quotes erd +\end_inset + +). Several shortcuts are available that, in most cases, straightforwardly give such equations. \end_layout @@ -6084,15 +6088,69 @@ noprefix "false" \end_inset - begins the study of techniques for simplifying types that contain universal - quantifiers. - The Yoneda identities provide such simplifications for a wide range of - such types, of which we show a number of examples. + begins a further study of parametricity-based techniques for simplifying + types that contain universal quantifiers. + The Yoneda identities already provide such simplifications for a wide range + of such types, of which we show a number of examples. We also show how the universal quantifier and the function types can encode other type constructions (void type, unit type, products, co-products, existentially quantified types, and recursive types). \end_layout +\begin_layout Standard +The Yoneda identities are an important application of category theory, which + proves an abstract version of the Yoneda identity for all categories. + The most important application to programming are the two Yoneda identities + involving covariant and contravariant functors. + Another version is a Yoneda identity for type constructors (Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:The-Yoneda-identities-for-type-constructors" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). +\end_layout + +\begin_layout Standard +*** +\end_layout + +\begin_layout Standard +A number of resulting type isomorphisms can be found in Tables +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Type-identities-proved-by-Yoneda" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +– +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Type-identities-for-existential-types" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +. +\end_layout + \begin_layout Standard *** \end_layout @@ -8874,7 +8932,7 @@ noprefix "false" status open \begin_layout Plain Layout -This was an open problem but it was solved by Hew Wolff. +This was an open problem solved in 2024 by Hew Wolff (private communication). \end_layout \end_inset @@ -9114,69 +9172,6 @@ Triang . \end_layout -\begin_layout Subsubsection -Exercise -\begin_inset CommandInset label -LatexCommand label -name "par:Exercise-additional-15" - -\end_inset - - -\begin_inset CommandInset ref -LatexCommand ref -reference "par:Exercise-additional-15" -plural "false" -caps "false" -noprefix "false" - -\end_inset - - -\end_layout - -\begin_layout Standard -Simplify the type -\begin_inset Formula $\forall A.\,((A\rightarrow A)\rightarrow A)\rightarrow A$ -\end_inset - -, or in Scala: -\begin_inset listings -inline false -status open - -\begin_layout Plain Layout - -def f[A]: ((A => A) => A) => A -\end_layout - -\end_inset - -into a type expression that contains no quantifiers. - Show how to implement all possible values of this type. - -\begin_inset Foot -status open - -\begin_layout Plain Layout -See -\family typewriter - -\begin_inset CommandInset href -LatexCommand href -target "https://cstheory.stackexchange.com/questions/53855/" -literal "false" - -\end_inset - - -\end_layout - -\end_inset - - -\end_layout - \begin_layout Subsubsection Exercise \begin_inset CommandInset label @@ -9572,7 +9567,7 @@ where is any covariant functor. \begin_inset Note Note -status collapsed +status open \begin_layout Plain Layout Use the Yoneda identities: @@ -9709,7 +9704,7 @@ Show that for any covariant functor , the following Yoneda-like formula holds: \begin_inset Note Note -status collapsed +status open \begin_layout Plain Layout Solution @@ -12766,6 +12761,21 @@ where functions of type \end_inset are required to be fully parametric. +\begin_inset Note Note +status open + +\begin_layout Plain Layout +(solved by transitive closure union of relations?) Do I actually have a + solution for this? +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +An equivalent statement \begin_inset Foot status open @@ -12785,27 +12795,65 @@ literal "false" \end_inset + is: +\begin_inset Formula +\[ +\forall A.\,F^{A\rightarrow A}\cong F^{\bbnum 1} +\] +\end_inset + +for any covariant functor +\begin_inset Formula $F$ +\end_inset + +, under assumptions of parametricity. + \end_layout \begin_layout Standard -An equivalent (but not actually simpler) question is to prove that: -\begin_inset Formula -\[ -P\cong\exists A.\,(A\rightarrow A)\rightarrow P\quad. -\] +Note that the last identity already holds for any +\emph on +strictly +\emph default + +\emph on +positive +\emph default + +\begin_inset Formula $F$ +\end_inset +; see Example +\begin_inset space ~ \end_inset -\begin_inset Note Note -status open +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-simplify-quantifier-A-A" +plural "false" +caps "false" +noprefix "false" -\begin_layout Plain Layout -(solved by transitive closure union of relations?) Do I actually have a - solution for this? +\end_inset + +(a). + Solving this problem would show if that identity holds for all covariant + functors +\begin_inset Formula $F$ +\end_inset + + (not necessarily strictly positive). \end_layout +\begin_layout Standard +An equivalent (but not actually simpler) question is to prove that: +\begin_inset Formula +\[ +P\cong\exists A.\,(A\rightarrow A)\rightarrow P\quad. +\] + \end_inset diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index a0c6bdd401e1f0435c0fbd76de4db4483acc64d8..dae874f30a9d63f1a6afad94b0ffbc7ce4abec0f 100644 GIT binary patch delta 183 zcmX?Ra?E7I8WCRe5JLki14An#3vC0#$vZ{#&_uq7JmfVrN=i;lO*YX@O)@sv{7968 zNypsKz`zi!N8P|cU6V`SH$TNCu_RT)#mdOQ$kfol2%%!Ln8am9CpS|=BR4Z6a|2To i3nw>Y3nMopb0ae|150ODV?!4MQ#%_%Dkf`7Ndo|lge|%N delta 183 zcmX?Ra?E7I8WCR85F;ZiLsKgwQ*8sI$vZ{#&_uq7JmgI^F-}P`GPKl9wM (F[X], G[X])!. -If we imagine that {[}X{]} were an ordinary argument (not a type parameter), -we would apply the standard type identities: +If we imagine that \lstinline![X]! were an ordinary argument (not +a type parameter), we would apply the standard type identities: \begin{align*} & A\rightarrow B\times C\cong(A\rightarrow B)\times(A\rightarrow C)\quad,\\ & A\rightarrow R\rightarrow B\cong R\rightarrow A\rightarrow B\quad, @@ -6849,13 +6849,14 @@ \subsubsection{Statement \label{subsec:Statement-general-identities-forall}\ref{ \end{lstlisting} These type formulas are exactly similar to the isomorphisms \textbf{(b)} and \textbf{(c)}. However, \lstinline!X! is a type parameter, not -a value parameter, so it is invalid to use ordinary type identities +a value parameter, and it is invalid to use ordinary type identities such as $A\rightarrow R\rightarrow B\cong R\rightarrow A\rightarrow B$ and assign $A=$ \lstinline![X]!. We need a new proof. \subparagraph{Proof} -\textbf{(a)} This isomorphism is shown in Example~\ref{subsec:Example-undisjunctive-type-constructors}(e). +\textbf{(a)} This isomorphism is proved in Example~\ref{subsec:Example-undisjunctive-type-constructors}(e). + It is a \textsf{``}non-constructive\textsf{''} isomorphism, in the following sense. We can define a function \lstinline!outS! that transforms the left-hand side into the right-hand side: @@ -7001,7 +7002,7 @@ \subsubsection{Statement \label{subsec:Statement-quantifier-across-functor}\ref{ For any strictly positive bifunctor $S$ and any type constructors $P$, $Q$, we have: \[ -\forall A.\,S^{P^{A},Q^{A}}\cong S^{\forall A.\,P^{A},\forall A.\,Q^{A}}\quad. +\forall A.\,S^{P^{A},\,Q^{A}}\cong S^{\forall A.\,P^{A},\,\forall A.\,Q^{A}}\quad. \] Similar identities hold for strictly positive $3$-functors, $4$-functors, etc. @@ -7049,9 +7050,9 @@ \subsubsection{Statement \label{subsec:Statement-quantifier-across-functor}\ref{ that the statement is already true for recursive usages of $F$ under $S$.) We get: \begin{align*} - & \forall A.\,F^{P^{A}}=\forall A.\,S^{P^{A},F^{P^{A}}}\\ -{\color{greenunder}\text{inductive assumption}:}\quad & \cong S^{\forall A.\,P^{A},\gunderline{\forall A.\,F^{P^{A}}}}\\ -{\color{greenunder}\text{inductive assumption}:}\quad & \cong S^{\forall A.\,P^{A},F^{\forall A.\,P^{A}}}=F^{\forall A.\,P^{A}}\quad. + & \forall A.\,F^{P^{A}}=\forall A.\,S^{P^{A},\,F^{P^{A}}}\\ +{\color{greenunder}\text{inductive assumption}:}\quad & \cong S^{\forall A.\,P^{A},\,\gunderline{\forall A.\,F^{P^{A}}}}\\ +{\color{greenunder}\text{inductive assumption}:}\quad & \cong S^{\forall A.\,P^{A},\,F^{\forall A.\,P^{A}}}=F^{\forall A.\,P^{A}}\quad. \end{align*} The identities for bifunctors, $3$-functors, etc., are proved in @@ -7060,7 +7061,7 @@ \subsubsection{Statement \label{subsec:Statement-quantifier-across-functor}\ref{ We will now prove some statements showing miscellaneous additional techniques for simplifying universally quantified types. -\subsubsection{Statement \label{subsec:Statement-Fubini-theorem-1}\ref{subsec:Statement-Fubini-theorem-1} } +\subsubsection{Statement \label{subsec:Statement-Fubini-theorem-1}\ref{subsec:Statement-Fubini-theorem-1}} If any type constructor $F$ is such that $F^{\bbnum 0}\cong\bbnum 0$ then: @@ -7232,7 +7233,9 @@ \subsubsection{Example \label{subsec:Example-complicated-type-equivalence-3}\ref \subsubsection{Example \label{subsec:Example-simplify-quantifier-A-A}\ref{subsec:Example-simplify-quantifier-A-A}} \textbf{(a)} Show that $\forall A.\,F^{A\rightarrow A}\cong F^{\bbnum 1}$ -for any strictly positive functor $F$. +for any strictly positive functor $F$. (See Definition~\ref{subsec:Definition-strictly-positive-functor}.) +It is unknown if this holds for covariant functors $F$ that are not +strictly positive; see Problem~\ref{par:Problem-Peirce-law-1}. \textbf{(b)} Show that for any contrafunctor $F$, the same holds: $\forall A.\,F^{A\rightarrow A}\cong F^{\bbnum 1}$. @@ -8458,9 +8461,9 @@ \subsection{Greatest fixpoints and the Church-co-Yoneda identity\label{subsec:Th the Church encoding type that involves a universally quantified higher-order function. An analogous encoding (with an existentially quantified type) exists for greatest fixpoints. We will now prove some properties -of that encoding.\footnote{This section follows the logic shown in P.~Wadler\textsf{'}s paper \textsf{``}Recursive -types for free\textsf{''} except that the existential types are defined by -Eq.~(\ref{eq:existential-via-universal-Yoneda}) via the universal +of that encoding.\footnote{This section follows the logic given in P.~Wadler\textsf{'}s paper \textsf{``}Recursive +types for free\textsf{''}, except that we \emph{define} existential types +by Eq.~(\ref{eq:existential-via-universal-Yoneda}) via the universal quantifier.} We work with a fixed covariant functor $F$ and denote by $C$ the @@ -8674,7 +8677,7 @@ \subsubsection{Statement \label{subsec:Statement-greatest-fixpoint-Church-encodi For any $F$-coalgebra $A$ with a structure map $u:A\rightarrow F^{A}$, there exists a unique $F$-algebra morphism $\psi_{u}^{A}$ of type -$A\rightarrow C$. The function $\psi_{u}^{A}$ is known as the \textbf{anamorphism}\index{anamorphism} +$A\rightarrow C$. The function $\psi_{u}^{A}$ is known as an \textbf{anamorphism}\index{anamorphism} and was defined as in Statement~\ref{subsec:Statement-coalgebra-morphism-unfold}: \[ \psi_{u}^{A}:A\rightarrow C\quad,\quad\quad\psi_{u}^{A}\triangleq a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\quad. @@ -8895,7 +8898,146 @@ \subsubsection{Statement \label{subsec:Statement-mutually-recursive-greatest-fix \] The formula for $U$ is derived similarly. $\square$ -\chapter{Solutions of some exercises} +\subsection{Summary of type isomorphisms} + +This Appendix has developed various parametricity techniques to prove +a number of type isomorphisms. The results are summarized in Tables~\ref{tab:Type-identities-proved-by-Yoneda}\textendash \ref{tab:Type-identities-for-existential-types}. + +\begin{table}[h] +\begin{centering} +\begin{tabular}{|c|c|} +\hline +\textbf{\footnotesize{}Identity} & \textbf{\footnotesize{}Assumptions}\tabularnewline +\hline +\hline +{\footnotesize{}$\forall A.\,A\rightarrow A\cong\bbnum 1$} & \tabularnewline +\hline +{\footnotesize{}$\forall A.\,A\rightarrow F^{A}\cong F^{\bbnum 1}$} & {\footnotesize{}$F$ is any functor}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,A\times A\rightarrow F^{A}\cong F^{\bbnum 2}$} & {\footnotesize{}$F$ is any functor}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,A\cong\bbnum 0$} & \tabularnewline +\hline +{\footnotesize{}$\forall A.\,F^{A}\cong F^{\bbnum 0}$} & {\footnotesize{}$F$ is any functor}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,H^{A}\cong H^{\bbnum 1}$} & {\footnotesize{}$H$ is any contrafunctor}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,(A\rightarrow P)\rightarrow A\rightarrow Q\cong P\rightarrow Q$} & {\footnotesize{}$P$, $Q$ are fixed types}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,(P\rightarrow A)\rightarrow Q\rightarrow A\cong Q\rightarrow P$} & {\footnotesize{}$P$, $Q$ are fixed types}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,((A\rightarrow P)\rightarrow Q)\rightarrow(A\rightarrow S)\rightarrow R\cong((S\rightarrow P)\rightarrow Q)\rightarrow R$} & {\footnotesize{}$P$, $Q$, $R$, $S$ are fixed types}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,(P\rightarrow A\times Q)\rightarrow(A+R)\times S\cong$$(P\rightarrow Q)\rightarrow(P+R)\times S$} & {\footnotesize{}$P$, $Q$, $R$, $S$ are fixed types}\tabularnewline +\hline +\end{tabular} +\par\end{centering} +\caption{Type isomorphisms proved via Yoneda identities.\label{tab:Type-identities-proved-by-Yoneda}} +\end{table} + +\begin{table} +\begin{centering} +\begin{tabular}{|c|c|c|} +\hline +\textbf{\footnotesize{}Identity} & \textbf{\footnotesize{}Assumptions} & \textbf{\footnotesize{}Source}\tabularnewline +\hline +\hline +{\footnotesize{}$\forall A.\,(F^{A}\rightarrow A)\rightarrow A\cong\mu A.\,F^{A}$} & {\footnotesize{}$F$ is any functor} & {\footnotesize{}Section~\ref{subsec:The-Church-encoding-of-recursive-types}}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,(H^{A}\rightarrow A)\rightarrow A\cong H^{\bbnum 1}$} & {\footnotesize{}$H$ is any contrafunctor} & {\footnotesize{}Statement~\ref{subsec:Example-simplify-quantifier-1-1}}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,(F^{A}\rightarrow A)\rightarrow G^{A}\cong G^{\mu A.\,F^{A}}$} & {\footnotesize{}$F$, $G$ are any functors} & {\footnotesize{}Statement~\ref{subsec:Statement-Church-Yoneda-identity}}\tabularnewline +\hline +{\footnotesize{}$\mu A.\,\mu B.\,F^{A,B}\cong\mu B.\,F^{B,B}$} & {\footnotesize{}$F$ is any bifunctor} & {\footnotesize{}Statement~\ref{subsec:Statement-nested-fixpoints}}\tabularnewline +\hline +{\footnotesize{}}% +\begin{minipage}[c]{0.43\columnwidth}% +\noindent \begin{center} +{\footnotesize{}$\mu A.\,P^{A,\,\mu B.\,Q^{A,B}}\cong$}\\ +{\footnotesize{}$\forall A.\,\forall B.\,(P^{A,B}\rightarrow A)\times(Q^{A,B}\rightarrow B)\rightarrow A$} +\par\end{center}% +\end{minipage} & {\footnotesize{}$P$, $Q$ are any bifunctors} & {\footnotesize{}Statement~\ref{subsec:Statement-nested-fixpoint-under-functor}}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,F^{A}\rightarrow P\cong P$} & {\footnotesize{}If $F^{A}\neq\bbnum 0$ for some $A$} & {\footnotesize{}Statement~\ref{subsec:Statement-application-full-relation}(a)}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,((A\rightarrow A)\rightarrow A)\rightarrow A\cong\bbnum 1+\bbnum 2+\bbnum 3+...$} & {\footnotesize{}~} & {\footnotesize{}Statement~\ref{subsec:Statement-advanced-type-equivalence}}\tabularnewline +\hline +{\footnotesize{}}% +\begin{minipage}[c]{0.43\columnwidth}% +\begin{center} +{\footnotesize{}$\forall A.\,(H^{A}\rightarrow A)\rightarrow F^{A}+G^{A}\cong$}\\ +{\footnotesize{}$(\forall A.\:(H^{A}\rightarrow A)\rightarrow F^{A})+$}\\ +{\footnotesize{}$(\forall A.\:(H^{A}\rightarrow A)\rightarrow G^{A})$} +\par\end{center}% +\end{minipage} & {\footnotesize{}For any $F$, $G$, $H$} & {\footnotesize{}Example~\ref{subsec:Example-undisjunctive-type-constructors}(c)}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,\forall B.\,F^{A,B}\cong\forall B.\,\forall A.\,F^{A,B}$} & {\footnotesize{}For any $F$} & {\footnotesize{}Statement~\ref{subsec:Statement-Fubini-theorem-1}}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,(F^{A}+G^{A})\cong(\forall A.\,F^{A})+(\forall A.\,G^{A})$} & {\footnotesize{}For any $F$, $G$} & {\footnotesize{}Statement~\ref{subsec:Statement-general-identities-forall}(a)}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,(F^{A}\times G^{A})\cong(\forall A.\,F^{A})\times(\forall A.\,G^{A})$} & {\footnotesize{}For any $F$, $G$} & {\footnotesize{}Statement~\ref{subsec:Statement-general-identities-forall}(b)}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,R\rightarrow F^{A}\cong R\rightarrow(\forall A.\,F^{A})$} & {\footnotesize{}For any $F$, $G$} & {\footnotesize{}Statement~\ref{subsec:Statement-general-identities-forall}(c)}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,F^{P^{A}}\cong F^{\forall A.\,P^{A}}$} & {\footnotesize{}$F$ is strictly positive} & {\footnotesize{}Statement~\ref{subsec:Statement-quantifier-across-functor}}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,F^{A}\cong\bbnum 0$ when $F^{\bbnum 0}\cong\bbnum 0$} & {\footnotesize{}$F$ is such that $F^{\bbnum 0}\cong\bbnum 0$} & {\footnotesize{}Statement~\ref{subsec:Statement-Fubini-theorem-1}}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,F^{A\rightarrow A}\cong F^{\bbnum 1}$} & {\footnotesize{}$F$ is strictly positive} & {\footnotesize{}Example~\ref{subsec:Example-simplify-quantifier-A-A}(a)}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,H^{A\rightarrow A}\cong H^{\bbnum 1}$} & {\footnotesize{}$H$ is a contrafunctor} & {\footnotesize{}Example~\ref{subsec:Example-simplify-quantifier-A-A}(b)}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,((A\rightarrow P)\rightarrow A\rightarrow A\cong P$} & {\footnotesize{}$P$ is a fixed type} & {\footnotesize{}Exercise~\ref{par:Problem-Peirce-law}}\tabularnewline +\hline +\end{tabular} +\par\end{centering} +\caption{Type identities proved by other parametricity techniques.\label{tab:Type-identities-proved-by-parametricity}} +\end{table} + +\begin{table}[h] +\begin{centering} +\begin{tabular}{|c|c|c|} +\hline +\textbf{\footnotesize{}Identity} & \textbf{\footnotesize{}Assumptions} & \textbf{\footnotesize{}Source}\tabularnewline +\hline +\hline +{\footnotesize{}$\exists C.\,F^{C}\cong\forall D.\,\big(\forall C.\,(F^{C}\rightarrow D)\big)\rightarrow D$} & {\footnotesize{}For any $F$} & {\footnotesize{}Equation~(\ref{eq:existential-via-universal-Yoneda})}\tabularnewline +\hline +{\footnotesize{}$(\exists C.\,F^{C})\rightarrow R\cong\forall C.\,(F^{C}\rightarrow R)$} & {\footnotesize{}For any $F$, $R$} & {\footnotesize{}Statement~\ref{subsec:Statement-function-extension-rule}}\tabularnewline +\hline +{\footnotesize{}$\exists A.\,F^{A}\cong F^{\bbnum 1}$} & {\footnotesize{}$F$ is any functor} & {\footnotesize{}Statement~\ref{subsec:Statement-co-Yoneda-two-identities-1}(a)}\tabularnewline +\hline +{\footnotesize{}$\exists A.\,H^{A}\cong H^{\bbnum 0}$} & {\footnotesize{}$H$ is any contrafunctor} & {\footnotesize{}Statement~\ref{subsec:Statement-co-Yoneda-two-identities-1}(b)}\tabularnewline +\hline +{\footnotesize{}$\exists A.\,F^{A}\rightarrow A\cong\bbnum 1$} & {\footnotesize{}For any $F$} & {\footnotesize{}Example~\ref{subsec:Example-simple-existential-derivation}}\tabularnewline +\hline +{\footnotesize{}$\exists A.\,(F^{A}+G^{A})\cong(\exists A.\,F^{A})+(\exists A.\,G^{A})$} & {\footnotesize{}For any $F$, $G$} & {\footnotesize{}Example~\ref{subsec:Example-simple-existential-derivation-1-1}(b)}\tabularnewline +\hline +{\footnotesize{}$\exists A.\,\exists B.\,F^{A,B}\cong\exists B.\,\exists A.\,F^{A,B}$} & {\footnotesize{}For any $F$} & {\footnotesize{}Statement~\ref{subsec:Statement-commute-existential}}\tabularnewline +\hline +{\footnotesize{}$\exists A.\,(A\rightarrow F^{A})\times A\cong\nu A.\,F^{A}$} & {\footnotesize{}$F$ is any functor} & {\footnotesize{}Section~\ref{subsec:The-greatest-fixpoints-and-Church-co-Yoneda}}\tabularnewline +\hline +{\footnotesize{}$\exists A.\,(A\rightarrow F^{A})\times G^{A}\cong G^{\nu A.\,F^{A}}$} & {\footnotesize{}$F$, $G$ are any functors} & {\footnotesize{}Statement~\ref{subsec:Statement-Church-co-Yoneda}}\tabularnewline +\hline +{\footnotesize{}$\nu A.\,\nu B.\,F^{A,B}\cong\nu B.\,F^{B,B}$} & {\footnotesize{}$F$ is any bifunctor} & {\footnotesize{}Statement~\ref{subsec:Statement-nested-greatest-fixpoints}}\tabularnewline +\hline +{\footnotesize{}}% +\begin{minipage}[c]{0.43\columnwidth}% +\begin{center} +{\footnotesize{}$\nu A.\,F^{A,\,\nu B.\,G^{A,B}}\cong$}\\ +{\footnotesize{}$\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times A$} +\par\end{center}% +\end{minipage} & {\footnotesize{}$F$, $G$ are any bifunctors} & {\footnotesize{}Statement~\ref{subsec:Statement-mutually-recursive-greatest-fixpoints}}\tabularnewline +\hline +{\footnotesize{}$G^{\exists C.\,F^{C}}\cong\forall D.\,(\forall C.\,F^{C}\rightarrow D)\rightarrow G^{D}$} & {\footnotesize{}Any $F$, any functor $G$} & {\footnotesize{}Exercise~\ref{par:Exercise-additional-16-3}}\tabularnewline +\hline +\end{tabular} +\par\end{centering} +\caption{Type isomorphisms for existential types.\label{tab:Type-identities-for-existential-types}} +\end{table} + + +\chapter{Solutions for selected exercises} \addsec{Chapter \ref{chap:1-Values,-types,-expressions,}} diff --git a/sofp-src/tex/sofp-back-cover-no-bg.tex b/sofp-src/tex/sofp-back-cover-no-bg.tex index d82b24deb..6d4e8b230 100644 --- a/sofp-src/tex/sofp-back-cover-no-bg.tex +++ b/sofp-src/tex/sofp-back-cover-no-bg.tex @@ -25,10 +25,10 @@ practical applications of parametricity. Long and difficult, yet boring explanations are logically -developed in excruciating detail through 1982 +developed in excruciating detail through 1981 Scala code snippets, 233 statements with step-by-step derivations, 105 diagrams, 237 examples -with tested Scala code, and 315 exercises. Discussions +with tested Scala code, and 314 exercises. Discussions build upon each chapter\textsf{'}s material further. Beginners in FP will find tutorials about the \texttt{map}/\texttt{reduce} diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index 00c60a702..88ef7993d 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -761,10 +761,11 @@ \subsection{Appendix~\ref{app:Proofs-of-naturality-parametricity}} all fully parametric code. Those properties are a mathematical expression of the idea that a fully parametric function works \textsf{``}in the same way\textsf{''} for all types. This appendix develops the necessary theory -and technique in order and proves the following results: +and technique to prove a number of results used in other parts of +the book. -A given type constructor may have one fully parametric and lawful -implementation of the \lstinline!Functor! or \lstinline!Contrafunctor! +We show that a given type constructor may have at most one fully parametric +and lawful implementation of the \lstinline!Functor! or \lstinline!Contrafunctor! typeclass instance. (For most other typeclasses, such as \lstinline!Filterable! or \lstinline!Monad!, type constructors often have several inequivalent and lawful typeclass instances.) The unique implementations are used @@ -774,22 +775,23 @@ \subsection{Appendix~\ref{app:Proofs-of-naturality-parametricity}} The lifting methods of any fully parametric bifunctor or profunctor obey the commutativity law such as Eq.~(\ref{eq:f-fmap-fmap-bifunctor-commutativity}). -Any fully parametric expression $t:\forall A.\,Q^{A}$ satisfies the -relational naturality law~(\ref{eq:relational-naturality-law-1}). +The a central theorem from which all applications of parametricity +will follow says that any fully parametric expression $t:\forall A.\,Q^{A}$ +satisfies a relational naturality law~(\ref{eq:relational-naturality-law-1}). In general, the relational naturality law expresses a property of \emph{relations} rather than functions and is not equivalent to any equation satisfied by $t$. The chapter explains how relations are -defined and introduces certain combinators that manipulate relations. -Using those combinators, we obtain an inductive proof of the relational -naturality law (Section~\ref{subsec:Relational-parametricity-theorem}). -This is a central theorem from which all applications of parametricity -will follow. - -Because the relational naturality law is formulated in terms of relations, -it is often hard to use directly. Programmers are more interested -in finding some equation that the expression $t$ satisfies. Several -shortcuts are available that, in most cases, straightforwardly give -such equations. +defined and introduces certain combinators that manipulate relations: +the relational product, co-product, and the \textsf{``}pair mapper\textsf{''} combinators. +Using those combinators and an important technical tool we call \textsf{``}simultaneous +relational lifting\textsf{''} (Definition~\ref{subsec:Definition-simultaneous-relational-lifting}), +we obtain an inductive proof of the relational naturality law (Section~\ref{subsec:Relational-parametricity-theorem}). + +Because the relational naturality law is formulated in terms of relations +rather than functions, it is often hard to use directly. Programmers +are more interested in proving that a fully parametric function satisfies +some equation (a \textsf{``}law\textsf{''}). Several shortcuts are available that, +in most cases, straightforwardly give such equations. One shortcut is the dinaturality law~(\ref{eq:dinaturality-law-for-profunctors}) obeyed by all fully parametric functions of type $P^{A,A}\rightarrow Q^{A,A}$ @@ -807,6 +809,34 @@ \subsection{Appendix~\ref{app:Proofs-of-naturality-parametricity}} gives more information than the ordinary dinaturality law and is simpler to use than the general relational naturality law~(\ref{eq:relational-naturality-law-1}). +The strong dinaturality law is the first of the parametricity techniques +that go beyond Yoneda identities. Section~\ref{subsec:Strong-dinaturality.-General-properties} +is an in-depth study of strongly dinatural transformations. We use +structural analysis to look for possible function types $P^{A,A}\rightarrow Q^{A,A}$ +for which the strong dinaturality law will hold. The results of this +analysis are used for proving properties of Church encodings as well +as in the proof of the type isomorphism between \lstinline!foldMap! +and \lstinline!reduce!. + +Section~\ref{subsec:Universal-type-quantifiers} begins a further +study of parametricity-based techniques for simplifying types that +contain universal quantifiers. The Yoneda identities already provide +such simplifications for a wide range of such types, of which we show +a number of examples. We also show how the universal quantifier and +the function types can encode other type constructions (void type, +unit type, products, co-products, existentially quantified types, +and recursive types). + +The Yoneda identities are an important application of category theory, +which proves an abstract version of the Yoneda identity for all categories. +The most important application to programming are the two Yoneda identities +involving covariant and contravariant functors. Another version is +a Yoneda identity for type constructors (Section~\ref{subsec:The-Yoneda-identities-for-type-constructors}). + +{*}{*}{*} + +A number of resulting type isomorphisms can be found in Tables~\ref{tab:Type-identities-proved-by-Yoneda}\textendash \ref{tab:Type-identities-for-existential-types}. + {*}{*}{*} \setcounter{secnumdepth}{3}% @@ -1227,7 +1257,7 @@ \subsubsection{Exercise \label{par:Exercise-additional-12}\ref{par:Exercise-addi \subsubsection{Exercise \label{par:Problem-monads-1}\ref{par:Problem-monads-1}} -\footnote{This was an open problem but it was solved by Hew Wolff.} +\footnote{This was an open problem solved in 2024 by Hew Wolff (private communication).} Prove that $L^{A}\triangleq\bbnum 1+\underbrace{A\times A\times...\times A}_{n\text{ times}}$ cannot be made into a monad if $n\ge2$. @@ -1266,16 +1296,6 @@ \subsubsection{Exercise \label{par:Exercise-additional-14}\ref{par:Exercise-addi Implement \lstinline!Functor!, \lstinline!Applicative!, and \lstinline!Traversable! instances for \lstinline!Triang!. -\subsubsection{Exercise \label{par:Exercise-additional-15}\ref{par:Exercise-additional-15}} - -Simplify the type $\forall A.\,((A\rightarrow A)\rightarrow A)\rightarrow A$, -or in Scala: -\begin{lstlisting} -def f[A]: ((A => A) => A) => A -\end{lstlisting} -into a type expression that contains no quantifiers. Show how to implement -all possible values of this type. \footnote{See \texttt{\href{https://cstheory.stackexchange.com/questions/53855/}{https://cstheory.stackexchange.com/questions/53855/}}} - \subsubsection{Exercise \label{par:Problem-Peirce-law}\ref{par:Problem-Peirce-law}} Consider the functor $F$ defined by: @@ -1786,7 +1806,19 @@ \subsubsection{Problem \label{par:Problem-Peirce-law-1}\ref{par:Problem-Peirce-l \[ F^{P,Q}\triangleq\forall A.\,((A\rightarrow A)\rightarrow P)\rightarrow Q\cong P\rightarrow Q\quad, \] -where functions of type $F^{P,Q}$ are required to be fully parametric.\footnote{See \texttt{\href{https://cstheory.stackexchange.com/questions/55588/}{https://cstheory.stackexchange.com/questions/55588/}}} +where functions of type $F^{P,Q}$ are required to be fully parametric. + +An equivalent statement\footnote{See \texttt{\href{https://cstheory.stackexchange.com/questions/55588/}{https://cstheory.stackexchange.com/questions/55588/}}} +is: +\[ +\forall A.\,F^{A\rightarrow A}\cong F^{\bbnum 1} +\] +for any covariant functor $F$, under assumptions of parametricity. + +Note that the last identity already holds for any \emph{strictly} +\emph{positive} $F$; see Example~\ref{subsec:Example-simplify-quantifier-A-A}(a). +Solving this problem would show if that identity holds for all covariant +functors $F$ (not necessarily strictly positive). An equivalent (but not actually simpler) question is to prove that: \[ diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 89f5525a8..f4aa476da 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): 16cf89e2cfef216f06713d61d0dfcada2688de9d709b9393c62520ea4fde7c87}\\ -{\scriptsize{}Git commit: c9ddd5d1803ec24b427361309548deed37c915b3}\\ -{\scriptsize{}PDF file built on Sat, 25 Oct 2025 22:15:44 +0200 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): c367278893beba00d55e7cab4805eb79efc4552e15e7a83c42fea00eeb185800}\\ +{\scriptsize{}Git commit: 71477ecd61f32647da1779cb06e10d29b815471c}\\ +{\scriptsize{}PDF file built on Mon, 27 Oct 2025 10:01:46 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, @@ -374,10 +374,10 @@ practical applications of parametricity.}\\ {\scriptsize{}}\\ {\scriptsize{}Long and difficult, yet boring explanations are logically -developed in excruciating detail through 1982 Scala +developed in excruciating detail through 1981 Scala code snippets, 233 statements with step-by-step derivations, 105 diagrams, 237 examples with tested Scala -code, and 315 exercises. Discussions build upon each +code, and 314 exercises. Discussions build upon each chapter's material further.}\\ {\scriptsize{}}\\ {\scriptsize{}Beginners in FP will find tutorials about the map/reduce From 548cc8f5d0465b7f4eac634f9cb1c4195b183f0c Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Mon, 27 Oct 2025 17:04:50 +0100 Subject: [PATCH 13/42] minor corrections --- sofp-src/lyx/sofp-appendices.lyx | 50 +++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/sofp-src/lyx/sofp-appendices.lyx b/sofp-src/lyx/sofp-appendices.lyx index af3ceff26..083951565 100644 --- a/sofp-src/lyx/sofp-appendices.lyx +++ b/sofp-src/lyx/sofp-appendices.lyx @@ -53313,7 +53313,7 @@ separation "3pt" shadowsize "4pt" framecolor "black" backgroundcolor "none" -status collapsed +status open \begin_layout Plain Layout \align center @@ -53327,7 +53327,7 @@ status collapsed \end_inset -\begin_inset Formula $(\forall A.\:(H^{A}\rightarrow A)\rightarrow F^{A})+$ +\begin_inset Formula $(\forall A.\:(H^{A}\rightarrow A)\rightarrow F^{A})\,+$ \end_inset @@ -53594,12 +53594,12 @@ noprefix "false" \begin_layout Plain Layout \size footnotesize -For any +Any \begin_inset Formula $F$ \end_inset -, -\begin_inset Formula $G$ +, a fixed type +\begin_inset Formula $R$ \end_inset @@ -53957,7 +53957,7 @@ status open \begin_layout Plain Layout \align center \begin_inset Tabular - + @@ -54111,6 +54111,40 @@ noprefix "false" \end_inset +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\exists A.\,A\cong\bbnum 1$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + \end_layout \end_inset @@ -54405,7 +54439,7 @@ noprefix "false" \begin_layout Plain Layout \size footnotesize -\begin_inset Formula $\exists A.\,(A\rightarrow F^{A})\times A\cong\nu A.\,F^{A}$ +\begin_inset Formula $\nu A.\,F^{A}\cong\exists A.\,(A\rightarrow F^{A})\times A$ \end_inset @@ -54460,7 +54494,7 @@ noprefix "false" \begin_layout Plain Layout \size footnotesize -\begin_inset Formula $\exists A.\,(A\rightarrow F^{A})\times G^{A}\cong G^{\nu A.\,F^{A}}$ +\begin_inset Formula $G^{\nu A.\,F^{A}}\cong\exists A.\,(A\rightarrow F^{A})\times G^{A}$ \end_inset From f31bad889f111a005acc97c441d660b5dea21d5d Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Mon, 27 Oct 2025 21:45:40 +0100 Subject: [PATCH 14/42] overview of the appendix --- sofp-src/lyx/sofp-appendices.lyx | 106 ++++++- sofp-src/lyx/sofp-summary.lyx | 449 +++++++++++++++++++++++++++++- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-appendices.tex | 21 +- sofp-src/tex/sofp.tex | 6 +- 5 files changed, 559 insertions(+), 23 deletions(-) diff --git a/sofp-src/lyx/sofp-appendices.lyx b/sofp-src/lyx/sofp-appendices.lyx index 083951565..efb608fc1 100644 --- a/sofp-src/lyx/sofp-appendices.lyx +++ b/sofp-src/lyx/sofp-appendices.lyx @@ -29643,11 +29643,11 @@ noprefix "false" \end_inset -\series bold +\end_layout -\begin_inset Formula $\quad$ -\end_inset +\begin_layout Standard +\series bold (b) \series default @@ -29745,11 +29745,11 @@ noprefix "false" (b) \series default The type signature -\begin_inset Formula $\forall A.\,(F^{A}\rightarrow G^{A})\rightarrow L^{A,A}$ +\begin_inset Formula $(F^{A}\rightarrow G^{A})\rightarrow L^{A,A}$ \end_inset needs to be expressed as -\begin_inset Formula $\forall A.\,K^{A,A}\rightarrow L^{A,A}$ +\begin_inset Formula $K^{A,A}\rightarrow L^{A,A}$ \end_inset with some profunctor @@ -29757,11 +29757,11 @@ noprefix "false" \end_inset . - We define + Then we can write \begin_inset Formula $K^{X,Y}\triangleq M^{Y,X}\rightarrow N^{X,Y}$ \end_inset - with suitably chosen profunctors + with the profunctors \begin_inset Formula $M$ \end_inset @@ -29769,7 +29769,7 @@ noprefix "false" \begin_inset Formula $N$ \end_inset -. + chosen appropriately. Reasoning as before, we find that the profunctors \begin_inset Formula $M$ \end_inset @@ -32320,7 +32320,17 @@ bound type parameter \emph on free \emph default - in the type expression + +\begin_inset Index idx +status open + +\begin_layout Plain Layout +free type parameter +\end_layout + +\end_inset + +in the type expression \begin_inset Formula $F^{X}$ \end_inset @@ -36733,6 +36743,13 @@ noprefix "false" \begin_layout Subsection The Church-Yoneda identity and its applications +\begin_inset CommandInset label +LatexCommand label +name "subsec:The-Church-Yoneda-identity" + +\end_inset + + \end_layout \begin_layout Standard @@ -38178,6 +38195,13 @@ noprefix "false" \begin_layout Subsection Non-disjunctive type constructors +\begin_inset CommandInset label +LatexCommand label +name "subsec:Non-disjunctive-type-constructors" + +\end_inset + + \end_layout \begin_layout Standard @@ -48094,6 +48118,13 @@ It follows that \begin_layout Subsection Existential type quantifiers. Co-Yoneda identities +\begin_inset CommandInset label +LatexCommand label +name "subsec:Existential-type-quantifiers" + +\end_inset + + \end_layout \begin_layout Standard @@ -52741,7 +52772,7 @@ status open \begin_layout Plain Layout \align center \begin_inset Tabular - + @@ -52900,6 +52931,61 @@ noprefix "false" \begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $\forall A.\,(A\rightarrow A)\rightarrow H^{A}\cong H^{\bbnum 1}$ +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $H$ +\end_inset + + is any contrafunctor +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +Example +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-strong-dinaturality-show-void" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +(b) +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + \size footnotesize \begin_inset Formula $\forall A.\,(F^{A}\rightarrow A)\rightarrow G^{A}\cong G^{\mu A.\,F^{A}}$ \end_inset diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 35921f42e..7d353a08a 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -6120,11 +6120,250 @@ noprefix "false" \end_layout \begin_layout Standard -*** +We turn to further applications of parametricity that go beyond what the + Yoneda identities can achieve. + Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:The-Church-encoding-of-recursive-types" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + gives full proofs of the Church encoding of a recursive type defined as + the least fixpoint ( +\begin_inset Formula $\mu A.\,F^{A}$ +\end_inset + +) of a pattern functor +\begin_inset Formula $F$ +\end_inset + +. + It is also shown (Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-existence-of-church-encoding-type" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +) that the least fixpoint is non-void if and only if the type +\begin_inset Formula $F^{\bbnum 0}$ +\end_inset + + is non-void. + This section develops the machinery of +\begin_inset Formula $F$ +\end_inset + +-functor algebras, catamorphisms, and defining the recursive type +\begin_inset Formula $\mu A.\,F^{A}$ +\end_inset + + via the standard functions +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +fix +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +unfix +\end_layout + +\end_inset + +. \end_layout \begin_layout Standard -A number of resulting type isomorphisms can be found in Tables +Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:The-Church-Yoneda-identity" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + proves a useful isomorphism that generalizes both the Church encoding and + the Yoneda identity: +\begin_inset Formula +\[ +G^{\mu A.\,F^{A}}\cong\forall A.\,(F^{A}\rightarrow A)\rightarrow G^{A}\quad. +\] + +\end_inset + +In this book, this is called the +\begin_inset Quotes eld +\end_inset + +Church-Yoneda +\begin_inset Quotes erd +\end_inset + + identity. + One application of that identity is in proving the +\begin_inset Quotes eld +\end_inset + +nested fixpoint lemma +\begin_inset Quotes erd +\end_inset + + (Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-nested-fixpoints" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +): +\begin_inset Formula +\[ +\mu A.\,(\mu B.\,N^{A,B})\cong\mu B.\,N^{B,B}\quad. +\] + +\end_inset + +Another is to establish the formula for the Church encoding of mutually + recursive types (Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Least-fixpoints-of-mutually-recursive-types" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). +\end_layout + +\begin_layout Standard +A general property of universal quantifiers is distributivity with respect + to products, co-products, and function types (Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-general-identities-forall" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). + Distributivity with respect to co-products, +\begin_inset Formula +\[ +\forall A.\,F^{A}+G^{A}\cong(\forall A.\,F^{A})+(\forall A.\,G^{A})\quad, +\] + +\end_inset + +can be generalized to the following isomorphism, +\begin_inset Formula +\[ +\forall A.\,P^{A}\rightarrow F^{A}+G^{A}\cong(\forall A.\,P^{A}\rightarrow F^{A})+(\forall A.\,P^{A}\rightarrow G^{A})\quad, +\] + +\end_inset + +where the type constructor +\begin_inset Formula $P$ +\end_inset + + must satisfy the property we call +\begin_inset Quotes eld +\end_inset + +non-disjunctivity +\begin_inset Quotes erd +\end_inset + +. + Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Non-disjunctive-type-constructors" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + gives a formal definition of that property and goes through structural + analysis, discovering what type constructors are non-disjunctive. + Several examples of non-disjunctive type constructors are shown in Example +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-undisjunctive-type-constructors" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +. +\end_layout + +\begin_layout Standard +These techniques allow us to derive a number of properties of types with + universal quantifiers. + Tables \begin_inset space ~ \end_inset @@ -6146,13 +6385,97 @@ plural "false" caps "false" noprefix "false" +\end_inset + + summarize the type isomorphisms proved in this Appendix by those techniques. +\end_layout + +\begin_layout Standard +The final sections of the Appendix study the Jaskelioff-O'Connor theorem + and its applications to problems raised in this book. + One of those applications is a proof that the identity function of type + +\begin_inset Formula $\forall A.\,M^{A}\rightarrow M^{A}$ +\end_inset + + is the only monad morphism between a monad +\begin_inset Formula $M$ +\end_inset + + and itself that obeys the monadic naturality law with respect to +\begin_inset Formula $M$ \end_inset . + This property means that the non-degeneracy law of base runners (derived + in Chapter +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "chap:monad-transformers" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +) is always satisfied automatically, and so we do not need to verify that + law. \end_layout \begin_layout Standard -*** +We turn to a brief study of existentially quantified types. + Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Existential-type-quantifiers" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + proves the two co-Yoneda identities and establishes some fundamental properties + of existential types. + Then Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:The-greatest-fixpoints-and-Church-co-Yoneda" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + shows that the greatest fixpoints are given by the Church encoding: +\begin_inset Formula +\[ +\nu A.\,F^{A}\cong\exists A.\,(A\rightarrow F^{A})\times A\quad, +\] + +\end_inset + +and proves the Church-co-Yoneda identity: +\begin_inset Formula +\[ +G^{\nu A.\,F^{A}}\cong\exists A.\,(A\rightarrow F^{A})\times G^{A}\quad. +\] + +\end_inset + +This identity allows us to derive the nested fixpoint lemma and the mutual + recursion formula for the greatest fixpoints. \end_layout \begin_layout Standard @@ -6178,7 +6501,7 @@ Restore the normal numbering of subsections and subsubsections \end_inset - +) \end_layout \begin_layout Section @@ -9613,7 +9936,7 @@ not ). \begin_inset Note Note -status collapsed +status open \begin_layout Plain Layout If @@ -9735,6 +10058,122 @@ G^{\exists C.\,F^{C}}\cong\forall D.\,(\forall C.\,F^{C}\rightarrow D)\rightarro \end_inset +\end_layout + +\begin_layout Subsubsection +Exercise +\begin_inset CommandInset label +LatexCommand label +name "par:Exercise-additional-16-3-1" + +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "par:Exercise-additional-16-3-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\begin_layout Standard +This is a generalization of Example +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-strong-dinaturality-show-void" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +. +\end_layout + +\begin_layout Standard + +\series bold +(a) +\series default + For any (covariant) functors +\begin_inset Formula $F$ +\end_inset + + and +\begin_inset Formula $G$ +\end_inset + +, show that: +\begin_inset Formula +\[ +\forall A.\,(A\times G^{A}\rightarrow A)\rightarrow F^{A}\cong F^{\bbnum 0}\quad. +\] + +\end_inset + + +\end_layout + +\begin_layout Standard + +\series bold +(b) +\series default + For any contrafunctor +\begin_inset Formula $H$ +\end_inset + + and a type constructor +\begin_inset Formula $G$ +\end_inset + + that is either covariant or contravariant, show that: +\begin_inset Formula +\[ +\forall A.\,(G^{A}\rightarrow A)\rightarrow H^{A}\cong H^{\bbnum 1}\quad. +\] + +\end_inset + + +\begin_inset Note Note +status open + +\begin_layout Plain Layout +Follow the proof of that example. + Since +\begin_inset Formula $G$ +\end_inset + + is either covariant or contravariant, we can use the strong dinaturality + law. + The same +\begin_inset Formula $f$ +\end_inset + +, +\begin_inset Formula $p$ +\end_inset + +, +\begin_inset Formula $q$ +\end_inset + + will work. +\end_layout + +\end_inset + + \end_layout \begin_layout Subsubsection diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index dae874f30a9d63f1a6afad94b0ffbc7ce4abec0f..fe69fa147e7851ffe01fd87414cfe3538a28ab82 100644 GIT binary patch delta 142 zcmX?Ra?E7IdJ%SWD?>9YW8=x&L`>l9k0MWaQxYxAEsabpbyJhfk~cpRf&T-WZ`7#X6kBb=;Ul+X<_7MXG2KEWNj&F E09#ZgtpET3 delta 142 zcmX?Ra?E7IdJ%R5D+5C-Ba6w~L`>l9k0MWa4ULkL6H}8-bW@Xz4K_a#2UW@cn=U}|FFFjE3=we`MXG2KEWNj&F E08@Y^Bme*a diff --git a/sofp-src/tex/sofp-appendices.tex b/sofp-src/tex/sofp-appendices.tex index 117e6da0f..4776a1b83 100644 --- a/sofp-src/tex/sofp-appendices.tex +++ b/sofp-src/tex/sofp-appendices.tex @@ -8951,8 +8951,11 @@ \subsection{Summary of type isomorphisms} {\footnotesize{}$\mu A.\,\mu B.\,F^{A,B}\cong\mu B.\,F^{B,B}$} & {\footnotesize{}$F$ is any bifunctor} & {\footnotesize{}Statement~\ref{subsec:Statement-nested-fixpoints}}\tabularnewline \hline {\footnotesize{}}% +\begin{minipage}[c][12mm][t]{0.1mm}% +% +\end{minipage}{\footnotesize{}}% \begin{minipage}[c]{0.43\columnwidth}% -\noindent \begin{center} +\begin{center} {\footnotesize{}$\mu A.\,P^{A,\,\mu B.\,Q^{A,B}}\cong$}\\ {\footnotesize{}$\forall A.\,\forall B.\,(P^{A,B}\rightarrow A)\times(Q^{A,B}\rightarrow B)\rightarrow A$} \par\end{center}% @@ -8963,10 +8966,13 @@ \subsection{Summary of type isomorphisms} {\footnotesize{}$\forall A.\,((A\rightarrow A)\rightarrow A)\rightarrow A\cong\bbnum 1+\bbnum 2+\bbnum 3+...$} & {\footnotesize{}~} & {\footnotesize{}Statement~\ref{subsec:Statement-advanced-type-equivalence}}\tabularnewline \hline {\footnotesize{}}% +\begin{minipage}[c][17mm][t]{0.1mm}% +% +\end{minipage}{\footnotesize{}}% \begin{minipage}[c]{0.43\columnwidth}% \begin{center} {\footnotesize{}$\forall A.\,(H^{A}\rightarrow A)\rightarrow F^{A}+G^{A}\cong$}\\ -{\footnotesize{}$(\forall A.\:(H^{A}\rightarrow A)\rightarrow F^{A})+$}\\ +{\footnotesize{}$(\forall A.\:(H^{A}\rightarrow A)\rightarrow F^{A})\,+$}\\ {\footnotesize{}$(\forall A.\:(H^{A}\rightarrow A)\rightarrow G^{A})$} \par\end{center}% \end{minipage} & {\footnotesize{}For any $F$, $G$, $H$} & {\footnotesize{}Example~\ref{subsec:Example-undisjunctive-type-constructors}(c)}\tabularnewline @@ -8977,7 +8983,7 @@ \subsection{Summary of type isomorphisms} \hline {\footnotesize{}$\forall A.\,(F^{A}\times G^{A})\cong(\forall A.\,F^{A})\times(\forall A.\,G^{A})$} & {\footnotesize{}For any $F$, $G$} & {\footnotesize{}Statement~\ref{subsec:Statement-general-identities-forall}(b)}\tabularnewline \hline -{\footnotesize{}$\forall A.\,R\rightarrow F^{A}\cong R\rightarrow(\forall A.\,F^{A})$} & {\footnotesize{}For any $F$, $G$} & {\footnotesize{}Statement~\ref{subsec:Statement-general-identities-forall}(c)}\tabularnewline +{\footnotesize{}$\forall A.\,R\rightarrow F^{A}\cong R\rightarrow(\forall A.\,F^{A})$} & {\footnotesize{}Any $F$, a fixed type $R$} & {\footnotesize{}Statement~\ref{subsec:Statement-general-identities-forall}(c)}\tabularnewline \hline {\footnotesize{}$\forall A.\,F^{P^{A}}\cong F^{\forall A.\,P^{A}}$} & {\footnotesize{}$F$ is strictly positive} & {\footnotesize{}Statement~\ref{subsec:Statement-quantifier-across-functor}}\tabularnewline \hline @@ -9005,6 +9011,8 @@ \subsection{Summary of type isomorphisms} \hline {\footnotesize{}$(\exists C.\,F^{C})\rightarrow R\cong\forall C.\,(F^{C}\rightarrow R)$} & {\footnotesize{}For any $F$, $R$} & {\footnotesize{}Statement~\ref{subsec:Statement-function-extension-rule}}\tabularnewline \hline +{\footnotesize{}$\exists A.\,A\cong\bbnum 1$} & & \tabularnewline +\hline {\footnotesize{}$\exists A.\,F^{A}\cong F^{\bbnum 1}$} & {\footnotesize{}$F$ is any functor} & {\footnotesize{}Statement~\ref{subsec:Statement-co-Yoneda-two-identities-1}(a)}\tabularnewline \hline {\footnotesize{}$\exists A.\,H^{A}\cong H^{\bbnum 0}$} & {\footnotesize{}$H$ is any contrafunctor} & {\footnotesize{}Statement~\ref{subsec:Statement-co-Yoneda-two-identities-1}(b)}\tabularnewline @@ -9015,13 +9023,16 @@ \subsection{Summary of type isomorphisms} \hline {\footnotesize{}$\exists A.\,\exists B.\,F^{A,B}\cong\exists B.\,\exists A.\,F^{A,B}$} & {\footnotesize{}For any $F$} & {\footnotesize{}Statement~\ref{subsec:Statement-commute-existential}}\tabularnewline \hline -{\footnotesize{}$\exists A.\,(A\rightarrow F^{A})\times A\cong\nu A.\,F^{A}$} & {\footnotesize{}$F$ is any functor} & {\footnotesize{}Section~\ref{subsec:The-greatest-fixpoints-and-Church-co-Yoneda}}\tabularnewline +{\footnotesize{}$\nu A.\,F^{A}\cong\exists A.\,(A\rightarrow F^{A})\times A$} & {\footnotesize{}$F$ is any functor} & {\footnotesize{}Section~\ref{subsec:The-greatest-fixpoints-and-Church-co-Yoneda}}\tabularnewline \hline -{\footnotesize{}$\exists A.\,(A\rightarrow F^{A})\times G^{A}\cong G^{\nu A.\,F^{A}}$} & {\footnotesize{}$F$, $G$ are any functors} & {\footnotesize{}Statement~\ref{subsec:Statement-Church-co-Yoneda}}\tabularnewline +{\footnotesize{}$G^{\nu A.\,F^{A}}\cong\exists A.\,(A\rightarrow F^{A})\times G^{A}$} & {\footnotesize{}$F$, $G$ are any functors} & {\footnotesize{}Statement~\ref{subsec:Statement-Church-co-Yoneda}}\tabularnewline \hline {\footnotesize{}$\nu A.\,\nu B.\,F^{A,B}\cong\nu B.\,F^{B,B}$} & {\footnotesize{}$F$ is any bifunctor} & {\footnotesize{}Statement~\ref{subsec:Statement-nested-greatest-fixpoints}}\tabularnewline \hline {\footnotesize{}}% +\begin{minipage}[c][12mm][t]{0.1mm}% +% +\end{minipage}{\footnotesize{}}% \begin{minipage}[c]{0.43\columnwidth}% \begin{center} {\footnotesize{}$\nu A.\,F^{A,\,\nu B.\,G^{A,B}}\cong$}\\ diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index f4aa476da..46a0e546e 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): c367278893beba00d55e7cab4805eb79efc4552e15e7a83c42fea00eeb185800}\\ -{\scriptsize{}Git commit: 71477ecd61f32647da1779cb06e10d29b815471c}\\ -{\scriptsize{}PDF file built on Mon, 27 Oct 2025 10:01:46 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): b43d0d17c2f973432a5c7d08f6f0968c0a3998ac5b93e2f1d9b7afac611a021f}\\ +{\scriptsize{}Git commit: 548cc8f5d0465b7f4eac634f9cb1c4195b183f0c}\\ +{\scriptsize{}PDF file built on Mon, 27 Oct 2025 17:16:51 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From 89b6dc7cdbf12072f49f0698b4ea0e178fb9f20d Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Wed, 29 Oct 2025 23:13:17 +0100 Subject: [PATCH 15/42] add a table for non-disjunctive type constructors --- sofp-src/lyx/sofp-appendices.lyx | 16197 ++++++++++++----------- sofp-src/lyx/sofp-summary.lyx | 129 +- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-appendices.tex | 3012 ++--- sofp-src/tex/sofp-back-cover-no-bg.tex | 2 +- sofp-src/tex/sofp-summary.tex | 89 +- sofp-src/tex/sofp.tex | 8 +- 7 files changed, 9951 insertions(+), 9486 deletions(-) diff --git a/sofp-src/lyx/sofp-appendices.lyx b/sofp-src/lyx/sofp-appendices.lyx index efb608fc1..e7f13a5f8 100644 --- a/sofp-src/lyx/sofp-appendices.lyx +++ b/sofp-src/lyx/sofp-appendices.lyx @@ -41129,823 +41129,773 @@ noprefix "false" \end_layout \begin_layout Standard -We will now show some application of these techniques. -\end_layout - -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-application-full-relation" - +Table +\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-application-full-relation" +reference "tab:Non-disjunctive-type-constructions" plural "false" caps "false" noprefix "false" \end_inset + shows some formulas for non-disjunctive type constructors that follow from + Statement +\begin_inset space ~ +\end_inset -\end_layout -\begin_layout Standard -Suppose -\begin_inset Formula $F$ -\end_inset +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-undisjunctive-type-constructors-structural" +plural "false" +caps "false" +noprefix "false" - is any lifting-to-full type constructor that is not identically void ( -\begin_inset Formula $F^{A}\neq\bbnum 0$ \end_inset - for some -\begin_inset Formula $A$ + and Example +\begin_inset space ~ \end_inset -). - Under assumptions of parametricity, we have the following type isomorphisms: -\end_layout - -\begin_layout Standard - -\series bold -(a) -\series default - For any fixed type -\begin_inset Formula $P$ -\end_inset -: -\begin_inset Formula -\[ -\forall A.\,F^{A}\rightarrow P\cong P\quad. -\] +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-undisjunctive-type-constructors" +plural "false" +caps "false" +noprefix "false" \end_inset - +. \end_layout \begin_layout Standard +\begin_inset Float table +wide false +sideways false +status open -\series bold -(b) -\series default - An analogous identity does -\emph on -not -\emph default - hold for two nested types: -\begin_inset Formula -\[ -\forall A.\,(F^{A}\rightarrow P_{1})\rightarrow P_{2}\not\cong P_{1}\rightarrow P_{2}\quad. -\] +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + + +\begin_inset Text -\end_inset +\begin_layout Plain Layout +\series bold +\size footnotesize +Construction +\end_layout -\begin_inset Note Note -status collapsed +\end_inset + + +\begin_inset Text \begin_layout Plain Layout \series bold -(c) -\series default - For any fixed types -\begin_inset Formula $P_{1}$ -\end_inset +\size footnotesize +Assumptions +\end_layout -, -\begin_inset Formula $P_{2}$ \end_inset + + + + +\begin_inset Text -, etc.: -\begin_inset Formula -\begin{align*} - & \forall A.\,((F^{A}\rightarrow P_{1})\rightarrow P_{2})\rightarrow P_{3}\cong(P_{1}\rightarrow P_{2})\rightarrow P_{3}\quad,\\ - & \forall A.\,((((F^{A}\rightarrow P_{1})\rightarrow P_{2})\rightarrow P_{3})\rightarrow P_{4})\rightarrow P_{5}\cong(((P_{1}\rightarrow P_{2})\rightarrow P_{3})\rightarrow P_{4})\rightarrow P_{5}\quad, -\end{align*} +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $F^{A}\triangleq A$ \end_inset -and so on, for any -\emph on -odd -\emph default - number of nested functions and fixed types. - - Proof seems complicated, not clear. + \end_layout \end_inset + + +\begin_inset Text +\begin_layout Plain Layout \end_layout -\begin_layout Subparagraph -Proof -\end_layout +\end_inset + + + + +\begin_inset Text -\begin_layout Standard +\begin_layout Plain Layout -\series bold -(a) -\series default - Choose an arbitrary type -\begin_inset Formula $A$ +\size footnotesize +\begin_inset Formula $F^{A}\triangleq G^{A}\rightarrow A$ \end_inset - such that -\begin_inset Formula $P^{A}\neq\bbnum 0$ -\end_inset - and a value -\begin_inset Formula $h:\forall A.\,F^{A}\rightarrow P$ -\end_inset +\end_layout -. - We will show that -\begin_inset Formula $h$ \end_inset + + +\begin_inset Text - must be a constant function, returning a fixed value of type -\begin_inset Formula $P$ +\begin_layout Plain Layout + +\size footnotesize +For any +\begin_inset Formula $G^{A}$ \end_inset -. -\end_layout -\begin_layout Standard -It will be convenient to view -\begin_inset Formula $P$ -\end_inset +\end_layout - as the result of applying a constant functor to the type parameter -\begin_inset Formula $A$ \end_inset + + + + +\begin_inset Text -. - Let us denote that functor temporarily by -\begin_inset Formula $G$ -\end_inset +\begin_layout Plain Layout -, and the functor -\begin_inset Formula $F^{A}\rightarrow P$ +\size footnotesize +\begin_inset Formula $F^{A}\triangleq G^{A}\rightarrow H^{A}$ \end_inset - by -\begin_inset Formula $H$ -\end_inset -: -\begin_inset Formula -\[ -G^{A}\triangleq P\quad,\quad\quad H^{A}\triangleq F^{A}\rightarrow P\quad,\quad\quad\forall H^{A}=\forall A.\,F^{A}\rightarrow P=\forall A.\,F^{A}\rightarrow G^{A}\quad. -\] +\end_layout \end_inset + + +\begin_inset Text -By assumption, -\begin_inset Formula $F$ -\end_inset +\begin_layout Plain Layout - is lifting-to-full, so for any types -\begin_inset Formula $A$ +\size footnotesize +For any +\begin_inset Formula $G^{A}$ \end_inset -, -\begin_inset Formula $B$ + and any lifting-to-full +\begin_inset Formula $H^{A}$ \end_inset - we may choose a relation -\begin_inset Formula $r^{:A\leftrightarrow B}$ -\end_inset - such that -\begin_inset Formula $r^{\updownarrow F}=\Omega$ -\end_inset +\end_layout -. - Then the relational naturality law of -\begin_inset Formula $h$ \end_inset + + + + +\begin_inset Text - says that for any -\begin_inset Formula $x^{:F^{A}}$ -\end_inset +\begin_layout Plain Layout -and -\begin_inset Formula $y^{:F^{B}}$ +\size footnotesize +\begin_inset Formula $F^{A}\triangleq A\times G^{A}\rightarrow H^{A}$ \end_inset -: -\begin_inset Formula -\[ -\text{when }(x,y)\in r^{\updownarrow F}\text{ then }(h^{A}(x),h^{B}(y))\in r^{\updownarrow G}\quad. -\] -\end_inset +\end_layout -The precondition -\begin_inset Formula $(x,y)\in r^{\updownarrow F}$ \end_inset + + +\begin_inset Text - holds for all -\begin_inset Formula $x$ +\begin_layout Plain Layout + +\size footnotesize +For any +\begin_inset Formula $G^{A}$ \end_inset and -\begin_inset Formula $y$ +\begin_inset Formula $H^{A}$ \end_inset - because -\begin_inset Formula $r^{\updownarrow F}=\Omega$ -\end_inset -. - The lifting of any relation to a constant functor ( -\begin_inset Formula $r^{\updownarrow G}$ -\end_inset +\end_layout -) is an identity relation ( -\begin_inset Formula $\text{id}^{:P\leftrightarrow P}$ \end_inset + + + + +\begin_inset Text -). - We conclude that -\begin_inset Formula $h^{A}(x)=h^{B}(y)$ -\end_inset +\begin_layout Plain Layout - for all -\begin_inset Formula $x$ +\size footnotesize +\begin_inset Formula $F^{A}\triangleq(Z+G^{A}\rightarrow A\times H^{A})\rightarrow K^{A}$ \end_inset - and -\begin_inset Formula $y$ + +\end_layout + \end_inset + + +\begin_inset Text -, which means that -\begin_inset Formula $h$ +\begin_layout Plain Layout + +\size footnotesize +For any +\begin_inset Formula $G^{A}$ \end_inset - is a constant function ( -\begin_inset Formula $h^{A}=\_^{:F^{A}}\rightarrow p_{0}$ +, +\begin_inset Formula $H^{A}$ \end_inset -) determined by a chosen value -\begin_inset Formula $p_{0}^{:P}$ +, +\begin_inset Formula $K^{A}$ \end_inset - independently of the type parameter -\begin_inset Formula $A$ +, and any fixed type +\begin_inset Formula $Z$ \end_inset -. - -\end_layout -\begin_layout Standard -Since -\begin_inset Formula $F^{A}\neq\bbnum 0$ -\end_inset +\end_layout -, no two constant functions -\begin_inset Formula $\_^{:F^{A}}\rightarrow p_{0}$ \end_inset + + + + +\begin_inset Text - for different -\begin_inset Formula $p_{0}$ -\end_inset +\begin_layout Plain Layout - are ever equal to each other. - It follows that values -\begin_inset Formula $p_{0}$ +\size footnotesize +\begin_inset Formula $F^{A}\triangleq((L^{A}\rightarrow Z+G^{A})\rightarrow A\times H^{A})\rightarrow K^{A}$ \end_inset - of type -\begin_inset Formula $P$ -\end_inset - are in a one-to-one correspondence with functions -\begin_inset Formula $h$ -\end_inset +\end_layout - of type -\begin_inset Formula $\forall A.\,F^{A}\rightarrow P$ \end_inset - - that satisfy the relational naturality law. - This proves the required type equivalence. -\begin_inset Note Note -status open + + +\begin_inset Text \begin_layout Plain Layout -\series bold -(c) -\series default - Not clear if this method will give a proof! Choose arbitrary types -\begin_inset Formula $A$ +\size footnotesize +For any +\begin_inset Formula $G^{A}$ \end_inset , -\begin_inset Formula $B$ +\begin_inset Formula $H^{A}$ \end_inset -. - Since -\begin_inset Formula $F$ +, +\begin_inset Formula $K^{A}$ \end_inset - is lifting-to-full, there exists a relation -\begin_inset Formula $r^{:A\leftrightarrow B}$ +, +\begin_inset Formula $L^{A}$ \end_inset - such that -\begin_inset Formula $r^{\updownarrow F}=\Omega$ +, and any fixed type +\begin_inset Formula $Z$ \end_inset -. - In item -\series bold -(a) -\series default - we have analyzed the subset of functions -\begin_inset Formula $h:F^{A}\rightarrow P$ -\end_inset - that obey the relational naturality law and found a one-to-one correspondence - between those -\begin_inset Formula $h$ -\end_inset +\end_layout - and values of type -\begin_inset Formula $P$ \end_inset + + + -. - We will now extend this approach to types that we will denote by -\begin_inset Formula $H_{n}$ \end_inset - and -\begin_inset Formula $T_{n}$ -\end_inset - for brevity: -\begin_inset Formula -\begin{align*} - & T_{1}^{A}\triangleq F^{A}\rightarrow P_{1}\quad,\quad\quad T_{n+1}^{A}\triangleq T_{n}^{A}\rightarrow P_{n+1}\quad\text{ for }n=1,2,...\quad,\\ - & H_{1}\triangleq P_{1}\quad,\quad\quad H_{n+1}\triangleq H_{n}\rightarrow P_{n+1}\quad\text{ for }n=1,2,...\quad. -\end{align*} +\end_layout -\end_inset +\begin_layout Plain Layout +\begin_inset Caption Standard -So, for example, -\begin_inset Formula $H_{3}=(P_{1}\rightarrow P_{2})\rightarrow P_{3}$ -\end_inset +\begin_layout Plain Layout +Lifting-to-full type constructors. +\begin_inset CommandInset label +LatexCommand label +name "tab:Non-disjunctive-type-constructions" - and -\begin_inset Formula $T_{3}^{A}=((F^{A}\rightarrow P_{1})\rightarrow P_{2})\rightarrow P_{3}$ \end_inset -. - The property we need to prove is formulated as: -\begin_inset Formula -\[ -\forall A.\,T_{2n+1}^{A}\cong H_{2n+1}\quad\quad\text{ for }n=1,2,...\quad, -\] -\end_inset +\end_layout -assuming that all values -\begin_inset Formula $t_{2n+1}:\forall A.\,T_{2n+1}^{A}$ \end_inset - satisfy the relational law: -\begin_inset Formula -\begin{align*} - & (t_{2n+1}^{A},t_{2n+1}^{A})\in r^{\updownarrow T_{2n+1}}\quad,\quad\quad\text{which means}:\\ - & \forall x_{2n}:T_{2n}^{A},\,\forall y_{2n}:T_{2n}^{A},\quad\text{ if }(x_{2n},y_{2n})\in r^{\updownarrow T_{2n}}\quad\text{then}\quad t_{2n+1}(x_{2n})=t_{2n+1}(y_{2n})\quad. -\end{align*} -\end_inset +\end_layout +\begin_layout Plain Layout \end_layout -\begin_layout Plain Layout -For each -\begin_inset Formula $h_{n}:H_{n}$ \end_inset - and for each type -\begin_inset Formula $A$ -\end_inset -, we now define a certain subset -\begin_inset Formula $U_{n}^{A}(h_{n})$ -\end_inset +\end_layout - of values of type -\begin_inset Formula $T_{n}^{A}$ -\end_inset +\begin_layout Standard +We will now show some application of these techniques. +\end_layout - like this: -\begin_inset Formula -\[ -x_{n}\in U_{n}^{A}(h_{n})\quad\text{if}\quad\forall h_{n-1}:H_{n-1}\text{ we have }x_{n}(x_{n-1})=h_{n}(h_{n-1})\text{ for }\forall x_{n-1}\in U_{n-1}^{A}(h_{n-1})\quad. -\] +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-application-full-relation" \end_inset -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-application-full-relation" +plural "false" +caps "false" +noprefix "false" -\begin_layout Plain Layout -It turns out that all values in the subsets -\begin_inset Formula $U_{n}^{A}(h_{n})$ \end_inset - always belong to the relation -\begin_inset Formula $r^{\updownarrow T_{n}}$ -\end_inset -. - More precisely, let us prove that: -\begin_inset Formula -\[ -\forall x_{n}\in U_{n}^{A}(h_{n}),\forall y_{n}\in U_{n}^{B}(h_{n}):\quad(x_{n},y_{n})\in r^{\updownarrow T_{n}}\quad\quad\text{ for }n=1,2,... -\] +\end_layout +\begin_layout Standard +Suppose +\begin_inset Formula $F$ \end_inset -Begin with -\begin_inset Formula $n=1$ + is any lifting-to-full type constructor that is not identically void ( +\begin_inset Formula $F^{A}\neq\bbnum 0$ \end_inset -, and define -\begin_inset Formula $U_{1}^{A}(h_{1})$ + for some +\begin_inset Formula $A$ \end_inset - to be the set of constant functions returning -\begin_inset Formula $h_{1}$ +). + Under assumptions of parametricity, we have the following type isomorphisms: +\end_layout + +\begin_layout Standard + +\series bold +(a) +\series default + For any fixed type +\begin_inset Formula $P$ \end_inset : \begin_inset Formula \[ -x_{1}:F^{A}\rightarrow P_{1}\quad,\quad\quad x_{1}\in U_{1}^{A}(h_{1})\quad\text{means}\quad x_{1}=\_^{:F^{A}}\rightarrow h_{1}\quad. +\forall A.\,F^{A}\rightarrow P\cong P\quad. \] \end_inset -The sets -\begin_inset Formula $U_{1}^{A}(h_{1})$ -\end_inset - contain exactly one function for each -\begin_inset Formula $h_{1}$ -\end_inset +\end_layout + +\begin_layout Standard -. - As we have seen in the proof of item \series bold -(a) +(b) \series default -, all pairs of such functions are in the relation -\begin_inset Formula $r^{\updownarrow T_{1}}$ -\end_inset - -. - -\end_layout - -\begin_layout Plain Layout -Now use induction in -\begin_inset Formula $n$ -\end_inset - - and consider -\begin_inset Formula $n\ge2$ -\end_inset - -. - The condition for -\begin_inset Formula $(x_{n},y_{n})\in r^{\updownarrow T_{n}}$ -\end_inset - - is: + An analogous identity does +\emph on +not +\emph default + hold for two nested types: \begin_inset Formula \[ -\forall x_{n-1}:T_{n-1}^{A},\,\forall y_{n-1}:T_{n-1}^{B},\quad\text{if}\quad(x_{n-1},y_{n-1})\in r^{\updownarrow T_{n-1}}\quad\text{then}\quad x_{n}(x_{n-1})=y_{n}(y_{n-1})\quad. +\forall A.\,(F^{A}\rightarrow P_{1})\rightarrow P_{2}\not\cong P_{1}\rightarrow P_{2}\quad. \] \end_inset -Given some -\begin_inset Formula $h_{n}:H_{n}$ -\end_inset -, we need to prove that -\begin_inset Formula $(x_{n},y_{n})\in r^{\updownarrow T_{n}}$ -\end_inset +\begin_inset Note Note +status collapsed - for all -\begin_inset Formula $x_{n}\in U_{n}^{A}(h_{n})$ +\begin_layout Plain Layout + +\series bold +(c) +\series default + For any fixed types +\begin_inset Formula $P_{1}$ \end_inset - and for all -\begin_inset Formula $y_{n}\in U_{n}^{B}(h_{n})$ +, +\begin_inset Formula $P_{2}$ \end_inset -. - The inductive assumption is: +, etc.: \begin_inset Formula -\[ -\forall h_{n-1}:H_{n-1},\,\forall x_{n-1}\in U_{n-1}^{A}(h_{n-1}),\,\forall y_{n-1}\in U_{n-1}^{B}(h_{n-1}),\,\quad(x_{n-1},y_{n-1})\in r^{\updownarrow T_{n-1}}\quad. -\] +\begin{align*} + & \forall A.\,((F^{A}\rightarrow P_{1})\rightarrow P_{2})\rightarrow P_{3}\cong(P_{1}\rightarrow P_{2})\rightarrow P_{3}\quad,\\ + & \forall A.\,((((F^{A}\rightarrow P_{1})\rightarrow P_{2})\rightarrow P_{3})\rightarrow P_{4})\rightarrow P_{5}\cong(((P_{1}\rightarrow P_{2})\rightarrow P_{3})\rightarrow P_{4})\rightarrow P_{5}\quad, +\end{align*} \end_inset - not clear how to continue +and so on, for any +\emph on +odd +\emph default + number of nested functions and fixed types. + - Proof seems complicated, not clear. \end_layout -\begin_layout Plain Layout -Finally, we show that each of the odd-numbered subsets -\begin_inset Formula $U_{2n+1}(h_{2n+1})$ \end_inset - has just one element: a single function of type -\begin_inset Formula $\forall A.\,T_{2n+1}^{A}$ -\end_inset - that satisfies the relational law. - \end_layout -\begin_layout Plain Layout -We will also show that any function -\begin_inset Formula $x_{2n+1}:\forall A.\,T_{2n+1}^{A}$ +\begin_layout Subparagraph +Proof +\end_layout + +\begin_layout Standard + +\series bold +(a) +\series default + Choose an arbitrary type +\begin_inset Formula $A$ \end_inset - that satisfies the relational law will belong to one of the subsets -\begin_inset Formula $U_{2n+1}(h_{2n+1})$ + such that +\begin_inset Formula $P^{A}\neq\bbnum 0$ \end_inset - for some choice of -\begin_inset Formula $h_{2n+1}:H_{2n+1}$ + and a value +\begin_inset Formula $h:\forall A.\,F^{A}\rightarrow P$ \end_inset . - This will establish a one-to-one correspondence between the types -\begin_inset Formula $\forall A.\,T_{2n+1}^{A}$ + We will show that +\begin_inset Formula $h$ \end_inset - and -\begin_inset Formula $H_{2n+1}$ + must be a constant function, returning a fixed value of type +\begin_inset Formula $P$ \end_inset . \end_layout +\begin_layout Standard +It will be convenient to view +\begin_inset Formula $P$ \end_inset + as the result of applying a constant functor to the type parameter +\begin_inset Formula $A$ +\end_inset -\end_layout +. + Let us denote that functor temporarily by +\begin_inset Formula $G$ +\end_inset -\begin_layout Standard +, and the functor +\begin_inset Formula $F^{A}\rightarrow P$ +\end_inset -\series bold -(b) -\series default - To show a counterexample, take -\begin_inset Formula $F^{A}\triangleq A$ + by +\begin_inset Formula $H$ \end_inset -; then +: +\begin_inset Formula +\[ +G^{A}\triangleq P\quad,\quad\quad H^{A}\triangleq F^{A}\rightarrow P\quad,\quad\quad\forall H^{A}=\forall A.\,F^{A}\rightarrow P=\forall A.\,F^{A}\rightarrow G^{A}\quad. +\] + +\end_inset + +By assumption, \begin_inset Formula $F$ \end_inset - is lifting-to-full with -\begin_inset Formula $r=\Omega$ + is lifting-to-full, so for any types +\begin_inset Formula $A$ \end_inset -. - All type expressions with an even nesting depth, such as -\begin_inset Formula $(F^{A}\rightarrow P_{1})\rightarrow P_{2}$ +, +\begin_inset Formula $B$ \end_inset -, will be covariant in -\begin_inset Formula $A$ + we may choose a relation +\begin_inset Formula $r^{:A\leftrightarrow B}$ \end_inset -. - By Statement -\begin_inset space ~ + such that +\begin_inset Formula $r^{\updownarrow F}=\Omega$ \end_inset +. + Then the relational naturality law of +\begin_inset Formula $h$ +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-simplify-forall-F" -plural "false" -caps "false" -noprefix "false" + says that for any +\begin_inset Formula $x^{:F^{A}}$ +\end_inset +and +\begin_inset Formula $y^{:F^{B}}$ \end_inset -(a), we will have: +: \begin_inset Formula -\begin{align*} - & \forall A.\,(F^{A}\rightarrow P_{1})\rightarrow P_{2}=(F^{\bbnum 0}\rightarrow P_{1})\rightarrow P_{2}\\ - & =(\bbnum 0\rightarrow P_{1})\rightarrow P_{2}\cong\bbnum 1\rightarrow P_{2}\cong P_{2}\quad. -\end{align*} +\[ +\text{when }(x,y)\in r^{\updownarrow F}\text{ then }(h^{A}(x),h^{B}(y))\in r^{\updownarrow G}\quad. +\] \end_inset -The type -\begin_inset Formula $P_{2}$ +The precondition +\begin_inset Formula $(x,y)\in r^{\updownarrow F}$ \end_inset - is not isomorphic to -\begin_inset Formula $P_{1}\rightarrow P_{2}$ + holds for all +\begin_inset Formula $x$ \end_inset -. -\end_layout + and +\begin_inset Formula $y$ +\end_inset -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Example-simplify-quantifier-1-1" + because +\begin_inset Formula $r^{\updownarrow F}=\Omega$ +\end_inset +. + The lifting of any relation to a constant functor ( +\begin_inset Formula $r^{\updownarrow G}$ \end_inset +) is an identity relation ( +\begin_inset Formula $\text{id}^{:P\leftrightarrow P}$ +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Example-simplify-quantifier-1-1" -plural "false" -caps "false" -noprefix "false" +). + We conclude that +\begin_inset Formula $h^{A}(x)=h^{B}(y)$ +\end_inset + for all +\begin_inset Formula $x$ \end_inset + and +\begin_inset Formula $y$ +\end_inset -\end_layout +, which means that +\begin_inset Formula $h$ +\end_inset -\begin_layout Standard -If -\begin_inset Formula $H$ + is a constant function ( +\begin_inset Formula $h^{A}=\_^{:F^{A}}\rightarrow p_{0}$ \end_inset - is a contrafunctor then -\begin_inset Formula $\forall A.\,(H^{A}\rightarrow A)\rightarrow A\cong H^{\bbnum 1}$ +) determined by a chosen value +\begin_inset Formula $p_{0}^{:P}$ \end_inset -. -\end_layout + independently of the type parameter +\begin_inset Formula $A$ +\end_inset -\begin_layout Subparagraph -Proof +. + \end_layout \begin_layout Standard -Consider the type constructor -\begin_inset Formula $F^{A,B}\triangleq(H^{B}\rightarrow A)\rightarrow A$ +Since +\begin_inset Formula $F^{A}\neq\bbnum 0$ \end_inset -; our goal is to simplify -\begin_inset Formula $\forall A.\,F^{A,A}$ +, no two constant functions +\begin_inset Formula $\_^{:F^{A}}\rightarrow p_{0}$ \end_inset -. - Since -\begin_inset Formula $F^{A,B}$ + for different +\begin_inset Formula $p_{0}$ \end_inset - is contravariant in -\begin_inset Formula $B$ + are ever equal to each other. + It follows that values +\begin_inset Formula $p_{0}$ \end_inset -, we may use the contravariant Yoneda identity: -\begin_inset Formula -\[ -F^{A,B}\cong\forall C.\,(C\rightarrow B)\rightarrow F^{A,C}=\forall C.\,(C\rightarrow B)\rightarrow(H^{C}\rightarrow A)\rightarrow A\quad. -\] - + of type +\begin_inset Formula $P$ \end_inset -Now substitute -\begin_inset Formula $B=A$ + are in a one-to-one correspondence with functions +\begin_inset Formula $h$ \end_inset - and write: -\begin_inset Formula -\begin{align*} - & \forall A.\,F^{A,A}=\gunderline{\forall A.\,\forall C.\,}(C\rightarrow A)\rightarrow(H^{C}\rightarrow A)\rightarrow A\\ -\text{swap the order of quantifiers}:\quad & \cong\forall C.\,\forall A.\,(\gunderline C\rightarrow A)\rightarrow(\gunderline{H^{C}}\rightarrow A)\rightarrow A\\ -\text{uncurry arguments}:\quad & \cong\forall C.\,\forall A.\,(C+H^{C}\rightarrow A)\rightarrow A\\ -\text{covariant Yoneda identity}:\quad & \cong\forall C.\,C+H^{C}\\ -\text{non-disjunctivity}:\quad & \cong(\forall C.\,C)+(\forall C.\,H^{C})\\ -\text{simplify each part}:\quad & \cong\bbnum 0+H^{\bbnum 1}\cong H^{\bbnum 1}\quad. -\end{align*} - + of type +\begin_inset Formula $\forall A.\,F^{A}\rightarrow P$ \end_inset + that satisfy the relational naturality law. + This proves the required type equivalence. +\begin_inset Note Note +status collapsed -\end_layout +\begin_layout Plain Layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-advanced-type-equivalence" +\series bold +(c) +\series default + Not clear if this method will give a proof! Choose arbitrary types +\begin_inset Formula $A$ +\end_inset +, +\begin_inset Formula $B$ \end_inset +. + Since +\begin_inset Formula $F$ +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-advanced-type-equivalence" -plural "false" -caps "false" -noprefix "false" + is lifting-to-full, there exists a relation +\begin_inset Formula $r^{:A\leftrightarrow B}$ +\end_inset + such that +\begin_inset Formula $r^{\updownarrow F}=\Omega$ \end_inset +. + In item +\series bold +(a) +\series default + we have analyzed the subset of functions +\begin_inset Formula $h:F^{A}\rightarrow P$ +\end_inset -\end_layout + that obey the relational naturality law and found a one-to-one correspondence + between those +\begin_inset Formula $h$ +\end_inset -\begin_layout Standard -Under assumptions of parametricity: -\begin_inset Formula -\[ -\forall A.\,((A\rightarrow A)\rightarrow A)\rightarrow A=T\cong\bbnum 1+\bbnum 2+\bbnum 3+...\quad. -\] + and values of type +\begin_inset Formula $P$ +\end_inset +. + We will now extend this approach to types that we will denote by +\begin_inset Formula $H_{n}$ \end_inset -The -\begin_inset Quotes eld + and +\begin_inset Formula $T_{n}$ \end_inset -infinite -\begin_inset Quotes erd + for brevity: +\begin_inset Formula +\begin{align*} + & T_{1}^{A}\triangleq F^{A}\rightarrow P_{1}\quad,\quad\quad T_{n+1}^{A}\triangleq T_{n}^{A}\rightarrow P_{n+1}\quad\text{ for }n=1,2,...\quad,\\ + & H_{1}\triangleq P_{1}\quad,\quad\quad H_{n+1}\triangleq H_{n}\rightarrow P_{n+1}\quad\text{ for }n=1,2,...\quad. +\end{align*} + \end_inset - type in the right-hand side is understood as the type of pairs of natural - numbers -\begin_inset Formula $\left(n,k\right)$ +So, for example, +\begin_inset Formula $H_{3}=(P_{1}\rightarrow P_{2})\rightarrow P_{3}$ \end_inset - such that -\begin_inset Formula $n\ge k\ge1$ + and +\begin_inset Formula $T_{3}^{A}=((F^{A}\rightarrow P_{1})\rightarrow P_{2})\rightarrow P_{3}$ \end_inset . - The value -\begin_inset Formula $n$ -\end_inset + The property we need to prove is formulated as: +\begin_inset Formula +\[ +\forall A.\,T_{2n+1}^{A}\cong H_{2n+1}\quad\quad\text{ for }n=1,2,...\quad, +\] - points to the part -\begin_inset Formula $\bbnum n$ \end_inset - of the disjunctive type; the value -\begin_inset Formula $k$ +assuming that all values +\begin_inset Formula $t_{2n+1}:\forall A.\,T_{2n+1}^{A}$ \end_inset - is one of the values of type -\begin_inset Formula $\bbnum n$ + satisfy the relational law: +\begin_inset Formula +\begin{align*} + & (t_{2n+1}^{A},t_{2n+1}^{A})\in r^{\updownarrow T_{2n+1}}\quad,\quad\quad\text{which means}:\\ + & \forall x_{2n}:T_{2n}^{A},\,\forall y_{2n}:T_{2n}^{A},\quad\text{ if }(x_{2n},y_{2n})\in r^{\updownarrow T_{2n}}\quad\text{then}\quad t_{2n+1}(x_{2n})=t_{2n+1}(y_{2n})\quad. +\end{align*} + \end_inset -. + \end_layout -\begin_layout Standard -A value of type -\begin_inset Formula $T$ +\begin_layout Plain Layout +For each +\begin_inset Formula $h_{n}:H_{n}$ \end_inset - corresponding to the pair -\begin_inset Formula $\left(n,k\right)$ + and for each type +\begin_inset Formula $A$ \end_inset - and applied to the type parameter -\begin_inset Formula $A$ +, we now define a certain subset +\begin_inset Formula $U_{n}^{A}(h_{n})$ \end_inset - can be written as: + of values of type +\begin_inset Formula $T_{n}^{A}$ +\end_inset + + like this: \begin_inset Formula \[ -t_{n,k}^{A}\triangleq p^{:(A\rightarrow A)\rightarrow A}\rightarrow p(a_{1}^{:A}\rightarrow p(a_{2}^{:A}\rightarrow...\rightarrow p(a_{n}^{:A}\rightarrow a_{k})...))\quad. +x_{n}\in U_{n}^{A}(h_{n})\quad\text{if}\quad\forall h_{n-1}:H_{n-1}\text{ we have }x_{n}(x_{n-1})=h_{n}(h_{n-1})\text{ for }\forall x_{n-1}\in U_{n-1}^{A}(h_{n-1})\quad. \] \end_inset @@ -41953,322 +41903,231 @@ t_{n,k}^{A}\triangleq p^{:(A\rightarrow A)\rightarrow A}\rightarrow p(a_{1}^{:A} \end_layout -\begin_layout Subparagraph -Proof -\begin_inset Foot -status open - \begin_layout Plain Layout -See -\family typewriter - -\begin_inset CommandInset href -LatexCommand href -target "https://cstheory.stackexchange.com/questions/53855/" -literal "false" - +It turns out that all values in the subsets +\begin_inset Formula $U_{n}^{A}(h_{n})$ \end_inset - -\end_layout - + always belong to the relation +\begin_inset Formula $r^{\updownarrow T_{n}}$ \end_inset - -\end_layout - -\begin_layout Standard -Rewrite the given type using various type identities: +. + More precisely, let us prove that: \begin_inset Formula -\begin{align*} - & \forall A.\,((\gunderline A\rightarrow A)\rightarrow A)\rightarrow A\\ -\text{Yoneda identity}:\quad & \cong\forall A.\,\forall B.\,\gunderline{(B\rightarrow A)\rightarrow((B\rightarrow A)\rightarrow A)}\rightarrow A\\ -\text{uncurry}:\quad & \cong\forall A.\,\forall B.\,(\gunderline B\rightarrow A)\times(\gunderline{(B\rightarrow A)}\rightarrow A)\rightarrow A\\ -\text{distributive law of }(\times):\quad & \cong\forall A.\,\forall B.\,(B+(B\rightarrow A)\rightarrow A)\rightarrow A\\ -\text{define }F^{B,X}\triangleq B+(B\rightarrow X):\quad & =\forall A.\,\forall B.\,(F^{B,A}\rightarrow A)\rightarrow A\\ - & =\forall B.\,\forall A.\,(F^{B,A}\rightarrow A)\rightarrow A\\ -\text{Church encoding}:\quad & =\forall B.\,\mu A.\,F^{B,A}\quad. -\end{align*} +\[ +\forall x_{n}\in U_{n}^{A}(h_{n}),\forall y_{n}\in U_{n}^{B}(h_{n}):\quad(x_{n},y_{n})\in r^{\updownarrow T_{n}}\quad\quad\text{ for }n=1,2,... +\] \end_inset -Denote for convenience the recursive type -\begin_inset Formula $T^{B}\triangleq\mu A.\,F^{B,A}$ +Begin with +\begin_inset Formula $n=1$ \end_inset - and unroll the recursion a few times: -\begin_inset Formula -\begin{align*} - & \forall B.\,T^{B}\cong\forall B.\,B+(B\rightarrow T^{B})\\ -\text{non-disjunctivity}:\quad & \cong(\forall B.\,B)+(\forall B.\,B\rightarrow T^{B})\cong\bbnum 0+\forall B.\,B\rightarrow T^{B}\\ -\text{unroll again}:\quad & \cong\forall B.\,B\rightarrow B+(B\rightarrow T^{B})\quad. -\end{align*} - +, and define +\begin_inset Formula $U_{1}^{A}(h_{1})$ \end_inset -Note that the identity functor ( -\begin_inset Formula $\text{Id}^{B}\triangleq B$ + to be the set of constant functions returning +\begin_inset Formula $h_{1}$ \end_inset -) is non-disjunctive, so we have: +: \begin_inset Formula \[ -\forall B.\,B\rightarrow P^{B}+Q^{B}\cong(\forall B.\,B\rightarrow P^{B})+(\forall B.\,B\rightarrow Q^{B})\quad. +x_{1}:F^{A}\rightarrow P_{1}\quad,\quad\quad x_{1}\in U_{1}^{A}(h_{1})\quad\text{means}\quad x_{1}=\_^{:F^{A}}\rightarrow h_{1}\quad. \] \end_inset -It follows that: -\begin_inset Formula -\begin{align*} - & \forall B.\,B\rightarrow B+(B\rightarrow T^{B})\cong(\gunderline{\forall B.\,B\rightarrow B})+(\forall B.\,\gunderline{B\rightarrow B}\rightarrow T^{B})\\ -\text{simplify, uncurry}:\quad & \cong\bbnum 1+\forall B.\,B\times B\rightarrow T^{B}\\ -\text{unroll again}:\quad & \cong\bbnum 1+\forall B.\,B\times B\rightarrow B+(B\rightarrow T^{B})\quad. -\end{align*} - +The sets +\begin_inset Formula $U_{1}^{A}(h_{1})$ \end_inset -The functor -\begin_inset Formula $B\times B$ + contain exactly one function for each +\begin_inset Formula $h_{1}$ \end_inset - is non-disjunctive (see Example -\begin_inset space ~ +. + As we have seen in the proof of item +\series bold +(a) +\series default +, all pairs of such functions are in the relation +\begin_inset Formula $r^{\updownarrow T_{1}}$ \end_inset +. + +\end_layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Example-undisjunctive-type-constructors" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout +Now use induction in +\begin_inset Formula $n$ +\end_inset + and consider +\begin_inset Formula $n\ge2$ \end_inset -d). - So, we may continue reducing the type as: -\begin_inset Formula -\begin{align*} - & \bbnum 1+\forall B.\,B\times B\rightarrow B+(B\rightarrow T^{B})\cong\bbnum 1+(\gunderline{\forall B.\,B\times B\rightarrow B})+(\forall B.\,\gunderline{B\times B\rightarrow B}\rightarrow T^{B})\\ - & \cong\bbnum 1+\bbnum 2+\forall B.\,B\times B\times B\rightarrow T^{B}\quad. -\end{align*} - -\end_inset - -Continue using induction to show that -\begin_inset Formula $\forall B.\:T^{B}\cong\bbnum 1+\bbnum 2+\bbnum 3+...$ +. + The condition for +\begin_inset Formula $(x_{n},y_{n})\in r^{\updownarrow T_{n}}$ \end_inset -, where the infinite co-product implies a suitable recursively defined type. -\begin_inset Note Note -status collapsed - -\begin_layout Plain Layout -Not clear. - Long and complicated, not sure what this brings. -\end_layout - -\begin_layout Plain Layout -Let us define for brevity: + is: \begin_inset Formula \[ -F^{B,X}\triangleq B+(R\rightarrow(P\rightarrow B)\rightarrow Q\times X)\quad. +\forall x_{n-1}:T_{n-1}^{A},\,\forall y_{n-1}:T_{n-1}^{B},\quad\text{if}\quad(x_{n-1},y_{n-1})\in r^{\updownarrow T_{n-1}}\quad\text{then}\quad x_{n}(x_{n-1})=y_{n}(y_{n-1})\quad. \] \end_inset -Rewrite the given type using various type identities, and define: -\begin_inset Formula -\begin{align*} - & \forall A.\,((R\times(P\rightarrow A)\rightarrow Q\times A)\rightarrow A)\rightarrow A\\ -\text{Yoneda identity}:\quad & \cong\forall A.\,\forall B.\,\gunderline{(B\rightarrow A)\rightarrow((R\rightarrow(P\rightarrow B)\rightarrow Q\times A)\rightarrow A)}\rightarrow A\\ -\text{uncurry}:\quad & \cong\forall A.\,\forall B.\,(\gunderline B\rightarrow A)\times(\gunderline{(R\rightarrow(P\rightarrow B)\rightarrow Q\times A)}\rightarrow A)\rightarrow A\\ -\text{type identity}:\quad & \cong\forall A.\,\forall B.\,(\gunderline{B+(R\rightarrow(P\rightarrow B)\rightarrow Q\times A)}\rightarrow A)\rightarrow A\\ -\text{definition of }F:\quad & =\forall A.\,\forall B.\,(F^{B,A}\rightarrow A)\rightarrow A=\forall B.\,\gunderline{\forall A.\,(F^{B,A}\rightarrow A)\rightarrow A}\\ -\text{Church encoding}:\quad & =\forall B.\,\mu A.\,F^{B,A}\quad. -\end{align*} - -\end_inset - - -\begin_inset Formula -\begin{align*} - & \text{Let }\mu X.\,F^{B,X}=T^{B}\quad\text{and}\quad\forall B.\,T^{B}=U_{0}\quad.\quad\text{Then}:\quad U_{0}=\forall B.\,B+(R\rightarrow(P\rightarrow B)\rightarrow Q\times T^{B})\quad.\\ - & =\forall B.\,R\rightarrow(P\rightarrow B)\rightarrow Q\times T^{B}=\big(\forall B.\,R\rightarrow(P\rightarrow B)\rightarrow Q\big)\times\big(\gunderline{\forall B.\,R\rightarrow(P\rightarrow B)\rightarrow T^{B}}\big)\triangleq(R\rightarrow Q)\times U_{1}\\ - & =(R\rightarrow Q)\times\big(\forall B.\,R\rightarrow(P\rightarrow B)\rightarrow B+(R\rightarrow(P\rightarrow B)\rightarrow Q\times T^{B})\big)\\ - & =(R\rightarrow Q)\times(\forall B.\,R\rightarrow(P\rightarrow B)\rightarrow B)+(R\rightarrow Q)\times\big(\forall B.\,R\rightarrow(P\rightarrow B)\rightarrow(P\rightarrow B)\rightarrow Q\big)\times U_{2}\\ - & =(R\rightarrow Q)\times(R\rightarrow P)+(R\rightarrow Q)\times(R\rightarrow Q)\times U_{2}\quad, -\end{align*} - -\end_inset - -where we defined: -\begin_inset Formula -\[ -U_{n}\triangleq\forall B.\,R\rightarrow\underbrace{(P\rightarrow B)\rightarrow...\rightarrow(P\rightarrow B)}_{n\text{ times}}\rightarrow T^{B}\quad. -\] - +Given some +\begin_inset Formula $h_{n}:H_{n}$ \end_inset -We can express each -\begin_inset Formula $U_{i}$ +, we need to prove that +\begin_inset Formula $(x_{n},y_{n})\in r^{\updownarrow T_{n}}$ \end_inset - via -\begin_inset Formula $U_{i+1}$ + for all +\begin_inset Formula $x_{n}\in U_{n}^{A}(h_{n})$ \end_inset - like this: -\begin_inset Formula -\begin{align*} - & U_{0}=(R\rightarrow Q)\times U_{1}\quad,\\ - & U_{1}=(R\rightarrow P)+(R\rightarrow Q)\times U_{2}\quad,\\ - & U_{2}=(R\rightarrow P)\times\bbnum 2+(R\rightarrow Q)\times U_{3}\quad, -\end{align*} - + and for all +\begin_inset Formula $y_{n}\in U_{n}^{B}(h_{n})$ \end_inset -and so on. - By induction, we obtain: +. + The inductive assumption is: \begin_inset Formula \[ -U_{0}=(R\rightarrow P)\times\big((R\rightarrow Q)+\bbnum 2\times(\bbnum 2\rightarrow R\rightarrow Q)+\bbnum 3\times(\bbnum 3\rightarrow R\rightarrow Q)+... +\forall h_{n-1}:H_{n-1},\,\forall x_{n-1}\in U_{n-1}^{A}(h_{n-1}),\,\forall y_{n-1}\in U_{n-1}^{B}(h_{n-1}),\,\quad(x_{n-1},y_{n-1})\in r^{\updownarrow T_{n-1}}\quad. \] \end_inset - + not clear how to continue \end_layout +\begin_layout Plain Layout +Finally, we show that each of the odd-numbered subsets +\begin_inset Formula $U_{2n+1}(h_{2n+1})$ \end_inset - -\begin_inset Formula $\square$ + has just one element: a single function of type +\begin_inset Formula $\forall A.\,T_{2n+1}^{A}$ \end_inset - + that satisfies the relational law. + \end_layout -\begin_layout Standard -There exist complicated quantified types that cannot be simplified by any - of the techniques shown in this Appendix. - An example is the codensity monad -\begin_inset Index idx -status open - \begin_layout Plain Layout -monads!codensity monad -\end_layout - +We will also show that any function +\begin_inset Formula $x_{2n+1}:\forall A.\,T_{2n+1}^{A}$ \end_inset - on -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -Option -\end_layout - + that satisfies the relational law will belong to one of the subsets +\begin_inset Formula $U_{2n+1}(h_{2n+1})$ \end_inset -: -\begin_inset Formula -\[ -\text{Cod}_{\text{Opt}}^{A}\triangleq\forall R.\,(A\rightarrow\bbnum 1+R)\rightarrow\bbnum 1+R\quad. -\] - + for some choice of +\begin_inset Formula $h_{2n+1}:H_{2n+1}$ \end_inset -It can be proved using methods of dependent type theory -\begin_inset Foot -status open +. + This will establish a one-to-one correspondence between the types +\begin_inset Formula $\forall A.\,T_{2n+1}^{A}$ +\end_inset -\begin_layout Plain Layout -See -\family typewriter + and +\begin_inset Formula $H_{2n+1}$ +\end_inset -\begin_inset CommandInset href -LatexCommand href -target "https://stackoverflow.com/questions/75178350/" -literal "false" +. +\end_layout \end_inset \end_layout +\begin_layout Standard + +\series bold +(b) +\series default + To show a counterexample, take +\begin_inset Formula $F^{A}\triangleq A$ \end_inset - that -\begin_inset Formula $\text{Cod}_{\text{Opt}}^{A}\cong(A\rightarrow\bbnum 2)\rightarrow\bbnum 1+A$ +; then +\begin_inset Formula $F$ \end_inset - with the additional restriction that values -\begin_inset Formula $q:(A\rightarrow\bbnum 2)\rightarrow\bbnum 1+A$ + is lifting-to-full with +\begin_inset Formula $r=\Omega$ \end_inset - must satisfy: -\begin_inset Formula $q(p^{:A\rightarrow\bbnum 2})=\bbnum 0+x^{:A}$ +. + All type expressions with an even nesting depth, such as +\begin_inset Formula $(F^{A}\rightarrow P_{1})\rightarrow P_{2}$ \end_inset - only if -\begin_inset Formula $p(x)=True$ +, will be covariant in +\begin_inset Formula $A$ \end_inset . - This restriction on values can be encoded in a type signature only via - dependent types. -\end_layout + By Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-simplify-forall-F" +plural "false" +caps "false" +noprefix "false" -\begin_layout Standard -So, -\begin_inset Formula $\text{Cod}_{\text{Opt}}^{A}$ \end_inset - is an example of a universally quantified type that cannot be reduced to - an ordinary (non-dependent, non-quantified) type. - There seems to be no simplification that could apply to types of the form - -\begin_inset Formula $\forall R.\,(A\rightarrow F^{R})\rightarrow G^{R}$ +(a), we will have: +\begin_inset Formula +\begin{align*} + & \forall A.\,(F^{A}\rightarrow P_{1})\rightarrow P_{2}=(F^{\bbnum 0}\rightarrow P_{1})\rightarrow P_{2}\\ + & =(\bbnum 0\rightarrow P_{1})\rightarrow P_{2}\cong\bbnum 1\rightarrow P_{2}\cong P_{2}\quad. +\end{align*} + \end_inset - with arbitrary -\begin_inset Formula $F$ +The type +\begin_inset Formula $P_{2}$ \end_inset - and -\begin_inset Formula $G$ + is not isomorphic to +\begin_inset Formula $P_{1}\rightarrow P_{2}$ \end_inset . \end_layout -\begin_layout Subsection -Other properties of universally quantified types -\end_layout - -\begin_layout Standard -We continue exploring various techniques that are useful for simplifying - universally quantified types under assumptions of parametricity. - In most cases, we can avoid using the parametricity theorem directly. -\end_layout - \begin_layout Subsubsection Statement \begin_inset CommandInset label LatexCommand label -name "subsec:Statement-isomorphism-under-type-constructor" +name "subsec:Example-simplify-quantifier-1-1" \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-isomorphism-under-type-constructor" +reference "subsec:Example-simplify-quantifier-1-1" plural "false" caps "false" noprefix "false" @@ -42279,796 +42138,762 @@ noprefix "false" \end_layout \begin_layout Standard - -\series bold -(a) -\series default - Suppose -\begin_inset Formula $F$ -\end_inset - - is a fully parametric type constructor (but not necessarily covariant or - contravariant). - Let -\begin_inset Formula $P$ -\end_inset - -, -\begin_inset Formula $Q$ +If +\begin_inset Formula $H$ \end_inset - be two types with a known isomorphism -\begin_inset Formula $P\cong Q$ + is a contrafunctor then +\begin_inset Formula $\forall A.\,(H^{A}\rightarrow A)\rightarrow A\cong H^{\bbnum 1}$ \end_inset . - Then -\begin_inset Formula $F^{P}\cong F^{Q}$ -\end_inset +\end_layout -. +\begin_layout Subparagraph +Proof \end_layout \begin_layout Standard +Consider the type constructor +\begin_inset Formula $F^{A,B}\triangleq(H^{B}\rightarrow A)\rightarrow A$ +\end_inset -\series bold -(b) -\series default - Suppose -\begin_inset Formula $F$ -\end_inset - - and -\begin_inset Formula $G$ +; our goal is to simplify +\begin_inset Formula $\forall A.\,F^{A,A}$ \end_inset - are type constructors such that -\begin_inset Formula $F^{A}\cong G^{A}$ +. + Since +\begin_inset Formula $F^{A,B}$ \end_inset - for all types -\begin_inset Formula $A$ + is contravariant in +\begin_inset Formula $B$ \end_inset -. - Then: +, we may use the contravariant Yoneda identity: \begin_inset Formula \[ -\forall A.\,F^{A}\cong\forall A.\,G^{A}\quad. +F^{A,B}\cong\forall C.\,(C\rightarrow B)\rightarrow F^{A,C}=\forall C.\,(C\rightarrow B)\rightarrow(H^{C}\rightarrow A)\rightarrow A\quad. \] \end_inset +Now substitute +\begin_inset Formula $B=A$ +\end_inset -\end_layout - -\begin_layout Subparagraph -Proof -\end_layout - -\begin_layout Standard + and write: +\begin_inset Formula +\begin{align*} + & \forall A.\,F^{A,A}=\gunderline{\forall A.\,\forall C.\,}(C\rightarrow A)\rightarrow(H^{C}\rightarrow A)\rightarrow A\\ +\text{swap the order of quantifiers}:\quad & \cong\forall C.\,\forall A.\,(\gunderline C\rightarrow A)\rightarrow(\gunderline{H^{C}}\rightarrow A)\rightarrow A\\ +\text{uncurry arguments}:\quad & \cong\forall C.\,\forall A.\,(C+H^{C}\rightarrow A)\rightarrow A\\ +\text{covariant Yoneda identity}:\quad & \cong\forall C.\,C+H^{C}\\ +\text{non-disjunctivity}:\quad & \cong(\forall C.\,C)+(\forall C.\,H^{C})\\ +\text{simplify each part}:\quad & \cong\bbnum 0+H^{\bbnum 1}\cong H^{\bbnum 1}\quad. +\end{align*} -\series bold -(a) -\series default - A fully parametric type constructor will have some type parameter occurrences - in a covariant position and others in a contravariant position. - So, it will have an -\begin_inset listings -inline true -status open +\end_inset -\begin_layout Plain Layout -xmap \end_layout -\end_inset +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-advanced-type-equivalence" - method (see Section -\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:f-Profunctors" +reference "subsec:Statement-advanced-type-equivalence" plural "false" caps "false" noprefix "false" \end_inset -): + +\end_layout + +\begin_layout Standard +Under assumptions of parametricity: \begin_inset Formula \[ -\text{xmap}_{F}:\forall A.\,\forall B.\,(A\rightarrow B)\rightarrow(B\rightarrow A)\rightarrow F^{A}\rightarrow F^{B}\quad. +\forall A.\,((A\rightarrow A)\rightarrow A)\rightarrow A=T\cong\bbnum 1+\bbnum 2+\bbnum 3+...\quad. \] \end_inset -An isomorphism between -\begin_inset Formula $P$ +The +\begin_inset Quotes eld \end_inset - and -\begin_inset Formula $Q$ +infinite +\begin_inset Quotes erd \end_inset - means having two functions -\begin_inset Formula $f_{1}^{:P\rightarrow Q}$ + type in the right-hand side is understood as the type of pairs of natural + numbers +\begin_inset Formula $\left(n,k\right)$ \end_inset - and -\begin_inset Formula $f_{2}^{:Q\rightarrow P}$ + such that +\begin_inset Formula $n\ge k\ge1$ \end_inset - such that -\begin_inset Formula $f_{1}\bef f_{2}=\text{id}$ +. + The value +\begin_inset Formula $n$ \end_inset - and -\begin_inset Formula $f_{2}\bef f_{1}=\text{id}$ + points to the part +\begin_inset Formula $\bbnum n$ \end_inset -. - Applying -\begin_inset listings -inline true -status open + of the disjunctive type; the value +\begin_inset Formula $k$ +\end_inset -\begin_layout Plain Layout + is one of the values of type +\begin_inset Formula $\bbnum n$ +\end_inset -xmap +. \end_layout +\begin_layout Standard +A value of type +\begin_inset Formula $T$ \end_inset - to those two functions in one or another order, we obtain two new functions - of the following types: + corresponding to the pair +\begin_inset Formula $\left(n,k\right)$ +\end_inset + + and applied to the type parameter +\begin_inset Formula $A$ +\end_inset + + can be written as: \begin_inset Formula -\begin{align*} - & g_{12}:F^{P}\rightarrow F^{Q}\quad,\quad\quad g_{12}\triangleq\text{xmap}_{F}(f_{1})(f_{2})\quad,\\ - & g_{21}:F^{Q}\rightarrow F^{P}\quad,\quad\quad g_{21}\triangleq\text{xmap}_{F}(f_{2})(f_{1})\quad. -\end{align*} +\[ +t_{n,k}^{A}\triangleq p^{:(A\rightarrow A)\rightarrow A}\rightarrow p(a_{1}^{:A}\rightarrow p(a_{2}^{:A}\rightarrow...\rightarrow p(a_{n}^{:A}\rightarrow a_{k})...))\quad. +\] \end_inset -Because of the laws of -\begin_inset listings -inline true + +\end_layout + +\begin_layout Subparagraph +Proof +\begin_inset Foot status open \begin_layout Plain Layout +See +\family typewriter -xmap -\end_layout - -\end_inset +\begin_inset CommandInset href +LatexCommand href +target "https://cstheory.stackexchange.com/questions/53855/" +literal "false" -, we find that -\begin_inset Formula $g_{12}$ \end_inset - and -\begin_inset Formula $g_{21}$ -\end_inset - are mutual inverses: -\begin_inset Formula -\begin{align*} - & g_{12}\bef g_{21}=\text{xmap}_{F}(f_{1})(f_{2})\bef\text{xmap}_{F}(f_{2})(f_{1})\\ - & \quad=\text{xmap}_{F}(f_{1}\bef f_{2})(f_{2}\bef f_{1})=\text{xmap}_{F}(\text{id})(\text{id})=\text{id}\quad,\\ - & g_{21}\bef g_{12}=\text{xmap}_{F}(f_{2})(f_{1})\bef\text{xmap}_{F}(f_{1})(f_{2})\\ - & \quad=\text{xmap}_{F}(f_{2}\bef f_{1})(f_{1}\bef f_{2})=\text{xmap}_{F}(\text{id})(\text{id})=\text{id}\quad. -\end{align*} +\end_layout \end_inset -This demonstrates an isomorphism -\begin_inset Formula $F^{P}\cong F^{Q}$ -\end_inset -. \end_layout \begin_layout Standard +Rewrite the given type using various type identities: +\begin_inset Formula +\begin{align*} + & \forall A.\,((\gunderline A\rightarrow A)\rightarrow A)\rightarrow A\\ +\text{Yoneda identity}:\quad & \cong\forall A.\,\forall B.\,\gunderline{(B\rightarrow A)\rightarrow((B\rightarrow A)\rightarrow A)}\rightarrow A\\ +\text{uncurry}:\quad & \cong\forall A.\,\forall B.\,(\gunderline B\rightarrow A)\times(\gunderline{(B\rightarrow A)}\rightarrow A)\rightarrow A\\ +\text{distributive law of }(\times):\quad & \cong\forall A.\,\forall B.\,(B+(B\rightarrow A)\rightarrow A)\rightarrow A\\ +\text{define }F^{B,X}\triangleq B+(B\rightarrow X):\quad & =\forall A.\,\forall B.\,(F^{B,A}\rightarrow A)\rightarrow A\\ + & =\forall B.\,\forall A.\,(F^{B,A}\rightarrow A)\rightarrow A\\ +\text{Church encoding}:\quad & =\forall B.\,\mu A.\,F^{B,A}\quad. +\end{align*} -\series bold -(b) -\series default - An isomorphism -\begin_inset Formula $F^{A}\cong G^{A}$ \end_inset - means that there is a pair of functions, +Denote for convenience the recursive type +\begin_inset Formula $T^{B}\triangleq\mu A.\,F^{B,A}$ +\end_inset + + and unroll the recursion a few times: \begin_inset Formula \begin{align*} - & f_{1}^{A}:F^{A}\rightarrow G^{A}\quad,\quad\quad f_{2}^{A}:G^{A}\rightarrow F^{A}\quad,\\ -\text{such that for all }A:\quad & f_{1}^{A}\bef f_{2}^{A}=\text{id}\quad\text{and}\quad f_{2}^{A}\bef f_{1}^{A}=\text{id}\quad. + & \forall B.\,T^{B}\cong\forall B.\,B+(B\rightarrow T^{B})\\ +\text{non-disjunctivity}:\quad & \cong(\forall B.\,B)+(\forall B.\,B\rightarrow T^{B})\cong\bbnum 0+\forall B.\,B\rightarrow T^{B}\\ +\text{unroll again}:\quad & \cong\forall B.\,B\rightarrow B+(B\rightarrow T^{B})\quad. \end{align*} \end_inset -To implement an isomorphism -\begin_inset Formula $\forall A.\,F^{A}\cong\forall A.\,G^{A}$ +Note that the identity functor ( +\begin_inset Formula $\text{Id}^{B}\triangleq B$ \end_inset -, we define two functions: +) is non-disjunctive, so we have: \begin_inset Formula -\begin{align*} - & g_{1}:(\forall A.\,F^{A})\rightarrow\forall B.\,G^{B}\quad,\quad\quad g_{2}:(\forall B.\,G^{B})\rightarrow\forall A.\,F^{A}\quad,\\ - & g_{1}\triangleq x^{:\forall A.\,F^{A}}\rightarrow\forall B.\,f_{1}^{B}(x^{B})\quad,\quad\quad g_{2}\triangleq y^{:\forall B.\,G^{B}}\rightarrow\forall A.\,f_{2}^{A}(y^{A})\quad. -\end{align*} +\[ +\forall B.\,B\rightarrow P^{B}+Q^{B}\cong(\forall B.\,B\rightarrow P^{B})+(\forall B.\,B\rightarrow Q^{B})\quad. +\] \end_inset -It remains to show that those functions are mutual inverses: +It follows that: \begin_inset Formula \begin{align*} -\text{expect to equal }\text{id}:\quad & g_{1}\bef g_{2}=x^{:\forall A.\,F^{A}}\rightarrow\forall A.\,\gunderline{f_{2}^{A}(f_{1}^{A}}(x^{A}))\\ -\text{use }f_{1}^{A}\bef f_{2}^{A}=\text{id}:\quad & \quad=x^{:\forall A.\,F^{A}}\rightarrow\forall A.\,x^{A}=x^{:\forall A.\,F^{A}}\rightarrow x=\text{id}\quad,\\ -\text{expect to equal }\text{id}:\quad & g_{2}\bef g_{1}=y^{:\forall B.\,G^{B}}\rightarrow\forall B.\,\gunderline{f_{1}^{B}(f_{2}^{B}}(y^{B}))\\ -\text{use }f_{2}^{B}\bef f_{1}^{B}=\text{id}:\quad & \quad=y^{:\forall B.\,G^{B}}\rightarrow\forall B.\,y^{B}=y^{:\forall B.\,G^{B}}\rightarrow y=\text{id}\quad. + & \forall B.\,B\rightarrow B+(B\rightarrow T^{B})\cong(\gunderline{\forall B.\,B\rightarrow B})+(\forall B.\,\gunderline{B\rightarrow B}\rightarrow T^{B})\\ +\text{simplify, uncurry}:\quad & \cong\bbnum 1+\forall B.\,B\times B\rightarrow T^{B}\\ +\text{unroll again}:\quad & \cong\bbnum 1+\forall B.\,B\times B\rightarrow B+(B\rightarrow T^{B})\quad. \end{align*} \end_inset +The functor +\begin_inset Formula $B\times B$ +\end_inset -\end_layout - -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-general-identities-forall" - + is non-disjunctive (see Example +\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-general-identities-forall" +reference "subsec:Example-undisjunctive-type-constructors" plural "false" caps "false" noprefix "false" \end_inset +d). + So, we may continue reducing the type as: +\begin_inset Formula +\begin{align*} + & \bbnum 1+\forall B.\,B\times B\rightarrow B+(B\rightarrow T^{B})\cong\bbnum 1+(\gunderline{\forall B.\,B\times B\rightarrow B})+(\forall B.\,\gunderline{B\times B\rightarrow B}\rightarrow T^{B})\\ + & \cong\bbnum 1+\bbnum 2+\forall B.\,B\times B\times B\rightarrow T^{B}\quad. +\end{align*} -\end_layout - -\begin_layout Standard -For any type constructors -\begin_inset Formula $F$ \end_inset -, -\begin_inset Formula $G$ +Continue using induction to show that +\begin_inset Formula $\forall B.\:T^{B}\cong\bbnum 1+\bbnum 2+\bbnum 3+...$ \end_inset - (not necessarily covariant or contravariant) and for any fixed type -\begin_inset Formula $R$ -\end_inset +, where the infinite co-product implies a suitable recursively defined type. +\begin_inset Note Note +status collapsed -, the following type isomorphisms hold under assumptions of full parametricity: +\begin_layout Plain Layout +Not clear. + Long and complicated, not sure what this brings. +\end_layout + +\begin_layout Plain Layout +Let us define for brevity: +\begin_inset Formula +\[ +F^{B,X}\triangleq B+(R\rightarrow(P\rightarrow B)\rightarrow Q\times X)\quad. +\] + +\end_inset + +Rewrite the given type using various type identities, and define: \begin_inset Formula \begin{align*} -\text{(a)}:\quad & \forall X.\,F^{X}+G^{X}\cong(\forall Y.\,F^{Y})+(\forall Z.\,G^{Z})\quad,\\ -\text{(b)}:\quad & \forall X.\,F^{X}\times G^{X}\cong(\forall Y.\,F^{Y})\times(\forall Z.\,G^{Z})\quad,\\ -\text{(c)}:\quad & \forall X.\,R\rightarrow F^{X}\cong R\rightarrow\forall Y.\,F^{Y}\quad. + & \forall A.\,((R\times(P\rightarrow A)\rightarrow Q\times A)\rightarrow A)\rightarrow A\\ +\text{Yoneda identity}:\quad & \cong\forall A.\,\forall B.\,\gunderline{(B\rightarrow A)\rightarrow((R\rightarrow(P\rightarrow B)\rightarrow Q\times A)\rightarrow A)}\rightarrow A\\ +\text{uncurry}:\quad & \cong\forall A.\,\forall B.\,(\gunderline B\rightarrow A)\times(\gunderline{(R\rightarrow(P\rightarrow B)\rightarrow Q\times A)}\rightarrow A)\rightarrow A\\ +\text{type identity}:\quad & \cong\forall A.\,\forall B.\,(\gunderline{B+(R\rightarrow(P\rightarrow B)\rightarrow Q\times A)}\rightarrow A)\rightarrow A\\ +\text{definition of }F:\quad & =\forall A.\,\forall B.\,(F^{B,A}\rightarrow A)\rightarrow A=\forall B.\,\gunderline{\forall A.\,(F^{B,A}\rightarrow A)\rightarrow A}\\ +\text{Church encoding}:\quad & =\forall B.\,\mu A.\,F^{B,A}\quad. \end{align*} \end_inset -\end_layout - -\begin_layout Subparagraph -Remarks -\end_layout +\begin_inset Formula +\begin{align*} + & \text{Let }\mu X.\,F^{B,X}=T^{B}\quad\text{and}\quad\forall B.\,T^{B}=U_{0}\quad.\quad\text{Then}:\quad U_{0}=\forall B.\,B+(R\rightarrow(P\rightarrow B)\rightarrow Q\times T^{B})\quad.\\ + & =\forall B.\,R\rightarrow(P\rightarrow B)\rightarrow Q\times T^{B}=\big(\forall B.\,R\rightarrow(P\rightarrow B)\rightarrow Q\big)\times\big(\gunderline{\forall B.\,R\rightarrow(P\rightarrow B)\rightarrow T^{B}}\big)\triangleq(R\rightarrow Q)\times U_{1}\\ + & =(R\rightarrow Q)\times\big(\forall B.\,R\rightarrow(P\rightarrow B)\rightarrow B+(R\rightarrow(P\rightarrow B)\rightarrow Q\times T^{B})\big)\\ + & =(R\rightarrow Q)\times(\forall B.\,R\rightarrow(P\rightarrow B)\rightarrow B)+(R\rightarrow Q)\times\big(\forall B.\,R\rightarrow(P\rightarrow B)\rightarrow(P\rightarrow B)\rightarrow Q\big)\times U_{2}\\ + & =(R\rightarrow Q)\times(R\rightarrow P)+(R\rightarrow Q)\times(R\rightarrow Q)\times U_{2}\quad, +\end{align*} -\begin_layout Standard -We renamed the bound type parameters for clarity; the identities could be - also written using the same type parameter name (say, -\begin_inset Formula $X$ \end_inset -): +where we defined: \begin_inset Formula \[ -\forall X.\,F^{X}+G^{X}\cong(\forall X.\,F^{X})+(\forall X.\,G^{X})\quad, +U_{n}\triangleq\forall B.\,R\rightarrow\underbrace{(P\rightarrow B)\rightarrow...\rightarrow(P\rightarrow B)}_{n\text{ times}}\rightarrow T^{B}\quad. \] \end_inset -and so on. -\end_layout +We can express each +\begin_inset Formula $U_{i}$ +\end_inset -\begin_layout Standard -To get some intuition for items -\series bold -(b) -\series default - and -\series bold -(c) -\series default -, consider how those types are written in the syntax of Scala 3. - The type corresponding to -\begin_inset Formula $\forall X.\,F^{X}\times G^{X}$ + via +\begin_inset Formula $U_{i+1}$ \end_inset - is written as -\begin_inset listings -inline true -status open + like this: +\begin_inset Formula +\begin{align*} + & U_{0}=(R\rightarrow Q)\times U_{1}\quad,\\ + & U_{1}=(R\rightarrow P)+(R\rightarrow Q)\times U_{2}\quad,\\ + & U_{2}=(R\rightarrow P)\times\bbnum 2+(R\rightarrow Q)\times U_{3}\quad, +\end{align*} -\begin_layout Plain Layout +\end_inset -[X] => (F[X], G[X]) -\end_layout +and so on. + By induction, we obtain: +\begin_inset Formula +\[ +U_{0}=(R\rightarrow P)\times\big((R\rightarrow Q)+\bbnum 2\times(\bbnum 2\rightarrow R\rightarrow Q)+\bbnum 3\times(\bbnum 3\rightarrow R\rightarrow Q)+... +\] \end_inset -. - If we imagine that -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout -[X] \end_layout \end_inset - were an ordinary argument (not a type parameter), we would apply the standard - type identities: -\begin_inset Formula -\begin{align*} - & A\rightarrow B\times C\cong(A\rightarrow B)\times(A\rightarrow C)\quad,\\ - & A\rightarrow R\rightarrow B\cong R\rightarrow A\rightarrow B\quad, -\end{align*} - + +\begin_inset Formula $\square$ \end_inset -written in Scala syntax as: -\begin_inset listings -inline false -status open - -\begin_layout Plain Layout -A => (B, C) === (A => B, A => C) \end_layout -\begin_layout Plain Layout +\begin_layout Standard +There exist complicated quantified types that cannot be simplified by any + of the techniques shown in this Appendix. + An example is the codensity monad +\begin_inset Index idx +status open -A => R => B === R => A => B +\begin_layout Plain Layout +monads!codensity monad \end_layout \end_inset -Assigning + on \begin_inset listings inline true status open \begin_layout Plain Layout -A = [X] +Option \end_layout \end_inset -, -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -B = F[X] -\end_layout +: +\begin_inset Formula +\[ +\text{Cod}_{\text{Opt}}^{A}\triangleq\forall R.\,(A\rightarrow\bbnum 1+R)\rightarrow\bbnum 1+R\quad. +\] \end_inset -, and -\begin_inset listings -inline true +It can be proved using methods of dependent type theory +\begin_inset Foot status open \begin_layout Plain Layout +See +\family typewriter -C = G[X] -\end_layout +\begin_inset CommandInset href +LatexCommand href +target "https://stackoverflow.com/questions/75178350/" +literal "false" \end_inset - in those identities, we get: -\begin_inset listings -inline false -status open - -\begin_layout Plain Layout -[X] => (F[X], G[X]) === ([X] => F[X], [X] => G[X]) \end_layout -\begin_layout Plain Layout +\end_inset -[X] => R => F[X] === R => [X] => F[X] -\end_layout + that +\begin_inset Formula $\text{Cod}_{\text{Opt}}^{A}\cong(A\rightarrow\bbnum 2)\rightarrow\bbnum 1+A$ +\end_inset + with the additional restriction that values +\begin_inset Formula $q:(A\rightarrow\bbnum 2)\rightarrow\bbnum 1+A$ \end_inset -These type formulas are exactly similar to the isomorphisms -\series bold -(b) -\series default - and -\series bold -(c) -\series default -. - However, -\begin_inset listings -inline true -status open + must satisfy: +\begin_inset Formula $q(p^{:A\rightarrow\bbnum 2})=\bbnum 0+x^{:A}$ +\end_inset -\begin_layout Plain Layout + only if +\begin_inset Formula $p(x)=True$ +\end_inset -X +. + This restriction on values can be encoded in a type signature only via + dependent types. \end_layout +\begin_layout Standard +So, +\begin_inset Formula $\text{Cod}_{\text{Opt}}^{A}$ \end_inset - is a type parameter, not a value parameter, and it is invalid to use ordinary - type identities such as -\begin_inset Formula $A\rightarrow R\rightarrow B\cong R\rightarrow A\rightarrow B$ + is an example of a universally quantified type that cannot be reduced to + an ordinary (non-dependent, non-quantified) type. + There seems to be no simplification that could apply to types of the form + +\begin_inset Formula $\forall R.\,(A\rightarrow F^{R})\rightarrow G^{R}$ \end_inset - and assign -\begin_inset Formula $A=$ + with arbitrary +\begin_inset Formula $F$ \end_inset - -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -[X] -\end_layout - + and +\begin_inset Formula $G$ \end_inset . - We need a new proof. - \end_layout -\begin_layout Subparagraph -Proof +\begin_layout Subsection +Other properties of universally quantified types \end_layout \begin_layout Standard +We continue exploring various techniques that are useful for simplifying + universally quantified types under assumptions of parametricity. + In most cases, we can avoid using the parametricity theorem directly. +\end_layout + +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-isomorphism-under-type-constructor" -\series bold -(a) -\series default - This isomorphism is proved in Example -\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Example-undisjunctive-type-constructors" +reference "subsec:Statement-isomorphism-under-type-constructor" plural "false" caps "false" noprefix "false" \end_inset -(e). - + \end_layout \begin_layout Standard -It is a -\begin_inset Quotes eld + +\series bold +(a) +\series default + Suppose +\begin_inset Formula $F$ \end_inset -non-constructive -\begin_inset Quotes erd -\end_inset - - isomorphism, in the following sense. - We can define a function -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -outS -\end_layout - -\end_inset - - that transforms the left-hand side into the right-hand side: -\begin_inset Formula -\begin{align*} - & \text{outS}:\big((\forall Y.\,F^{Y})+(\forall Z.\,G^{Z})\big)\rightarrow\forall X.\,F^{X}+G^{X}\quad,\\ - & \text{outS}\triangleq\,\begin{array}{|c||c|} - & \forall X.\,F^{X}+G^{X}\\ -\hline \forall Y.\,F^{Y} & f\rightarrow\forall X.\,f^{X}+\bbnum 0\\ -\forall Z.\,G^{Z} & g\rightarrow\forall X.\,\bbnum 0+g^{X} -\end{array}\quad. -\end{align*} - + is a fully parametric type constructor (but not necessarily covariant or + contravariant). + Let +\begin_inset Formula $P$ \end_inset -This function implements one direction of the isomorphism. - But one cannot implement a fully parameteric function -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -inS -\end_layout - +, +\begin_inset Formula $Q$ \end_inset - with the converse type signature: -\begin_inset Formula -\[ -\text{inS}:\big(\forall X.\,F^{X}+G^{X}\big)\rightarrow(\forall Y.\,F^{Y})+(\forall Z.\,G^{Z})\quad,\quad\quad\text{inS}=??? -\] - + be two types with a known isomorphism +\begin_inset Formula $P\cong Q$ \end_inset -Example -\begin_inset space ~ +. + Then +\begin_inset Formula $F^{P}\cong F^{Q}$ \end_inset +. +\end_layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Example-undisjunctive-type-constructors" -plural "false" -caps "false" -noprefix "false" - -\end_inset +\begin_layout Standard -(e) proves that there is a one-to-one correspondence between values of types - -\begin_inset Formula $\forall X.\,F^{X}+G^{X}$ +\series bold +(b) +\series default + Suppose +\begin_inset Formula $F$ \end_inset and -\begin_inset Formula $(\forall Y.\,F^{Y})+(\forall Z.\,G^{Z})$ +\begin_inset Formula $G$ \end_inset - even though one cannot write fully parametric code for the function -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -inS -\end_layout + are type constructors such that +\begin_inset Formula $F^{A}\cong G^{A}$ +\end_inset + for all types +\begin_inset Formula $A$ \end_inset . -\end_layout - -\begin_layout Standard - -\series bold -(b) -\series default - To prove the second isomorphism, define a pair of functions: + Then: \begin_inset Formula -\begin{align*} - & \text{inP}:(\forall X.\,F^{X}\times G^{X})\rightarrow(\forall Y.\,F^{Y})\times(\forall Z.\,G^{Z})\quad,\\ - & \text{inP}\triangleq r^{:\forall X.\,F^{X}\times G^{X}}\rightarrow(\forall Y.\,r^{Y}\triangleright\pi_{1})\times(\forall Z.\,r^{Z}\triangleright\pi_{2})\quad,\\ - & \text{outP}:(\forall Y.\,F^{Y})\times(\forall Z.\,G^{Z})\rightarrow\forall X.\,F^{X}\times G^{X}\quad,\\ - & \text{outP}\triangleq p^{:\forall Y.\,F^{Y}}\times q^{:\forall Z.\,G^{Z}}\rightarrow\forall X.\,p^{X}\times q^{X}\quad. -\end{align*} +\[ +\forall A.\,F^{A}\cong\forall A.\,G^{A}\quad. +\] \end_inset \end_layout -\begin_layout Standard -Now we need to prove the two sides of the composition: +\begin_layout Subparagraph +Proof \end_layout \begin_layout Standard -(1) For any -\begin_inset Formula $r$ -\end_inset - - of type -\begin_inset Formula $\forall X.\,F^{X}\times G^{X}$ -\end_inset -, applying +\series bold +(a) +\series default + A fully parametric type constructor will have some type parameter occurrences + in a covariant position and others in a contravariant position. + So, it will have an \begin_inset listings inline true status open \begin_layout Plain Layout -inP +xmap \end_layout \end_inset - to -\begin_inset Formula $r$ + method (see Section +\begin_inset space ~ \end_inset - and then -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout -outP -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:f-Profunctors" +plural "false" +caps "false" +noprefix "false" \end_inset - should again give the value -\begin_inset Formula $r$ +): +\begin_inset Formula +\[ +\text{xmap}_{F}:\forall A.\,\forall B.\,(A\rightarrow B)\rightarrow(B\rightarrow A)\rightarrow F^{A}\rightarrow F^{B}\quad. +\] + \end_inset -: -\begin_inset Formula -\begin{align*} -\text{expect to equal }r:\quad & r^{:\forall X.\,F^{X}\times G^{X}}\triangleright\text{inP}\triangleright\text{outP}\\ - & =\big((\forall Y.\,r^{Y}\triangleright\pi_{1})\times(\forall Z.\,r^{Z}\triangleright\pi_{2})\big)\triangleright\text{outP}\\ - & =\forall X.\,(r^{X}\triangleright\pi_{1})\times(r^{X}\triangleright\pi_{2})=\forall X.\,r^{X}=r\quad. -\end{align*} +An isomorphism between +\begin_inset Formula $P$ +\end_inset + and +\begin_inset Formula $Q$ \end_inset + means having two functions +\begin_inset Formula $f_{1}^{:P\rightarrow Q}$ +\end_inset -\end_layout + and +\begin_inset Formula $f_{2}^{:Q\rightarrow P}$ +\end_inset -\begin_layout Standard -(2) For any -\begin_inset Formula $p:\forall Y.\,F^{Y}$ + such that +\begin_inset Formula $f_{1}\bef f_{2}=\text{id}$ \end_inset and -\begin_inset Formula $q:\forall Z.\,G^{Z}$ +\begin_inset Formula $f_{2}\bef f_{1}=\text{id}$ \end_inset -, applying +. + Applying \begin_inset listings inline true status open \begin_layout Plain Layout -outP +xmap \end_layout \end_inset - to -\begin_inset Formula $p\times q$ + to those two functions in one or another order, we obtain two new functions + of the following types: +\begin_inset Formula +\begin{align*} + & g_{12}:F^{P}\rightarrow F^{Q}\quad,\quad\quad g_{12}\triangleq\text{xmap}_{F}(f_{1})(f_{2})\quad,\\ + & g_{21}:F^{Q}\rightarrow F^{P}\quad,\quad\quad g_{21}\triangleq\text{xmap}_{F}(f_{2})(f_{1})\quad. +\end{align*} + \end_inset - and then +Because of the laws of \begin_inset listings inline true status open \begin_layout Plain Layout -inP +xmap \end_layout \end_inset - should again give the value -\begin_inset Formula $p\times q$ +, we find that +\begin_inset Formula $g_{12}$ \end_inset -: + and +\begin_inset Formula $g_{21}$ +\end_inset + + are mutual inverses: \begin_inset Formula \begin{align*} -\text{expect to equal }p\times q:\quad & (p\times q)\triangleright\text{outP}\triangleright\text{inP}=(\forall X.\,p^{X}\times q^{X})\triangleright\text{inP}\\ - & =(\forall Y.\,(p^{Y}\times q^{Y})\triangleright\pi_{1})\times(\forall Z.\,(p^{Z}\times q^{Z})\triangleright\pi_{2})\\ - & =(\forall Y.\,p^{Y})\times(\forall Z.\,q^{Z})=p\times q\quad. + & g_{12}\bef g_{21}=\text{xmap}_{F}(f_{1})(f_{2})\bef\text{xmap}_{F}(f_{2})(f_{1})\\ + & \quad=\text{xmap}_{F}(f_{1}\bef f_{2})(f_{2}\bef f_{1})=\text{xmap}_{F}(\text{id})(\text{id})=\text{id}\quad,\\ + & g_{21}\bef g_{12}=\text{xmap}_{F}(f_{2})(f_{1})\bef\text{xmap}_{F}(f_{1})(f_{2})\\ + & \quad=\text{xmap}_{F}(f_{2}\bef f_{1})(f_{1}\bef f_{2})=\text{xmap}_{F}(\text{id})(\text{id})=\text{id}\quad. \end{align*} \end_inset +This demonstrates an isomorphism +\begin_inset Formula $F^{P}\cong F^{Q}$ +\end_inset +. \end_layout \begin_layout Standard \series bold -(c) +(b) \series default - To prove the third isomorphism, define a pair of functions: + An isomorphism +\begin_inset Formula $F^{A}\cong G^{A}$ +\end_inset + + means that there is a pair of functions, \begin_inset Formula \begin{align*} - & \text{inR}:(\forall X.\,R\rightarrow F^{X})\rightarrow R\rightarrow\forall Y.\,F^{Y}\quad,\\ - & \text{inR}\triangleq f^{:\forall X.\,R\rightarrow F^{X}}\rightarrow r^{:R}\rightarrow\forall Y.\,f^{Y}(r)\quad,\\ - & \text{outR}:(R\rightarrow\forall Y.\,F^{Y})\rightarrow\forall X.\,R\rightarrow F^{X}\quad,\\ - & \text{outR}\triangleq\big(g^{:R\rightarrow\forall Y.\,F^{Y}}\big)\rightarrow\forall X.\,r^{:R}\rightarrow(g(r))^{X}\quad. + & f_{1}^{A}:F^{A}\rightarrow G^{A}\quad,\quad\quad f_{2}^{A}:G^{A}\rightarrow F^{A}\quad,\\ +\text{such that for all }A:\quad & f_{1}^{A}\bef f_{2}^{A}=\text{id}\quad\text{and}\quad f_{2}^{A}\bef f_{1}^{A}=\text{id}\quad. \end{align*} \end_inset +To implement an isomorphism +\begin_inset Formula $\forall A.\,F^{A}\cong\forall A.\,G^{A}$ +\end_inset -\end_layout - -\begin_layout Standard -Now we need to prove the two sides of the composition: -\end_layout +, we define two functions: +\begin_inset Formula +\begin{align*} + & g_{1}:(\forall A.\,F^{A})\rightarrow\forall B.\,G^{B}\quad,\quad\quad g_{2}:(\forall B.\,G^{B})\rightarrow\forall A.\,F^{A}\quad,\\ + & g_{1}\triangleq x^{:\forall A.\,F^{A}}\rightarrow\forall B.\,f_{1}^{B}(x^{B})\quad,\quad\quad g_{2}\triangleq y^{:\forall B.\,G^{B}}\rightarrow\forall A.\,f_{2}^{A}(y^{A})\quad. +\end{align*} -\begin_layout Standard -(1) For any -\begin_inset Formula $f$ \end_inset - of type -\begin_inset Formula $\forall X.\,R\rightarrow F^{X}$ -\end_inset +It remains to show that those functions are mutual inverses: +\begin_inset Formula +\begin{align*} +\text{expect to equal }\text{id}:\quad & g_{1}\bef g_{2}=x^{:\forall A.\,F^{A}}\rightarrow\forall A.\,\gunderline{f_{2}^{A}(f_{1}^{A}}(x^{A}))\\ +\text{use }f_{1}^{A}\bef f_{2}^{A}=\text{id}:\quad & \quad=x^{:\forall A.\,F^{A}}\rightarrow\forall A.\,x^{A}=x^{:\forall A.\,F^{A}}\rightarrow x=\text{id}\quad,\\ +\text{expect to equal }\text{id}:\quad & g_{2}\bef g_{1}=y^{:\forall B.\,G^{B}}\rightarrow\forall B.\,\gunderline{f_{1}^{B}(f_{2}^{B}}(y^{B}))\\ +\text{use }f_{2}^{B}\bef f_{1}^{B}=\text{id}:\quad & \quad=y^{:\forall B.\,G^{B}}\rightarrow\forall B.\,y^{B}=y^{:\forall B.\,G^{B}}\rightarrow y=\text{id}\quad. +\end{align*} -, applying -\begin_inset listings -inline true -status open +\end_inset -\begin_layout Plain Layout -inR \end_layout +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-general-identities-forall" + \end_inset - and then -\begin_inset listings -inline true -status open -\begin_layout Plain Layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-general-identities-forall" +plural "false" +caps "false" +noprefix "false" + +\end_inset + -outR \end_layout +\begin_layout Standard +For any type constructors +\begin_inset Formula $F$ \end_inset - should give -\begin_inset Formula $f$ +, +\begin_inset Formula $G$ \end_inset -: + (not necessarily covariant or contravariant) and for any fixed type +\begin_inset Formula $R$ +\end_inset + +, the following type isomorphisms hold under assumptions of full parametricity: \begin_inset Formula \begin{align*} -\text{expect to equal }f:\quad & f\triangleright\text{inR}\triangleright\text{outR}=\big(r^{:R}\rightarrow\forall Y.\,f^{Y}(r)\big)\triangleright\text{outR}\\ - & =\forall X.\,r^{:R}\rightarrow\big(\big(r^{:R}\rightarrow\forall Y.\,f^{Y}(r)\big)(r)\big)^{X}\\ - & =\forall X.\,r^{:R}\rightarrow f^{X}(r)=\forall X.\,f^{X}=f\quad. +\text{(a)}:\quad & \forall X.\,F^{X}+G^{X}\cong(\forall Y.\,F^{Y})+(\forall Z.\,G^{Z})\quad,\\ +\text{(b)}:\quad & \forall X.\,F^{X}\times G^{X}\cong(\forall Y.\,F^{Y})\times(\forall Z.\,G^{Z})\quad,\\ +\text{(c)}:\quad & \forall X.\,R\rightarrow F^{X}\cong R\rightarrow\forall Y.\,F^{Y}\quad. \end{align*} \end_inset @@ -43076,355 +42901,385 @@ outR \end_layout +\begin_layout Subparagraph +Remarks +\end_layout + \begin_layout Standard -(2) For any -\begin_inset Formula $g$ +We renamed the bound type parameters for clarity; the identities could be + also written using the same type parameter name (say, +\begin_inset Formula $X$ \end_inset - of type -\begin_inset Formula $R\rightarrow\forall Y.\,F^{Y}$ +): +\begin_inset Formula +\[ +\forall X.\,F^{X}+G^{X}\cong(\forall X.\,F^{X})+(\forall X.\,G^{X})\quad, +\] + \end_inset -, applying +and so on. +\end_layout + +\begin_layout Standard +To get some intuition for items +\series bold +(b) +\series default + and +\series bold +(c) +\series default +, consider how those types are written in the syntax of Scala 3. + The type corresponding to +\begin_inset Formula $\forall X.\,F^{X}\times G^{X}$ +\end_inset + + is written as \begin_inset listings inline true status open \begin_layout Plain Layout -outR +[X] => (F[X], G[X]) \end_layout \end_inset - and then +. + If we imagine that \begin_inset listings inline true status open \begin_layout Plain Layout -inR +[X] \end_layout \end_inset - should give -\begin_inset Formula $g$ -\end_inset - -: + were an ordinary argument (not a type parameter), we would apply the standard + type identities: \begin_inset Formula \begin{align*} -\text{expect to equal }g:\quad & g\triangleright\text{outR}\triangleright\text{inR}=\big(\forall X.\,r^{:R}\rightarrow(g(r))^{X}\big)\triangleright\text{inR}\\ - & =r^{:R}\rightarrow\forall Y.\,\big(\forall X.\,r^{:R}\rightarrow(g(r))^{X}\big)^{Y}(r)\\ - & =r^{:R}\rightarrow\gunderline{\forall Y.\,(g(r))^{Y}}=r^{:R}\rightarrow g(r)=g\quad. + & A\rightarrow B\times C\cong(A\rightarrow B)\times(A\rightarrow C)\quad,\\ + & A\rightarrow R\rightarrow B\cong R\rightarrow A\rightarrow B\quad, \end{align*} \end_inset +written in Scala syntax as: +\begin_inset listings +inline false +status open -\begin_inset Formula $\square$ -\end_inset - +\begin_layout Plain Layout +A => (B, C) === (A => B, A => C) \end_layout -\begin_layout Standard -The three type constructions from Statement -\begin_inset space ~ -\end_inset - +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-general-identities-forall" -plural "false" -caps "false" -noprefix "false" +A => R => B === R => A => B +\end_layout \end_inset -, together with a recursive construction, produce functors whose type parameter - never appears to the left of a function arrow. - Those functors are known as -\begin_inset Quotes eld -\end_inset +Assigning +\begin_inset listings +inline true +status open -strictly positive -\begin_inset Quotes erd -\end_inset +\begin_layout Plain Layout - functors. - Here is a formal inductive definition: +A = [X] \end_layout -\begin_layout Subsubsection -Definition -\begin_inset CommandInset label -LatexCommand label -name "subsec:Definition-strictly-positive-functor" - \end_inset +, +\begin_inset listings +inline true +status open -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Definition-strictly-positive-functor" -plural "false" -caps "false" -noprefix "false" - -\end_inset - +\begin_layout Plain Layout +B = F[X] \end_layout -\begin_layout Standard -A functor -\begin_inset Formula $F$ \end_inset - is -\begin_inset Index idx +, and +\begin_inset listings +inline true status open \begin_layout Plain Layout -functor!strictly positive + +C = G[X] \end_layout \end_inset - -\series bold -strictly positive -\series default - if -\begin_inset Formula $F$ -\end_inset + in those identities, we get: +\begin_inset listings +inline false +status open - is expressed in any of the following ways: -\end_layout +\begin_layout Plain Layout -\begin_layout Standard -(1) -\begin_inset Formula $F^{A}\triangleq R$ -\end_inset +[X] => (F[X], G[X]) === ([X] => F[X], [X] => G[X]) +\end_layout +\begin_layout Plain Layout +[X] => R => F[X] === R => [X] => F[X] \end_layout -\begin_layout Standard -(2) -\begin_inset Formula $F^{A}\triangleq A$ \end_inset +These type formulas are exactly similar to the isomorphisms +\series bold +(b) +\series default + and +\series bold +(c) +\series default +. + However, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +X \end_layout -\begin_layout Standard -(3) -\begin_inset Formula $F^{A}\triangleq G^{A}+H^{A}$ \end_inset + is a type parameter, not a value parameter, and it is invalid to use ordinary + type identities such as +\begin_inset Formula $A\rightarrow R\rightarrow B\cong R\rightarrow A\rightarrow B$ +\end_inset -\end_layout - -\begin_layout Standard -(4) -\begin_inset Formula $F^{A}\triangleq G^{A}\times H^{A}$ + and assign +\begin_inset Formula $A=$ \end_inset + +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +[X] \end_layout -\begin_layout Standard -(5) -\begin_inset Formula $F^{A}\triangleq R\rightarrow G^{A}$ \end_inset +. + We need a new proof. + +\end_layout +\begin_layout Subparagraph +Proof \end_layout \begin_layout Standard -(6) -\begin_inset Formula $F^{A}\triangleq S^{A,F^{A}}$ -\end_inset - -\end_layout - -\begin_layout Standard -Here -\begin_inset Formula $G$ +\series bold +(a) +\series default + This isomorphism is proved in Example +\begin_inset space ~ \end_inset -, -\begin_inset Formula $H$ -\end_inset - are any strictly positive functors; -\begin_inset Formula $R$ -\end_inset +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-undisjunctive-type-constructors" +plural "false" +caps "false" +noprefix "false" - is any fixed type; and the pattern bifunctor -\begin_inset Formula $S$ \end_inset - is any strictly positive -\emph on -bifunctor -\emph default -, which we will define next: +(e). + \end_layout \begin_layout Standard -A bifunctor -\begin_inset Formula $S$ +It is a +\begin_inset Quotes eld \end_inset - is strictly positive if -\begin_inset Formula $S$ +non-constructive +\begin_inset Quotes erd \end_inset - is expressed in any of the following ways: -\end_layout - -\begin_layout Standard -(1) -\begin_inset Formula $S^{A,B}\triangleq R$ -\end_inset + isomorphism, in the following sense. + We can define a function +\begin_inset listings +inline true +status open +\begin_layout Plain Layout +outS \end_layout -\begin_layout Standard -(2) -\begin_inset Formula $S^{A,B}\triangleq A$ \end_inset - or -\begin_inset Formula $S^{A,B}=B$ + that transforms the left-hand side into the right-hand side: +\begin_inset Formula +\begin{align*} + & \text{outS}:\big((\forall Y.\,F^{Y})+(\forall Z.\,G^{Z})\big)\rightarrow\forall X.\,F^{X}+G^{X}\quad,\\ + & \text{outS}\triangleq\,\begin{array}{|c||c|} + & \forall X.\,F^{X}+G^{X}\\ +\hline \forall Y.\,F^{Y} & f\rightarrow\forall X.\,f^{X}+\bbnum 0\\ +\forall Z.\,G^{Z} & g\rightarrow\forall X.\,\bbnum 0+g^{X} +\end{array}\quad. +\end{align*} + \end_inset +This function implements one direction of the isomorphism. + But one cannot implement a fully parameteric function +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +inS \end_layout -\begin_layout Standard -(3) -\begin_inset Formula $S^{A,B}\triangleq P^{A,B}+Q^{A,B}$ \end_inset + with the converse type signature: +\begin_inset Formula +\[ +\text{inS}:\big(\forall X.\,F^{X}+G^{X}\big)\rightarrow(\forall Y.\,F^{Y})+(\forall Z.\,G^{Z})\quad,\quad\quad\text{inS}=??? +\] -\end_layout +\end_inset -\begin_layout Standard -(4) -\begin_inset Formula $S^{A,B}\triangleq P^{A,B}\times Q^{A,B}$ +Example +\begin_inset space ~ \end_inset -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-undisjunctive-type-constructors" +plural "false" +caps "false" +noprefix "false" -\begin_layout Standard -(5) -\begin_inset Formula $S^{A,B}\triangleq R\rightarrow P^{A,B}$ \end_inset +(e) proves that there is a one-to-one correspondence between values of types + +\begin_inset Formula $\forall X.\,F^{X}+G^{X}$ +\end_inset -\end_layout - -\begin_layout Standard -(6) -\begin_inset Formula $S^{A,B}\triangleq U^{A,B,S^{A,B}}$ + and +\begin_inset Formula $(\forall Y.\,F^{Y})+(\forall Z.\,G^{Z})$ \end_inset + even though one cannot write fully parametric code for the function +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +inS \end_layout -\begin_layout Standard -Here -\begin_inset Formula $P$ \end_inset -, -\begin_inset Formula $Q$ -\end_inset +. +\end_layout - are any strictly positive bifunctors; -\begin_inset Formula $R$ -\end_inset +\begin_layout Standard - is any fixed type; and the pattern -\begin_inset Formula $3$ -\end_inset +\series bold +(b) +\series default + To prove the second isomorphism, define a pair of functions: +\begin_inset Formula +\begin{align*} + & \text{inP}:(\forall X.\,F^{X}\times G^{X})\rightarrow(\forall Y.\,F^{Y})\times(\forall Z.\,G^{Z})\quad,\\ + & \text{inP}\triangleq r^{:\forall X.\,F^{X}\times G^{X}}\rightarrow(\forall Y.\,r^{Y}\triangleright\pi_{1})\times(\forall Z.\,r^{Z}\triangleright\pi_{2})\quad,\\ + & \text{outP}:(\forall Y.\,F^{Y})\times(\forall Z.\,G^{Z})\rightarrow\forall X.\,F^{X}\times G^{X}\quad,\\ + & \text{outP}\triangleq p^{:\forall Y.\,F^{Y}}\times q^{:\forall Z.\,G^{Z}}\rightarrow\forall X.\,p^{X}\times q^{X}\quad. +\end{align*} --functor -\begin_inset Formula $U$ \end_inset - is any strictly positive -\begin_inset Formula $3$ -\end_inset --functor. \end_layout \begin_layout Standard -Similarly, we define strictly positive -\begin_inset Formula $3$ -\end_inset +Now we need to prove the two sides of the composition: +\end_layout --functors, -\begin_inset Formula $4$ +\begin_layout Standard +(1) For any +\begin_inset Formula $r$ \end_inset --functors, etc., by induction. - -\begin_inset Formula $\square$ + of type +\begin_inset Formula $\forall X.\,F^{X}\times G^{X}$ \end_inset +, applying +\begin_inset listings +inline true +status open +\begin_layout Plain Layout + +inP \end_layout -\begin_layout Standard -Examples of strictly positive functors are all polynomial functors. - Examples of non-strictly positive functors are the continuation monad -\begin_inset Formula $F^{A}\triangleq(A\rightarrow C)\rightarrow C$ \end_inset - and the selection monad -\begin_inset Formula $F^{A}\triangleq(A\rightarrow C)\rightarrow A$ + to +\begin_inset Formula $r$ \end_inset -. - Those functors are covariant and even non-recursive, but their type parameters - ( -\begin_inset Formula $A$ -\end_inset + and then +\begin_inset listings +inline true +status open -) appear to the -\emph on -left -\emph default - of some function arrows, which is not allowed for strictly positive functors. -\end_layout +\begin_layout Plain Layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-quantifier-across-functor" +outP +\end_layout \end_inset + should again give the value +\begin_inset Formula $r$ +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-quantifier-across-functor" -plural "false" -caps "false" -noprefix "false" +: +\begin_inset Formula +\begin{align*} +\text{expect to equal }r:\quad & r^{:\forall X.\,F^{X}\times G^{X}}\triangleright\text{inP}\triangleright\text{outP}\\ + & =\big((\forall Y.\,r^{Y}\triangleright\pi_{1})\times(\forall Z.\,r^{Z}\triangleright\pi_{2})\big)\triangleright\text{outP}\\ + & =\forall X.\,(r^{X}\triangleright\pi_{1})\times(r^{X}\triangleright\pi_{2})=\forall X.\,r^{X}=r\quad. +\end{align*} \end_inset @@ -43432,80 +43287,53 @@ noprefix "false" \end_layout \begin_layout Standard -For any strictly positive functor -\begin_inset Formula $F$ +(2) For any +\begin_inset Formula $p:\forall Y.\,F^{Y}$ \end_inset - and any type constructor -\begin_inset Formula $P$ + and +\begin_inset Formula $q:\forall Z.\,G^{Z}$ \end_inset -, we have: -\begin_inset Formula -\[ -\forall A.\,F^{P^{A}}\cong F^{\forall A.\,P^{A}}\quad. -\] +, applying +\begin_inset listings +inline true +status open -\end_inset +\begin_layout Plain Layout -For any strictly positive bifunctor -\begin_inset Formula $S$ -\end_inset +outP +\end_layout - and any type constructors -\begin_inset Formula $P$ \end_inset -, -\begin_inset Formula $Q$ + to +\begin_inset Formula $p\times q$ \end_inset -, we have: -\begin_inset Formula -\[ -\forall A.\,S^{P^{A},\,Q^{A}}\cong S^{\forall A.\,P^{A},\,\forall A.\,Q^{A}}\quad. -\] - -\end_inset - -Similar identities hold for strictly positive -\begin_inset Formula $3$ -\end_inset - --functors, -\begin_inset Formula $4$ -\end_inset - --functors, etc. -\end_layout - -\begin_layout Subparagraph -Proof -\end_layout + and then +\begin_inset listings +inline true +status open -\begin_layout Standard -The functor -\begin_inset Formula $F$ -\end_inset +\begin_layout Plain Layout - must be expressed in one of the six ways: +inP \end_layout -\begin_layout Standard -(1) -\begin_inset Formula $F^{A}=R$ \end_inset - with a fixed type -\begin_inset Formula $R$ + should again give the value +\begin_inset Formula $p\times q$ \end_inset -. - Then we get: +: \begin_inset Formula -\[ -\forall A.\,F^{P^{A}}=\forall A.\,R\cong R\quad,\quad\quad F^{\forall A.\,P^{A}}=R\quad. -\] +\begin{align*} +\text{expect to equal }p\times q:\quad & (p\times q)\triangleright\text{outP}\triangleright\text{inP}=(\forall X.\,p^{X}\times q^{X})\triangleright\text{inP}\\ + & =(\forall Y.\,(p^{Y}\times q^{Y})\triangleright\pi_{1})\times(\forall Z.\,(p^{Z}\times q^{Z})\triangleright\pi_{2})\\ + & =(\forall Y.\,p^{Y})\times(\forall Z.\,q^{Z})=p\times q\quad. +\end{align*} \end_inset @@ -43513,16 +43341,18 @@ The functor \end_layout \begin_layout Standard -(2) -\begin_inset Formula $F^{A}=A$ -\end_inset -. - Then we get: +\series bold +(c) +\series default + To prove the third isomorphism, define a pair of functions: \begin_inset Formula -\[ -\forall A.\,F^{P^{A}}=\forall A.\,P^{A}\quad,\quad\quad F^{\forall A.\,P^{A}}=\forall A.\,P^{A}\quad. -\] +\begin{align*} + & \text{inR}:(\forall X.\,R\rightarrow F^{X})\rightarrow R\rightarrow\forall Y.\,F^{Y}\quad,\\ + & \text{inR}\triangleq f^{:\forall X.\,R\rightarrow F^{X}}\rightarrow r^{:R}\rightarrow\forall Y.\,f^{Y}(r)\quad,\\ + & \text{outR}:(R\rightarrow\forall Y.\,F^{Y})\rightarrow\forall X.\,R\rightarrow F^{X}\quad,\\ + & \text{outR}\triangleq\big(g^{:R\rightarrow\forall Y.\,F^{Y}}\big)\rightarrow\forall X.\,r^{:R}\rightarrow(g(r))^{X}\quad. +\end{align*} \end_inset @@ -43530,52 +43360,52 @@ The functor \end_layout \begin_layout Standard -(3) -\begin_inset Formula $F^{A}=G^{A}+H^{A}$ -\end_inset +Now we need to prove the two sides of the composition: +\end_layout -, where the statement is already true for -\begin_inset Formula $G$ +\begin_layout Standard +(1) For any +\begin_inset Formula $f$ \end_inset - and -\begin_inset Formula $H$ + of type +\begin_inset Formula $\forall X.\,R\rightarrow F^{X}$ \end_inset - by the inductive assumptions. - Then we get: -\begin_inset Formula -\begin{align*} - & \forall A.\,F^{P^{A}}=\forall A.\,G^{P^{A}}+H^{P^{A}}\\ -\text{Statement\,\ref{subsec:Statement-general-identities-forall}(a)}:\quad & =\big(\gunderline{\forall A.\,G^{P^{A}}}\big)+\big(\gunderline{\forall A.\,H^{P^{A}}}\big)\\ -\text{inductive assumptions}:\quad & =G^{\forall A.\,P^{A}}+H^{\forall A.\,P^{A}}=F^{\forall A.\,P^{A}}\quad. -\end{align*} - -\end_inset +, applying +\begin_inset listings +inline true +status open +\begin_layout Plain Layout +inR \end_layout -\begin_layout Standard -(4) -\begin_inset Formula $F^{A}=G^{A}\times H^{A}$ \end_inset -, where the statement is already true for -\begin_inset Formula $G$ + and then +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +outR +\end_layout + \end_inset - and -\begin_inset Formula $H$ + should give +\begin_inset Formula $f$ \end_inset - by the inductive assumptions. - Then we get: +: \begin_inset Formula \begin{align*} - & \forall A.\,F^{P^{A}}=\forall A.\,G^{P^{A}}\times H^{P^{A}}\\ -\text{Statement\,\ref{subsec:Statement-general-identities-forall}(b)}:\quad & =\big(\gunderline{\forall A.\,G^{P^{A}}}\big)\times\big(\gunderline{\forall A.\,H^{P^{A}}}\big)\\ -\text{inductive assumptions}:\quad & =G^{\forall A.\,P^{A}}\times H^{\forall A.\,P^{A}}=F^{\forall A.\,P^{A}}\quad. +\text{expect to equal }f:\quad & f\triangleright\text{inR}\triangleright\text{outR}=\big(r^{:R}\rightarrow\forall Y.\,f^{Y}(r)\big)\triangleright\text{outR}\\ + & =\forall X.\,r^{:R}\rightarrow\big(\big(r^{:R}\rightarrow\forall Y.\,f^{Y}(r)\big)(r)\big)^{X}\\ + & =\forall X.\,r^{:R}\rightarrow f^{X}(r)=\forall X.\,f^{X}=f\quad. \end{align*} \end_inset @@ -43584,90 +43414,100 @@ The functor \end_layout \begin_layout Standard -(5) -\begin_inset Formula $F^{A}=R\rightarrow G^{A}$ +(2) For any +\begin_inset Formula $g$ \end_inset -, where the statement is already true for -\begin_inset Formula $G$ + of type +\begin_inset Formula $R\rightarrow\forall Y.\,F^{Y}$ \end_inset - by the inductive assumption. - Then we get: -\begin_inset Formula -\begin{align*} - & \forall A.\,F^{P^{A}}=\forall A.\,R\rightarrow G^{P^{A}}\\ -\text{Statement\,\ref{subsec:Statement-general-identities-forall}(c)}:\quad & =R\rightarrow\big(\gunderline{\forall A.\,G^{P^{A}}}\big)\\ -\text{inductive assumption}:\quad & =R\rightarrow G^{\forall A.\,P^{A}}=F^{\forall A.\,P^{A}}\quad. -\end{align*} - -\end_inset +, applying +\begin_inset listings +inline true +status open +\begin_layout Plain Layout +outR \end_layout -\begin_layout Standard -(6) -\begin_inset Formula $F^{A}=S^{A,F^{A}}$ \end_inset -, where the statement is already true for -\begin_inset Formula $S$ -\end_inset + and then +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +inR +\end_layout - by the inductive assumption. - (Another inductive assumption is that the statement is already true for - recursive usages of -\begin_inset Formula $F$ \end_inset - under -\begin_inset Formula $S$ + should give +\begin_inset Formula $g$ \end_inset -.) We get: +: \begin_inset Formula \begin{align*} - & \forall A.\,F^{P^{A}}=\forall A.\,S^{P^{A},\,F^{P^{A}}}\\ -\text{inductive assumption}:\quad & \cong S^{\forall A.\,P^{A},\,\gunderline{\forall A.\,F^{P^{A}}}}\\ -\text{inductive assumption}:\quad & \cong S^{\forall A.\,P^{A},\,F^{\forall A.\,P^{A}}}=F^{\forall A.\,P^{A}}\quad. +\text{expect to equal }g:\quad & g\triangleright\text{outR}\triangleright\text{inR}=\big(\forall X.\,r^{:R}\rightarrow(g(r))^{X}\big)\triangleright\text{inR}\\ + & =r^{:R}\rightarrow\forall Y.\,\big(\forall X.\,r^{:R}\rightarrow(g(r))^{X}\big)^{Y}(r)\\ + & =r^{:R}\rightarrow\gunderline{\forall Y.\,(g(r))^{Y}}=r^{:R}\rightarrow g(r)=g\quad. \end{align*} \end_inset +\begin_inset Formula $\square$ +\end_inset + + \end_layout \begin_layout Standard -The identities for bifunctors, -\begin_inset Formula $3$ +The three type constructions from Statement +\begin_inset space ~ \end_inset --functors, etc., are proved in a similar way. - -\begin_inset Formula $\square$ + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-general-identities-forall" +plural "false" +caps "false" +noprefix "false" + \end_inset +, together with a recursive construction, produce functors whose type parameter + never appears to the left of a function arrow. + Those functors are known as +\begin_inset Quotes eld +\end_inset -\end_layout +strictly positive +\begin_inset Quotes erd +\end_inset -\begin_layout Standard -We will now prove some statements showing miscellaneous additional techniques - for simplifying universally quantified types. + functors. + Here is a formal inductive definition: \end_layout \begin_layout Subsubsection -Statement +Definition \begin_inset CommandInset label LatexCommand label -name "subsec:Statement-Fubini-theorem-1" +name "subsec:Definition-strictly-positive-functor" \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-Fubini-theorem-1" +reference "subsec:Definition-strictly-positive-functor" plural "false" caps "false" noprefix "false" @@ -43678,268 +43518,247 @@ noprefix "false" \end_layout \begin_layout Standard -If any type constructor +A functor \begin_inset Formula $F$ \end_inset - is such that -\begin_inset Formula $F^{\bbnum 0}\cong\bbnum 0$ -\end_inset + is +\begin_inset Index idx +status open - then: -\begin_inset Formula -\[ -\forall A.\,F^{A}\cong\bbnum 0\quad. -\] +\begin_layout Plain Layout +functor!strictly positive +\end_layout \end_inset + +\series bold +strictly positive +\series default + if +\begin_inset Formula $F$ +\end_inset + is expressed in any of the following ways: \end_layout -\begin_layout Subparagraph -Proof +\begin_layout Standard +(1) +\begin_inset Formula $F^{A}\triangleq R$ +\end_inset + + \end_layout \begin_layout Standard -We need to show that there exist no values of type -\begin_inset Formula $\forall A.\,F^{A}$ +(2) +\begin_inset Formula $F^{A}\triangleq A$ \end_inset -. - Suppose there existed such a value -\begin_inset Formula $f$ -\end_inset -; then we would be apply to apply -\begin_inset Formula $f$ +\end_layout + +\begin_layout Standard +(3) +\begin_inset Formula $F^{A}\triangleq G^{A}+H^{A}$ \end_inset - to the void type. - The resulting value would be: -\begin_inset Formula -\[ -x:F^{\bbnum 0}\quad,\quad\quad x\triangleq f^{\bbnum 0}\quad. -\] -\end_inset +\end_layout -But this contradicts the given assumption that the type -\begin_inset Formula $F^{\bbnum 0}$ +\begin_layout Standard +(4) +\begin_inset Formula $F^{A}\triangleq G^{A}\times H^{A}$ \end_inset - is void. - This contradiction proves the statement. + \end_layout \begin_layout Standard -The proof is non-constructive: we have shown that assuming the existence - of values of type -\begin_inset Formula $\forall A.\,F^{A}$ +(5) +\begin_inset Formula $F^{A}\triangleq R\rightarrow G^{A}$ \end_inset - leads to a contradiction. - + \end_layout \begin_layout Standard -Let us also show a constructive proof that computes a -\emph on -witness -\emph default - that -\begin_inset Formula $\forall A.\,F^{A}$ +(6) +\begin_inset Formula $F^{A}\triangleq S^{A,F^{A}}$ \end_inset - is void (that is, a value of type -\begin_inset Formula $(\forall A.\,F^{A})\rightarrow\bbnum 0$ -\end_inset -) from a witness that -\begin_inset Formula $F^{\bbnum 0}$ +\end_layout + +\begin_layout Standard +Here +\begin_inset Formula $G$ \end_inset - is void (a value of type -\begin_inset Formula $F^{\bbnum 0}\rightarrow\bbnum 0$ +, +\begin_inset Formula $H$ \end_inset -). - The computation is expressed as a function -\begin_inset listings -inline true -status open + are any strictly positive functors; +\begin_inset Formula $R$ +\end_inset -\begin_layout Plain Layout + is any fixed type; and the pattern bifunctor +\begin_inset Formula $S$ +\end_inset -proof + is any strictly positive +\emph on +bifunctor +\emph default +, which we will define next: \end_layout +\begin_layout Standard +A bifunctor +\begin_inset Formula $S$ \end_inset -: -\begin_inset Formula -\begin{align*} - & \text{proof}:(F^{\bbnum 0}\rightarrow\bbnum 0)\rightarrow(\forall A.\,F^{A})\rightarrow\bbnum 0\quad,\\ - & \text{proof}\triangleq k^{:F^{\bbnum 0}\rightarrow\bbnum 0}\rightarrow f^{:\forall A.\,F^{A}}\rightarrow k(f^{\bbnum 0})\quad. -\end{align*} + is strictly positive if +\begin_inset Formula $S$ +\end_inset + is expressed in any of the following ways: +\end_layout + +\begin_layout Standard +(1) +\begin_inset Formula $S^{A,B}\triangleq R$ \end_inset \end_layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-Fubini-theorem" +\begin_layout Standard +(2) +\begin_inset Formula $S^{A,B}\triangleq A$ +\end_inset + or +\begin_inset Formula $S^{A,B}=B$ \end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-Fubini-theorem" -plural "false" -caps "false" -noprefix "false" +\end_layout +\begin_layout Standard +(3) +\begin_inset Formula $S^{A,B}\triangleq P^{A,B}+Q^{A,B}$ \end_inset - (Fubini theorem -\begin_inset Index idx -status open -\begin_layout Plain Layout -Fubini theorem \end_layout +\begin_layout Standard +(4) +\begin_inset Formula $S^{A,B}\triangleq P^{A,B}\times Q^{A,B}$ \end_inset -) + \end_layout \begin_layout Standard -For any type constructor -\begin_inset Formula $S$ +(5) +\begin_inset Formula $S^{A,B}\triangleq R\rightarrow P^{A,B}$ \end_inset - with two type parameters (not necessarily covariant or contravariant), - we have: -\begin_inset Formula -\[ -\forall A.\,\forall B.\,S^{A,B}\cong\forall B.\,\forall A.\,S^{A,B}\quad. -\] -\end_inset +\end_layout +\begin_layout Standard +(6) +\begin_inset Formula $S^{A,B}\triangleq U^{A,B,S^{A,B}}$ +\end_inset -\end_layout -\begin_layout Subparagraph -Proof \end_layout \begin_layout Standard -The isomorphism is implemented by the function -\begin_inset Formula $f$ +Here +\begin_inset Formula $P$ \end_inset -: -\begin_inset Formula -\begin{align*} - & f:\big(\forall(A,B).\,S^{A,B}\big)\rightarrow\forall B.\,\forall A.\,S^{A,B}\\ - & f\triangleq k^{:\forall(A,B).\,S^{A,B}}\rightarrow\forall B.\,\forall A.\,k^{A,B}\quad. -\end{align*} - +, +\begin_inset Formula $Q$ \end_inset -This function is its own inverse: for any -\begin_inset Formula $k:\forall(A,B).\,S^{A,B}$ + are any strictly positive bifunctors; +\begin_inset Formula $R$ \end_inset -, -\begin_inset Formula -\begin{align*} -\text{expect to equal }k:\quad & k\triangleright f\triangleright f=\big(\forall B.\,\forall A.\,k^{A,B}\big)\triangleright f\\ - & =\forall B.\,\forall A.\,k^{B,A}\\ -\text{rename type parameters}:\quad & =\forall A.\,\forall B.\,k^{A,B}=k. -\end{align*} - + is any fixed type; and the pattern +\begin_inset Formula $3$ \end_inset - -\begin_inset Formula $\square$ +-functor +\begin_inset Formula $U$ \end_inset - -\begin_inset Note Note -status collapsed + is any strictly positive +\begin_inset Formula $3$ +\end_inset -\begin_layout Subsubsection -Statement +-functor. \end_layout -\begin_layout Plain Layout -For any type constructor -\begin_inset Formula $F$ +\begin_layout Standard +Similarly, we define strictly positive +\begin_inset Formula $3$ \end_inset -: (not sure any of this is true!) -\begin_inset Formula -\begin{align*} -\text{(a)}:\quad & \forall X.\,\forall Y.\,F^{X\times Y}\cong\forall Z.\,F^{Z}\quad,\\ -\text{(b)}:\quad & \forall X.\,\forall Y.\,F^{X+Y}\cong\forall Z.\,F^{Z}\quad,\\ -\text{(c)}:\quad & \forall X.\,\forall Y.\,F^{X\rightarrow Y}\cong\forall Z.\,F^{Z}\quad. -\end{align*} - +-functors, +\begin_inset Formula $4$ \end_inset +-functors, etc., by induction. + +\begin_inset Formula $\square$ +\end_inset -\end_layout -\begin_layout Subparagraph -Proof \end_layout -\begin_layout Plain Layout -Item (b) is certainly wrong: use a contravariant -\begin_inset Formula $F$ +\begin_layout Standard +Examples of strictly positive functors are all polynomial functors. + Examples of non-strictly positive functors are the continuation monad +\begin_inset Formula $F^{A}\triangleq(A\rightarrow C)\rightarrow C$ \end_inset - as a counterexample and get -\begin_inset Formula $F^{\bbnum 1+\bbnum 1}\not\cong F^{\bbnum 1}$ + and the selection monad +\begin_inset Formula $F^{A}\triangleq(A\rightarrow C)\rightarrow A$ \end_inset . - Other items might be correct but it is not clear how to prove them, as - parametricity does not directly apply to a replacement of a pair of type - parameters by a single type parameter. -\end_layout - + Those functors are covariant and even non-recursive, but their type parameters + ( +\begin_inset Formula $A$ \end_inset - -\end_layout - -\begin_layout Standard -With these techniques, together with the Yoneda and Church-Yoneda identities, - we can often reduce a type that contains a universal quantifier to an equivalen -t simpler type without quantifiers. +) appear to the +\emph on +left +\emph default + of some function arrows, which is not allowed for strictly positive functors. \end_layout \begin_layout Subsubsection -Example +Statement \begin_inset CommandInset label LatexCommand label -name "subsec:Example-complicated-type-equivalence-2-1" +name "subsec:Statement-quantifier-across-functor" \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Example-complicated-type-equivalence-2-1" +reference "subsec:Statement-quantifier-across-functor" plural "false" caps "false" noprefix "false" @@ -43947,178 +43766,176 @@ noprefix "false" \end_inset -\begin_inset Index idx -status open - -\begin_layout Plain Layout -examples \end_layout +\begin_layout Standard +For any strictly positive functor +\begin_inset Formula $F$ \end_inset - -\end_layout - -\begin_layout Standard -Show that the type -\begin_inset Formula $\forall A.\,\bbnum 1+A\rightarrow A$ + and any type constructor +\begin_inset Formula $P$ \end_inset - is void. -\end_layout - -\begin_layout Subparagraph -Solution -\end_layout - -\begin_layout Standard -Transform the type using the Yoneda identities: +, we have: \begin_inset Formula -\begin{align*} - & \forall A.\,\bbnum 1+A\rightarrow A\cong\forall A.\,(\bbnum 1\rightarrow A)\times(A\rightarrow A)\\ - & \cong(\forall A.\,\bbnum 1\rightarrow A)\times(\forall A.\,A\rightarrow A)\\ - & \cong\bbnum 0\times\bbnum 1=\bbnum 0\quad. -\end{align*} +\[ +\forall A.\,F^{P^{A}}\cong F^{\forall A.\,P^{A}}\quad. +\] \end_inset +For any strictly positive bifunctor +\begin_inset Formula $S$ +\end_inset -\end_layout - -\begin_layout Subsubsection -Example -\begin_inset CommandInset label -LatexCommand label -name "subsec:Example-simplify-quantifier" + and any type constructors +\begin_inset Formula $P$ +\end_inset +, +\begin_inset Formula $Q$ \end_inset +, we have: +\begin_inset Formula +\[ +\forall A.\,S^{P^{A},\,Q^{A}}\cong S^{\forall A.\,P^{A},\,\forall A.\,Q^{A}}\quad. +\] -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Example-simplify-quantifier" -plural "false" -caps "false" -noprefix "false" +\end_inset + +Similar identities hold for strictly positive +\begin_inset Formula $3$ +\end_inset +-functors, +\begin_inset Formula $4$ \end_inset +-functors, etc. +\end_layout +\begin_layout Subparagraph +Proof \end_layout \begin_layout Standard -Simplify all fully parametric types of the form -\begin_inset Formula $\forall A.\,T^{A}$ +The functor +\begin_inset Formula $F$ \end_inset - where -\begin_inset Formula $T^{A}$ -\end_inset + must be expressed in one of the six ways: +\end_layout - is any type expression containing no recursion and at most two type constructio -ns (using Table -\begin_inset space ~ +\begin_layout Standard +(1) +\begin_inset Formula $F^{A}=R$ \end_inset + with a fixed type +\begin_inset Formula $R$ +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "tab:six-pure-type-constructions" -plural "false" -caps "false" -noprefix "false" +. + Then we get: +\begin_inset Formula +\[ +\forall A.\,F^{P^{A}}=\forall A.\,R\cong R\quad,\quad\quad F^{\forall A.\,P^{A}}=R\quad. +\] \end_inset - without the recursive type). - The type expression -\begin_inset Formula $T^{A}$ -\end_inset - may contain -\begin_inset Formula $A$ -\end_inset +\end_layout - and other fixed types ( -\begin_inset Formula $P,$ +\begin_layout Standard +(2) +\begin_inset Formula $F^{A}=A$ \end_inset +. + Then we get: +\begin_inset Formula +\[ +\forall A.\,F^{P^{A}}=\forall A.\,P^{A}\quad,\quad\quad F^{\forall A.\,P^{A}}=\forall A.\,P^{A}\quad. +\] -\begin_inset Formula $Q$ \end_inset -). -\end_layout -\begin_layout Subparagraph -Solution \end_layout \begin_layout Standard -Fully parametric types are built via the five type constructions So, we - can enumerate all type expressions -\begin_inset Formula $T^{A}$ +(3) +\begin_inset Formula $F^{A}=G^{A}+H^{A}$ \end_inset - of the specified form: -\begin_inset Formula $\forall A.\,P$ +, where the statement is already true for +\begin_inset Formula $G$ \end_inset -, -\begin_inset Formula $\forall A.\,A$ + and +\begin_inset Formula $H$ \end_inset -, -\begin_inset Formula $\forall A.\,P\times A$ -\end_inset + by the inductive assumptions. + Then we get: +\begin_inset Formula +\begin{align*} + & \forall A.\,F^{P^{A}}=\forall A.\,G^{P^{A}}+H^{P^{A}}\\ +\text{Statement\,\ref{subsec:Statement-general-identities-forall}(a)}:\quad & =\big(\gunderline{\forall A.\,G^{P^{A}}}\big)+\big(\gunderline{\forall A.\,H^{P^{A}}}\big)\\ +\text{inductive assumptions}:\quad & =G^{\forall A.\,P^{A}}+H^{\forall A.\,P^{A}}=F^{\forall A.\,P^{A}}\quad. +\end{align*} -, -\begin_inset Formula $\forall A.\,A\rightarrow P+A$ \end_inset -, and so on. - For each of those expressions, we need to apply an appropriate technique - that will simplify the type. + \end_layout \begin_layout Standard -We begin by noticing that many type expressions -\begin_inset Formula $T^{A}$ +(4) +\begin_inset Formula $F^{A}=G^{A}\times H^{A}$ \end_inset - will be covariant in -\begin_inset Formula $A$ +, where the statement is already true for +\begin_inset Formula $G$ \end_inset - or contravariant in -\begin_inset Formula $A$ + and +\begin_inset Formula $H$ \end_inset -. - Examples are: + by the inductive assumptions. + Then we get: \begin_inset Formula \begin{align*} -\text{covariant}:\quad & A\quad,\quad P\rightarrow A\quad,\quad P+A\times A\quad,\quad(A\rightarrow P)\rightarrow Q\quad,\quad...\\ -\text{contravariant}:\quad & A\rightarrow P\quad,\quad P+(A\rightarrow Q)\quad,\quad(P\rightarrow A)\rightarrow Q\quad,\quad... + & \forall A.\,F^{P^{A}}=\forall A.\,G^{P^{A}}\times H^{P^{A}}\\ +\text{Statement\,\ref{subsec:Statement-general-identities-forall}(b)}:\quad & =\big(\gunderline{\forall A.\,G^{P^{A}}}\big)\times\big(\gunderline{\forall A.\,H^{P^{A}}}\big)\\ +\text{inductive assumptions}:\quad & =G^{\forall A.\,P^{A}}\times H^{\forall A.\,P^{A}}=F^{\forall A.\,P^{A}}\quad. \end{align*} \end_inset -The Yoneda identities can simplify such type expressions: -\begin_inset Formula -\begin{align*} -\text{if }T\text{ is covariant}:\quad & \forall A.\,T^{A}\cong T^{\bbnum 0}\quad,\\ -\text{if }T\text{ is contravariant}:\quad & \forall A.\,T^{A}\cong T^{\bbnum 1}\quad. -\end{align*} +\end_layout + +\begin_layout Standard +(5) +\begin_inset Formula $F^{A}=R\rightarrow G^{A}$ \end_inset -This gives us the following results: +, where the statement is already true for +\begin_inset Formula $G$ +\end_inset + + by the inductive assumption. + Then we get: \begin_inset Formula \begin{align*} - & \forall A.\,P\cong P\quad,\quad\forall A.\,A\cong\bbnum 0\quad,\\ - & \forall A.\,A+P\cong P\quad,\quad\forall A.\,A\times P\cong\bbnum 0\quad,\quad\forall A.\,A\rightarrow P\cong P\quad,\quad\forall A.\,P\rightarrow A\cong\bbnum 0\quad,\\ - & \forall A.\,P\rightarrow A+Q\cong P\rightarrow Q\quad,\quad\forall A.\,(P\rightarrow A)\rightarrow Q\cong Q\quad,\quad\forall A.\,(A\rightarrow P)\rightarrow Q\cong Q\quad. + & \forall A.\,F^{P^{A}}=\forall A.\,R\rightarrow G^{P^{A}}\\ +\text{Statement\,\ref{subsec:Statement-general-identities-forall}(c)}:\quad & =R\rightarrow\big(\gunderline{\forall A.\,G^{P^{A}}}\big)\\ +\text{inductive assumption}:\quad & =R\rightarrow G^{\forall A.\,P^{A}}=F^{\forall A.\,P^{A}}\quad. \end{align*} \end_inset @@ -44127,38 +43944,30 @@ This gives us the following results: \end_layout \begin_layout Standard -Because of the known identities that hold for any type constructors -\begin_inset Formula $U$ -\end_inset - -, -\begin_inset Formula $V$ +(6) +\begin_inset Formula $F^{A}=S^{A,F^{A}}$ \end_inset -: -\begin_inset Formula -\begin{align*} - & \forall A.\,U^{A}+V^{A}=(\forall A.\,U^{A})+(\forall A.\,V^{A})\quad,\\ - & \forall A.\,U^{A}\times V^{A}=(\forall A.\,U^{A})\times(\forall A.\,V^{A})\quad, -\end{align*} - +, where the statement is already true for +\begin_inset Formula $S$ \end_inset -we may also use the Yoneda identity to simplify the type -\begin_inset Formula $\forall A.\,T^{A}$ + by the inductive assumption. + (Another inductive assumption is that the statement is already true for + recursive usages of +\begin_inset Formula $F$ \end_inset - where -\begin_inset Formula $T^{A}$ + under +\begin_inset Formula $S$ \end_inset - is equivalent to a product or a co-product of simpler expressions: +.) We get: \begin_inset Formula \begin{align*} - & \forall A.\,A+(P\rightarrow A)\cong(\forall A.\,A)+(\forall A.\,P\rightarrow A)\cong\bbnum 0+\bbnum 0\cong\bbnum 0\quad,\\ - & \forall A.\,A+P\rightarrow A\cong\forall A.\,(A\rightarrow A)\times(P\rightarrow A)\cong\bbnum 1\times\bbnum 0\cong\bbnum 0\quad,\\ - & \forall A.\,A+A\rightarrow A\cong\forall A.\,(A\rightarrow A)\times(A\rightarrow A)\cong\bbnum 1\quad,\\ - & \forall A.\,A\rightarrow P\times A\cong\forall A.\,(A\rightarrow P)\times(A\rightarrow A)\cong P\times\bbnum 1\cong P\quad. + & \forall A.\,F^{P^{A}}=\forall A.\,S^{P^{A},\,F^{P^{A}}}\\ +\text{inductive assumption}:\quad & \cong S^{\forall A.\,P^{A},\,\gunderline{\forall A.\,F^{P^{A}}}}\\ +\text{inductive assumption}:\quad & \cong S^{\forall A.\,P^{A},\,F^{\forall A.\,P^{A}}}=F^{\forall A.\,P^{A}}\quad. \end{align*} \end_inset @@ -44167,138 +43976,148 @@ we may also use the Yoneda identity to simplify the type \end_layout \begin_layout Standard -It remains to consider types of the form -\begin_inset Formula $\forall A.\,U^{A}\rightarrow V^{A}$ +The identities for bifunctors, +\begin_inset Formula $3$ \end_inset - when -\begin_inset Formula $U^{A}$ +-functors, etc., are proved in a similar way. + +\begin_inset Formula $\square$ \end_inset - is -\emph on -not -\emph default - a co-product and -\begin_inset Formula $V^{A}$ -\end_inset - is -\emph on -not -\emph default - a product. - To simplify those types, we apply a suitable technique as indicated: -\begin_inset Formula -\begin{align*} -\text{use Yoneda identity}:\quad & \forall A.\,A\rightarrow A\cong\bbnum 1\quad,\quad\forall A.\,A\times A\rightarrow A\cong\bbnum 2\quad,\\ -\text{uncurry, use Yoneda}:\quad & \forall A.\,A\times P\rightarrow A\cong\forall A.\,A\rightarrow P\rightarrow A\cong P\rightarrow\bbnum 1\cong\bbnum 1\quad,\\ -\text{because }T^{\bbnum 0}\cong\bbnum 0:\quad & \forall A.\,(A\rightarrow A)\rightarrow A\cong\bbnum 0\quad\text{and}\quad\forall A.\,(A\rightarrow P)\rightarrow A\cong\bbnum 0\quad,\\ -\text{use Yoneda identity}:\quad & \forall A.\,(P\rightarrow A)\rightarrow A\cong P\quad,\quad\forall A.\,A\rightarrow P+A\cong P+\bbnum 1\quad,\\ -\text{Church-Yoneda identity}:\quad & \forall A.\,(A\rightarrow A)\rightarrow R\cong R\quad. -\end{align*} +\end_layout -\end_inset +\begin_layout Standard +We will now prove some statements showing miscellaneous additional techniques + for simplifying universally quantified types. +\end_layout + +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-Fubini-theorem-1" -(For the last line, use the Church-Yoneda identity from Statement -\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-Church-Yoneda-identity" +reference "subsec:Statement-Fubini-theorem-1" plural "false" caps "false" noprefix "false" \end_inset - with -\begin_inset Formula $F^{A}\triangleq A$ + +\end_layout + +\begin_layout Standard +If any type constructor +\begin_inset Formula $F$ \end_inset - and -\begin_inset Formula $G^{A}\triangleq R$ + is such that +\begin_inset Formula $F^{\bbnum 0}\cong\bbnum 0$ \end_inset -, and get -\begin_inset Formula $G^{\mu A.\,F^{A}}=R$ + then: +\begin_inset Formula +\[ +\forall A.\,F^{A}\cong\bbnum 0\quad. +\] + \end_inset -.) + \end_layout -\begin_layout Subsubsection -Example -\begin_inset CommandInset label -LatexCommand label -name "subsec:Example-complicated-type-equivalence-3" +\begin_layout Subparagraph +Proof +\end_layout +\begin_layout Standard +We need to show that there exist no values of type +\begin_inset Formula $\forall A.\,F^{A}$ \end_inset +. + Suppose there existed such a value +\begin_inset Formula $f$ +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Example-complicated-type-equivalence-3" -plural "false" -caps "false" -noprefix "false" +; then we would be apply to apply +\begin_inset Formula $f$ +\end_inset + + to the void type. + The resulting value would be: +\begin_inset Formula +\[ +x:F^{\bbnum 0}\quad,\quad\quad x\triangleq f^{\bbnum 0}\quad. +\] \end_inset +But this contradicts the given assumption that the type +\begin_inset Formula $F^{\bbnum 0}$ +\end_inset + is void. + This contradiction proves the statement. \end_layout \begin_layout Standard -Simplify the type -\begin_inset Formula $\forall A.\,(P\rightarrow A\times Q)\rightarrow(A+R)\times S$ +The proof is non-constructive: we have shown that assuming the existence + of values of type +\begin_inset Formula $\forall A.\,F^{A}$ \end_inset -. -\end_layout - -\begin_layout Subparagraph -Solution + leads to a contradiction. + \end_layout \begin_layout Standard -First, perform some equivalence transformations on the type, trying to transform - some of its sub-expressions into a Yoneda-like form: -\begin_inset Formula -\begin{align*} - & \forall A.\,(P\rightarrow A\times Q)\rightarrow(A+R)\times S\\ - & \cong\forall A.\,((P\rightarrow A\times Q)\rightarrow A+R)\times((P\rightarrow A\times Q)\rightarrow S)\\ - & =(\forall A.\,(P\rightarrow A)\rightarrow(P\rightarrow Q)\rightarrow A+R)\times(\forall A.\,H^{A})\\ - & =(\forall A.\,(P\rightarrow A)\rightarrow F^{A})\times(\forall A.\,H^{A})\quad. -\end{align*} +Let us also show a constructive proof that computes a +\emph on +witness +\emph default + that +\begin_inset Formula $\forall A.\,F^{A}$ +\end_inset + is void (that is, a value of type +\begin_inset Formula $(\forall A.\,F^{A})\rightarrow\bbnum 0$ \end_inset -Here -\begin_inset Formula $F^{A}\triangleq(P\rightarrow Q)\rightarrow A+R$ +) from a witness that +\begin_inset Formula $F^{\bbnum 0}$ \end_inset - is a functor and -\begin_inset Formula $H^{A}\triangleq(A\rightarrow P\rightarrow Q)\rightarrow S$ + is void (a value of type +\begin_inset Formula $F^{\bbnum 0}\rightarrow\bbnum 0$ \end_inset - is a contrafunctor we introduced. - The Yoneda identities give: -\begin_inset Formula -\begin{align*} - & \forall A.\,(P\rightarrow A)\rightarrow F^{A}\cong F^{P}\quad,\\ - & \forall A.\,H^{A}\cong H^{\bbnum 1}\quad. -\end{align*} +). + The computation is expressed as a function +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +proof +\end_layout \end_inset -Now we can finish the derivation: +: \begin_inset Formula \begin{align*} - & \forall A.\,(P\rightarrow A\times Q)\rightarrow(A+R)\times S\cong F^{P}\times H^{\bbnum 1}\\ - & =((P\rightarrow Q)\rightarrow P+R)\times((P\rightarrow Q)\rightarrow S)\\ - & \cong(P\rightarrow Q)\rightarrow(P+R)\times S\quad. + & \text{proof}:(F^{\bbnum 0}\rightarrow\bbnum 0)\rightarrow(\forall A.\,F^{A})\rightarrow\bbnum 0\quad,\\ + & \text{proof}\triangleq k^{:F^{\bbnum 0}\rightarrow\bbnum 0}\rightarrow f^{:\forall A.\,F^{A}}\rightarrow k(f^{\bbnum 0})\quad. \end{align*} \end_inset @@ -44307,201 +44126,217 @@ Now we can finish the derivation: \end_layout \begin_layout Subsubsection -Example +Statement \begin_inset CommandInset label LatexCommand label -name "subsec:Example-simplify-quantifier-A-A" +name "subsec:Statement-Fubini-theorem" \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Example-simplify-quantifier-A-A" +reference "subsec:Statement-Fubini-theorem" plural "false" caps "false" noprefix "false" \end_inset + (Fubini theorem +\begin_inset Index idx +status open +\begin_layout Plain Layout +Fubini theorem \end_layout -\begin_layout Standard - -\series bold -(a) -\series default - Show that -\begin_inset Formula $\forall A.\,F^{A\rightarrow A}\cong F^{\bbnum 1}$ \end_inset - for any strictly positive functor -\begin_inset Formula $F$ +) +\end_layout + +\begin_layout Standard +For any type constructor +\begin_inset Formula $S$ \end_inset -. - (See Definition -\begin_inset space ~ + with two type parameters (not necessarily covariant or contravariant), + we have: +\begin_inset Formula +\[ +\forall A.\,\forall B.\,S^{A,B}\cong\forall B.\,\forall A.\,S^{A,B}\quad. +\] + \end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Definition-strictly-positive-functor" -plural "false" -caps "false" -noprefix "false" +\end_layout + +\begin_layout Subparagraph +Proof +\end_layout +\begin_layout Standard +The isomorphism is implemented by the function +\begin_inset Formula $f$ \end_inset -.) It is unknown if this holds for covariant functors -\begin_inset Formula $F$ +: +\begin_inset Formula +\begin{align*} + & f:\big(\forall(A,B).\,S^{A,B}\big)\rightarrow\forall B.\,\forall A.\,S^{A,B}\\ + & f\triangleq k^{:\forall(A,B).\,S^{A,B}}\rightarrow\forall B.\,\forall A.\,k^{A,B}\quad. +\end{align*} + \end_inset - that are not strictly positive; see Problem -\begin_inset space ~ +This function is its own inverse: for any +\begin_inset Formula $k:\forall(A,B).\,S^{A,B}$ \end_inset +, +\begin_inset Formula +\begin{align*} +\text{expect to equal }k:\quad & k\triangleright f\triangleright f=\big(\forall B.\,\forall A.\,k^{A,B}\big)\triangleright f\\ + & =\forall B.\,\forall A.\,k^{B,A}\\ +\text{rename type parameters}:\quad & =\forall A.\,\forall B.\,k^{A,B}=k. +\end{align*} + +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "par:Problem-Peirce-law-1" -plural "false" -caps "false" -noprefix "false" +\begin_inset Formula $\square$ \end_inset -. -\end_layout + +\begin_inset Note Note +status collapsed -\begin_layout Standard +\begin_layout Subsubsection +Statement +\end_layout -\series bold -(b) -\series default - Show that for any contrafunctor +\begin_layout Plain Layout +For any type constructor \begin_inset Formula $F$ \end_inset -, the same holds: -\begin_inset Formula $\forall A.\,F^{A\rightarrow A}\cong F^{\bbnum 1}$ +: (not sure any of this is true!) +\begin_inset Formula +\begin{align*} +\text{(a)}:\quad & \forall X.\,\forall Y.\,F^{X\times Y}\cong\forall Z.\,F^{Z}\quad,\\ +\text{(b)}:\quad & \forall X.\,\forall Y.\,F^{X+Y}\cong\forall Z.\,F^{Z}\quad,\\ +\text{(c)}:\quad & \forall X.\,\forall Y.\,F^{X\rightarrow Y}\cong\forall Z.\,F^{Z}\quad. +\end{align*} + \end_inset -. + \end_layout -\begin_layout Standard +\begin_layout Subparagraph +Proof +\end_layout -\series bold -(c) -\series default - The same equivalence no longer holds when +\begin_layout Plain Layout +Item (b) is certainly wrong: use a contravariant \begin_inset Formula $F$ \end_inset - is neither covariant nor contravariant. + as a counterexample and get +\begin_inset Formula $F^{\bbnum 1+\bbnum 1}\not\cong F^{\bbnum 1}$ +\end_inset + +. + Other items might be correct but it is not clear how to prove them, as + parametricity does not directly apply to a replacement of a pair of type + parameters by a single type parameter. \end_layout -\begin_layout Subparagraph -Solution +\end_inset + + \end_layout \begin_layout Standard +With these techniques, together with the Yoneda and Church-Yoneda identities, + we can often reduce a type that contains a universal quantifier to an equivalen +t simpler type without quantifiers. +\end_layout + +\begin_layout Subsubsection +Example +\begin_inset CommandInset label +LatexCommand label +name "subsec:Example-complicated-type-equivalence-2-1" -\series bold -(a) -\series default - This follows from Statement -\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-quantifier-across-functor" +reference "subsec:Example-complicated-type-equivalence-2-1" plural "false" caps "false" noprefix "false" \end_inset -: -\begin_inset Formula -\[ -\forall A.\,F^{A\rightarrow A}\cong F^{\forall A.\,A\rightarrow A}\cong F^{\bbnum 1}\quad. -\] - -\end_inset - -\begin_inset Note Note -status collapsed +\begin_inset Index idx +status open \begin_layout Plain Layout -Not sure if we can remove the double quantifier! +examples \end_layout -\begin_layout Plain Layout -Define the profunctor -\begin_inset Formula $P^{A,B}\triangleq F^{A\rightarrow B}$ \end_inset - and rewrite the given type as: -\begin_inset Formula -\[ -\forall A.\,F^{A\rightarrow A}=\forall A.\,P^{A,A}\quad. -\] - -\end_inset -Now, -\begin_inset Formula $P^{A,B}$ -\end_inset +\end_layout - is contravariant in -\begin_inset Formula $A$ +\begin_layout Standard +Show that the type +\begin_inset Formula $\forall A.\,\bbnum 1+A\rightarrow A$ \end_inset - and covariant in -\begin_inset Formula $B$ -\end_inset + is void. +\end_layout -. - So, we may apply the contravariant Yoneda identity with respect to the - first type parameter in -\begin_inset Formula $P^{A,B}$ -\end_inset +\begin_layout Subparagraph +Solution +\end_layout -: +\begin_layout Standard +Transform the type using the Yoneda identities: \begin_inset Formula -\[ -P^{A,B}\cong\forall C.\,(C\rightarrow A)\rightarrow P^{C,B}\quad. -\] +\begin{align*} + & \forall A.\,\bbnum 1+A\rightarrow A\cong\forall A.\,(\bbnum 1\rightarrow A)\times(A\rightarrow A)\\ + & \cong(\forall A.\,\bbnum 1\rightarrow A)\times(\forall A.\,A\rightarrow A)\\ + & \cong\bbnum 0\times\bbnum 1=\bbnum 0\quad. +\end{align*} \end_inset -Then we set -\begin_inset Formula $B=A$ -\end_inset - in the last formula and write: -\begin_inset Formula -\begin{align*} - & \forall A.\,F^{A\rightarrow A}=\forall A.\,\gunderline{P^{A,A}}\\ -\text{use the contravariant Yoneda identity}:\quad & \cong\forall A.\,\forall C.\,\left(C\rightarrow A\right)\rightarrow\gunderline{P^{C,A}}\\ -\text{use the definition of }P:\quad & =\forall A.\,\forall C.\,\gunderline{\left(C\rightarrow A\right)}\rightarrow F^{\gunderline{C\rightarrow A}}\\ -\text{define }Q^{X}\triangleq X\rightarrow F^{X}:\quad & =\gunderline{\forall A.\,\forall C.}\,Q^{\gunderline{C\rightarrow A}}\\ -\text{remove the double quantifier}:\quad & =\forall X.\,Q^{X}=\forall X.\,\gunderline X\rightarrow F^{X}\\ -\text{type equivalence }X\cong\bbnum 1\rightarrow X:\quad & \cong\forall X.\,(\bbnum 1\rightarrow X)\rightarrow F^{X}\\ -\text{covariant Yoneda identity}:\quad & \cong F^{\bbnum 1}\quad. -\end{align*} +\end_layout + +\begin_layout Subsubsection +Example +\begin_inset CommandInset label +LatexCommand label +name "subsec:Example-simplify-quantifier" \end_inset -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-simplify-quantifier" +plural "false" +caps "false" +noprefix "false" \end_inset @@ -44509,145 +44344,159 @@ Then we set \end_layout \begin_layout Standard - -\series bold -(b) -\series default - Use the contravariant Yoneda identity to introduce another quantifier ( -\begin_inset Formula $\forall B$ +Simplify all fully parametric types of the form +\begin_inset Formula $\forall A.\,T^{A}$ \end_inset -): -\begin_inset Formula -\begin{align*} - & \forall A.\,F^{A\rightarrow A}\cong\forall A.\,\forall B.\,(\gunderline{B\rightarrow A\rightarrow}\,A)\rightarrow F^{B}\\ -\text{uncurry arguments}:\quad & \cong\forall A.\,\forall B.\,(\gunderline{B\times A}\rightarrow A)\rightarrow F^{B}\\ -\text{define }G^{A}\triangleq B\times A:\quad & \cong\forall A.\,\gunderline{\forall B.\,(G^{A}\rightarrow A)\rightarrow F^{B}}\\ -\text{contravariant Yoneda identity}:\quad & \cong\forall A.\,(G^{A}\rightarrow A)\rightarrow F^{\bbnum 1}\\ -\text{Statement \ref{subsec:Statement-application-full-relation}}:\quad & \cong F^{\bbnum 1}\quad. -\end{align*} - + where +\begin_inset Formula $T^{A}$ \end_inset -In the last line, we used Statement + is any type expression containing no recursion and at most two type constructio +ns (using Table \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-application-full-relation" +reference "tab:six-pure-type-constructions" plural "false" caps "false" noprefix "false" \end_inset -) with -\begin_inset Formula $F^{A}=G^{A}\rightarrow A$ + without the recursive type). + The type expression +\begin_inset Formula $T^{A}$ \end_inset - and -\begin_inset Formula $P=F^{\bbnum 1}$ + may contain +\begin_inset Formula $A$ \end_inset - as the type constructor -\begin_inset Formula $F$ + and other fixed types ( +\begin_inset Formula $P,$ \end_inset - is lifting-to-full. + +\begin_inset Formula $Q$ +\end_inset + +). \end_layout -\begin_layout Standard +\begin_layout Subparagraph +Solution +\end_layout -\series bold -(c) -\series default - If we set -\begin_inset Formula $F^{X}=X\rightarrow X$ +\begin_layout Standard +Fully parametric types are built via the five type constructions So, we + can enumerate all type expressions +\begin_inset Formula $T^{A}$ \end_inset - then the type -\begin_inset Formula $\forall A.\,F^{A\rightarrow A}$ + of the specified form: +\begin_inset Formula $\forall A.\,P$ \end_inset - becomes -\begin_inset Formula $\forall A.\,(A\rightarrow A)\rightarrow A\rightarrow A$ +, +\begin_inset Formula $\forall A.\,A$ \end_inset -, which is equivalent to the type of natural numbers. - That type is -\emph on -not -\emph default - equivalent to -\begin_inset Formula $F^{\bbnum 1}$ +, +\begin_inset Formula $\forall A.\,P\times A$ \end_inset -. - -\begin_inset Formula $\square$ +, +\begin_inset Formula $\forall A.\,A\rightarrow P+A$ \end_inset - -\end_layout - -\begin_layout Subsection -The Jaskelioff-O'Connor theorem for simple types +, and so on. + For each of those expressions, we need to apply an appropriate technique + that will simplify the type. \end_layout \begin_layout Standard -The Jaskelioff-O'Connor theorem -\begin_inset Foot -status open - -\begin_layout Plain Layout -See -\family typewriter - -\begin_inset CommandInset href -LatexCommand href -target "https://arxiv.org/abs/1402.1699" -literal "false" +We begin by noticing that many type expressions +\begin_inset Formula $T^{A}$ +\end_inset + will be covariant in +\begin_inset Formula $A$ \end_inset + or contravariant in +\begin_inset Formula $A$ +\end_inset -\end_layout +. + Examples are: +\begin_inset Formula +\begin{align*} +\text{covariant}:\quad & A\quad,\quad P\rightarrow A\quad,\quad P+A\times A\quad,\quad(A\rightarrow P)\rightarrow Q\quad,\quad...\\ +\text{contravariant}:\quad & A\rightarrow P\quad,\quad P+(A\rightarrow Q)\quad,\quad(P\rightarrow A)\rightarrow Q\quad,\quad... +\end{align*} \end_inset - is a type equivalence between certain type constructors quantified over - a typeclass. - This section proves a version of that theorem that holds for simple types - belonging to a -\begin_inset Formula $P$ +The Yoneda identities can simplify such type expressions: +\begin_inset Formula +\begin{align*} +\text{if }T\text{ is covariant}:\quad & \forall A.\,T^{A}\cong T^{\bbnum 0}\quad,\\ +\text{if }T\text{ is contravariant}:\quad & \forall A.\,T^{A}\cong T^{\bbnum 1}\quad. +\end{align*} + \end_inset --typeclass. - Then the theorem gives a general type formula for the free construction - of any -\begin_inset Formula $P$ +This gives us the following results: +\begin_inset Formula +\begin{align*} + & \forall A.\,P\cong P\quad,\quad\forall A.\,A\cong\bbnum 0\quad,\\ + & \forall A.\,A+P\cong P\quad,\quad\forall A.\,A\times P\cong\bbnum 0\quad,\quad\forall A.\,A\rightarrow P\cong P\quad,\quad\forall A.\,P\rightarrow A\cong\bbnum 0\quad,\\ + & \forall A.\,P\rightarrow A+Q\cong P\rightarrow Q\quad,\quad\forall A.\,(P\rightarrow A)\rightarrow Q\cong Q\quad,\quad\forall A.\,(A\rightarrow P)\rightarrow Q\cong Q\quad. +\end{align*} + \end_inset --typeclass. -\end_layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-JOC-theorem-simple-types" +\end_layout +\begin_layout Standard +Because of the known identities that hold for any type constructors +\begin_inset Formula $U$ \end_inset +, +\begin_inset Formula $V$ +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-JOC-theorem-simple-types" -plural "false" -caps "false" -noprefix "false" +: +\begin_inset Formula +\begin{align*} + & \forall A.\,U^{A}+V^{A}=(\forall A.\,U^{A})+(\forall A.\,V^{A})\quad,\\ + & \forall A.\,U^{A}\times V^{A}=(\forall A.\,U^{A})\times(\forall A.\,V^{A})\quad, +\end{align*} + +\end_inset + +we may also use the Yoneda identity to simplify the type +\begin_inset Formula $\forall A.\,T^{A}$ +\end_inset + + where +\begin_inset Formula $T^{A}$ +\end_inset + + is equivalent to a product or a co-product of simpler expressions: +\begin_inset Formula +\begin{align*} + & \forall A.\,A+(P\rightarrow A)\cong(\forall A.\,A)+(\forall A.\,P\rightarrow A)\cong\bbnum 0+\bbnum 0\cong\bbnum 0\quad,\\ + & \forall A.\,A+P\rightarrow A\cong\forall A.\,(A\rightarrow A)\times(P\rightarrow A)\cong\bbnum 1\times\bbnum 0\cong\bbnum 0\quad,\\ + & \forall A.\,A+A\rightarrow A\cong\forall A.\,(A\rightarrow A)\times(A\rightarrow A)\cong\bbnum 1\quad,\\ + & \forall A.\,A\rightarrow P\times A\cong\forall A.\,(A\rightarrow P)\times(A\rightarrow A)\cong P\times\bbnum 1\cong P\quad. +\end{align*} \end_inset @@ -44655,431 +44504,341 @@ noprefix "false" \end_layout \begin_layout Standard -The free -\begin_inset Formula $P$ +It remains to consider types of the form +\begin_inset Formula $\forall A.\,U^{A}\rightarrow V^{A}$ \end_inset --typeclass instance -\begin_inset Formula $E^{T}$ + when +\begin_inset Formula $U^{A}$ \end_inset - generated by a type -\begin_inset Formula $T$ + is +\emph on +not +\emph default + a co-product and +\begin_inset Formula $V^{A}$ \end_inset - is equivalent to the type defined by: + is +\emph on +not +\emph default + a product. + To simplify those types, we apply a suitable technique as indicated: \begin_inset Formula -\begin{equation} -E^{T}\cong\forall(A\in P\text{-typeclass}).\,(T\rightarrow A)\rightarrow A\quad.\label{eq:free-typeclass-via-church-encoding} -\end{equation} - -\end_inset - -Here the quantifier goes only over the types -\begin_inset Formula $A$ -\end_inset +\begin{align*} +\text{use Yoneda identity}:\quad & \forall A.\,A\rightarrow A\cong\bbnum 1\quad,\quad\forall A.\,A\times A\rightarrow A\cong\bbnum 2\quad,\\ +\text{uncurry, use Yoneda}:\quad & \forall A.\,A\times P\rightarrow A\cong\forall A.\,A\rightarrow P\rightarrow A\cong P\rightarrow\bbnum 1\cong\bbnum 1\quad,\\ +\text{because }T^{\bbnum 0}\cong\bbnum 0:\quad & \forall A.\,(A\rightarrow A)\rightarrow A\cong\bbnum 0\quad\text{and}\quad\forall A.\,(A\rightarrow P)\rightarrow A\cong\bbnum 0\quad,\\ +\text{use Yoneda identity}:\quad & \forall A.\,(P\rightarrow A)\rightarrow A\cong P\quad,\quad\forall A.\,A\rightarrow P+A\cong P+\bbnum 1\quad,\\ +\text{Church-Yoneda identity}:\quad & \forall A.\,(A\rightarrow A)\rightarrow R\cong R\quad. +\end{align*} - that belong to the -\begin_inset Formula $P$ \end_inset --typeclass. - It is also assumed that the type in the right-hand side of Eq. +(For the last line, use the Church-Yoneda identity from Statement \begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:free-typeclass-via-church-encoding" +reference "subsec:Statement-Church-Yoneda-identity" plural "false" caps "false" noprefix "false" \end_inset -) admits only functions that satisfy the naturality law with respect to - -\begin_inset Formula $A$ -\end_inset - -. -\end_layout - -\begin_layout Subparagraph -Proof -\end_layout - -\begin_layout Standard -One of the defining properties of the free typeclass constructor -\begin_inset Formula $E$ -\end_inset - - is the one-to-one correspondence between functions of type -\begin_inset Formula $T\rightarrow A$ + with +\begin_inset Formula $F^{A}\triangleq A$ \end_inset and -\begin_inset Formula $P$ -\end_inset - --typeclass morphisms of type -\begin_inset Formula $E^{T}\rightarrow A$ -\end_inset - -. - Denoting by -\begin_inset Formula $E^{T}\overset{P}{\rightarrow}A$ +\begin_inset Formula $G^{A}\triangleq R$ \end_inset - the type of those morphisms, we have: -\begin_inset Formula -\[ -\forall(A\in P\text{-typeclass}).\,(T\rightarrow A)\rightarrow A\cong\forall(A\in P\text{-typeclass}).\,(E^{T}\overset{P}{\rightarrow}A)\rightarrow A\quad. -\] - +, and get +\begin_inset Formula $G^{\mu A.\,F^{A}}=R$ \end_inset - +.) \end_layout -\begin_layout Standard -All types -\begin_inset Formula $A$ -\end_inset - - belonging to the -\begin_inset Formula $P$ -\end_inset - --typeclass are -\begin_inset Formula $E$ -\end_inset - --monad algebras, and those algebras form a category. - Now we use the Yoneda identity in that category: -\begin_inset Formula -\[ -\forall(A\in P\text{-typeclass}).\,(X\overset{P}{\rightarrow}A)\rightarrow A\cong X\quad, -\] +\begin_layout Subsubsection +Example +\begin_inset CommandInset label +LatexCommand label +name "subsec:Example-complicated-type-equivalence-3" \end_inset -where -\begin_inset Formula $X$ -\end_inset - is any fixed type that also belongs to the -\begin_inset Formula $P$ -\end_inset +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-complicated-type-equivalence-3" +plural "false" +caps "false" +noprefix "false" --typeclass. - We use this identity with -\begin_inset Formula $X=E^{T}$ \end_inset - and obtain: -\begin_inset Formula -\[ -\forall(A\in P\text{-typeclass}).\,(E^{T}\overset{P}{\rightarrow}A)\rightarrow A\cong E^{T}\quad, -\] -\end_inset +\end_layout -as required. - -\begin_inset Formula $\square$ +\begin_layout Standard +Simplify the type +\begin_inset Formula $\forall A.\,(P\rightarrow A\times Q)\rightarrow(A+R)\times S$ \end_inset - +. \end_layout -\begin_layout Subsection -The Jaskelioff-O'Connor theorem for type constructors +\begin_layout Subparagraph +Solution \end_layout \begin_layout Standard -The full formulation of the theorem involves functor typeclasses instead - of typeclasses for simple types. - The theorem applies to all -\begin_inset Formula $P$ -\end_inset +First, perform some equivalence transformations on the type, trying to transform + some of its sub-expressions into a Yoneda-like form: +\begin_inset Formula +\begin{align*} + & \forall A.\,(P\rightarrow A\times Q)\rightarrow(A+R)\times S\\ + & \cong\forall A.\,((P\rightarrow A\times Q)\rightarrow A+R)\times((P\rightarrow A\times Q)\rightarrow S)\\ + & =(\forall A.\,(P\rightarrow A)\rightarrow(P\rightarrow Q)\rightarrow A+R)\times(\forall A.\,H^{A})\\ + & =(\forall A.\,(P\rightarrow A)\rightarrow F^{A})\times(\forall A.\,H^{A})\quad. +\end{align*} --typeclasses for functors. - Those typeclasses have method signatures of the form -\begin_inset Formula $\forall A.\,(P^{F})^{A}\rightarrow F^{A}$ \end_inset -, where -\begin_inset Formula $P$ +Here +\begin_inset Formula $F^{A}\triangleq(P\rightarrow Q)\rightarrow A+R$ \end_inset - is a functor on functors (the kind of -\begin_inset Formula $P$ + is a functor and +\begin_inset Formula $H^{A}\triangleq(A\rightarrow P\rightarrow Q)\rightarrow S$ \end_inset - is -\begin_inset Formula $(*\rightarrow*)\rightarrow*\rightarrow*$ -\end_inset + is a contrafunctor we introduced. + The Yoneda identities give: +\begin_inset Formula +\begin{align*} + & \forall A.\,(P\rightarrow A)\rightarrow F^{A}\cong F^{P}\quad,\\ + & \forall A.\,H^{A}\cong H^{\bbnum 1}\quad. +\end{align*} -) and functions of type -\begin_inset Formula $(P^{F})^{A}\rightarrow F^{A}$ \end_inset - are restricted to natural transformations between functors -\begin_inset Formula $P^{F}$ -\end_inset +Now we can finish the derivation: +\begin_inset Formula +\begin{align*} + & \forall A.\,(P\rightarrow A\times Q)\rightarrow(A+R)\times S\cong F^{P}\times H^{\bbnum 1}\\ + & =((P\rightarrow Q)\rightarrow P+R)\times((P\rightarrow Q)\rightarrow S)\\ + & \cong(P\rightarrow Q)\rightarrow(P+R)\times S\quad. +\end{align*} - and -\begin_inset Formula $F$ \end_inset -. - Examples of well-known -\begin_inset Formula $P$ -\end_inset --typeclasses of that form are pointed functors, filterable functors, applicative - functors, and monads. \end_layout \begin_layout Subsubsection -Statement +Example \begin_inset CommandInset label LatexCommand label -name "subsec:Statement-Jaskelioff-OConnor" +name "subsec:Example-simplify-quantifier-A-A" \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-Jaskelioff-OConnor" +reference "subsec:Example-simplify-quantifier-A-A" plural "false" caps "false" noprefix "false" \end_inset - (Jaskelioff-O'Connor) + \end_layout \begin_layout Standard -Given any fixed -\begin_inset Formula $P$ -\end_inset --typeclass for functors, denote by -\begin_inset Formula $E$ +\series bold +(a) +\series default + Show that +\begin_inset Formula $\forall A.\,F^{A\rightarrow A}\cong F^{\bbnum 1}$ \end_inset - the constructor of free instances of that typeclass: if -\begin_inset Formula $T$ + for any strictly positive functor +\begin_inset Formula $F$ \end_inset - is any functor then the functor -\begin_inset Formula $E^{T}$ +. + (See Definition +\begin_inset space ~ \end_inset - is guaranteed to be an instance of the -\begin_inset Formula $P$ -\end_inset --typeclass. - Suppose -\begin_inset Formula $A$ -\end_inset +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Definition-strictly-positive-functor" +plural "false" +caps "false" +noprefix "false" -, -\begin_inset Formula $B$ \end_inset -, -\begin_inset Formula $C$ +.) It is unknown if this holds for covariant functors +\begin_inset Formula $F$ \end_inset - are some fixed types. - Then the following type equivalence holds: -\begin_inset Formula -\begin{align} - & \forall(F\in P\text{-typeclass}).\,(A\rightarrow F^{B})\rightarrow F^{C}\cong(E^{R})^{C}\quad,\label{eq:jaskelioff-o-connor-theorem}\\ -\text{where }R\text{ is defined by}:\quad & R^{T}\triangleq A\times(B\rightarrow T)\quad.\nonumber -\end{align} - + that are not strictly positive; see Problem +\begin_inset space ~ \end_inset -Here, it is assumed that the type -\begin_inset Formula $(A\rightarrow F^{B})\rightarrow F^{C}$ -\end_inset - is restricted to functions satisfying the naturality law with respect to - -\begin_inset Formula $F$ +\begin_inset CommandInset ref +LatexCommand ref +reference "par:Problem-Peirce-law-1" +plural "false" +caps "false" +noprefix "false" + \end_inset . \end_layout -\begin_layout Subparagraph -Proof -\end_layout - \begin_layout Standard -Denote by -\begin_inset Formula $K\overset{P}{\rightarrow}L$ -\end_inset - the type of -\begin_inset Formula $P$ +\series bold +(b) +\series default + Show that for any contrafunctor +\begin_inset Formula $F$ \end_inset --typeclass morphisms between functors -\begin_inset Formula $K$ +, the same holds: +\begin_inset Formula $\forall A.\,F^{A\rightarrow A}\cong F^{\bbnum 1}$ \end_inset - and -\begin_inset Formula $L$ -\end_inset +. +\end_layout - that belong to the typeclass. - (The full type signature of a -\begin_inset Formula $P$ -\end_inset +\begin_layout Standard --typeclass morphism is -\begin_inset Formula $\forall A.\,K^{A}\overset{P}{\rightarrow}L^{A}$ +\series bold +(c) +\series default + The same equivalence no longer holds when +\begin_inset Formula $F$ \end_inset -.) + is neither covariant nor contravariant. +\end_layout + +\begin_layout Subparagraph +Solution \end_layout \begin_layout Standard -We will prove the type equivalence + +\series bold +(a) +\series default + This follows from Statement \begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:jaskelioff-o-connor-theorem" +reference "subsec:Statement-quantifier-across-functor" plural "false" caps "false" noprefix "false" \end_inset -) in three steps. -\end_layout - -\begin_layout Standard - -\series bold -(1) -\series default - Use the Yoneda identity to obtain this type equivalence: +: \begin_inset Formula \[ -A\rightarrow F^{B}\cong\forall X.\,R^{X}\rightarrow F^{X}\quad. +\forall A.\,F^{A\rightarrow A}\cong F^{\forall A.\,A\rightarrow A}\cong F^{\bbnum 1}\quad. \] \end_inset -To derive this formula, write: -\begin_inset Formula -\begin{align*} - & A\rightarrow F^{B}\\ -\text{covariant Yoneda identity}:\quad & \cong A\rightarrow\forall X.\,(B\rightarrow X)\rightarrow F^{X}\\ -\text{move }\forall X\text{ to front}:\quad & \cong\forall X.\,A\rightarrow(B\rightarrow X)\rightarrow F^{X}\\ -\text{uncurry the function}:\quad & \cong\forall X.\,A\times(B\rightarrow X)\rightarrow F^{X}=\forall X.\,R^{X}\rightarrow F^{X}\quad. -\end{align*} - -\end_inset -In the first line of this derivation, we have used the assumption that -\begin_inset Formula $F$ -\end_inset +\begin_inset Note Note +status collapsed - is a (covariant) functor. +\begin_layout Plain Layout +Not sure if we can remove the double quantifier! \end_layout -\begin_layout Standard - -\series bold -(2) -\series default - By the universal property of the free -\begin_inset Formula $P$ -\end_inset - --typeclass runner, for any functor -\begin_inset Formula $F$ +\begin_layout Plain Layout +Define the profunctor +\begin_inset Formula $P^{A,B}\triangleq F^{A\rightarrow B}$ \end_inset - that belongs to the -\begin_inset Formula $P$ -\end_inset + and rewrite the given type as: +\begin_inset Formula +\[ +\forall A.\,F^{A\rightarrow A}=\forall A.\,P^{A,A}\quad. +\] --typeclass and for any functor -\begin_inset Formula $R$ \end_inset - (not necessarily a member of the -\begin_inset Formula $P$ +Now, +\begin_inset Formula $P^{A,B}$ \end_inset --typeclass) there is a one-to-one correspondence between -\begin_inset Formula $P$ + is contravariant in +\begin_inset Formula $A$ \end_inset --typeclass morphisms -\begin_inset Formula $E^{R}\overset{P}{\rightarrow}F$ + and covariant in +\begin_inset Formula $B$ \end_inset - and natural transformations -\begin_inset Formula $R\leadsto F$ +. + So, we may apply the contravariant Yoneda identity with respect to the + first type parameter in +\begin_inset Formula $P^{A,B}$ \end_inset -. - In other words, there is a type equivalence between the following types - (where we wrote out the full type signatures): +: \begin_inset Formula \[ -\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X}\cong\forall X.\,R^{X}\rightarrow F^{X}\quad. +P^{A,B}\cong\forall C.\,(C\rightarrow A)\rightarrow P^{C,B}\quad. \] \end_inset -Now we set -\begin_inset Formula $R^{T}\triangleq A\times(B\rightarrow T)$ +Then we set +\begin_inset Formula $B=A$ \end_inset - and obtain: + in the last formula and write: \begin_inset Formula -\[ -(A\rightarrow F^{B})\rightarrow F^{C}\cong(\forall X.\,R^{X}\rightarrow F^{X})\rightarrow F^{C}\cong(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\quad. -\] - -\end_inset +\begin{align*} + & \forall A.\,F^{A\rightarrow A}=\forall A.\,\gunderline{P^{A,A}}\\ +\text{use the contravariant Yoneda identity}:\quad & \cong\forall A.\,\forall C.\,\left(C\rightarrow A\right)\rightarrow\gunderline{P^{C,A}}\\ +\text{use the definition of }P:\quad & =\forall A.\,\forall C.\,\gunderline{\left(C\rightarrow A\right)}\rightarrow F^{\gunderline{C\rightarrow A}}\\ +\text{define }Q^{X}\triangleq X\rightarrow F^{X}:\quad & =\gunderline{\forall A.\,\forall C.}\,Q^{\gunderline{C\rightarrow A}}\\ +\text{remove the double quantifier}:\quad & =\forall X.\,Q^{X}=\forall X.\,\gunderline X\rightarrow F^{X}\\ +\text{type equivalence }X\cong\bbnum 1\rightarrow X:\quad & \cong\forall X.\,(\bbnum 1\rightarrow X)\rightarrow F^{X}\\ +\text{covariant Yoneda identity}:\quad & \cong F^{\bbnum 1}\quad. +\end{align*} -So, the left-hand side of Eq. -\begin_inset space ~ \end_inset -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:jaskelioff-o-connor-theorem" -plural "false" -caps "false" -noprefix "false" - -\end_inset -) is equivalent to: -\begin_inset Formula -\[ -\forall(F\in P\text{-typeclass}).\,(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\quad. -\] +\end_layout \end_inset @@ -45089,204 +44848,223 @@ noprefix "false" \begin_layout Standard \series bold -(3) +(b) \series default - We use the covariant Yoneda identity in the category of functors that belong - to the -\begin_inset Formula $P$ + Use the contravariant Yoneda identity to introduce another quantifier ( +\begin_inset Formula $\forall B$ \end_inset --typeclass. - As we have found in Section +): +\begin_inset Formula +\begin{align*} + & \forall A.\,F^{A\rightarrow A}\cong\forall A.\,\forall B.\,(\gunderline{B\rightarrow A\rightarrow}\,A)\rightarrow F^{B}\\ +\text{uncurry arguments}:\quad & \cong\forall A.\,\forall B.\,(\gunderline{B\times A}\rightarrow A)\rightarrow F^{B}\\ +\text{define }G^{A}\triangleq B\times A:\quad & \cong\forall A.\,\gunderline{\forall B.\,(G^{A}\rightarrow A)\rightarrow F^{B}}\\ +\text{contravariant Yoneda identity}:\quad & \cong\forall A.\,(G^{A}\rightarrow A)\rightarrow F^{\bbnum 1}\\ +\text{Statement \ref{subsec:Statement-application-full-relation}}:\quad & \cong F^{\bbnum 1}\quad. +\end{align*} + +\end_inset + +In the last line, we used Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Imposing-laws-of-P-typeclasses-via-monad-algebras" +reference "subsec:Statement-application-full-relation" plural "false" caps "false" noprefix "false" \end_inset -, all those functors are -\begin_inset Formula $E$ +) with +\begin_inset Formula $F^{A}=G^{A}\rightarrow A$ \end_inset --monad algebras, which form a category. - The -\begin_inset Formula $P$ + and +\begin_inset Formula $P=F^{\bbnum 1}$ \end_inset --typeclass morphisms are in one-to-one correspondence with the -\begin_inset Formula $E$ + as the type constructor +\begin_inset Formula $F$ \end_inset --monad algebra morphisms. - Therefore, we may write the covariant Yoneda identity for that category - as: -\begin_inset Formula -\[ -\forall(F\in P\text{-typeclass}).\,(\forall X.\,Q^{X}\overset{P}{\rightarrow}F^{X})\rightarrow S^{F}\cong S^{Q}\quad, -\] + is lifting-to-full. +\end_layout -\end_inset +\begin_layout Standard -where -\begin_inset Formula $Q$ +\series bold +(c) +\series default + If we set +\begin_inset Formula $F^{X}=X\rightarrow X$ \end_inset - is any fixed functor from the -\begin_inset Formula $P$ + then the type +\begin_inset Formula $\forall A.\,F^{A\rightarrow A}$ \end_inset --typeclass, -\begin_inset Formula $S^{F}$ + becomes +\begin_inset Formula $\forall A.\,(A\rightarrow A)\rightarrow A\rightarrow A$ \end_inset - is any type expression that is covariant in -\begin_inset Formula $F$ +, which is equivalent to the type of natural numbers. + That type is +\emph on +not +\emph default + equivalent to +\begin_inset Formula $F^{\bbnum 1}$ \end_inset -, and the naturality law with respect to -\begin_inset Formula $F$ +. + +\begin_inset Formula $\square$ \end_inset - is assumed to hold. - We will use this Yoneda identity with -\begin_inset Formula $Q=E^{R}$ -\end_inset -, and set -\begin_inset Formula $S^{F}$ -\end_inset +\end_layout - to just -\begin_inset Formula $F^{C}$ -\end_inset +\begin_layout Subsection +Existential type quantifiers. + Co-Yoneda identities +\begin_inset CommandInset label +LatexCommand label +name "subsec:Existential-type-quantifiers" - (the application of -\begin_inset Formula $F$ \end_inset - to the fixed type -\begin_inset Formula $C$ -\end_inset -). - Then we get: -\begin_inset Formula -\[ -\forall(F\in P\text{-typeclass}).\,(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\cong(E^{R})^{C}\quad. -\] +\end_layout -\end_inset +\begin_layout Standard +The Yoneda identities allow us in many cases to simplify type expressions + with universal quantifiers. + Similar identities hold for existentially quantified types. +\end_layout -The last type is the right-hand side of Eq. +\begin_layout Standard +For the purposes of this and the following sections, we define the existential + quantifier via Eq. \begin_inset space ~ \end_inset ( \begin_inset CommandInset ref LatexCommand ref -reference "eq:jaskelioff-o-connor-theorem" +reference "eq:existential-via-universal-Yoneda" plural "false" caps "false" noprefix "false" \end_inset -). - So, Eq. -\begin_inset space ~ +): +\begin_inset Formula +\[ +\exists C.\,F^{C}\cong\forall D.\,\big(\forall C.\,(F^{C}\rightarrow D)\big)\rightarrow D\quad. +\] + \end_inset -( +Here +\begin_inset Formula $F$ +\end_inset + + is any type constructor (not necessarily covariant or contravariant). +\end_layout + +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-co-Yoneda-two-identities" + +\end_inset + + \begin_inset CommandInset ref LatexCommand ref -reference "eq:jaskelioff-o-connor-theorem" +reference "subsec:Statement-co-Yoneda-two-identities" plural "false" caps "false" noprefix "false" \end_inset -) holds. + \end_layout \begin_layout Standard -Let us now derive the code that implements the type equivalence -\begin_inset space ~ +For any functor +\begin_inset Formula $F$ \end_inset -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:jaskelioff-o-connor-theorem" -plural "false" -caps "false" -noprefix "false" - + and any contrafunctor +\begin_inset Formula $H$ \end_inset -) in the direction of right-to-left. - Suppose we are given a value -\begin_inset Formula $q$ +, the following identities hold: +\begin_inset Formula +\begin{align*} +\text{\textbf{(a)} }\text{covariant co-Yoneda identity}:\quad & \exists A.\,(A\rightarrow R)\times F^{A}\cong F^{R}\quad,\\ +\text{\textbf{(b)} }\text{contravariant co-Yoneda identity}:\quad & \exists A.\,(R\rightarrow A)\times H^{A}\cong H^{R}\quad. +\end{align*} + \end_inset - of the type in the right-hand side of Eq. + +\end_layout + +\begin_layout Subparagraph +Proof +\end_layout + +\begin_layout Standard +We use Eq. \begin_inset space ~ \end_inset ( \begin_inset CommandInset ref LatexCommand ref -reference "eq:jaskelioff-o-connor-theorem" +reference "eq:existential-via-universal-Yoneda" plural "false" caps "false" noprefix "false" \end_inset -): -\begin_inset Formula -\[ -q:(E^{R})^{C}\quad. -\] - -\end_inset - -We need to retrace step -\series bold -(3) -\series default - above and convert this -\begin_inset Formula $q$ +) to express +\begin_inset Formula $\exists A$ \end_inset - to a function -\begin_inset Formula $f$ + via +\begin_inset Formula $\forall A$ \end_inset - of type: -\begin_inset Formula -\[ -f:\forall(F\in P\text{-typeclass}).\,(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\quad. -\] - -\end_inset +. + +\end_layout -The required function -\begin_inset Formula $f$ -\end_inset +\begin_layout Standard - is defined by: +\series bold +(a) +\series default + We write: \begin_inset Formula -\[ -f^{F}\big(k^{:\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X}}\big)\triangleq k^{C}(q)\quad. -\] +\begin{align*} +\text{expect to equal }F^{R}:\quad & \exists A.\,(A\rightarrow R)\times F^{A}\\ +\text{definition of }\exists\text{ in Eq.~}(\ref{eq:existential-via-universal-Yoneda}):\quad & \cong\forall B.\,\big(\forall A.\,\gunderline{(A\rightarrow R)\times F^{A}}\rightarrow B\big)\rightarrow B\\ +\text{uncurry arguments}:\quad & \cong\forall B.\,\big(\gunderline{\forall A.\,(A\rightarrow R)\rightarrow F^{A}\rightarrow B}\big)\rightarrow B\\ +\text{contravariant Yoneda identity}:\quad & \cong\gunderline{\forall B.\,\big(F^{R}\rightarrow B\big)\rightarrow B}\\ +\text{covariant Yoneda identity}:\quad & \cong F^{R}\quad. +\end{align*} \end_inset @@ -45294,47 +45072,56 @@ f^{F}\big(k^{:\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X}}\big)\triangl \end_layout \begin_layout Standard -Continue by retracing step + \series bold -(2) +(b) \series default -, converting -\begin_inset Formula $f$ + We write: +\begin_inset Formula +\begin{align*} +\text{expect to equal }H^{R}:\quad & \exists A.\,(R\rightarrow A)\times H^{A}\\ +\text{definition of }\exists\text{ in Eq.~}(\ref{eq:existential-via-universal-Yoneda}):\quad & \cong\forall B.\,\big(\forall A.\,\gunderline{(R\rightarrow A)\times H^{A}}\rightarrow B\big)\rightarrow B\\ +\text{uncurry arguments}:\quad & \cong\forall B.\,\big(\gunderline{\forall A.\,(R\rightarrow A)\rightarrow H^{A}\rightarrow B}\big)\rightarrow B\\ +\text{covariant Yoneda identity}:\quad & \cong\gunderline{\forall B.\,\big(H^{R}\rightarrow B\big)\rightarrow B}\\ +\text{covariant Yoneda identity}:\quad & \cong H^{R}\quad. +\end{align*} + \end_inset - to a function -\begin_inset Formula $g$ + +\begin_inset Formula $\square$ \end_inset - of type: -\begin_inset Formula -\[ -g:\forall(F\in P\text{-typeclass}).\,(\forall X.\,R^{X}\rightarrow F^{X})\rightarrow F^{C}\quad. -\] +\end_layout + +\begin_layout Standard +To build up intuition, let us substitute +\begin_inset Formula $R=\bbnum 0$ \end_inset -The function -\begin_inset Formula $g$ + and +\begin_inset Formula $R=\bbnum 1$ \end_inset - is defined by: -\begin_inset Formula -\[ -g^{F}\big(k^{:\forall X.\,R^{X}\rightarrow F^{X}}\big)\triangleq f^{F}\big(\forall Y.\,r^{:(E^{R})^{Y}}\rightarrow\text{run}_{E}^{R,Y}(k)(r)\big)\quad, -\] + into the co-Yoneda identities: +\end_layout -\end_inset +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-co-Yoneda-two-identities-1" -where the universal runner ( -\begin_inset Formula $\text{run}_{E}^{T,Y}$ \end_inset -) has type: -\begin_inset Formula -\[ -\text{run}_{E}^{T,Y}:(\forall X.\,T^{X}\rightarrow F^{X})\rightarrow(E^{T})^{Y}\rightarrow F^{Y}\quad. -\] + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-co-Yoneda-two-identities-1" +plural "false" +caps "false" +noprefix "false" \end_inset @@ -45342,790 +45129,585 @@ where the universal runner ( \end_layout \begin_layout Standard -It remains to retrace step -\series bold -(1) -\series default - and define a function -\begin_inset Formula $h$ -\end_inset - - of type: +The following type equivalences hold: \begin_inset Formula -\[ -h:\forall(F\in P\text{-typeclass}).\,(A\rightarrow F^{B})\rightarrow F^{C}\quad. -\] +\begin{align*} +\text{\textbf{(a)} for any functor }F:\quad & \exists A.\,F^{A}\cong F^{\bbnum 1}\quad,\\ +\text{\textbf{(b)} for any contrafunctor }F:\quad & \exists A.\,H^{A}\cong H^{\bbnum 0}\quad. +\end{align*} \end_inset -We implement -\begin_inset Formula $h$ -\end_inset - via this code: -\begin_inset Formula -\[ -h^{F}(k^{:A\rightarrow F^{B}})\triangleq g^{F}\big(\forall X.\,a^{:A}\times t^{:B\rightarrow X}\rightarrow k(a)\triangleright t^{\uparrow F}\big)\quad. -\] +\end_layout -\end_inset +\begin_layout Subparagraph +Proof +\end_layout -This completes the code that transforms -\begin_inset Formula $q$ +\begin_layout Standard +For +\series bold +(a) +\series default +, set +\begin_inset Formula $R=\bbnum 1$ \end_inset - into -\begin_inset Formula $h$ -\end_inset + in the covariant co-Yoneda identity: +\begin_inset Formula +\begin{align*} +\text{left-hand side}:\quad & \exists A.\,(\gunderline{A\rightarrow\bbnum 1})\times F^{A}\cong\exists A.\,\bbnum 1\times F^{A}\cong\exists A.\,F^{A}\quad,\\ +\text{right-hand side}:\quad & F^{\bbnum 1}\quad. +\end{align*} -. - -\begin_inset Formula $\square$ \end_inset \end_layout \begin_layout Standard -We will now apply the Jaskelioff-O'Connor theorem to prove some useful type - equivalences. -\end_layout - -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-identity-monad-morphism" - +For +\series bold +(b) +\series default +, set +\begin_inset Formula $R=\bbnum 0$ \end_inset + in the contravariant co-Yoneda identity: +\begin_inset Formula +\begin{align*} +\text{left-hand side}:\quad & \exists A.\,(\gunderline{\bbnum 0\rightarrow A})\times H^{A}\cong\exists A.\,\bbnum 1\times H^{A}\cong\exists A.\,H^{A}\quad,\\ +\text{right-hand side}:\quad & H^{\bbnum 0}\quad. +\end{align*} -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-identity-monad-morphism" -plural "false" -caps "false" -noprefix "false" +\end_inset + +\begin_inset Formula $\square$ \end_inset \end_layout \begin_layout Standard -Denote by -\begin_inset Formula $F\xrightarrow{\text{Monad}}G$ -\end_inset - - (more verbosely, -\begin_inset Formula $\forall X.\,F^{X}\xrightarrow{\text{Monad}}G^{X}$ -\end_inset - -) the type of monad morphisms between monads -\begin_inset Formula $F$ -\end_inset - - and -\begin_inset Formula $G$ -\end_inset +With these properties, we get the following examples of type equivalences: +\begin_inset Formula +\begin{align*} + & \exists A.\,A\cong\bbnum 1\quad,\quad\quad\exists A.\,A\rightarrow R\cong\bbnum 1\quad,\quad\quad\exists A.\,A+R\cong\bbnum 1+R\quad,\\ + & \exists A.\,(R\rightarrow A)\times(A\rightarrow S)\cong R\rightarrow S\quad,\quad\quad\exists A.\,(A\rightarrow R)\times A\times A\cong R\times R\quad. +\end{align*} -. - Those are natural transformations of type -\begin_inset Formula $\forall X.\,F^{X}\rightarrow G^{X}$ \end_inset - that additionally satisfy the laws of monad morphisms. - Denote by -\begin_inset Formula $\text{Id}$ -\end_inset - the identity monad ( -\begin_inset Formula $\text{Id}^{A}\triangleq A$ -\end_inset +\end_layout -). - +\begin_layout Paragraph +Remarks \end_layout \begin_layout Standard \series bold -(a) +(1) \series default - The standard monad method -\begin_inset Formula $\text{pu}_{M}:\forall A.\,A\rightarrow M^{A}$ -\end_inset - - is the only monad morphism of type -\begin_inset Formula $\text{Id}\xrightarrow{\text{Monad}}M$ -\end_inset - - that works in the same way for all monads -\begin_inset Formula $M$ -\end_inset - -. -\begin_inset Foot + The Scala type +\begin_inset listings +inline true status open \begin_layout Plain Layout -See -\family typewriter - -\begin_inset CommandInset href -LatexCommand href -target "https://cstheory.stackexchange.com/questions/53389/" -literal "false" - -\end_inset - +Any \end_layout \end_inset - We can express this as a type equivalence: -\begin_inset Formula -\[ -\forall M^{:\text{Monad}}.\,\text{Id}\xrightarrow{\text{Monad}}M\cong\bbnum 1\quad. -\] - + closely corresponds to the type +\begin_inset Formula $\exists X.\,X$ \end_inset +, which is equivalent to +\begin_inset listings +inline true +status open -\end_layout - -\begin_layout Standard - -\series bold -(b) -\series default - The identity function of type -\begin_inset Formula $\forall X.\,M^{X}\rightarrow M^{X}$ -\end_inset +\begin_layout Plain Layout - is the only monad morphism of type -\begin_inset Formula $M\xrightarrow{\text{Monad}}M$ -\end_inset +Unit +\end_layout - that works in the same way for all monads -\begin_inset Formula $M$ \end_inset . -\begin_inset Foot + The advantage of using +\begin_inset listings +inline true status open \begin_layout Plain Layout -See -\family typewriter - -\begin_inset CommandInset href -LatexCommand href -target "https://stackoverflow.com/questions/61444425/" -literal "false" - -\end_inset - +Any \end_layout \end_inset - We can express this as a type equivalence: -\begin_inset Formula -\[ -\forall M^{:\text{Monad}}.\,M\xrightarrow{\text{Monad}}M\cong\bbnum 1\quad. -\] - -\end_inset - - -\end_layout - -\begin_layout Subparagraph -Proof -\end_layout - -\begin_layout Standard -The + instead of \begin_inset listings inline true status open \begin_layout Plain Layout -Monad +Unit \end_layout \end_inset - typeclass has methods in the form of a -\begin_inset Formula $P$ -\end_inset + is that +\begin_inset listings +inline true +status open --typeclass for functors -\begin_inset Formula $K$ -\end_inset +\begin_layout Plain Layout - if we define -\begin_inset Formula $P$ -\end_inset +Any +\end_layout - by -\begin_inset Formula $(P^{K})^{A}\triangleq A+K^{K^{A}}$ \end_inset -. - Then the methods of the + is understood by the Scala compiler as a supertype of +\emph on +all +\emph default + Scala types (while \begin_inset listings inline true status open \begin_layout Plain Layout -Monad +Unit \end_layout \end_inset - typeclass are represented by a single value of type: -\begin_inset Formula -\[ -\forall A.\,(P^{K})^{A}\rightarrow K^{A}=\forall A.\,A+K^{K^{A}}\rightarrow K^{A}\cong(\forall A.\,A\rightarrow K^{A})\times(\forall A.\,K^{K^{A}}\rightarrow K^{A})\quad. -\] - + is not). + Indeed, for any type +\begin_inset Formula $T$ \end_inset -This is a tuple type describing the type signatures of -\begin_inset Formula $K$ + there is an injective function +\begin_inset Formula $T\rightarrow\exists X.\,X$ \end_inset -'s +, which corresponds to a function of type \begin_inset listings inline true status open \begin_layout Plain Layout -pure +T => Any \end_layout \end_inset - and + in Scala: \begin_inset listings -inline true +inline false status open \begin_layout Plain Layout -flatten +def toAny[T](t: T): Any = t \end_layout \end_inset - methods when -\begin_inset Formula $K$ -\end_inset - - is a monad. - So, the Jaskelioff-O'Connor theorem applies to the + This is just an identity function that relabels the types. + So, this function establishes the subtyping relation \begin_inset listings inline true status open \begin_layout Plain Layout -Monad +T <: Any \end_layout \end_inset - typeclass. - The free monad constructor ( -\begin_inset Formula $E$ -\end_inset - -) is defined recursively as -\begin_inset Formula $(E^{F})^{A}\triangleq A+F^{(E^{F})^{A}}$ -\end_inset - -, making -\begin_inset Formula $E^{F}$ -\end_inset - - a monad when -\begin_inset Formula $F$ -\end_inset - - is any functor. - The free monad's universal runner is defined by: -\begin_inset Formula -\begin{align*} - & \text{run}_{E}^{F,A}:(\forall X.\,F^{X}\rightarrow M^{X})\rightarrow(E^{F})^{A}\rightarrow M^{A}\quad,\\ - & \text{run}_{E}^{F,A}\big(k^{:\forall X.\,F^{X}\rightarrow M^{X}}\big)\triangleq\,\begin{array}{|c||c|} - & M^{A}\\ -\hline A & \text{pu}_{M}\\ -F^{(E^{F})^{A}} & k^{(E^{F})^{A}}\bef\text{flm}_{M}\big(\overline{\text{run}}_{E}^{F,A}(k)\big) -\end{array}\quad. -\end{align*} - -\end_inset - - +. + \end_layout \begin_layout Standard \series bold -(a) +(2) \series default - Monad morphisms are natural transformations that satisfy additional laws. - We first consider the given type without restricting the functions of type - -\begin_inset Formula $A\rightarrow M^{A}$ -\end_inset - - to monad morphisms but still assuming that they are natural transformations: -\begin_inset Formula -\[ -\forall M^{:\text{Monad}}.\,\forall A.\,A\rightarrow M^{A}\quad. -\] - -\end_inset - -By the Yoneda identity, we get the type equivalence: -\begin_inset Formula -\[ -\forall A.\,A\rightarrow M^{A}\cong M^{\bbnum 1}\quad. -\] - + The type equivalence +\begin_inset Formula $\exists X.\,X\cong\bbnum 1$ \end_inset -So, we have reduced the type to -\begin_inset Formula $\forall M^{:\text{Monad}}.\,M^{\bbnum 1}$ + may appear counterintuitive. + The unit type has only one distinct value; but there are infinitely many + ways of creating a value of type +\begin_inset Formula $\exists X.\,X$ \end_inset . - This type will be in the form suitable for the Jaskelioff-O'Connor theorem -\begin_inset space ~ -\end_inset - -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:jaskelioff-o-connor-theorem" -plural "false" -caps "false" -noprefix "false" - -\end_inset - -) if we set -\begin_inset Formula $F=M$ + We may take any value +\begin_inset Formula $t:T$ \end_inset -, -\begin_inset Formula $A=\bbnum 0$ + of any type +\begin_inset Formula $T$ \end_inset -, -\begin_inset Formula $C=\bbnum 1$ + and +\begin_inset Quotes eld \end_inset -; the parameter -\begin_inset Formula $B$ +pack +\begin_inset Quotes erd \end_inset - remains unused since -\begin_inset Formula $A\rightarrow M^{B}=\bbnum 0\rightarrow M^{B}\cong\bbnum 1$ + that value into a value of type +\begin_inset Formula $\exists X.\,X$ \end_inset -. - Then Eq. -\begin_inset space ~ + by hiding the type +\begin_inset Formula $T$ \end_inset -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:jaskelioff-o-connor-theorem" -plural "false" -caps "false" -noprefix "false" - -\end_inset +, similarly to the function +\begin_inset listings +inline true +status open -) gives: -\begin_inset Formula -\[ -\forall M^{:\text{Monad}}.\,M^{\bbnum 1}\cong\forall M^{:\text{Monad}}.\,(\bbnum 0\rightarrow M^{B})\rightarrow M^{\bbnum 1}\cong(E^{R})^{\bbnum 1}\quad, -\] +\begin_layout Plain Layout -\end_inset +toAny +\end_layout -where we must define -\begin_inset Formula $R^{X}=A\times(B\rightarrow X)$ \end_inset . - However, setting -\begin_inset Formula $A=\bbnum 0$ -\end_inset - - gives also -\begin_inset Formula $R=\bbnum 0$ -\end_inset +\begin_inset listings +lstparams "mathescape=true" +inline false +status open -. - Then the free monad -\begin_inset Formula $E^{R}$ -\end_inset +\begin_layout Plain Layout - is the identity functor: -\begin_inset Formula -\[ -(E^{R})^{C}=C+R^{(E^{R})^{C}}=C+\bbnum 0\cong C\quad. -\] +sealed trait ExistsX // Implements the type $ +\backslash +color{dkgreen} +\backslash +exists X. +\backslash +,X$. +\end_layout -\end_inset +\begin_layout Plain Layout -Finally, we obtain -\begin_inset Formula $(E^{R})^{\bbnum 1}=\bbnum 1$ -\end_inset +final case class ExistsX0[X](x: X) +\end_layout -, and so: -\begin_inset Formula -\[ -\forall M^{:\text{Monad}}.\,\forall A.\,A\rightarrow M^{A}\cong\bbnum 1\quad. -\] +\begin_layout Plain Layout -\end_inset +def hide[T](t: T): ExistsX = ExistsX0[T](t) +\end_layout +\begin_layout Plain Layout +val x1: ExistsX = hide(123) \end_layout -\begin_layout Standard -We conclude that -\emph on -without -\emph default - restricting to monad morphisms there is only a single function of the given - type. - It remains to derive the code for that function and to verify that it is - indeed a monad morphism. +\begin_layout Plain Layout + +val x2: ExistsX = hide(124) \end_layout -\begin_layout Standard -We begin with a unit value (that we denote by -\begin_inset Formula $1$ -\end_inset +\begin_layout Plain Layout -) viewed as a value of type -\begin_inset Formula $(E^{R})^{C}$ +val x3: ExistsX = hide( +\begin_inset Quotes eld \end_inset - in the right-hand side of Eq. -\begin_inset space ~ +abc +\begin_inset Quotes erd \end_inset -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:jaskelioff-o-connor-theorem" -plural "false" -caps "false" -noprefix "false" +) +\end_layout \end_inset -). - We follow the proof of Statement -\begin_inset space ~ -\end_inset +This code may suggest that we are able to create many different values of + type +\begin_inset listings +inline true +status open +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-Jaskelioff-OConnor" -plural "false" -caps "false" -noprefix "false" +ExistsX +\end_layout \end_inset . - The first step is to convert the value of type -\begin_inset Formula $(E^{R})^{C}$ -\end_inset + How can it be that +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +ExistsX +\end_layout - into a function -\begin_inset Formula $f$ \end_inset - of type: -\begin_inset Formula -\[ -f:\forall M^{:\text{Monad}}.\,\big(\forall X.\,(E^{R})^{X}\xrightarrow{\text{Monad}}M^{X}\big)\rightarrow M^{C}\quad. -\] + is equivalent to a unit type with a single distinct value? The reason is + that no fully parametric functions will be able to detect any difference + between all those values. + A fully parametric function may pattern-match on +\begin_inset listings +inline true +status open -\end_inset +\begin_layout Plain Layout -In our case, this function is simplified to: -\begin_inset Formula -\begin{align*} - & f:\forall M^{:\text{Monad}}.\,\big(\forall X.\,\text{Id}^{X}\xrightarrow{\text{Monad}}M^{X}\big)\rightarrow M^{\bbnum 1}\quad,\\ - & f^{M}\big(k^{:\forall X.\,\text{Id}^{X}\xrightarrow{\text{Monad}}M^{X}}\big)\triangleq k^{\bbnum 1}(1)\quad. -\end{align*} +ExistsX0(x) +\end_layout \end_inset -The next step is to convert -\begin_inset Formula $f$ -\end_inset + but must treat the type of +\begin_inset listings +inline true +status open - to a function -\begin_inset Formula $g$ -\end_inset +\begin_layout Plain Layout - of type: -\begin_inset Formula -\[ -g:\forall M^{:\text{Monad}}.\,(\forall X.\,R^{X}\rightarrow M^{X})\rightarrow M^{C}\quad. -\] +x +\end_layout \end_inset -In our case, -\begin_inset Formula $R^{X}=\bbnum 0$ -\end_inset + as arbitrary and unknown, with no operations available for computing anything + out of +\begin_inset listings +inline true +status open - and -\begin_inset Formula $R^{X}\rightarrow M^{X}\cong\bbnum 1$ -\end_inset +\begin_layout Plain Layout -, so this function is simplified to: -\begin_inset Formula -\begin{align*} - & g:\forall M^{:\text{Monad}}.\,\bbnum 1\rightarrow M^{\bbnum 1}\quad,\\ - & g^{M}(k^{:\bbnum 1})\triangleq f^{M}\big(\forall Y.\,r^{:(E^{R})^{Y}}\rightarrow\text{run}_{E}^{R,Y}(k)(r)\big)\\ - & \quad=f^{M}(\forall Y.\,r^{:Y}\rightarrow\text{pu}_{M}^{Y}(r))=\text{pu}_{M}^{\bbnum 1}(1)\quad. -\end{align*} +x +\end_layout \end_inset -Finally, we convert -\begin_inset Formula $g$ -\end_inset +. + So, there will be no way to determine the actual type and value of +\begin_inset listings +inline true +status open - to a function -\begin_inset Formula $h$ -\end_inset +\begin_layout Plain Layout - of type: -\begin_inset Formula -\begin{align*} - & h:\forall M^{:\text{Monad}}.\,(A\rightarrow M^{B})\rightarrow M^{C}\\ - & =\forall M^{:\text{Monad}}.\,(\bbnum 0\rightarrow M^{B})\rightarrow M^{\bbnum 1}\quad.\\ - & \cong\forall M^{:\text{Monad}}.\,\bbnum 1\rightarrow M^{\bbnum 1}\cong\forall M^{:\text{Monad}}.\,M^{\bbnum 1}\quad. -\end{align*} +x +\end_layout \end_inset - There exists only one value of type -\begin_inset Formula $\forall M^{:\text{Monad}}.\,M^{\bbnum 1}$ -\end_inset + and to make any decisions based on them. + A computer's memory will probably store different bit patterns when representin +g +\begin_inset listings +inline true +status open -, and that value is -\begin_inset Formula $\text{pu}_{M}(1)$ -\end_inset +\begin_layout Plain Layout + +hide(123) +\end_layout -. - Converting that to the type signature -\begin_inset Formula $\forall A.\:A\rightarrow M^{A}$ \end_inset -, we recover just the standard monad method -\begin_inset Formula $\text{pu}_{M}$ + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +hide(124) +\end_layout + \end_inset . - We know that -\begin_inset Formula $\text{pu}_{M}$ + But that difference remains unobservable in fully parametric code. + +\begin_inset Formula $\square$ \end_inset - gives a monad morphism between the identity monad and -\begin_inset Formula $M$ -\end_inset - (see Statement +\end_layout + +\begin_layout Standard +We may use Eq. \begin_inset space ~ \end_inset - +( \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-pure-M-is-monad-morphism" +reference "eq:existential-via-universal-Yoneda" plural "false" caps "false" noprefix "false" \end_inset -). - So, we have proved that there exists a unique monad morphism of type -\begin_inset Formula $\forall M^{:\text{Monad}}.\,\text{Id}\xrightarrow{\text{Monad}}M$ -\end_inset - -. - +) to replace the existential quantifier by the universal one when proving + properties of existentially quantified types. \end_layout -\begin_layout Standard - -\series bold -(b) -\series default - Again, we first consider the given type without restricting the functions - of type -\begin_inset Formula $M^{X}\rightarrow M^{X}$ -\end_inset - - to monad morphisms (but still assuming that they are natural transformations): -\begin_inset Formula -\[ -\forall M^{:\text{Monad}}.\,\forall X.\,M^{X}\rightarrow M^{X}\quad. -\] +\begin_layout Subsubsection +Example +\begin_inset CommandInset label +LatexCommand label +name "subsec:Example-simple-existential-derivation" \end_inset -This type will be in the form suitable for the Jaskelioff-O'Connor theorem -\begin_inset space ~ -\end_inset -( \begin_inset CommandInset ref LatexCommand ref -reference "eq:jaskelioff-o-connor-theorem" +reference "subsec:Example-simple-existential-derivation" plural "false" caps "false" noprefix "false" \end_inset -) if we set -\begin_inset Formula $F=M$ -\end_inset -, -\begin_inset Formula $A=\bbnum 1$ -\end_inset +\begin_inset Index idx +status open -, and -\begin_inset Formula $B=C=X$ -\end_inset +\begin_layout Plain Layout +examples +\end_layout -. - The functor -\begin_inset Formula $R$ \end_inset - is then defined by: -\begin_inset Formula -\[ -R^{T}\triangleq A\times(B\rightarrow T)\cong X\rightarrow T\quad, -\] -\end_inset +\end_layout -and the functor -\begin_inset Formula $E^{R}$ +\begin_layout Standard +Show that +\begin_inset Formula $\exists A.\,F^{A}\rightarrow A\cong\bbnum 1$ \end_inset - (the free monad on -\begin_inset Formula $R$ + for any type constructor +\begin_inset Formula $F$ \end_inset -) is defined recursively by: -\begin_inset Formula -\[ -(E^{R})^{T}\triangleq T+\big(X\rightarrow(E^{R})^{T}\big)\quad. -\] +. +\end_layout -\end_inset +\begin_layout Subparagraph +Solution +\end_layout - With these definitions, Eq. +\begin_layout Standard +Use Eq. \begin_inset space ~ \end_inset ( \begin_inset CommandInset ref LatexCommand ref -reference "eq:jaskelioff-o-connor-theorem" +reference "eq:existential-via-universal-Yoneda" plural "false" caps "false" noprefix "false" \end_inset -) gives: +) and write: \begin_inset Formula \[ -\forall M^{:\text{Monad}}.\,\forall X.\,M^{X}\rightarrow M^{X}\cong\forall X.\,(E^{R})^{X}\quad. +\exists A.\,F^{A}\rightarrow A=\forall B.\,(\forall A.\,(F^{A}\rightarrow A)\rightarrow B)\rightarrow B\quad. \] \end_inset -We are using the functor -\begin_inset Formula $(E^{R})^{T}$ +Statement +\begin_inset space ~ \end_inset - with the type parameter -\begin_inset Formula $T=X$ + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-application-full-relation" +plural "false" +caps "false" +noprefix "false" + \end_inset -; however, -\begin_inset Formula $E^{R}$ + with +\begin_inset Formula $P^{A}\triangleq F^{A}\rightarrow A$ \end_inset - also contains -\begin_inset Formula $X$ + and +\begin_inset Formula $K\triangleq B$ \end_inset - through the definition of -\begin_inset Formula $R$ + shows that +\begin_inset Formula $\forall A.\,(F^{A}\rightarrow A)\rightarrow B\cong B$ \end_inset -. - To avoid confusion and to simplify notation, let us write -\begin_inset Formula $G^{X}$ + as the type constructor +\begin_inset Formula $F^{A}\rightarrow A$ \end_inset - instead of -\begin_inset Formula $(E^{R})^{X}$ + is +\begin_inset Quotes eld \end_inset -, where the type constructor -\begin_inset Formula $G$ +lifting-to-full +\begin_inset Quotes erd \end_inset - is defined recursively by: -\begin_inset Formula -\[ -G^{X}\triangleq X+(X\rightarrow G^{X})\quad. -\] - + by Statement +\begin_inset space ~ \end_inset -(Note that -\begin_inset Formula $G$ + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-undisjunctive-type-constructors-structural" +plural "false" +caps "false" +noprefix "false" + \end_inset - is neither covariant nor contravariant.) With this definition, we obtain: +(c, d). + So, we get: \begin_inset Formula \[ -\forall M^{:\text{Monad}}.\,\forall X.\,M^{X}\rightarrow M^{X}\cong\forall X.\,G^{X}\quad. +\exists A.\,F^{A}\rightarrow A=\forall B.\,B\rightarrow B\cong\bbnum 1\quad. \] \end_inset @@ -46133,533 +45715,427 @@ G^{X}\triangleq X+(X\rightarrow G^{X})\quad. \end_layout -\begin_layout Standard -To simpify the type -\begin_inset Formula $\forall X.\,G^{X}$ -\end_inset - -, begin by expanding the recursive type -\begin_inset Formula $G^{X}$ -\end_inset - -: -\begin_inset Formula -\begin{align*} - & \forall X.\,G^{X}\cong\forall X.\,X+(X\rightarrow G^{X})\\ -\text{non-disjunctivity}:\quad & \cong(\forall X.\,X)+(\forall X.\,X\rightarrow G^{X})\\ -\text{use }\forall X.\,X\cong\bbnum 0:\quad & \cong\forall X.\,X\rightarrow G^{X}\quad. -\end{align*} - -\end_inset +\begin_layout Subsubsection +Example +\begin_inset CommandInset label +LatexCommand label +name "subsec:Example-simple-existential-derivation-1-1" -Here we used the non-disjunctivity property from Example -\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Example-undisjunctive-type-constructors" +reference "subsec:Example-simple-existential-derivation-1-1" plural "false" caps "false" noprefix "false" \end_inset -(e). + \end_layout \begin_layout Standard -Continue expanding the recursive type: -\begin_inset Formula -\begin{align*} - & \forall X.\,X\rightarrow G^{X}\cong\forall X.\,X\rightarrow(X+(X\rightarrow G^{X}))\\ -\text{non-disjunctivity}:\quad & \cong(\gunderline{\forall X.\,X\rightarrow X})+\big(\forall X.\,X\rightarrow X\rightarrow G^{X}\big)\\ - & \cong\bbnum 1+\forall X.\,X\times X\rightarrow G^{X}\quad. -\end{align*} - +Let +\begin_inset Formula $P$ \end_inset -The relevant non-disjunctivity property was shown in Example -\begin_inset space ~ + and +\begin_inset Formula $Q$ \end_inset + be any type constructors. +\end_layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Example-undisjunctive-type-constructors" -plural "false" -caps "false" -noprefix "false" +\begin_layout Standard +\series bold +(a) +\series default + If +\begin_inset Formula $P^{A}\cong Q^{A}$ \end_inset -(f). - Expand further, using the same non-disjunctivity property: -\begin_inset Formula -\begin{align*} - & \forall X.\,G^{X}\cong\bbnum 1+\forall X.\,X\times X\rightarrow G^{X}\\ - & \cong\bbnum 1+\forall X.\,X\times X\rightarrow(X+(X\rightarrow G^{X}))\\ -\text{non-disjunctivity}:\quad & \cong\bbnum 1+(\gunderline{\forall X.\,X\times X\rightarrow X})+\big(\forall X.\,X\times X\rightarrow X\rightarrow G^{X}\big)\\ - & \cong\bbnum 1+\bbnum 2+\forall X.\,X\times X\times X\rightarrow G^{X}\quad. -\end{align*} - + for all +\begin_inset Formula $A$ \end_inset -Proceeding similarly, we obtain: -\begin_inset Formula -\[ -\forall X.\,\underbrace{X\times...\times X}_{n\text{ times}}\rightarrow G^{X}\cong\underbrace{\bbnum 1+...+\bbnum 1}_{n\text{ times}}+\forall X.\,\underbrace{X\times...\times X}_{n+1\text{ times}}\rightarrow G^{X}\quad. -\] - + then +\begin_inset Formula $\exists A.\,P^{A}\cong\exists A.\,Q^{A}$ \end_inset -It follows by induction that -\begin_inset Formula $\forall X.\,G^{X}$ -\end_inset +. +\end_layout - is equivalent to an -\begin_inset Quotes eld +\begin_layout Standard + +\series bold +(b) +\series default + For arbitrary +\begin_inset Formula $P$ \end_inset -infinite -\begin_inset Quotes erd + and +\begin_inset Formula $Q$ \end_inset - sum type: +: \begin_inset Formula \[ -\forall X.\,G^{X}\cong\bbnum 1+\bbnum 2+\bbnum 3+... +\exists A.\,P^{A}+Q^{A}\cong(\exists A.\,P^{A})+(\exists A.\,Q^{A})\quad. \] \end_inset -Values of that type may be described by pairs -\begin_inset Formula $\left(n,k\right)$ -\end_inset - - of natural numbers such that -\begin_inset Formula $1\le k\le n$ -\end_inset -. - The number -\begin_inset Formula $n$ -\end_inset +\end_layout - chooses the part -\begin_inset Quotes eld -\end_inset +\begin_layout Standard +\series bold +(c) +\series default + Show that following type identities do +\emph on +not +\emph default + hold in general: +\begin_inset Formula +\begin{align*} + & \exists A.\,P^{A}\times Q^{A}\not\cong(\exists A.\,P^{A})\times(\exists A.\,Q^{A})\quad,\\ + & R\rightarrow(\exists A.\,P^{A})\not\cong\exists A.\,R\rightarrow P^{A}\quad. +\end{align*} -\begin_inset Formula $\bbnum n$ \end_inset - -\begin_inset Quotes erd +(Similar identities do hold for the universal quantifiers; see Statement +\begin_inset space ~ \end_inset - within the disjunctive type -\begin_inset Formula $\bbnum 1+\bbnum 2+\bbnum 3+...$ -\end_inset -, where we denoted by -\begin_inset Quotes eld +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-general-identities-forall" +plural "false" +caps "false" +noprefix "false" + \end_inset +.) +\end_layout -\begin_inset Formula $\bbnum n$ -\end_inset +\begin_layout Subparagraph +Solution +\end_layout +\begin_layout Standard -\begin_inset Quotes erd -\end_inset +\series bold +(a) +\series default + Suppose we have an isomorphism: +\begin_inset Formula +\[ +f^{A}:P^{A}\rightarrow Q^{A}\quad,\quad\quad g^{A}:Q^{A}\rightarrow P^{A}\quad. +\] - the type -\begin_inset Formula $\underbrace{\bbnum 1+...+\bbnum 1}_{n\text{ times}}$ \end_inset -. - The number -\begin_inset Formula $k$ +The types +\begin_inset Formula $\exists A.\,P^{A}$ \end_inset - chooses a specific unit value within -\begin_inset Formula $\underbrace{\bbnum 1+...+\bbnum 1}_{n\text{ times}}$ + and +\begin_inset Formula $\exists A.\,Q^{A}$ \end_inset -. -\end_layout - -\begin_layout Standard -The next step is to convert values -\begin_inset Formula $\left(n,k\right)$ + are equivalent to some type expressions involving only universal quantifiers + and the type constructors +\begin_inset Formula $P$ \end_inset - of that type into functions of type -\begin_inset Formula $M^{X}\rightarrow M^{X}$ +, +\begin_inset Formula $Q$ \end_inset - that work in the same way for all monads -\begin_inset Formula $M$ -\end_inset +. +\begin_inset Formula +\begin{align*} + & \exists A.\,P^{A}\cong\exists A.\,Q^{A}\\ +\text{is the same as}:\quad & \forall D.\,(\forall A.\,P^{A}\rightarrow D)\rightarrow D\cong\forall D.\,(\forall A.\,Q^{A}\rightarrow D)\rightarrow D\quad. +\end{align*} - and all types -\begin_inset Formula $X$ \end_inset -. - We have to find out whether any of those functions obey the laws of monad - morphisms. - For that, we need to derive the specific code of those functions. - We follow the steps outlined in the proof of Statement +Then we can apply Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-Jaskelioff-OConnor" +reference "subsec:Statement-isomorphism-under-type-constructor" plural "false" caps "false" noprefix "false" \end_inset -. -\end_layout + repeatedly to show that those type expressions are isomorphic as types: +\begin_inset Formula +\begin{align*} + & \forall A.\,P^{A}\rightarrow D\cong\forall A.\,Q^{A}\rightarrow D\quad,\\ + & (\forall A.\,P^{A}\rightarrow D)\rightarrow D\cong(\forall A.\,Q^{A}\rightarrow D)\rightarrow D\quad,\\ + & \forall D.\,(\forall A.\,P^{A}\rightarrow D)\rightarrow D\cong\forall D.\,(\forall A.\,Q^{A}\rightarrow D)\rightarrow D\quad. +\end{align*} -\begin_layout Standard -First, we translate pairs -\begin_inset Formula $\left(n,k\right)$ \end_inset - into values of type -\begin_inset Formula $\forall X.\,G^{X}$ -\end_inset - that we will denote by -\begin_inset Formula $q_{n,k}$ -\end_inset +\end_layout -. - To achieve that, we need to retrace the way we expanded the recursive type - -\begin_inset Formula $G^{X}$ -\end_inset +\begin_layout Standard -. - As an example, consider the pair -\begin_inset Formula $\left(n=2,k=1\right)$ +\series bold +(b) +\series default + Use Eq. +\begin_inset space ~ \end_inset -. - The value -\begin_inset Formula $n=2$ -\end_inset +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:existential-via-universal-Yoneda" +plural "false" +caps "false" +noprefix "false" - corresponds to the type -\begin_inset Formula $\bbnum 2$ \end_inset -, which was obtained from -\begin_inset Formula $\forall X.\,X\rightarrow X\rightarrow X$ -\end_inset +) and write: +\begin_inset Formula +\begin{align*} + & \exists A.\,P^{A}+Q^{A}=\forall B.\,(\forall A.\,\gunderline{P^{A}+Q^{A}\rightarrow B})\rightarrow B\\ + & =\forall B.\,(\forall A.\,(P^{A}\rightarrow B)\times(Q^{A}\rightarrow B))\rightarrow B\\ + & =\forall B.\,(\gunderline{\forall A.\,P^{A}\rightarrow B})\times(\gunderline{\forall A.\,Q^{A}\rightarrow B})\rightarrow B\\ +\text{use Eq.\,(\ref{eq:existential-via-universal})}:\quad & =\forall B.\,(\gunderline{(\exists A.\,P^{A})\rightarrow B)\times((\exists A.\,Q^{A})\rightarrow B})\rightarrow B\\ + & =\forall B.\,\big((\exists A.\,P^{A})+(\exists A.\,Q^{A})\,\gunderline{\rightarrow B\big)\rightarrow B}\\ +\text{Yoneda identity}:\quad & =(\exists A.\,P^{A})+(\exists A.\,Q^{A})\quad. +\end{align*} - during expansion of -\begin_inset Formula $\forall X.\,G^{X}$ \end_inset -. - The type -\begin_inset Formula $\forall X.\,X\rightarrow X\rightarrow X$ -\end_inset - has only two distinct values, which are functions that return the first - or the second argument of type -\begin_inset Formula $X$ -\end_inset +\end_layout -. - The index -\begin_inset Formula $k=1$ -\end_inset +\begin_layout Standard + +\series bold +(c) +\series default + The first counter-example is found via the co-Yoneda identity itself: +\begin_inset Formula +\[ +\exists A.\,(A\rightarrow R)\times F^{A}\cong F^{R}\quad. +\] - selects the first of those values, which is a function whose code is written - as -\begin_inset Formula $x_{1}^{:X}\rightarrow x_{2}^{:X}\rightarrow x_{1}$ \end_inset -. - -\end_layout +Splitting the left-hand side into a product of two existential types, we + get: +\begin_inset Formula +\[ +(\exists A.\,(A\rightarrow R))\times(\exists A.\,F^{A})\cong\bbnum 1\times F^{\bbnum 1}\cong F^{\bbnum 1}\quad. +\] -\begin_layout Standard -To simplify notation, let us temporarily fix the type parameter -\begin_inset Formula $X$ \end_inset -; we will restore the quantifier -\begin_inset Formula $\forall X$ +But the last type is not equivalent to +\begin_inset Formula $F^{R}$ \end_inset - at the end of the derivation. +. \end_layout \begin_layout Standard -The type -\begin_inset Formula $X\rightarrow X\rightarrow X$ -\end_inset - - was found during expansion of the recursive type -\begin_inset Formula $G^{X}$ -\end_inset - - as: +The second counter-example is with the following type: \begin_inset Formula \[ -G^{X}=X+(X\rightarrow(X+(X\rightarrow(X+...))))\quad. +P^{A}\triangleq(A\rightarrow Q)\times A\quad. \] \end_inset -So, the pair -\begin_inset Formula $\left(n=2,k=1\right)$ +Here +\begin_inset Formula $Q$ \end_inset - corresponds to the function -\begin_inset Formula $q_{2,1}^{X}:G^{X}$ + is a fixed type. + By the co-Yoneda identity, we have +\begin_inset Formula $\exists A.\,P^{A}\cong Q$ \end_inset - written as: + and so +\begin_inset Formula $R\rightarrow(\exists A.\,P^{A})\cong R\rightarrow Q$ +\end_inset + +. + Now let us simplify the other side: \begin_inset Formula \begin{align*} - & q_{2,1}^{X}:X+(X\rightarrow(X+(X\rightarrow(X+(X\rightarrow G^{X})))))\quad,\\ - & q_{2,1}^{X}\triangleq\bbnum 0^{:X}+(x_{1}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{2}^{:X}\rightarrow(x_{1}+\bbnum 0^{:X\rightarrow G^{X}}))))\quad. + & \exists A.\,R\rightarrow P^{A}=\exists A.\,R\rightarrow(A\rightarrow Q)\times A\\ + & \quad\cong\exists A.\,(R\rightarrow A\rightarrow Q)\times(R\rightarrow A)\\ +\text{co-Yoneda identity}:\quad & \quad\cong R\rightarrow R\rightarrow Q\quad. \end{align*} \end_inset -In a similar way, we define the functions -\begin_inset Formula $q_{n,k}$ +The last type is not equivalent to +\begin_inset Formula $R\rightarrow Q$ \end_inset - for any -\begin_inset Formula $1\le k\le n$ +. + +\begin_inset Formula $\square$ \end_inset -: -\begin_inset Formula -\[ -q_{n,k}^{X}\triangleq\bbnum 0^{:X}+(x_{1}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{2}^{:X}\rightarrow...\rightarrow(\bbnum 0^{:X}+(x_{n}^{:X}\rightarrow(x_{k}+\bbnum 0^{:X\rightarrow G^{X}})))...)))\quad. -\] -\end_inset +\end_layout -To make this code description rigorous, let us define -\begin_inset Formula $u_{i,n,k}$ -\end_inset +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-commute-existential" - and -\begin_inset Formula $v_{i,n}$ \end_inset - like this: -\begin_inset Formula -\begin{align*} - & u_{i,n,k}\triangleq\bbnum 0^{:X}+(x_{i}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{i+1}^{:X}\rightarrow...\rightarrow(x_{n}^{:X}\rightarrow(x_{k}+\bbnum 0^{:X\rightarrow G^{X}}))...))),\\ - & v_{i,n}(x_{0})\triangleq\bbnum 0^{:X}+(x_{i}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{i+1}^{:X}\rightarrow...\rightarrow(x_{n}^{:X}\rightarrow(x_{0}+\bbnum 0^{:X\rightarrow G^{X}}))...))). -\end{align*} - -\end_inset -These formulas hold for -\begin_inset Formula $1\le i\le k\le n$ -\end_inset +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-commute-existential" +plural "false" +caps "false" +noprefix "false" -. - An inductive definition of -\begin_inset Formula $q_{n,k}^{X}$ \end_inset -, -\begin_inset Formula $u_{i,n,k}$ -\end_inset + (co-Fubini theorem) +\end_layout -, and -\begin_inset Formula $v_{i,n}$ +\begin_layout Standard +For any type constructor +\begin_inset Formula $P$ \end_inset - is: + with two parameters (not necessarily covariant or contravariant): \begin_inset Formula -\begin{align*} - & q_{n,k}^{X}=u_{1,n,k}\quad,\quad\quad u_{i,n,k}:G^{X}\quad,\quad\quad v_{i,n}:X\rightarrow G^{X}\quad,\\ -\text{for }1\le i m.flatMap { x_2 => pure(x_1) - } } -\end_layout - -\end_inset - -This code can be rewritten as a functor block, making its logic more visually - clear: +identity laws!of \begin_inset listings -inline false +inline true status open \begin_layout Plain Layout -def h_2_1(m: M[X]): M[X] = for { -\end_layout - -\begin_layout Plain Layout - - x_1 <- m +pack \end_layout -\begin_layout Plain Layout - - x_2 <- m -\end_layout +\end_inset -\begin_layout Plain Layout -} yield x_1 \end_layout \end_inset -The code runs two effects of + \begin_inset listings inline true status open \begin_layout Plain Layout -m +pack \end_layout \end_inset - but returns the first value ( -\begin_inset listings -inline true -status open + holds: for any value +\begin_inset Formula $e:E$ +\end_inset -\begin_layout Plain Layout +, +\begin_inset Formula +\begin{equation} +e^{E}(\text{pack})=e\quad.\label{eq:identity-law-of-pack} +\end{equation} -x_1 -\end_layout +\end_inset +It is assumed that all values +\begin_inset Formula $e^{:E}$ \end_inset -), ignoring -\begin_inset listings -inline true + obey their naturality law: +\begin_inset Formula +\begin{equation} +\text{for all }f^{:B\rightarrow C},k^{:\forall A.\,P^{A}\rightarrow B}:\quad f(e^{B}(k))=e^{C}(\forall A.\,k^{A}\bef f)\quad.\label{eq:naturality-law-of-e-derivation1} +\end{equation} + +\end_inset + + +\end_layout + +\begin_layout Subparagraph +Proof +\begin_inset Foot status open \begin_layout Plain Layout +The author thanks +\begin_inset Index idx +status open -x_2 +\begin_layout Plain Layout +Dan Doel \end_layout \end_inset -. -\end_layout +Dan Doel for assistance with the proof of this statement. + See the discussion at +\family typewriter -\begin_layout Standard -Now we can generalize the code pattern from -\begin_inset Formula $h_{2,1}$ -\end_inset +\begin_inset CommandInset href +LatexCommand href +target "https://cstheory.stackexchange.com/questions/54124" +literal "false" - to -\begin_inset Formula $h_{n,k}$ \end_inset - and write symbolically: -\begin_inset listings -inline false -status open - -\begin_layout Plain Layout -def h_n_k(m: M[X]): M[X] = for { \end_layout -\begin_layout Plain Layout +\end_inset + - x_1 <- m \end_layout -\begin_layout Plain Layout +\begin_layout Standard +Both sides of Eq. +\begin_inset space ~ +\end_inset - x_2 <- m -\end_layout +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:identity-law-of-pack" +plural "false" +caps "false" +noprefix "false" -\begin_layout Plain Layout +\end_inset - ... -\end_layout +) have type +\begin_inset Formula $E$ +\end_inset -\begin_layout Plain Layout +. + Since +\begin_inset Formula $E$ +\end_inset - x_n <- m -\end_layout + is a type of functions with a type parameter, the two sides can be applied + to an arbitrary type +\begin_inset Formula $U$ +\end_inset -\begin_layout Plain Layout + and an arbitrary value +\begin_inset Formula $u:\forall A.\,P^{A}\rightarrow U$ +\end_inset -} yield x_k -\end_layout + to get two values of type +\begin_inset Formula $U$ +\end_inset + +: +\begin_inset Formula +\begin{align*} +\text{both sides of}:\quad & e^{E}(\text{pack})\overset{?}{=}e\\ +\text{can be applied to }U\text{ and }u\text{ and yield}:\quad & \big(e^{E}(\text{pack})\big)^{U}(u)\overset{?}{=}e^{U}(u)\quad. +\end{align*} \end_inset @@ -46857,1100 +46319,1327 @@ def h_n_k(m: M[X]): M[X] = for { \end_layout \begin_layout Standard -To prove that this is indeed the correct code for -\begin_inset Formula $h_{n,k}^{M}(m)$ +So, let us prove that for all types +\begin_inset Formula $U$ \end_inset -, we need to use induction in -\begin_inset Formula $n$ + and all values +\begin_inset Formula $u:\forall A.\,P^{A}\rightarrow U$ \end_inset -. - We rewrite -\begin_inset Formula $q_{n,k}^{X}=u_{1,n,k}$ -\end_inset +, +\begin_inset Formula +\begin{equation} +\big(e^{E}(\text{pack})\big)^{U}(u)\overset{?}{=}e^{U}(u)\quad.\label{eq:identity-law-of-pack-derivation1} +\end{equation} - and compute -\begin_inset Formula $\text{run}_{E}^{R,X}(p)(q_{n,k})=\text{run}_{E}^{R,X}(p)(u_{1,n,k})$ \end_inset -. - Using the code of -\begin_inset Formula $\text{run}_{E}$ +To prove the last equation, we will rewrite it in the form of the naturality + law +\begin_inset space ~ \end_inset -, we obtain the following inductive code definitions: -\begin_inset Formula -\begin{align*} -\text{for }1\le i (A, Int) -\end_layout +\end_inset -\begin_layout Plain Layout +The function +\begin_inset Formula $f$ +\end_inset -val q: M[M[Unit]] = { s => ( { t => ((), s + 1) }, s) } -\end_layout + substitutes +\begin_inset Formula $B=U$ +\end_inset + and +\begin_inset Formula $q=u$ \end_inset + into its function parameter: +\begin_inset Formula +\[ +f\big(\forall B.\,\big(q^{:\forall A.\,P^{A}\rightarrow B}\big)\rightarrow q^{T}(p)\big)=\big(\forall B.\,\big(q^{:\forall A.\,P^{A}\rightarrow B}\big)\rightarrow q^{T}(p)\big)^{U}(u)=u^{T}(p)\quad. +\] + +\end_inset +So, we find: \begin_inset Formula \[ -M^{A}\triangleq\text{Int}\rightarrow A\times\text{Int}\quad,\quad\quad q:M^{M^{\bbnum 1}}\quad,\quad q\triangleq s^{:\text{Int}}\rightarrow(\_^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}})\times s\quad. +\forall T.\,\text{pack}^{T}\bef f=\forall T.\,p^{:P^{T}}\rightarrow u^{T}(p)=\forall T.\,u^{T}=u\quad. \] \end_inset -For more intuition, let us express -\begin_inset listings -inline true -status open +This completes the proof. + +\begin_inset Formula $\square$ +\end_inset -\begin_layout Plain Layout -q \end_layout +\begin_layout Standard +Finally, here is the key property required for proving the equivalence of + two formulations of existential types, Eq. +\begin_inset space ~ \end_inset - via the -\begin_inset listings -inline true -status open +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:existential-via-universal" +plural "false" +caps "false" +noprefix "false" -\begin_layout Plain Layout +\end_inset -State +) and Eq. +\begin_inset space ~ +\end_inset + +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:existential-via-universal-Yoneda" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). \end_layout +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-function-extension-rule" + \end_inset - monad operations -\begin_inset listings -inline true -status open -\begin_layout Plain Layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-function-extension-rule" +plural "false" +caps "false" +noprefix "false" + +\end_inset + -get \end_layout +\begin_layout Standard +The following type isomorphism holds: +\begin_inset Formula +\begin{align*} + & E\rightarrow R=(\exists A.\,P^{A})\rightarrow R\cong\forall C.\,P^{C}\rightarrow R\quad,\\ +\text{or equivalently}:\quad & \big(\forall B.\,(\forall A.\,P^{A}\rightarrow B)\rightarrow B\big)\rightarrow R\cong\forall C.\,P^{C}\rightarrow R\quad, +\end{align*} + \end_inset - and -\begin_inset listings -inline true -status open +where +\begin_inset Formula $R$ +\end_inset -\begin_layout Plain Layout + is a fixed type. + In this isomorphism, it is assumed that the type +\begin_inset Formula $E$ +\end_inset -set -\end_layout + contains only functions +\begin_inset Formula $e^{:E}$ +\end_inset + that obey the naturality law +\begin_inset space ~ \end_inset -: -\begin_inset listings -inline false -status open +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:naturality-law-of-e-derivation1" +plural "false" +caps "false" +noprefix "false" -\begin_layout Plain Layout +\end_inset -val get: M[Int] = s => (s, s) +). + \end_layout -\begin_layout Plain Layout +\begin_layout Standard +This isomorphism can be also formulated via code like this: +\begin_inset Formula +\begin{equation} +\text{for all }e^{:E}\text{ and }r^{:E\rightarrow R}:\quad r(e)=e^{R}(\forall C.\,\text{pack}^{C}\bef r)\quad,\label{eq:surjectivity-of-pack} +\end{equation} -val set: Int => M[Unit] = x => s => ((), x) -\end_layout +\end_inset + +where the standard function +\begin_inset listings +inline true +status open \begin_layout Plain Layout -// Assuming that map and flatMap are defined for M: +pack \end_layout -\begin_layout Plain Layout +\end_inset -val q: M[M[Unit]] = for { -\end_layout + was defined in the proof of Statement +\begin_inset space ~ +\end_inset -\begin_layout Plain Layout - s <- get -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-identity-law-of-pack" +plural "false" +caps "false" +noprefix "false" -\begin_layout Plain Layout +\end_inset -} yield set(s + 1) -\end_layout +. + Any function +\begin_inset Formula $r$ +\end_inset + that consumes values of type +\begin_inset Formula $e$ \end_inset -Now we compute the two sides of the composition law, step by step. - First, we will use Scala's functor block syntax. - The + can be expressed via application of +\begin_inset Formula $r$ +\end_inset + + to values constructed via \begin_inset listings inline true status open \begin_layout Plain Layout -flatten +pack \end_layout \end_inset - method can be written as: +. +\end_layout + +\begin_layout Subparagraph +Proof +\end_layout + +\begin_layout Standard +The isomorphism is shown by defining two functions ( \begin_inset listings -inline false +inline true status open \begin_layout Plain Layout -def flatten[A](mm: M[M[A]]): M[A] = for { +inF \end_layout -\begin_layout Plain Layout +\end_inset - m <- mm -\end_layout + and +\begin_inset listings +inline true +status open \begin_layout Plain Layout - x <- m +outF \end_layout -\begin_layout Plain Layout +\end_inset -} yield x -\end_layout +): +\begin_inset Formula +\begin{align*} + & \text{inF}:(\forall C.\,P^{C}\rightarrow R)\rightarrow E\rightarrow R\quad,\\ + & \text{inF}\triangleq k^{:\forall C.\,P^{C}\rightarrow R}\rightarrow e^{:E}\rightarrow e^{R}(k)\quad,\\ + & \text{outF}:(E\rightarrow R)\rightarrow\forall C.\,P^{C}\rightarrow R\quad,\\ + & \text{outF}\triangleq r^{:E\rightarrow R}\rightarrow\forall C.\,p^{:P^{C}}\rightarrow r(\text{pack}^{C}(p))=r^{:E\rightarrow R}\rightarrow\forall C.\,\text{pack}^{C}\bef r\quad, +\end{align*} \end_inset -Substituting the value +and by proving that those functions are inverses of each other. +\end_layout + +\begin_layout Standard +Without the type annotations, the code of \begin_inset listings inline true status open \begin_layout Plain Layout -q +inF \end_layout \end_inset - defined above, we get: + and \begin_inset listings -inline false +inline true status open \begin_layout Plain Layout -val flatten_q: M[Unit] = for { // This is flatten(q). +outF \end_layout -\begin_layout Plain Layout +\end_inset - m <- for { -\end_layout - -\begin_layout Plain Layout - - s <- get -\end_layout + is: +\begin_inset Formula +\[ +\text{inF}=k\rightarrow q\rightarrow q(k)\quad,\quad\quad\text{outF}=r\rightarrow p\rightarrow r(k\rightarrow k(p))\quad. +\] -\begin_layout Plain Layout +\end_inset - } yield set(s + 1) -\end_layout +Now it is quick to prove one direction of isomorphism ( +\begin_inset Formula $\text{inF}\bef\text{outF}\overset{?}{=}\text{id}$ +\end_inset -\begin_layout Plain Layout +): +\begin_inset Formula +\begin{align*} +\text{expect to equal }\text{id}:\quad & \text{inF}\bef\text{outF}=k\rightarrow\text{outF}\,(q\rightarrow q(k))\\ + & =k\rightarrow p\rightarrow(q\rightarrow q(k))(k\rightarrow k(p))\\ + & =k\rightarrow\gunderline{p\rightarrow k(p)}=k\rightarrow k=\text{id}\quad. +\end{align*} - x <- m -\end_layout +\end_inset -\begin_layout Plain Layout -} yield x \end_layout +\begin_layout Standard +The other direction ( +\begin_inset Formula $\text{outF}\bef\text{inF}\overset{?}{=}\text{id}$ \end_inset -Eliminate the nested -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -for -\end_layout +) requires more work. + The argument of the function +\begin_inset Formula $\text{outF}\bef\text{inF}$ +\end_inset + has type +\begin_inset Formula $E\rightarrow R$ \end_inset - and obtain: -\begin_inset listings -inline false -status open +, and we need to show that for any function +\begin_inset Formula $r^{:E\rightarrow R}$ +\end_inset -\begin_layout Plain Layout + the following equation holds: +\begin_inset Formula +\[ +\text{inF}\,(\text{outF}\,(r))\overset{?}{=}r\quad,\quad\text{or equivalently}:\quad r\triangleright\text{outF}\triangleright\text{inF}\overset{?}{=}r\quad. +\] -val flatten_q: M[Unit] = for { -\end_layout +\end_inset -\begin_layout Plain Layout +The last equation is between functions of type +\begin_inset Formula $E\rightarrow R$ +\end_inset - s <- get -\end_layout +; we may apply both sides to an arbitrary value +\begin_inset Formula $e^{:E}$ +\end_inset -\begin_layout Plain Layout + and require that the results (of type +\begin_inset Formula $R$ +\end_inset - m = set(s + 1) -\end_layout +) should be equal: +\begin_inset Formula +\[ +\big(r\triangleright\text{outF}\triangleright\text{inF}\big)(e)\overset{?}{=}r(e)\quad. +\] -\begin_layout Plain Layout +\end_inset - x <- m -\end_layout +We begin by subtituting the definitions of +\begin_inset listings +inline true +status open \begin_layout Plain Layout -} yield x +inF \end_layout \end_inset -Or equivalently (as the returned value is always a unit value): + and \begin_inset listings -inline false +inline true status open \begin_layout Plain Layout -val flatten_q: M[Unit] = for { +outF \end_layout -\begin_layout Plain Layout +\end_inset - s <- get -\end_layout +: +\begin_inset Formula +\begin{align*} +\text{expect to equal }r(e):\quad & e\triangleright\big(r\triangleright\text{outF}\triangleright\text{inF}\big)=e\triangleright\big((\forall A.\,p^{:P^{A}}\rightarrow r(\text{pack}^{A}(p)))\triangleright\text{inF}\big)\\ + & =e^{R}\big(\forall A.\,p^{:P^{A}}\rightarrow r(\text{pack}^{A}(p))\big)=e^{R}(\forall A.\,\text{pack}^{A}\bef r)\quad. +\end{align*} -\begin_layout Plain Layout +\end_inset - _ <- set(s + 1) -\end_layout +Since +\begin_inset Formula $e$ +\end_inset -\begin_layout Plain Layout + is unknown and arbitrary, we can make progress in the proof only if we + use the naturality law of +\begin_inset Formula $e$ +\end_inset -} yield () -\end_layout + as given by Eq. +\begin_inset space ~ +\end_inset + +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:naturality-law-of-e-derivation1" +plural "false" +caps "false" +noprefix "false" \end_inset -Applying -\begin_inset listings -inline true -status open +). + We assign +\begin_inset Formula $B=E$ +\end_inset -\begin_layout Plain Layout +, +\begin_inset Formula $C=R$ +\end_inset -h_n_k -\end_layout +, +\begin_inset Formula $f=r$ +\end_inset +, +\begin_inset Formula $k=\text{pack}$ \end_inset - to this value means writing code of the form: -\begin_inset listings -inline false -status open + in that law and obtain: +\begin_inset Formula +\[ +r(e^{E}(\text{pack}))=e^{R}(\forall A.\,\text{pack}^{A}\bef r)\quad. +\] -\begin_layout Plain Layout +\end_inset -val h_flatten_q: M[Unit] = for { -\end_layout +By the identity law of pack (Statement +\begin_inset space ~ +\end_inset -\begin_layout Plain Layout - x_1 <- flatten_q -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-identity-law-of-pack" +plural "false" +caps "false" +noprefix "false" -\begin_layout Plain Layout +\end_inset - ... -\end_layout +), +\begin_inset Formula $e^{E}(\text{pack})=e$ +\end_inset -\begin_layout Plain Layout +. + So, we conclude the derivation: +\begin_inset Formula +\begin{align*} +\text{expect to equal }r(e):\quad & e\triangleright\big(r\triangleright\text{outF}\triangleright\text{inF}\big)=\gunderline{e^{R}(\forall A.\,\text{pack}^{A}\bef r)}\\ +\text{naturality law of }e:\quad & =r(\gunderline{e^{E}(\text{pack})})\\ +\text{identity law of }\text{pack}:\quad & =r(e)\quad. +\end{align*} - x_n <- flatten_q -\end_layout +\end_inset -\begin_layout Plain Layout +We have proved the isomorphism and also verified Eq. +\begin_inset space ~ +\end_inset -} yield x_k -\end_layout +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:surjectivity-of-pack" +plural "false" +caps "false" +noprefix "false" \end_inset -The returned value in -\begin_inset listings -inline true -status open +). + +\begin_inset Formula $\square$ +\end_inset -\begin_layout Plain Layout -x_k \end_layout -\end_inset +\begin_layout Subsection +Greatest fixpoints and the Church-co-Yoneda identity +\begin_inset CommandInset label +LatexCommand label +name "subsec:The-greatest-fixpoints-and-Church-co-Yoneda" - is in any case the unit value, so let us focus on the state updates. - Each -\begin_inset listings -inline true -status open +\end_inset -\begin_layout Plain Layout -flatten_q \end_layout -\end_inset - - has the effect of reading the state value -\begin_inset listings -inline true +\begin_layout Standard +We have seen that the least fixpoints of functors are expressed via the + Church encoding type that involves a universally quantified higher-order + function. + An analogous encoding (with an existentially quantified type) exists for + greatest fixpoints. + We will now prove some properties of that encoding. +\begin_inset Foot status open \begin_layout Plain Layout - -s -\end_layout - +This section follows the logic given in P. +\begin_inset space ~ \end_inset - and storing the incremented value -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout +Wadler's paper +\begin_inset Quotes eld +\end_inset -s + 1 -\end_layout +Recursive types for free +\begin_inset Quotes erd +\end_inset +, except that we +\emph on +define +\emph default + existential types by Eq. +\begin_inset space ~ \end_inset -. - The function -\begin_inset listings -inline true -status open +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:existential-via-universal-Yoneda" +plural "false" +caps "false" +noprefix "false" -\begin_layout Plain Layout +\end_inset -h_n_k +) via the universal quantifier. \end_layout \end_inset - repeats -\begin_inset Formula $n$ -\end_inset - - times the effect of -\begin_inset listings -inline true -status open -\begin_layout Plain Layout - -flatten_q \end_layout +\begin_layout Standard +We work with a fixed covariant functor +\begin_inset Formula $F$ \end_inset -. - This increments the internal state -\begin_inset Formula $n$ + and denote by +\begin_inset Formula $C$ \end_inset - times. - So, the left-hand side of the law is equivalent to: -\begin_inset listings -inline false -status open - -\begin_layout Plain Layout - -val lhs: M[Unit] = for { // This is h_flatten_q === h_n_k(flatten(q)). -\end_layout - -\begin_layout Plain Layout + the following Church-encoded type: +\begin_inset Formula +\[ +C\triangleq\exists A.\,(A\rightarrow F^{A})\times A\quad. +\] - s <- get -\end_layout +\end_inset -\begin_layout Plain Layout +We will prove that +\begin_inset Formula $C$ +\end_inset - _ <- set(s + n) -\end_layout + is the greatest fixpoint of the type equation +\begin_inset Formula $X\cong F^{X}$ +\end_inset -\begin_layout Plain Layout +; that is, +\begin_inset Formula $C=\nu X.\,F^{X}$ +\end_inset -} yield () +. + \end_layout +\begin_layout Standard +First, we define some auxiliary functions that work with the type +\begin_inset Formula $C$ \end_inset - + and prove their properties. \end_layout \begin_layout Standard -Turning now to the right-hand side of the law, we write the first sub-expression - ( -\begin_inset Formula $q\triangleright h_{n,k}^{\uparrow M}$ -\end_inset - -, or in Scala, +The function \begin_inset listings inline true status open \begin_layout Plain Layout -q.map(h_n_k) +unfold \end_layout \end_inset -) as the following Scala code: -\begin_inset listings -inline false -status open - -\begin_layout Plain Layout - -val q_map_h: M[M[Unit]] = for { -\end_layout - -\begin_layout Plain Layout - - m <- q -\end_layout - -\begin_layout Plain Layout + constructs values of type +\begin_inset Formula $C$ +\end_inset -} yield h_n_k(m) -\end_layout +: +\begin_inset Formula +\begin{align*} + & \text{unfold}:\forall T.\,(T\rightarrow F^{T})\times T\rightarrow C\quad,\\ + & \text{unfold}^{T}(u^{:T\rightarrow F^{T}}\times t^{:T})\triangleq\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times A\rightarrow R}\rightarrow p^{T}(u\times t)\quad. +\end{align*} \end_inset -Substituting the code of +Note that \begin_inset listings inline true status open \begin_layout Plain Layout -q +unfold \end_layout \end_inset - (but not yet expanding + is the same as the function \begin_inset listings inline true status open \begin_layout Plain Layout -h_n_k +pack \end_layout \end_inset -), we find: -\begin_inset listings -inline false -status open - -\begin_layout Plain Layout - -val q_map_h: M[M[Unit]] = for { -\end_layout + from Statement +\begin_inset space ~ +\end_inset -\begin_layout Plain Layout - s <- get -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-identity-law-of-pack" +plural "false" +caps "false" +noprefix "false" -\begin_layout Plain Layout +\end_inset -} yield h_n_k(set(s + 1)) -\end_layout + if we set +\begin_inset Formula $E=C$ +\end_inset + and +\begin_inset Formula $P^{A}\triangleq(A\rightarrow F^{A})\times A$ \end_inset -The function call + in the definition of \begin_inset listings inline true status open \begin_layout Plain Layout -h_n_k(set(s + 1)) +pack \end_layout \end_inset - repeats -\begin_inset Formula $n$ -\end_inset +. +\end_layout - times the effect of +\begin_layout Standard +By parametricity, the function \begin_inset listings inline true status open \begin_layout Plain Layout -set(s + 1) +unfold \end_layout \end_inset -, but -\begin_inset listings -inline true -status open + satisfies a relational naturality law: for all types +\begin_inset Formula $A$ +\end_inset -\begin_layout Plain Layout +, +\begin_inset Formula $B$ +\end_inset -s -\end_layout + and all functions +\begin_inset Formula $f^{:A\rightarrow B}$ +\end_inset + +, +\begin_inset Formula +\begin{equation} +\text{if}\quad u\bef f^{\uparrow F}=f\bef v\quad\text{then}\quad\text{unfold}^{A}(u^{:A\rightarrow F^{A}}\times a^{:A})=\text{unfold}^{B}(v^{:B\rightarrow F^{B}}\times f(a))\quad.\label{eq:relational-naturality-law-of-unfold} +\end{equation} \end_inset - is a fixed value in that scope, so the result is equal to just a single - effect: -\begin_inset listings -inline false -status open +In category theory, the precondition +\begin_inset Formula $u\bef f^{\uparrow F}=f\bef v$ +\end_inset -\begin_layout Plain Layout + is known as the +\begin_inset Quotes eld +\end_inset -val q_map_h: M[M[Unit]] = for { -\end_layout -\begin_layout Plain Layout +\begin_inset Formula $F$ +\end_inset - s <- get -\end_layout +-coalgebra morphism law +\begin_inset Quotes erd +\end_inset -\begin_layout Plain Layout + of +\begin_inset Formula $f$ +\end_inset -} yield set(s + 1) +. + Let us give some definitions for reference: \end_layout -\end_inset +\begin_layout Subsubsection +Definition +\begin_inset CommandInset label +LatexCommand label +name "subsec:Definition-F-coalgebra" -This is the same value as -\begin_inset listings -inline true -status open +\end_inset -\begin_layout Plain Layout -q -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Definition-F-coalgebra" +plural "false" +caps "false" +noprefix "false" \end_inset - itself. + \end_layout \begin_layout Standard -The next sub-expression is -\begin_inset listings -inline true -status open +Given a functor +\begin_inset Formula $F$ +\end_inset -\begin_layout Plain Layout +, a type +\begin_inset Formula $A$ +\end_inset -h_n_k(q_map_h) -\end_layout + together with a function +\begin_inset Formula $u:A\rightarrow F^{A}$ +\end_inset + is called an +\begin_inset Formula $F$ \end_inset -, which equals -\begin_inset listings -inline true + +\series bold +-coalgebra +\series default +. +\begin_inset Index idx status open \begin_layout Plain Layout +\begin_inset Formula $F$ +\end_inset -h_n_k(q) +-coalgebra \end_layout \end_inset -: -\begin_inset listings -inline false -status open - -\begin_layout Plain Layout - -val h_q_map_h: M[M[Unit]] = for { -\end_layout - -\begin_layout Plain Layout + The type +\begin_inset Formula $A$ +\end_inset - x_1 <- q -\end_layout + is called the +\series bold +carrier +\series default + of the +\begin_inset Formula $F$ +\end_inset -\begin_layout Plain Layout +-coalgebra, and the function +\begin_inset Formula $u$ +\end_inset - ... -\end_layout + is called the +\series bold +structure map +\series default + of the +\begin_inset Formula $F$ +\end_inset -\begin_layout Plain Layout +-coalgebra. + (Keep in mind that +\begin_inset Formula $u$ +\end_inset - x_n <- q -\end_layout + is not universally quantified over +\begin_inset Formula $A$ +\end_inset -\begin_layout Plain Layout +; it is a function that only works with a single, specified type +\begin_inset Formula $A$ +\end_inset -} yield x_k -\end_layout +. + For a given type +\begin_inset Formula $A$ +\end_inset +, there could be several different structure maps +\begin_inset Formula $u$ \end_inset -Substituting the code for -\begin_inset listings -inline true -status open +, +\begin_inset Formula $u^{\prime}$ +\end_inset -\begin_layout Plain Layout +, and so on; each of them will then define a different +\begin_inset Formula $F$ +\end_inset -q +-coalgebra.) \end_layout +\begin_layout Standard +If +\begin_inset Formula $A$ \end_inset -, we get: -\begin_inset listings -inline false -status open - -\begin_layout Plain Layout - -val h_q_map_h: M[M[Unit]] = for { -\end_layout + and +\begin_inset Formula $B$ +\end_inset -\begin_layout Plain Layout + are two +\begin_inset Formula $F$ +\end_inset - x_1 <- for { -\end_layout +-coalgebras with structure maps +\begin_inset Formula $u:A\rightarrow F^{A}$ +\end_inset -\begin_layout Plain Layout + and +\begin_inset Formula $v:B\rightarrow F^{B}$ +\end_inset - s <- get -\end_layout + then a function +\begin_inset Formula $f:A\rightarrow B$ +\end_inset -\begin_layout Plain Layout + is called an +\begin_inset Formula $F$ +\end_inset - } yield set(s + 1) -\end_layout +-coalgebra morphism if this law holds: +\begin_inset Preview -\begin_layout Plain Layout +\begin_layout Standard +\begin_inset Formula +\[ +\xymatrix{\xyScaleY{2.3pc}\xyScaleX{2.5pc}A\ar[d]\sb(0.4){u}\ar[r]\sp(0.5){f} & B\ar[d]\sp(0.4){v}\\ +F^{A}\ar[r]\sp(0.5){f^{\uparrow F}} & F^{B} +} +\] - ... -\end_layout +\end_inset -\begin_layout Plain Layout - x_n <- for { \end_layout -\begin_layout Plain Layout - - s <- get -\end_layout +\end_inset -\begin_layout Plain Layout - } yield set(s + 1) -\end_layout +\begin_inset Formula +\[ +u\bef f^{\uparrow F}=f\bef v\quad. +\] -\begin_layout Plain Layout +\end_inset -} yield x_k -\end_layout +This is the +\begin_inset Formula $F$ +\end_inset +-coalgebra morphism law of +\begin_inset Formula $f$ \end_inset -Eliminate the nested -\begin_inset listings -inline true -status open +. + +\begin_inset Formula $\square$ +\end_inset -\begin_layout Plain Layout -for \end_layout -\end_inset - - and obtain: +\begin_layout Standard +It is also helpful to define a function \begin_inset listings -inline false +inline true status open \begin_layout Plain Layout -val h_q_map_h: M[M[Unit]] = for { -\end_layout - -\begin_layout Plain Layout - - s <- get -\end_layout - -\begin_layout Plain Layout - - x_1 = set(s + 1) -\end_layout - -\begin_layout Plain Layout - - ... +unfoldF \end_layout -\begin_layout Plain Layout +\end_inset - s <- get -\end_layout + that constructs values of type +\begin_inset Formula $F^{C}$ +\end_inset -\begin_layout Plain Layout +: +\begin_inset Formula +\begin{align*} + & \text{unfoldF}:\forall T.\,(T\rightarrow F^{T})\times T\rightarrow F^{C}\quad,\\ + & \text{unfoldF}^{T}(u^{:T\rightarrow F^{T}}\times t^{:T})\triangleq t\triangleright u\triangleright\big(a^{:T}\rightarrow\text{unfold}^{T}(u\times a)\big)^{\uparrow F}\quad. +\end{align*} - x_n = set(s + 1) -\end_layout +\end_inset -\begin_layout Plain Layout -} yield x_k \end_layout +\begin_layout Standard +The isomorphism +\begin_inset Formula $C\cong F^{C}$ \end_inset -The code runs -\begin_inset Formula $n$ + will be implemented via two functions: +\begin_inset Formula +\[ +\text{fix}:F^{C}\rightarrow C\quad,\quad\quad\text{unfix}:C\rightarrow F^{C}\quad, +\] + \end_inset - times the effect of +which we define via \begin_inset listings inline true status open \begin_layout Plain Layout -get +unfold \end_layout \end_inset - but actually never runs the effect of + and \begin_inset listings inline true status open \begin_layout Plain Layout -set +unfoldF \end_layout \end_inset -; the unevaluated effectful value -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -set(s + 1) -\end_layout + like this: +\begin_inset Formula +\begin{align*} + & \text{unfix}:C\rightarrow F^{C}\quad,\quad\quad\text{unfix}\triangleq c^{:C}\rightarrow c^{F^{C}}(\forall A.\,\text{unfoldF}^{A})=c^{:C}\rightarrow c^{F^{C}}(\text{unfoldF})\quad,\\ + & \text{fix}:F^{C}\rightarrow C\quad,\quad\quad\text{fix}\triangleq p^{:F^{C}}\rightarrow\text{unfold}^{F^{C}}(\text{unfix}^{\uparrow F}\times p)\quad. +\end{align*} \end_inset - is merely assigned to each -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -x_i -\end_layout - +Because of these functions, +\begin_inset Formula $C$ \end_inset - and then returned. - So, the code is equivalent to: -\begin_inset listings -inline false -status open + is at the same time an +\begin_inset Formula $F$ +\end_inset -\begin_layout Plain Layout +-algebra and an +\begin_inset Formula $F$ +\end_inset -val h_q_map_h: M[M[Unit]] = for { +-coalgebra. \end_layout -\begin_layout Plain Layout +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-coalgebra-morphism-unfold" - s <- get -\end_layout +\end_inset -\begin_layout Plain Layout -} yield set(s + 1) -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-coalgebra-morphism-unfold" +plural "false" +caps "false" +noprefix "false" \end_inset -This is again just equal to -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout -q \end_layout +\begin_layout Standard +For any +\begin_inset Formula $F$ \end_inset -. -\end_layout - -\begin_layout Standard -It remains to apply -\begin_inset listings -inline true -status open +-coalgebra +\begin_inset Formula $A$ +\end_inset -\begin_layout Plain Layout + with a structure map +\begin_inset Formula $u:A\rightarrow F^{A}$ +\end_inset -flatten -\end_layout +, denote by +\begin_inset Formula $\psi_{u}^{A}$ +\end_inset + the following function of type +\begin_inset Formula $A\rightarrow C$ \end_inset - to -\begin_inset listings -inline true -status open +: +\begin_inset Formula +\[ +\psi_{u}^{A}:A\rightarrow C\quad,\quad\quad\psi_{u}^{A}\triangleq a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\quad. +\] -\begin_layout Plain Layout +\end_inset -h_q_map_h -\end_layout +Then +\begin_inset Formula $\psi_{u}^{A}$ +\end_inset + is an +\begin_inset Formula $F$ \end_inset -, which is the same as -\begin_inset listings -inline true -status open +-coalgebra morphism of type +\begin_inset Formula $A\rightarrow C$ +\end_inset -\begin_layout Plain Layout +. + +\end_layout -flatten(q) +\begin_layout Subparagraph +Proof \end_layout +\begin_layout Standard +Write the +\begin_inset Formula $F$ \end_inset - and was already computed as -\begin_inset listings -inline true -status open +-coalgebra morphism law for that function: +\begin_inset Formula +\[ +u\bef\big(a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\big)^{\uparrow F}\overset{?}{=}\big(a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\big)\bef v\quad. +\] -\begin_layout Plain Layout +\end_inset -flatten_q -\end_layout +Apply both sides to an arbitrary value +\begin_inset Formula $t^{:A}$ +\end_inset + + and obtain: +\begin_inset Formula +\[ +t\triangleright u\triangleright(a\rightarrow\text{unfold}^{A}(u\times a))^{\uparrow F}\overset{?}{=}\text{unfix}\,(\text{unfold}^{A}(u\times t))\quad. +\] \end_inset - above: -\begin_inset listings -inline false -status open +Begin with the right-hand side: +\begin_inset Formula +\begin{align*} + & \text{unfix}\,(\text{unfold}^{A}(u\times t))\\ +\text{definition of }\text{unfix}:\quad & =(\text{unfold}^{A}(u\times t))^{F^{C}}(\text{unfoldF})\\ +\text{definition of }\text{unfold}:\quad & =\text{unfoldF}^{A}(u\times t)\\ +\text{definition of }\text{unfoldF}:\quad & =t\triangleright u\triangleright\big(a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\big)^{\uparrow F}\quad. +\end{align*} -\begin_layout Plain Layout +\end_inset -val rhs: M[Unit] = for { // This is flatten(h_q_map_h) === flatten(q). -\end_layout +This is now equal to the left-hand side. + +\begin_inset Formula $\square$ +\end_inset -\begin_layout Plain Layout - s <- get \end_layout -\begin_layout Plain Layout +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-identity-law-of-unfold" - _ <- set(s + 1) -\end_layout +\end_inset -\begin_layout Plain Layout -} yield () -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-identity-law-of-unfold" +plural "false" +caps "false" +noprefix "false" \end_inset @@ -47958,298 +47647,295 @@ val rhs: M[Unit] = for { // This is flatten(h_q_map_h) === flatten(q). \end_layout \begin_layout Standard -The left-hand side and the right-hand side of the law differ only in the - +The function \begin_inset listings inline true status open \begin_layout Plain Layout -set +unfold \end_layout \end_inset - operation ( -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -set(s + n) -\end_layout - -\end_inset + satisfies an +\series bold +identity law +\series default +: +\begin_inset Formula +\[ +\text{for all }c^{:C}:\quad\text{unfold}^{C}(\text{unfix}\times c)\overset{?}{=}c\quad. +\] - vs. -\begin_inset space ~ \end_inset +This law +\begin_inset Index idx +status open +\begin_layout Plain Layout +identity laws!of \begin_inset listings inline true status open \begin_layout Plain Layout -set(s + 1) +unfold \end_layout \end_inset -). - So, they are equal only when -\begin_inset Formula $n=1$ + +\end_layout + \end_inset - (that is, for + is similar to the identity law of \begin_inset listings inline true status open \begin_layout Plain Layout -h_1_1 +pack \end_layout \end_inset -). - It follows that, for all -\begin_inset Formula $n\ge2$ + (Statement +\begin_inset space ~ \end_inset - and for all -\begin_inset Formula $1\le k\le n$ -\end_inset -, the function -\begin_inset Formula $h_{n,k}$ -\end_inset +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-identity-law-of-pack" +plural "false" +caps "false" +noprefix "false" - of type -\begin_inset Formula $M^{X}\rightarrow M^{X}$ \end_inset - violates the composition law of monad morphisms when applied to the chosen - value -\begin_inset Formula $q:M^{M^{X}}$ -\end_inset +). +\end_layout -. +\begin_layout Subparagraph +Proof \end_layout \begin_layout Standard -Let us now summarize this derivation in code notation. - The left-hand side of the composition law is: -\begin_inset Formula -\begin{align*} - & \text{ftn}_{M}(q)=s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}}\quad,\\ - & h_{n,k}(\text{ftn}_{M}(q))=s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+n)^{:\text{Int}}\quad. -\end{align*} - +Apply Statement +\begin_inset space ~ \end_inset -Here we used the fact that -\begin_inset Formula $h_{n,k}(m)$ -\end_inset - repeats -\begin_inset Formula $n$ -\end_inset +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-identity-law-of-pack" +plural "false" +caps "false" +noprefix "false" - times the effect of -\begin_inset Formula $m$ \end_inset - (and that effect increments the value -\begin_inset Formula $s$ +, which gives +\begin_inset Formula $e^{E}(\text{pack})=e$ \end_inset -). - -\end_layout - -\begin_layout Standard -Turn to the right-hand side of the law and calculate: -\begin_inset Formula -\begin{align*} - & q\triangleright h_{n,k}^{\uparrow M}=s^{:\text{Int}}\rightarrow(\_^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}})\times s=q\quad,\\ - & h_{n,k}(q\triangleright h_{n,k}^{\uparrow M})=s^{:\text{Int}}\rightarrow(\_^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}})\times s=q\quad,\\ - & \text{ftn}_{M}(q)=s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}}\quad. -\end{align*} - +, and substitute +\begin_inset Formula $E=C$ \end_inset -The condition for the two sides of the law to be equal is: -\begin_inset Formula -\[ -s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+n)^{:\text{Int}}\overset{?}{=}s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}}\quad. -\] - +, +\begin_inset Formula $e=c$ \end_inset -This holds only if -\begin_inset Formula $n=1$ +, +\begin_inset Formula $P^{A}=(A\rightarrow F^{A})\times A$ \end_inset -. -\end_layout +, and +\begin_inset listings +inline true +status open -\begin_layout Standard -It follows that -\begin_inset Formula $h_{1,1}$ -\end_inset +\begin_layout Plain Layout - (which is an identity function of type -\begin_inset Formula $M^{X}\rightarrow M^{X}$ -\end_inset +unfold +\end_layout -) is the only monad morphism that fits the required type. - -\begin_inset Formula $\square$ \end_inset + instead of +\begin_inset listings +inline true +status open -\end_layout +\begin_layout Plain Layout -\begin_layout Subsection -Existential type quantifiers. - Co-Yoneda identities -\begin_inset CommandInset label -LatexCommand label -name "subsec:Existential-type-quantifiers" +pack +\end_layout \end_inset +. + We obtain: +\begin_inset Formula +\begin{equation} +c=c^{C}(\text{unfold})\quad.\label{eq:unfold-id-law-derivation1} +\end{equation} -\end_layout - -\begin_layout Standard -The Yoneda identities allow us in many cases to simplify type expressions - with universal quantifiers. - Similar identities hold for existentially quantified types. -\end_layout +\end_inset -\begin_layout Standard -For the purposes of this and the following sections, we define the existential - quantifier via Eq. +Now use the law \begin_inset space ~ \end_inset ( \begin_inset CommandInset ref LatexCommand ref -reference "eq:existential-via-universal-Yoneda" +reference "eq:surjectivity-of-pack" plural "false" caps "false" noprefix "false" \end_inset -): +) where we substitute +\begin_inset Formula $E=R=C$ +\end_inset + + and +\begin_inset Formula $e=c$ +\end_inset + +: \begin_inset Formula \[ -\exists C.\,F^{C}\cong\forall D.\,\big(\forall C.\,(F^{C}\rightarrow D)\big)\rightarrow D\quad. +\text{for all }r^{:C\rightarrow C}:\quad r(c)=c^{C}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times a^{:A}\rightarrow r(\text{unfold}^{A}(u\times a))\big)\quad. \] \end_inset -Here -\begin_inset Formula $F$ +We will use this law with the function +\begin_inset Formula $r$ \end_inset - is any type constructor (not necessarily covariant or contravariant). -\end_layout + defined by: +\begin_inset Formula +\[ +r:C\rightarrow C\quad,\quad\quad r(c)\triangleq\text{unfold}^{C}(\text{unfix}\times c)\quad. +\] -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-co-Yoneda-two-identities" +\end_inset + +Then we get: +\begin_inset Formula +\begin{align} + & \text{unfold}^{C}(\text{unfix}\times c)=r(c)=c^{C}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times a^{:A}\rightarrow r(\text{unfold}^{A}(u\times a))\big)\nonumber \\ + & =c^{C}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times a^{:A}\rightarrow\text{unfold}^{C}(\text{unfix}\times\text{unfold}^{A}(u\times a)))\big)\quad.\label{eq:unfold-id-law-derivation3} +\end{align} \end_inset +Now we apply the naturality law +\begin_inset space ~ +\end_inset +( \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-co-Yoneda-two-identities" +reference "eq:relational-naturality-law-of-unfold" plural "false" caps "false" noprefix "false" \end_inset +) with +\begin_inset Formula $B=C$ +\end_inset -\end_layout - -\begin_layout Standard -For any functor -\begin_inset Formula $F$ +, +\begin_inset Formula $f=a\rightarrow\text{unfold}^{A}(u\times a)$ \end_inset - and any contrafunctor -\begin_inset Formula $H$ +, and +\begin_inset Formula $v=\text{unfix}$ \end_inset -, the following identities hold: +: \begin_inset Formula -\begin{align*} -\text{\textbf{(a)} }\text{covariant co-Yoneda identity}:\quad & \exists A.\,(A\rightarrow R)\times F^{A}\cong F^{R}\quad,\\ -\text{\textbf{(b)} }\text{contravariant co-Yoneda identity}:\quad & \exists A.\,(R\rightarrow A)\times H^{A}\cong H^{R}\quad. -\end{align*} +\begin{equation} +\text{unfold}^{A}(u\times a)=\text{unfold}^{C}(\text{unfix}\times\text{unfold}^{A}(u\times a)))\quad.\label{eq:unfold-id-law-derivation2} +\end{equation} \end_inset +The precondition of this law ( +\begin_inset Formula $u\bef f^{\uparrow F}\overset{?}{=}f\bef v$ +\end_inset -\end_layout +) is the +\begin_inset Formula $F$ +\end_inset -\begin_layout Subparagraph -Proof +-coalgebra morphism law of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +unfold \end_layout -\begin_layout Standard -We use Eq. +\end_inset + +, and it has been demonstrated in Statement \begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:existential-via-universal-Yoneda" +reference "subsec:Statement-coalgebra-morphism-unfold" plural "false" caps "false" noprefix "false" \end_inset -) to express -\begin_inset Formula $\exists A$ +. + So, Eq. +\begin_inset space ~ \end_inset - via -\begin_inset Formula $\forall A$ +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:unfold-id-law-derivation2" +plural "false" +caps "false" +noprefix "false" + \end_inset -. +) holds. \end_layout \begin_layout Standard - -\series bold -(a) -\series default - We write: +Finally, we can finish the proof: \begin_inset Formula \begin{align*} -\text{expect to equal }F^{R}:\quad & \exists A.\,(A\rightarrow R)\times F^{A}\\ -\text{definition of }\exists\text{ in Eq.~}(\ref{eq:existential-via-universal-Yoneda}):\quad & \cong\forall B.\,\big(\forall A.\,\gunderline{(A\rightarrow R)\times F^{A}}\rightarrow B\big)\rightarrow B\\ -\text{uncurry arguments}:\quad & \cong\forall B.\,\big(\gunderline{\forall A.\,(A\rightarrow R)\rightarrow F^{A}\rightarrow B}\big)\rightarrow B\\ -\text{contravariant Yoneda identity}:\quad & \cong\gunderline{\forall B.\,\big(F^{R}\rightarrow B\big)\rightarrow B}\\ -\text{covariant Yoneda identity}:\quad & \cong F^{R}\quad. +\text{expect to equal }c:\quad & \text{unfold}^{C}(\text{unfix}\times c)\\ +\text{use Eq.~(\ref{eq:unfold-id-law-derivation3})}:\quad & =c^{C}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times a^{:A}\rightarrow\gunderline{\text{unfold}^{C}(\text{unfix}\times\text{unfold}^{A}(u\times a)))}\big)\\ +\text{use Eq.~(\ref{eq:unfold-id-law-derivation2})}:\quad & =c^{C}\big(\gunderline{\forall A.\,u^{:A\rightarrow F^{A}}\times a^{:A}\rightarrow\text{unfold}^{A}(u\times a)}\big)=c^{C}(\text{unfold})\\ +\text{use Eq.~(\ref{eq:unfold-id-law-derivation1})}:\quad & =c\quad. \end{align*} \end_inset @@ -48257,490 +47943,482 @@ noprefix "false" \end_layout -\begin_layout Standard - -\series bold -(b) -\series default - We write: -\begin_inset Formula -\begin{align*} -\text{expect to equal }H^{R}:\quad & \exists A.\,(R\rightarrow A)\times H^{A}\\ -\text{definition of }\exists\text{ in Eq.~}(\ref{eq:existential-via-universal-Yoneda}):\quad & \cong\forall B.\,\big(\forall A.\,\gunderline{(R\rightarrow A)\times H^{A}}\rightarrow B\big)\rightarrow B\\ -\text{uncurry arguments}:\quad & \cong\forall B.\,\big(\gunderline{\forall A.\,(R\rightarrow A)\rightarrow H^{A}\rightarrow B}\big)\rightarrow B\\ -\text{covariant Yoneda identity}:\quad & \cong\gunderline{\forall B.\,\big(H^{R}\rightarrow B\big)\rightarrow B}\\ -\text{covariant Yoneda identity}:\quad & \cong H^{R}\quad. -\end{align*} +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-greatest-fixpoint-church-encoding" \end_inset -\begin_inset Formula $\square$ +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-greatest-fixpoint-church-encoding" +plural "false" +caps "false" +noprefix "false" + \end_inset \end_layout \begin_layout Standard -To build up intuition, let us substitute -\begin_inset Formula $R=\bbnum 0$ +The functions +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +fix +\end_layout + \end_inset and -\begin_inset Formula $R=\bbnum 1$ +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +unfix +\end_layout + \end_inset - into the co-Yoneda identities: + are inverses to each other. \end_layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-co-Yoneda-two-identities-1" +\begin_layout Subparagraph +Proof +\end_layout +\begin_layout Standard +Translate the existential quantifier via Eq. +\begin_inset space ~ \end_inset - +( \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-co-Yoneda-two-identities-1" +reference "eq:existential-via-universal-Yoneda" plural "false" caps "false" noprefix "false" \end_inset +) and write +\begin_inset Formula $C$ +\end_inset -\end_layout - -\begin_layout Standard -The following type equivalences hold: + as: \begin_inset Formula -\begin{align*} -\text{\textbf{(a)} for any functor }F:\quad & \exists A.\,F^{A}\cong F^{\bbnum 1}\quad,\\ -\text{\textbf{(b)} for any contrafunctor }F:\quad & \exists A.\,H^{A}\cong H^{\bbnum 0}\quad. -\end{align*} +\[ +C\triangleq\forall R.\,(\forall A.\,(A\rightarrow F^{A})\times A\rightarrow R)\rightarrow R\quad. +\] \end_inset - -\end_layout - -\begin_layout Subparagraph -Proof +We need to verify that: \end_layout \begin_layout Standard -For + \series bold -(a) +(1) \series default -, set -\begin_inset Formula $R=\bbnum 1$ + For any +\begin_inset Formula $c:C$ \end_inset - in the covariant co-Yoneda identity: -\begin_inset Formula -\begin{align*} -\text{left-hand side}:\quad & \exists A.\,(\gunderline{A\rightarrow\bbnum 1})\times F^{A}\cong\exists A.\,\bbnum 1\times F^{A}\cong\exists A.\,F^{A}\quad,\\ -\text{right-hand side}:\quad & F^{\bbnum 1}\quad. -\end{align*} - + we have +\begin_inset Formula $\text{fix}\,(\text{unfix}\,(c))=c$ \end_inset - +. \end_layout \begin_layout Standard -For + \series bold -(b) +(2) \series default -, set -\begin_inset Formula $R=\bbnum 0$ -\end_inset - - in the contravariant co-Yoneda identity: -\begin_inset Formula -\begin{align*} -\text{left-hand side}:\quad & \exists A.\,(\gunderline{\bbnum 0\rightarrow A})\times H^{A}\cong\exists A.\,\bbnum 1\times H^{A}\cong\exists A.\,H^{A}\quad,\\ -\text{right-hand side}:\quad & H^{\bbnum 0}\quad. -\end{align*} - + For any +\begin_inset Formula $q:F^{C}$ \end_inset - -\begin_inset Formula $\square$ + we have +\begin_inset Formula $\text{unfix}\,(\text{fix}\,(q))=q$ \end_inset - +. \end_layout \begin_layout Standard -With these properties, we get the following examples of type equivalences: +To prove item +\series bold +(1) +\series default +: \begin_inset Formula \begin{align*} - & \exists A.\,A\cong\bbnum 1\quad,\quad\quad\exists A.\,A\rightarrow R\cong\bbnum 1\quad,\quad\quad\exists A.\,A+R\cong\bbnum 1+R\quad,\\ - & \exists A.\,(R\rightarrow A)\times(A\rightarrow S)\cong R\rightarrow S\quad,\quad\quad\exists A.\,(A\rightarrow R)\times A\times A\cong R\times R\quad. +\text{expect to equal }c:\quad & \gunderline{\text{fix}}\,(\text{unfix}\,(c))\\ +\text{definition of }\text{fix}:\quad & =\text{unfold}^{F^{C}}(\text{unfix}^{\uparrow F}\times\text{unfix}\,(c))\\ +\text{naturality law of }\text{unfold}:\quad & =\text{unfold}^{C}(\text{unfix}\times c)\\ +\text{identity law of }\text{unfold}:\quad & =c\quad. \end{align*} \end_inset +Here we applied the naturality law +\begin_inset space ~ +\end_inset -\end_layout - -\begin_layout Paragraph -Remarks -\end_layout - -\begin_layout Standard - -\series bold -(1) -\series default - The Scala type -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:relational-naturality-law-of-unfold" +plural "false" +caps "false" +noprefix "false" -Any -\end_layout +\end_inset +) with +\begin_inset Formula $A=C$ \end_inset - closely corresponds to the type -\begin_inset Formula $\exists X.\,X$ +, +\begin_inset Formula $B=F^{C}$ \end_inset -, which is equivalent to -\begin_inset listings -inline true -status open +, +\begin_inset Formula $a=c$ +\end_inset -\begin_layout Plain Layout +, +\begin_inset Formula $f=\text{unfix}$ +\end_inset -Unit -\end_layout +, +\begin_inset Formula $u=\text{unfix}$ +\end_inset +, and +\begin_inset Formula $v=\text{unfix}^{\uparrow F}$ \end_inset . - The advantage of using -\begin_inset listings -inline true -status open + To verify the precondition of that law, write: +\begin_inset Formula +\[ +u\bef f^{\uparrow F}\overset{?}{=}f\bef v\quad,\quad\text{or equivalently:}\quad\text{unfix}\bef\text{unfix}^{\uparrow F}\overset{?}{=}\text{unfix}\bef\text{unfix}^{\uparrow F}\quad. +\] -\begin_layout Plain Layout +\end_inset -Any +This holds trivially. \end_layout +\begin_layout Standard +To prove item +\series bold +(2) +\series default +, write: +\begin_inset Formula +\begin{align*} +\text{expect to equal }q:\quad & \text{unfix}\,(\gunderline{\text{fix}\,(q)})\\ +\text{definition of }\text{fix}:\quad & =\gunderline{\text{unfix}}\,\big(\text{unfold}^{F^{C}}(\text{unfix}^{\uparrow F}\times q)\big)\\ +\text{definition of }\text{unfold}:\quad & =\text{unfix}\,\big(\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times A\rightarrow R}\rightarrow p^{F^{C}}(\text{unfix}^{\uparrow F}\times q)\big)\\ +\text{definition of }\text{unfix}:\quad & =\big(\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times A\rightarrow R}\rightarrow p^{F^{C}}(\text{unfix}^{\uparrow F}\times q)\big)^{F^{C}}(\text{unfoldF})\\ +\text{apply function}:\quad & =\text{unfoldF}^{F^{C}}(\text{unfix}^{\uparrow F}\times q)\\ +\text{definition of }\text{unfoldF}:\quad & =q\triangleright\gunderline{\text{unfix}^{\uparrow F}\bef\big(a^{:F^{C}}\rightarrow\text{unfold}\,(\text{unfix}^{\uparrow F}\times a)\big)^{\uparrow F}}\\ +\text{composition under }^{\uparrow F}:\quad & =q\triangleright\big(x^{:C}\rightarrow\gunderline{\text{unfold}\,(\text{unfix}^{\uparrow F}\times\text{unfix}\,(x))}\big)^{\uparrow F}\\ +\text{definition of }\text{fix}:\quad & =q\triangleright\big(x^{:C}\rightarrow\gunderline{\text{fix}\,(\text{unfix}\,(x))}\big)^{\uparrow F}\\ +\text{item \textbf{(1)}}:\quad & =q\triangleright\gunderline{(x^{:C}\rightarrow x)^{\uparrow F}}=x\triangleright\text{id}=q\quad. +\end{align*} + \end_inset - instead of -\begin_inset listings -inline true -status open -\begin_layout Plain Layout +\begin_inset Formula $\square$ +\end_inset + -Unit \end_layout +\begin_layout Standard +It follows that +\begin_inset Formula $C$ \end_inset - is that -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -Any -\end_layout + is a fixpoint of the type equation +\begin_inset Formula $C\cong F^{C}$ +\end_inset +. + To show that +\begin_inset Formula $C$ \end_inset - is understood by the Scala compiler as a supertype of + is indeed the \emph on -all +greatest \emph default - Scala types (while -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -Unit -\end_layout - + fixpoint, we need to prove that for any other fixpoint +\begin_inset Formula $T$ \end_inset - is not). - Indeed, for any type -\begin_inset Formula $T$ + there exists a unique fixpoint-preserving morphism +\begin_inset Formula $\psi^{T}:T\rightarrow C$ \end_inset - there is an injective function -\begin_inset Formula $T\rightarrow\exists X.\,X$ +. + Similarly to what we saw in Statement +\begin_inset space ~ \end_inset -, which corresponds to a function of type -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout -T => Any -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-fixpoint-preserving-fix" +plural "false" +caps "false" +noprefix "false" \end_inset - in Scala: -\begin_inset listings -inline false -status open +, it is sufficient to check that +\begin_inset Formula $\psi^{T}$ +\end_inset -\begin_layout Plain Layout + is an +\begin_inset Formula $F$ +\end_inset -def toAny[T](t: T): Any = t +-coalgebra morphism. \end_layout -\end_inset +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-greatest-fixpoint-Church-encoding-morphism" - This is just an identity function that relabels the types. - So, this function establishes the subtyping relation -\begin_inset listings -inline true -status open +\end_inset -\begin_layout Plain Layout -T <: Any -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-greatest-fixpoint-Church-encoding-morphism" +plural "false" +caps "false" +noprefix "false" \end_inset -. - + \end_layout \begin_layout Standard - -\series bold -(2) -\series default - The type equivalence -\begin_inset Formula $\exists X.\,X\cong\bbnum 1$ +For any +\begin_inset Formula $F$ \end_inset - may appear counterintuitive. - The unit type has only one distinct value; but there are infinitely many - ways of creating a value of type -\begin_inset Formula $\exists X.\,X$ +-coalgebra +\begin_inset Formula $A$ \end_inset -. - We may take any value -\begin_inset Formula $t:T$ + with a structure map +\begin_inset Formula $u:A\rightarrow F^{A}$ \end_inset - of any type -\begin_inset Formula $T$ +, there exists a unique +\begin_inset Formula $F$ \end_inset - and -\begin_inset Quotes eld +-algebra morphism +\begin_inset Formula $\psi_{u}^{A}$ \end_inset -pack -\begin_inset Quotes erd + of type +\begin_inset Formula $A\rightarrow C$ \end_inset - that value into a value of type -\begin_inset Formula $\exists X.\,X$ +. + The function +\begin_inset Formula $\psi_{u}^{A}$ \end_inset - by hiding the type -\begin_inset Formula $T$ -\end_inset + is known as an +\series bold +anamorphism +\series default -, similarly to the function -\begin_inset listings -inline true +\begin_inset Index idx status open \begin_layout Plain Layout - -toAny +anamorphism \end_layout \end_inset -. -\begin_inset listings -lstparams "mathescape=true" -inline false -status open + and was defined as in Statement +\begin_inset space ~ +\end_inset -\begin_layout Plain Layout -sealed trait ExistsX // Implements the type $ -\backslash -color{dkgreen} -\backslash -exists X. -\backslash -,X$. -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-coalgebra-morphism-unfold" +plural "false" +caps "false" +noprefix "false" -\begin_layout Plain Layout +\end_inset -final case class ExistsX0[X](x: X) -\end_layout +: +\begin_inset Formula +\[ +\psi_{u}^{A}:A\rightarrow C\quad,\quad\quad\psi_{u}^{A}\triangleq a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\quad. +\] -\begin_layout Plain Layout +\end_inset -def hide[T](t: T): ExistsX = ExistsX0[T](t) -\end_layout -\begin_layout Plain Layout +\end_layout -val x1: ExistsX = hide(123) +\begin_layout Subparagraph +Proof \end_layout -\begin_layout Plain Layout +\begin_layout Standard +We know from Statement +\begin_inset space ~ +\end_inset -val x2: ExistsX = hide(124) -\end_layout -\begin_layout Plain Layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-coalgebra-morphism-unfold" +plural "false" +caps "false" +noprefix "false" -val x3: ExistsX = hide( -\begin_inset Quotes eld \end_inset -abc -\begin_inset Quotes erd + that +\begin_inset Formula $\psi_{u}^{A}$ \end_inset -) -\end_layout - + satisfies the law of +\begin_inset Formula $F$ \end_inset -This code may suggest that we are able to create many different values of - type -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout +-coalgebra morphisms. + Let +\begin_inset Formula $f:A\rightarrow C$ +\end_inset -ExistsX -\end_layout + be any other +\begin_inset Formula $F$ +\end_inset +-coalgebra morphism; we need to prove that +\begin_inset Formula $f=\psi_{u}^{A}$ \end_inset . - How can it be that -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -ExistsX \end_layout +\begin_layout Standard +We know that +\begin_inset Formula $f$ \end_inset - is equivalent to a unit type with a single distinct value? The reason is - that no fully parametric functions will be able to detect any difference - between all those values. - A fully parametric function may pattern-match on -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout + satisfies the +\begin_inset Formula $F$ +\end_inset -ExistsX0(x) -\end_layout +-coalgebra morphism law: +\begin_inset Formula +\[ +u\bef f^{\uparrow F}=f\bef\text{unfix}\quad. +\] \end_inset - but must treat the type of -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout +This is the precondition of the relational naturality law +\begin_inset space ~ +\end_inset -x -\end_layout +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:relational-naturality-law-of-unfold" +plural "false" +caps "false" +noprefix "false" \end_inset - as arbitrary and unknown, with no operations available for computing anything - out of +) of \begin_inset listings inline true status open \begin_layout Plain Layout -x +unfold \end_layout \end_inset -. - So, there will be no way to determine the actual type and value of -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout + if we set +\begin_inset Formula $B=C$ +\end_inset -x -\end_layout + and +\begin_inset Formula $v=\text{unfix}$ +\end_inset +. + So, the conclusion of that law holds. + We use that equation as well as Statement +\begin_inset space ~ \end_inset - and to make any decisions based on them. - A computer's memory will probably store different bit patterns when representin -g -\begin_inset listings -inline true -status open -\begin_layout Plain Layout - -hide(123) -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-identity-law-of-unfold" +plural "false" +caps "false" +noprefix "false" \end_inset - and -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout + and get: +\begin_inset Formula +\begin{align*} +\text{for any }a^{:A}:\quad & \psi_{u}^{A}(a)=\text{unfold}^{A}(u^{:A\rightarrow F^{A}}\times a^{:A})\\ +\text{naturality law of }\text{unfold}:\quad & =\text{unfold}^{C}(\text{unfix}\times f(a))\\ +\text{identity law of }\text{unfold}:\quad & =f(a)\quad. +\end{align*} -hide(124) -\end_layout +\end_inset +It follows that +\begin_inset Formula $\psi_{u}^{A}=f$ \end_inset . - But that difference remains unobservable in fully parametric code. \begin_inset Formula $\square$ \end_inset @@ -48749,36 +48427,55 @@ hide(124) \end_layout \begin_layout Standard -We may use Eq. +We conclude this Appendix with the proof of a type identity dual to the + Church-Yoneda identity +\begin_inset Index idx +status open + +\begin_layout Plain Layout +Church-co-Yoneda identity +\end_layout + +\end_inset + + shown in Statement \begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:existential-via-universal-Yoneda" +reference "subsec:Statement-Church-Yoneda-identity" plural "false" caps "false" noprefix "false" \end_inset -) to replace the existential quantifier by the universal one when proving - properties of existentially quantified types. +. + That identity has no accepted name, and this book calls it the +\begin_inset Quotes eld +\end_inset + +Church-co-Yoneda +\begin_inset Quotes erd +\end_inset + + identity. \end_layout \begin_layout Subsubsection -Example +Statement \begin_inset CommandInset label LatexCommand label -name "subsec:Example-simple-existential-derivation" +name "subsec:Statement-Church-co-Yoneda" \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Example-simple-existential-derivation" +reference "subsec:Statement-Church-co-Yoneda" plural "false" caps "false" noprefix "false" @@ -48786,136 +48483,131 @@ noprefix "false" \end_inset -\begin_inset Index idx -status open - -\begin_layout Plain Layout -examples \end_layout +\begin_layout Standard +For any covariant functors +\begin_inset Formula $F$ \end_inset + and +\begin_inset Formula $G$ +\end_inset -\end_layout +: +\begin_inset Formula +\[ +G^{\nu X.\,F^{X}}\cong\exists A.\,(A\rightarrow F^{A})\times G^{A}\quad. +\] -\begin_layout Standard -Show that -\begin_inset Formula $\exists A.\,F^{A}\rightarrow A\cong\bbnum 1$ \end_inset - for any type constructor -\begin_inset Formula $F$ -\end_inset -. \end_layout \begin_layout Subparagraph -Solution +Proof \end_layout \begin_layout Standard -Use Eq. -\begin_inset space ~ -\end_inset - -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:existential-via-universal-Yoneda" -plural "false" -caps "false" -noprefix "false" - +Denote for brevity +\begin_inset Formula $C\triangleq\nu X.\,F^{X}$ \end_inset -) and write: +. + The existential type is rewritten as: \begin_inset Formula \[ -\exists A.\,F^{A}\rightarrow A=\forall B.\,(\forall A.\,(F^{A}\rightarrow A)\rightarrow B)\rightarrow B\quad. +\exists A.\,(A\rightarrow F^{A})\times G^{A}=\forall R.\,(\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R)\rightarrow R\quad. \] \end_inset -Statement -\begin_inset space ~ -\end_inset - +We will demonstrate the isomorphism if we define functions +\begin_inset listings +inline true +status open -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-application-full-relation" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout -\end_inset +toG +\end_layout - with -\begin_inset Formula $P^{A}\triangleq F^{A}\rightarrow A$ \end_inset and -\begin_inset Formula $K\triangleq B$ +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +fromG +\end_layout + \end_inset - shows that -\begin_inset Formula $\forall A.\,(F^{A}\rightarrow A)\rightarrow B\cong B$ + that are mutual inverses, with type signatures: +\begin_inset Formula +\[ +\text{toG}:(\exists A.\,(A\rightarrow F^{A})\times G^{A})\rightarrow G^{C}\quad,\quad\quad\text{fromG}:G^{C}\rightarrow\exists A.\,(A\rightarrow F^{A})\times G^{A}\quad. +\] + \end_inset - as the type constructor -\begin_inset Formula $F^{A}\rightarrow A$ +The first type signature can be implemented as: +\begin_inset Formula +\begin{align*} + & \text{toG}:\big(\forall R.\,(\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R)\rightarrow R\big)\rightarrow G^{C}\quad,\\ + & \text{toG}\triangleq k^{:\forall R.\,(\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R)\rightarrow R}\rightarrow k^{G^{C}}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow g\triangleright(\psi_{u}^{A})^{\uparrow F}\big)\quad, +\end{align*} + \end_inset - is -\begin_inset Quotes eld +where +\begin_inset Formula $\psi_{u}^{A}$ \end_inset -lifting-to-full -\begin_inset Quotes erd + is the anamorphism of type +\begin_inset Formula $A\rightarrow C$ \end_inset - by Statement + defined in Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-undisjunctive-type-constructors-structural" +reference "subsec:Statement-coalgebra-morphism-unfold" plural "false" caps "false" noprefix "false" \end_inset -(c, d). - So, we get: -\begin_inset Formula -\[ -\exists A.\,F^{A}\rightarrow A=\forall B.\,B\rightarrow B\cong\bbnum 1\quad. -\] +. +\end_layout -\end_inset +\begin_layout Standard +The function +\begin_inset listings +inline true +status open +\begin_layout Plain Layout +fromG \end_layout -\begin_layout Subsubsection -Example -\begin_inset CommandInset label -LatexCommand label -name "subsec:Example-simple-existential-derivation-1-1" - \end_inset - -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Example-simple-existential-derivation-1-1" -plural "false" -caps "false" -noprefix "false" + is implemented as: +\begin_inset Formula +\begin{align*} + & \text{fromG}:G^{C}\rightarrow\forall R.\,(\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R)\rightarrow R\quad,\\ + & \text{fromG}\triangleq g^{:G^{C}}\rightarrow\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R}\rightarrow p^{C}(\text{unfix}\times g)\quad. +\end{align*} \end_inset @@ -48923,32 +48615,20 @@ noprefix "false" \end_layout \begin_layout Standard -Let -\begin_inset Formula $P$ -\end_inset - - and -\begin_inset Formula $Q$ -\end_inset - - be any type constructors. +It remains to prove the two directions of the isomorphism roundtrip: \end_layout \begin_layout Standard \series bold -(a) +(1) \series default - If -\begin_inset Formula $P^{A}\cong Q^{A}$ -\end_inset - - for all -\begin_inset Formula $A$ + For any +\begin_inset Formula $g:G^{C}$ \end_inset - then -\begin_inset Formula $\exists A.\,P^{A}\cong\exists A.\,Q^{A}$ + we have: +\begin_inset Formula $\text{toG}\,(\text{fromG}\,(g))=g$ \end_inset . @@ -48957,231 +48637,218 @@ Let \begin_layout Standard \series bold -(b) +(2) \series default - For arbitrary -\begin_inset Formula $P$ -\end_inset - - and -\begin_inset Formula $Q$ + For any +\begin_inset Formula $k:\exists A.\,(A\rightarrow F^{A})\times G^{A}$ \end_inset -: -\begin_inset Formula -\[ -\exists A.\,P^{A}+Q^{A}\cong(\exists A.\,P^{A})+(\exists A.\,Q^{A})\quad. -\] - + we have: +\begin_inset Formula $\text{fromG}\,(\text{toG}\,(k))=k$ \end_inset - +. \end_layout \begin_layout Standard - +To prove item \series bold -(c) +(1) \series default - Show that following type identities do -\emph on -not -\emph default - hold in general: +: \begin_inset Formula \begin{align*} - & \exists A.\,P^{A}\times Q^{A}\not\cong(\exists A.\,P^{A})\times(\exists A.\,Q^{A})\quad,\\ - & R\rightarrow(\exists A.\,P^{A})\not\cong\exists A.\,R\rightarrow P^{A}\quad. + & \text{toG}\,(\gunderline{\text{fromG}}\,(g))=\gunderline{\text{toG}}\,\big(\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R}\rightarrow p^{C}(\text{unfix}\times g)\big)\\ + & =\big(\forall A.\,u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow g\triangleright(\psi_{u}^{A})^{\uparrow F}\big)^{C}(\text{unfix}\times g)\\ + & =g\triangleright(\psi_{\text{unfix}}^{C})^{\uparrow F}\quad. \end{align*} \end_inset -(Similar identities do hold for the universal quantifiers; see Statement +We note that +\begin_inset Formula $\psi_{\text{unfix}}^{C}$ +\end_inset + + is the identity function ( +\begin_inset Formula $\text{id}^{:C\rightarrow C}$ +\end_inset + +) because it is the unique +\begin_inset Formula $F$ +\end_inset + +-coalgebra morphism of type +\begin_inset Formula $C\rightarrow C$ +\end_inset + + by Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-general-identities-forall" +reference "subsec:Statement-greatest-fixpoint-Church-encoding-morphism" plural "false" caps "false" noprefix "false" \end_inset -.) -\end_layout - -\begin_layout Subparagraph -Solution -\end_layout - -\begin_layout Standard - -\series bold -(a) -\series default - Suppose we have an isomorphism: +. + It follows that: \begin_inset Formula \[ -f^{A}:P^{A}\rightarrow Q^{A}\quad,\quad\quad g^{A}:Q^{A}\rightarrow P^{A}\quad. +\text{toG}\,(\text{fromG}\,(g))=g\triangleright(\psi_{\text{unfix}}^{C})^{\uparrow F}=g\triangleright\text{id}^{\uparrow F}=g\quad. \] \end_inset -The types -\begin_inset Formula $\exists A.\,P^{A}$ -\end_inset - and -\begin_inset Formula $\exists A.\,Q^{A}$ -\end_inset +\end_layout - are equivalent to some type expressions involving only universal quantifiers - and the type constructors -\begin_inset Formula $P$ +\begin_layout Standard +To prove item +\series bold +(2) +\series default +, apply both sides to a type +\begin_inset Formula $R$ \end_inset -, -\begin_inset Formula $Q$ + and a value +\begin_inset Formula $p^{:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R}$ \end_inset -. +: \begin_inset Formula \begin{align*} - & \exists A.\,P^{A}\cong\exists A.\,Q^{A}\\ -\text{is the same as}:\quad & \forall D.\,(\forall A.\,P^{A}\rightarrow D)\rightarrow D\cong\forall D.\,(\forall A.\,Q^{A}\rightarrow D)\rightarrow D\quad. +\text{expect to equal }k^{R}(p):\quad & \big(\text{fromG}\,(\text{toG}\,(k))\big)^{R}(p)=p^{C}(\text{unfix}\times\text{toG}\,(k))\\ + & =p^{C}\big(\text{unfix}\times k^{G^{C}}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow g\triangleright(\psi_{u}^{A})^{\uparrow F}\big)\big)\quad. \end{align*} \end_inset -Then we can apply Statement -\begin_inset space ~ +To proceed, we need to use the naturality law of +\begin_inset Formula $k$ \end_inset - -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-isomorphism-under-type-constructor" -plural "false" -caps "false" -noprefix "false" +: +\begin_inset Formula +\[ +\text{for all }Q,R,f^{:Q\rightarrow R},q^{:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow Q}:\quad k^{R}(\forall A.\:q^{A}\bef f)=f(k^{Q}(q))\quad. +\] \end_inset - repeatedly to show that those type expressions are isomorphic as types: +Setting the following parameters in this law: \begin_inset Formula -\begin{align*} - & \forall A.\,P^{A}\rightarrow D\cong\forall A.\,Q^{A}\rightarrow D\quad,\\ - & (\forall A.\,P^{A}\rightarrow D)\rightarrow D\cong(\forall A.\,Q^{A}\rightarrow D)\rightarrow D\quad,\\ - & \forall D.\,(\forall A.\,P^{A}\rightarrow D)\rightarrow D\cong\forall D.\,(\forall A.\,Q^{A}\rightarrow D)\rightarrow D\quad. -\end{align*} +\[ +Q=G^{C}\quad,\quad\quad f=t^{:G^{C}}\rightarrow p^{C}(\text{unfix}\times t)\quad,\quad q=\forall A.\,u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow g\triangleright(\psi_{u}^{A})^{\uparrow F}\quad, +\] \end_inset +we obtain: +\begin_inset Formula +\begin{align*} + & k^{R}(\forall A.\:u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow p^{C}(\text{unfix}\times g\triangleright(\psi_{u}^{A})^{\uparrow F}))\\ + & =p^{C}\big(\text{unfix}\times k^{G^{C}}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow g\triangleright(\psi_{u}^{A})^{\uparrow F}\big)\big)\quad. +\end{align*} -\end_layout - -\begin_layout Standard - -\series bold -(b) -\series default - Use Eq. -\begin_inset space ~ \end_inset -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:existential-via-universal-Yoneda" -plural "false" -caps "false" -noprefix "false" - +We expect the left-hand side to equal +\begin_inset Formula $k^{R}(p)$ \end_inset -) and write: +, so the remaining difference is: \begin_inset Formula \begin{align*} - & \exists A.\,P^{A}+Q^{A}=\forall B.\,(\forall A.\,\gunderline{P^{A}+Q^{A}\rightarrow B})\rightarrow B\\ - & =\forall B.\,(\forall A.\,(P^{A}\rightarrow B)\times(Q^{A}\rightarrow B))\rightarrow B\\ - & =\forall B.\,(\gunderline{\forall A.\,P^{A}\rightarrow B})\times(\gunderline{\forall A.\,Q^{A}\rightarrow B})\rightarrow B\\ -\text{use Eq.\,(\ref{eq:existential-via-universal})}:\quad & =\forall B.\,(\gunderline{(\exists A.\,P^{A})\rightarrow B)\times((\exists A.\,Q^{A})\rightarrow B})\rightarrow B\\ - & =\forall B.\,\big((\exists A.\,P^{A})+(\exists A.\,Q^{A})\,\gunderline{\rightarrow B\big)\rightarrow B}\\ -\text{Yoneda identity}:\quad & =(\exists A.\,P^{A})+(\exists A.\,Q^{A})\quad. + & p\overset{?}{=}\forall A.\:u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow p^{C}(\text{unfix}\times g\triangleright(\psi_{u}^{A})^{\uparrow F})\quad,\\ +\text{or equivalently}:\quad & p^{A}(u^{:A\rightarrow F^{A}}\times g^{:G^{A}})\overset{?}{=}p^{C}(\text{unfix}\times g\triangleright(\psi_{u}^{A})^{\uparrow F})\quad. \end{align*} \end_inset +This should hold for all types +\begin_inset Formula $A$ +\end_inset -\end_layout + and for all +\begin_inset Formula $g^{:G^{A}}$ +\end_inset -\begin_layout Standard +, +\begin_inset Formula $u^{:A\rightarrow F^{A}}$ +\end_inset -\series bold -(c) -\series default - The first counter-example is found via the co-Yoneda identity itself: +, +\begin_inset Formula $p:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R$ +\end_inset + +. + We may assume that all such +\begin_inset Formula $p$ +\end_inset + + obey their relational naturality law: \begin_inset Formula \[ -\exists A.\,(A\rightarrow R)\times F^{A}\cong F^{R}\quad. +\forall A,B,f^{:A\rightarrow B}:\quad\text{if}\quad u^{:A\rightarrow F^{A}}\bef f^{\uparrow F}=f\bef v^{:B\rightarrow F^{B}}\quad\text{then}\quad p^{A}(u\times a)=p^{B}(v\times a\triangleright f^{\uparrow F})\quad. \] \end_inset -Splitting the left-hand side into a product of two existential types, we - get: +We set the following parameters in this law, \begin_inset Formula \[ -(\exists A.\,(A\rightarrow R))\times(\exists A.\,F^{A})\cong\bbnum 1\times F^{\bbnum 1}\cong F^{\bbnum 1}\quad. +B=C\quad,\quad a=g\quad,\quad f=\psi_{u}^{A}\quad,\quad v=\text{unfix}\quad, \] \end_inset -But the last type is not equivalent to -\begin_inset Formula $F^{R}$ -\end_inset - -. -\end_layout - -\begin_layout Standard -The second counter-example is with the following type: +and obtain: \begin_inset Formula \[ -P^{A}\triangleq(A\rightarrow Q)\times A\quad. +p^{A}(u\times g)=p^{C}(\text{unfix}\times g\triangleright(\psi_{u}^{A})^{\uparrow F})\quad. \] \end_inset -Here -\begin_inset Formula $Q$ -\end_inset +This will complete the proof of item +\series bold +(2) +\series default + as long as the precondition holds: +\begin_inset Formula +\begin{align*} + & u^{:A\rightarrow F^{A}}\bef f^{\uparrow F}\overset{?}{=}f\bef v^{:B\rightarrow F^{B}}\quad,\\ +\text{or equivalently}:\quad & u\bef(\psi_{u}^{A})^{\uparrow F}\overset{?}{=}\psi_{u}^{A}\bef\text{unfix}\quad. +\end{align*} - is a fixed type. - By the co-Yoneda identity, we have -\begin_inset Formula $\exists A.\,P^{A}\cong Q$ \end_inset - and so -\begin_inset Formula $R\rightarrow(\exists A.\,P^{A})\cong R\rightarrow Q$ +This holds by Statement +\begin_inset space ~ \end_inset -. - Now let us simplify the other side: -\begin_inset Formula -\begin{align*} - & \exists A.\,R\rightarrow P^{A}=\exists A.\,R\rightarrow(A\rightarrow Q)\times A\\ - & \quad\cong\exists A.\,(R\rightarrow A\rightarrow Q)\times(R\rightarrow A)\\ -\text{co-Yoneda identity}:\quad & \quad\cong R\rightarrow R\rightarrow Q\quad. -\end{align*} + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-coalgebra-morphism-unfold" +plural "false" +caps "false" +noprefix "false" \end_inset -The last type is not equivalent to -\begin_inset Formula $R\rightarrow Q$ +: it is the +\begin_inset Formula $F$ +\end_inset + +-coalgebra morphism law of +\begin_inset Formula $\psi_{u}^{A}$ \end_inset . @@ -49192,118 +48859,138 @@ The last type is not equivalent to \end_layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-commute-existential" - +\begin_layout Standard +The Church-co-Yoneda identity can be used to prove the Church encoding formula + for simultaneous greatest fixpoints of several functors, similarly to what + we did in Section +\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-commute-existential" +reference "subsec:Least-fixpoints-of-mutually-recursive-types" plural "false" caps "false" noprefix "false" \end_inset - (co-Fubini theorem) +. + For simplicity, we will now show a proof for just two mutually recursive + types; the proof can be extended to any number of types. + \end_layout \begin_layout Standard -For any type constructor -\begin_inset Formula $P$ -\end_inset +We will first prove a property of nested fixpoints. +\end_layout - with two parameters (not necessarily covariant or contravariant): -\begin_inset Formula -\[ -\exists A.\,\exists B.\,P^{A,B}\cong\exists B.\,\exists A.\,P^{A,B}\quad. -\] +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-nested-greatest-fixpoints" \end_inset -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-nested-greatest-fixpoints" +plural "false" +caps "false" +noprefix "false" + +\end_inset + -\begin_layout Subparagraph -Proof \end_layout \begin_layout Standard -We rewrite -\begin_inset Formula $\exists A.\,\exists B.\,P^{A,B}$ +For any bifunctor +\begin_inset Formula $F$ \end_inset - via universal quantifiers: +, the following equivalence holds: \begin_inset Formula -\begin{align*} - & \gunderline{\exists A.}\,\exists B.\,P^{A,B}\\ -\text{use Eq.\,(\ref{eq:existential-via-universal-Yoneda})}:\quad & \cong\forall D.\,\big(\forall A.\,\gunderline{(\exists B.\,P^{A,B})\rightarrow D})\rightarrow D\\ -\text{use Eq.\,(\ref{eq:existential-via-universal})}:\quad & \cong\forall D.\,\big(\forall A.\,\forall B.\,P^{A,B}\rightarrow D)\rightarrow D\quad. -\end{align*} +\[ +\nu A.\,(\nu B.\,F^{A,B})\cong\nu B.\,F^{B,B}\quad. +\] \end_inset -If we rewrite -\begin_inset Formula $\exists B.\,\exists A.\,P^{A,B}$ + +\end_layout + +\begin_layout Subparagraph +Proof +\end_layout + +\begin_layout Standard +Denote +\begin_inset Formula $G^{A,C}\triangleq(A\rightarrow C)\times A$ \end_inset - similarly, we will get: + and write the Church encoding for the fixpoints: \begin_inset Formula \[ -\exists B.\,\exists A.\,P^{A,B}\cong\forall D.\,\big(\forall B.\,\forall A.\,P^{A,B}\rightarrow D)\rightarrow D\quad. +\nu A.\,(\nu B.\,F^{A,B})=\exists A.\,(A\rightarrow\nu B.\,F^{A,B})\times A=\exists A.\,G^{A,\,\nu B.\,F^{A,B}}\quad. \] \end_inset -Statement +View +\begin_inset Formula $A$ +\end_inset + + as fixed and use the Church-co-Yoneda identity (Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-Fubini-theorem" +reference "subsec:Statement-Church-co-Yoneda" plural "false" caps "false" noprefix "false" \end_inset - gives -\begin_inset Formula $\forall A.\,\forall B.\,P^{A,B}\cong\forall B.\,\forall A.\,P^{A,B}$ -\end_inset +): +\begin_inset Formula +\begin{align*} + & G^{A,\,\nu B.\,F^{A,B}}\cong\exists B.\,(B\rightarrow F^{A,B})\times\gunderline{G^{A,B}}\\ + & =\exists B.\,(B\rightarrow F^{A,B})\times(A\rightarrow B)\times A\\ + & =\exists B.\,(A\rightarrow B)\times H^{A,B}\quad, +\end{align*} -, completing the proof. - -\begin_inset Formula $\square$ \end_inset - -\end_layout - -\begin_layout Standard -Now we will prove some more technical properties of existential types. -\end_layout - -\begin_layout Standard -In the next two statements, we work with a fixed type constructor -\begin_inset Formula $P$ +where we defined +\begin_inset Formula $H$ \end_inset -, which is not assumed to be covariant or contravariant. - For brevity, we denote: + by: \begin_inset Formula \[ -E\triangleq\forall B.\,(\forall A.\,P^{A}\rightarrow B)\rightarrow B\quad. +H^{A,B}\triangleq(B\rightarrow F^{A,B})\times A\quad. \] \end_inset +Now we can simplify the nested fixpoints: +\begin_inset Formula +\begin{align*} +\text{expect }\nu B.\,F^{B,B}:\quad & \nu A.\,(\nu B.\,F^{A,B})=\gunderline{\exists A.\,\exists B.}\,(A\rightarrow B)\times H^{A,B}\\ +\text{co-Fubini theorem (Statement~\ref{subsec:Statement-commute-existential})}:\quad & \cong\exists B.\,\exists A.\,(A\rightarrow B)\times H^{A,B}\\ +\text{co-Yoneda identity}:\quad & \cong\exists B.\,\gunderline{H^{B,B}}=\exists B.\,(B\rightarrow F^{B,B})\times B\\ +\text{Church encoding}:\quad & \cong\nu B.\,F^{B,B}\quad. +\end{align*} + +\end_inset + \end_layout @@ -49311,14 +48998,14 @@ E\triangleq\forall B.\,(\forall A.\,P^{A}\rightarrow B)\rightarrow B\quad. Statement \begin_inset CommandInset label LatexCommand label -name "subsec:Statement-identity-law-of-pack" +name "subsec:Statement-mutually-recursive-greatest-fixpoints" \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-identity-law-of-pack" +reference "subsec:Statement-mutually-recursive-greatest-fixpoints" plural "false" caps "false" noprefix "false" @@ -49329,1113 +49016,1028 @@ noprefix "false" \end_layout \begin_layout Standard -Values of type -\begin_inset Formula $E$ +Given any bifunctors +\begin_inset Formula $F$ \end_inset - are constructed via the standard function -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout +, +\begin_inset Formula $G$ +\end_inset -pack -\end_layout +, define +\begin_inset Formula $T$ +\end_inset + and +\begin_inset Formula $U$ \end_inset - that has the following type signature: + as the simultaneous greatest fixpoints of two type equations: \begin_inset Formula -\begin{align*} - & \text{pack}:\forall T.\,P^{T}\rightarrow E\quad,\\ -\text{or equivalently}:\quad & \text{pack}:\forall T.\,P^{T}\rightarrow\forall B.\,(\forall A.\,P^{A}\rightarrow B)\rightarrow B\quad,\\ - & \text{pack}^{T}(p^{:P^{T}})\triangleq\forall B.\,\big(k^{:\forall A.\,P^{A}\rightarrow B}\big)\rightarrow k^{T}(p)\quad. -\end{align*} +\[ +T=F^{T,U}\quad,\quad\quad U=G^{T,U}\quad. +\] \end_inset -Then the -\series bold -identity law -\series default - of -\begin_inset Index idx -status open - -\begin_layout Plain Layout -identity laws!of -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -pack -\end_layout - +Then the types +\begin_inset Formula $T$ \end_inset + and +\begin_inset Formula $U$ +\end_inset -\end_layout + can be expressed as: +\begin_inset Formula +\begin{align*} + & T\cong\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times A\quad,\\ + & U\cong\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times B\quad. +\end{align*} \end_inset - -\begin_inset listings -inline true -status open -\begin_layout Plain Layout +\end_layout -pack +\begin_layout Subparagraph +Proof \end_layout +\begin_layout Standard +If +\begin_inset Formula $T$ \end_inset - holds: for any value -\begin_inset Formula $e:E$ + and +\begin_inset Formula $U$ \end_inset -, + are fixed (and equal to the correct greatest fixpoints) then we can write: \begin_inset Formula -\begin{equation} -e^{E}(\text{pack})=e\quad.\label{eq:identity-law-of-pack} -\end{equation} +\[ +T=\nu A.\,F^{A,U}\quad,\quad\quad U=\nu B.\,G^{T,B}\quad. +\] \end_inset -It is assumed that all values -\begin_inset Formula $e^{:E}$ +Now we can substitute +\begin_inset Formula $U$ \end_inset - obey their naturality law: + into the equation for +\begin_inset Formula $T$ +\end_inset + +: \begin_inset Formula -\begin{equation} -\text{for all }f^{:B\rightarrow C},k^{:\forall A.\,P^{A}\rightarrow B}:\quad f(e^{B}(k))=e^{C}(\forall A.\,k^{A}\bef f)\quad.\label{eq:naturality-law-of-e-derivation1} -\end{equation} +\[ +T=\nu A.\,F^{A,\,\nu B.\,G^{T,B}}\quad. +\] \end_inset +The last line is a fixpoint equation involving only +\begin_inset Formula $T$ +\end_inset -\end_layout - -\begin_layout Subparagraph -Proof -\begin_inset Foot -status open +, so we may express +\begin_inset Formula $T$ +\end_inset -\begin_layout Plain Layout -The author thanks -\begin_inset Index idx -status open + as the greatest fixpoint of that equation. + Then we get: +\begin_inset Formula +\begin{align*} + & T=\nu C.\,\nu A.\,F^{A,\,\nu B.\,G^{C,B}}\\ +\text{use Statement~\ref{subsec:Statement-nested-greatest-fixpoints} and set }A=C:\quad & \cong\gunderline{\nu A.}\,F^{A,\,\nu B.\,G^{A,B}}\\ +\text{use Church encoding}:\quad & \cong\exists A.\:(A\rightarrow F^{A,\,\nu B.\,G^{A,B}})\times A\\ +\text{define }N^{A,C}\triangleq(A\rightarrow F^{A,C})\times A:\quad & =\exists A.\:N^{A,\,\nu B.\,G^{A,B}}\\ +\text{Church-co-Yoneda identity (Statement~\ref{subsec:Statement-Church-co-Yoneda})}:\quad & \cong\gunderline{\exists A.\,\exists B.}\,(B\rightarrow G^{A,B})\times N^{A,B}\quad. +\end{align*} -\begin_layout Plain Layout -Dan Doel -\end_layout +\end_inset +Writing out the definition of +\begin_inset Formula $N^{A,B}$ \end_inset -Dan Doel for assistance with the proof of this statement. - See the discussion at -\family typewriter +, we obtain the claimed Church encoding for +\begin_inset Formula $T$ +\end_inset -\begin_inset CommandInset href -LatexCommand href -target "https://cstheory.stackexchange.com/questions/54124" -literal "false" +: +\begin_inset Formula +\[ +T\cong\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times A\quad. +\] \end_inset + The formula for +\begin_inset Formula $U$ +\end_inset -\end_layout - + is derived similarly. + +\begin_inset Formula $\square$ \end_inset \end_layout +\begin_layout Subsection +Summary of type isomorphisms +\end_layout + \begin_layout Standard -Both sides of Eq. -\begin_inset space ~ +This Appendix has developed various parametricity techniques to prove a + number of type isomorphisms. + The results are summarized in Tables +\begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:identity-law-of-pack" +reference "tab:Type-identities-proved-by-Yoneda" plural "false" caps "false" noprefix "false" \end_inset -) have type -\begin_inset Formula $E$ +– +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Type-identities-for-existential-types" +plural "false" +caps "false" +noprefix "false" + \end_inset . - Since -\begin_inset Formula $E$ -\end_inset +\end_layout - is a type of functions with a type parameter, the two sides can be applied - to an arbitrary type -\begin_inset Formula $U$ -\end_inset +\begin_layout Standard +\begin_inset Float table +placement h +wide false +sideways false +status open - and an arbitrary value -\begin_inset Formula $u:\forall A.\,P^{A}\rightarrow U$ -\end_inset +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + + +\begin_inset Text - to get two values of type -\begin_inset Formula $U$ -\end_inset +\begin_layout Plain Layout -: -\begin_inset Formula -\begin{align*} -\text{both sides of}:\quad & e^{E}(\text{pack})\overset{?}{=}e\\ -\text{can be applied to }U\text{ and }u\text{ and yield}:\quad & \big(e^{E}(\text{pack})\big)^{U}(u)\overset{?}{=}e^{U}(u)\quad. -\end{align*} +\series bold +\size footnotesize +Identity +\end_layout \end_inset + + +\begin_inset Text +\begin_layout Plain Layout +\series bold +\size footnotesize +Assumptions \end_layout -\begin_layout Standard -So, let us prove that for all types -\begin_inset Formula $U$ \end_inset + + + + +\begin_inset Text - and all values -\begin_inset Formula $u:\forall A.\,P^{A}\rightarrow U$ +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,A\rightarrow A\cong\bbnum 1$ \end_inset -, -\begin_inset Formula -\begin{equation} -\big(e^{E}(\text{pack})\big)^{U}(u)\overset{?}{=}e^{U}(u)\quad.\label{eq:identity-law-of-pack-derivation1} -\end{equation} -\end_inset +\end_layout -To prove the last equation, we will rewrite it in the form of the naturality - law -\begin_inset space ~ \end_inset + + +\begin_inset Text -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:naturality-law-of-e-derivation1" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout -\end_inset +\end_layout -) by finding suitable parameters -\begin_inset Formula $B$ \end_inset + + + + +\begin_inset Text -, -\begin_inset Formula $C$ -\end_inset +\begin_layout Plain Layout -, -\begin_inset Formula $f$ +\size footnotesize +\begin_inset Formula $\forall A.\,A\rightarrow F^{A}\cong F^{\bbnum 1}$ \end_inset -, and -\begin_inset Formula $k$ -\end_inset -. - Once we manage to do that, the proof of Eq. -\begin_inset space ~ +\end_layout + \end_inset + + +\begin_inset Text -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:identity-law-of-pack" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $F$ \end_inset -) will be completed. - + is any functor \end_layout -\begin_layout Standard -The left-hand side of Eq. -\begin_inset space ~ \end_inset + + + + +\begin_inset Text -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:identity-law-of-pack-derivation1" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $\forall A.\,A\times A\rightarrow F^{A}\cong F^{\bbnum 2}$ \end_inset -) will match the left-hand side of Eq. -\begin_inset space ~ -\end_inset -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:naturality-law-of-e-derivation1" -plural "false" -caps "false" -noprefix "false" +\end_layout \end_inset + + +\begin_inset Text -) if we assign -\begin_inset Formula $B=E$ -\end_inset +\begin_layout Plain Layout -, -\begin_inset Formula $k=\text{pack}$ +\size footnotesize +\begin_inset Formula $F$ \end_inset -, and -\begin_inset Formula $f(e)\triangleq e^{U}(u)$ -\end_inset + is any functor +\end_layout -. - The type of -\begin_inset Formula $f$ \end_inset + + + + +\begin_inset Text - must be -\begin_inset Formula $B\rightarrow C$ -\end_inset +\begin_layout Plain Layout -; since -\begin_inset Formula $f(e)$ +\size footnotesize +\begin_inset Formula $\forall A.\,A\cong\bbnum 0$ \end_inset - has type -\begin_inset Formula $U$ -\end_inset -, we need to set -\begin_inset Formula $C=U$ -\end_inset +\end_layout -. - With these assignments, the right-hand side of Eq. -\begin_inset space ~ \end_inset + + +\begin_inset Text -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:naturality-law-of-e-derivation1" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout + +\end_layout \end_inset + + + + +\begin_inset Text -) becomes: -\begin_inset Formula -\[ -e^{C}(k\bef f)=e^{U}(\forall A.\,\text{pack}^{A}\bef f)\quad. -\] +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $\forall A.\,F^{A}\cong F^{\bbnum 0}$ \end_inset -This will be equal to the right-hand side -\begin_inset Formula $e^{U}(u)$ + +\end_layout + \end_inset + + +\begin_inset Text - of Eq. -\begin_inset space ~ +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ \end_inset -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:identity-law-of-pack-derivation1" -plural "false" -caps "false" -noprefix "false" + is any functor +\end_layout \end_inset + + + + +\begin_inset Text -) if we show that: -\begin_inset Formula -\[ -\forall A.\,\text{pack}^{A}\bef f\overset{?}{=}u\quad. -\] +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $\forall A.\,H^{A}\cong H^{\bbnum 1}$ \end_inset -Substitute the definitions of -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout -pack \end_layout \end_inset + + +\begin_inset Text - and -\begin_inset Formula $f$ -\end_inset - -, renaming -\begin_inset Formula $A$ -\end_inset +\begin_layout Plain Layout - to -\begin_inset Formula $T$ +\size footnotesize +\begin_inset Formula $H$ \end_inset -: -\begin_inset Formula -\[ -\forall T.\,\text{pack}^{T}\bef f=\forall T.\,p^{:P^{T}}\rightarrow f\big(\forall B.\,\big(q^{:\forall A.\,P^{A}\rightarrow B}\big)\rightarrow q^{T}(p)\big)\quad. -\] + is any contrafunctor +\end_layout \end_inset + + + + +\begin_inset Text -The function -\begin_inset Formula $f$ -\end_inset +\begin_layout Plain Layout - substitutes -\begin_inset Formula $B=U$ +\size footnotesize +\begin_inset Formula $\forall A.\,(A\rightarrow P)\rightarrow A\rightarrow Q\cong P\rightarrow Q$ \end_inset - and -\begin_inset Formula $q=u$ -\end_inset - into its function parameter: -\begin_inset Formula -\[ -f\big(\forall B.\,\big(q^{:\forall A.\,P^{A}\rightarrow B}\big)\rightarrow q^{T}(p)\big)=\big(\forall B.\,\big(q^{:\forall A.\,P^{A}\rightarrow B}\big)\rightarrow q^{T}(p)\big)^{U}(u)=u^{T}(p)\quad. -\] +\end_layout \end_inset + + +\begin_inset Text -So, we find: -\begin_inset Formula -\[ -\forall T.\,\text{pack}^{T}\bef f=\forall T.\,p^{:P^{T}}\rightarrow u^{T}(p)=\forall T.\,u^{T}=u\quad. -\] +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $P$ \end_inset -This completes the proof. - -\begin_inset Formula $\square$ +, +\begin_inset Formula $Q$ \end_inset - + are fixed types \end_layout -\begin_layout Standard -Finally, here is the key property required for proving the equivalence of - two formulations of existential types, Eq. -\begin_inset space ~ \end_inset + + + + +\begin_inset Text -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:existential-via-universal" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $\forall A.\,(P\rightarrow A)\rightarrow Q\rightarrow A\cong Q\rightarrow P$ \end_inset -) and Eq. -\begin_inset space ~ -\end_inset -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:existential-via-universal-Yoneda" -plural "false" -caps "false" -noprefix "false" +\end_layout \end_inset + + +\begin_inset Text -). -\end_layout +\begin_layout Plain Layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-function-extension-rule" +\size footnotesize +\begin_inset Formula $P$ +\end_inset +, +\begin_inset Formula $Q$ \end_inset + are fixed types +\end_layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-function-extension-rule" -plural "false" -caps "false" -noprefix "false" +\end_inset + + + + +\begin_inset Text +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,((A\rightarrow P)\rightarrow Q)\rightarrow(A\rightarrow S)\rightarrow R\cong((S\rightarrow P)\rightarrow Q)\rightarrow R$ \end_inset \end_layout -\begin_layout Standard -The following type isomorphism holds: -\begin_inset Formula -\begin{align*} - & E\rightarrow R=(\exists A.\,P^{A})\rightarrow R\cong\forall C.\,P^{C}\rightarrow R\quad,\\ -\text{or equivalently}:\quad & \big(\forall B.\,(\forall A.\,P^{A}\rightarrow B)\rightarrow B\big)\rightarrow R\cong\forall C.\,P^{C}\rightarrow R\quad, -\end{align*} - \end_inset + + +\begin_inset Text -where -\begin_inset Formula $R$ -\end_inset +\begin_layout Plain Layout - is a fixed type. - In this isomorphism, it is assumed that the type -\begin_inset Formula $E$ +\size footnotesize +\begin_inset Formula $P$ \end_inset - contains only functions -\begin_inset Formula $e^{:E}$ +, +\begin_inset Formula $Q$ \end_inset - that obey the naturality law -\begin_inset space ~ +, +\begin_inset Formula $R$ \end_inset -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:naturality-law-of-e-derivation1" -plural "false" -caps "false" -noprefix "false" - +, +\begin_inset Formula $S$ \end_inset -). - + are fixed types \end_layout -\begin_layout Standard -This isomorphism can be also formulated via code like this: -\begin_inset Formula -\begin{equation} -\text{for all }e^{:E}\text{ and }r^{:E\rightarrow R}:\quad r(e)=e^{R}(\forall C.\,\text{pack}^{C}\bef r)\quad,\label{eq:surjectivity-of-pack} -\end{equation} - \end_inset - -where the standard function -\begin_inset listings -inline true -status open + + + + +\begin_inset Text \begin_layout Plain Layout -pack -\end_layout - +\size footnotesize +\begin_inset Formula $\forall A.\,(P\rightarrow A\times Q)\rightarrow(A+R)\times S\cong$ \end_inset - was defined in the proof of Statement -\begin_inset space ~ + +\begin_inset Formula $(P\rightarrow Q)\rightarrow(P+R)\times S$ \end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-identity-law-of-pack" -plural "false" -caps "false" -noprefix "false" +\end_layout \end_inset + + +\begin_inset Text -. - Any function -\begin_inset Formula $r$ -\end_inset +\begin_layout Plain Layout - that consumes values of type -\begin_inset Formula $e$ +\size footnotesize +\begin_inset Formula $P$ \end_inset - can be expressed via application of -\begin_inset Formula $r$ +, +\begin_inset Formula $Q$ \end_inset - to values constructed via -\begin_inset listings -inline true -status open +, +\begin_inset Formula $R$ +\end_inset -\begin_layout Plain Layout +, +\begin_inset Formula $S$ +\end_inset -pack + are fixed types \end_layout \end_inset + + + -. -\end_layout - -\begin_layout Subparagraph -Proof -\end_layout +\end_inset -\begin_layout Standard -The isomorphism is shown by defining two functions ( -\begin_inset listings -inline true -status open + +\end_layout \begin_layout Plain Layout +\begin_inset Caption Standard -inF -\end_layout +\begin_layout Plain Layout +Type isomorphisms proved via Yoneda identities. +\begin_inset CommandInset label +LatexCommand label +name "tab:Type-identities-proved-by-Yoneda" \end_inset - and -\begin_inset listings -inline true -status open -\begin_layout Plain Layout - -outF \end_layout \end_inset -): -\begin_inset Formula -\begin{align*} - & \text{inF}:(\forall C.\,P^{C}\rightarrow R)\rightarrow E\rightarrow R\quad,\\ - & \text{inF}\triangleq k^{:\forall C.\,P^{C}\rightarrow R}\rightarrow e^{:E}\rightarrow e^{R}(k)\quad,\\ - & \text{outF}:(E\rightarrow R)\rightarrow\forall C.\,P^{C}\rightarrow R\quad,\\ - & \text{outF}\triangleq r^{:E\rightarrow R}\rightarrow\forall C.\,p^{:P^{C}}\rightarrow r(\text{pack}^{C}(p))=r^{:E\rightarrow R}\rightarrow\forall C.\,\text{pack}^{C}\bef r\quad, -\end{align*} + +\end_layout \end_inset -and by proving that those functions are inverses of each other. + \end_layout \begin_layout Standard -Without the type annotations, the code of -\begin_inset listings -inline true +\begin_inset Float table +wide false +sideways false status open +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + + + +\begin_inset Text + \begin_layout Plain Layout -inF +\series bold +\size footnotesize +Identity \end_layout \end_inset - - and -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -outF +\series bold +\size footnotesize +Assumptions \end_layout \end_inset + + +\begin_inset Text - is: -\begin_inset Formula -\[ -\text{inF}=k\rightarrow q\rightarrow q(k)\quad,\quad\quad\text{outF}=r\rightarrow p\rightarrow r(k\rightarrow k(p))\quad. -\] +\begin_layout Plain Layout -\end_inset +\series bold +\size footnotesize +Source +\end_layout -Now it is quick to prove one direction of isomorphism ( -\begin_inset Formula $\text{inF}\bef\text{outF}\overset{?}{=}\text{id}$ \end_inset + + + + +\begin_inset Text -): -\begin_inset Formula -\begin{align*} -\text{expect to equal }\text{id}:\quad & \text{inF}\bef\text{outF}=k\rightarrow\text{outF}\,(q\rightarrow q(k))\\ - & =k\rightarrow p\rightarrow(q\rightarrow q(k))(k\rightarrow k(p))\\ - & =k\rightarrow\gunderline{p\rightarrow k(p)}=k\rightarrow k=\text{id}\quad. -\end{align*} +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $\forall A.\,(F^{A}\rightarrow A)\rightarrow A\cong\mu A.\,F^{A}$ \end_inset \end_layout -\begin_layout Standard -The other direction ( -\begin_inset Formula $\text{outF}\bef\text{inF}\overset{?}{=}\text{id}$ -\end_inset - -) requires more work. - The argument of the function -\begin_inset Formula $\text{outF}\bef\text{inF}$ \end_inset + + +\begin_inset Text - has type -\begin_inset Formula $E\rightarrow R$ -\end_inset +\begin_layout Plain Layout -, and we need to show that for any function -\begin_inset Formula $r^{:E\rightarrow R}$ +\size footnotesize +\begin_inset Formula $F$ \end_inset - the following equation holds: -\begin_inset Formula -\[ -\text{inF}\,(\text{outF}\,(r))\overset{?}{=}r\quad,\quad\text{or equivalently}:\quad r\triangleright\text{outF}\triangleright\text{inF}\overset{?}{=}r\quad. -\] + is any functor +\end_layout \end_inset + + +\begin_inset Text -The last equation is between functions of type -\begin_inset Formula $E\rightarrow R$ -\end_inset +\begin_layout Plain Layout -; we may apply both sides to an arbitrary value -\begin_inset Formula $e^{:E}$ +\size footnotesize +Section +\begin_inset space ~ \end_inset - and require that the results (of type -\begin_inset Formula $R$ -\end_inset -) should be equal: -\begin_inset Formula -\[ -\big(r\triangleright\text{outF}\triangleright\text{inF}\big)(e)\overset{?}{=}r(e)\quad. -\] +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:The-Church-encoding-of-recursive-types" +plural "false" +caps "false" +noprefix "false" \end_inset -We begin by subtituting the definitions of -\begin_inset listings -inline true -status open -\begin_layout Plain Layout - -inF \end_layout \end_inset - - and -\begin_inset listings -inline true -status open + + + + +\begin_inset Text \begin_layout Plain Layout -outF +\size footnotesize +\begin_inset Formula $\forall A.\,(H^{A}\rightarrow A)\rightarrow A\cong H^{\bbnum 1}$ +\end_inset + + \end_layout \end_inset + + +\begin_inset Text -: -\begin_inset Formula -\begin{align*} -\text{expect to equal }r(e):\quad & e\triangleright\big(r\triangleright\text{outF}\triangleright\text{inF}\big)=e\triangleright\big((\forall A.\,p^{:P^{A}}\rightarrow r(\text{pack}^{A}(p)))\triangleright\text{inF}\big)\\ - & =e^{R}\big(\forall A.\,p^{:P^{A}}\rightarrow r(\text{pack}^{A}(p))\big)=e^{R}(\forall A.\,\text{pack}^{A}\bef r)\quad. -\end{align*} +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $H$ \end_inset -Since -\begin_inset Formula $e$ -\end_inset + is any contrafunctor +\end_layout - is unknown and arbitrary, we can make progress in the proof only if we - use the naturality law of -\begin_inset Formula $e$ \end_inset + + +\begin_inset Text - as given by Eq. +\begin_layout Plain Layout + +\size footnotesize +Statement \begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:naturality-law-of-e-derivation1" +reference "subsec:Example-simplify-quantifier-1-1" plural "false" caps "false" noprefix "false" \end_inset -). - We assign -\begin_inset Formula $B=E$ -\end_inset -, -\begin_inset Formula $C=R$ -\end_inset +\end_layout -, -\begin_inset Formula $f=r$ \end_inset + + + + +\begin_inset Text -, -\begin_inset Formula $k=\text{pack}$ +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,(A\rightarrow A)\rightarrow H^{A}\cong H^{\bbnum 1}$ \end_inset - in that law and obtain: -\begin_inset Formula -\[ -r(e^{E}(\text{pack}))=e^{R}(\forall A.\,\text{pack}^{A}\bef r)\quad. -\] + +\end_layout \end_inset + + +\begin_inset Text -By the identity law of pack (Statement -\begin_inset space ~ +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $H$ \end_inset + is any contrafunctor +\end_layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-identity-law-of-pack" -plural "false" -caps "false" -noprefix "false" - -\end_inset - -), -\begin_inset Formula $e^{E}(\text{pack})=e$ \end_inset + + +\begin_inset Text -. - So, we conclude the derivation: -\begin_inset Formula -\begin{align*} -\text{expect to equal }r(e):\quad & e\triangleright\big(r\triangleright\text{outF}\triangleright\text{inF}\big)=\gunderline{e^{R}(\forall A.\,\text{pack}^{A}\bef r)}\\ -\text{naturality law of }e:\quad & =r(\gunderline{e^{E}(\text{pack})})\\ -\text{identity law of }\text{pack}:\quad & =r(e)\quad. -\end{align*} - -\end_inset +\begin_layout Plain Layout -We have proved the isomorphism and also verified Eq. +\size footnotesize +Example \begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:surjectivity-of-pack" +reference "subsec:Example-strong-dinaturality-show-void" plural "false" caps "false" noprefix "false" \end_inset -). - -\begin_inset Formula $\square$ -\end_inset - - +(b) \end_layout -\begin_layout Subsection -Greatest fixpoints and the Church-co-Yoneda identity -\begin_inset CommandInset label -LatexCommand label -name "subsec:The-greatest-fixpoints-and-Church-co-Yoneda" +\end_inset + + + + +\begin_inset Text +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,(F^{A}\rightarrow A)\rightarrow G^{A}\cong G^{\mu A.\,F^{A}}$ \end_inset \end_layout -\begin_layout Standard -We have seen that the least fixpoints of functors are expressed via the - Church encoding type that involves a universally quantified higher-order - function. - An analogous encoding (with an existentially quantified type) exists for - greatest fixpoints. - We will now prove some properties of that encoding. -\begin_inset Foot -status open +\end_inset + + +\begin_inset Text \begin_layout Plain Layout -This section follows the logic given in P. -\begin_inset space ~ + +\size footnotesize +\begin_inset Formula $F$ \end_inset -Wadler's paper -\begin_inset Quotes eld +, +\begin_inset Formula $G$ \end_inset -Recursive types for free -\begin_inset Quotes erd + are any functors +\end_layout + \end_inset + + +\begin_inset Text -, except that we -\emph on -define -\emph default - existential types by Eq. +\begin_layout Plain Layout + +\size footnotesize +Statement \begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:existential-via-universal-Yoneda" +reference "subsec:Statement-Church-Yoneda-identity" plural "false" caps "false" noprefix "false" \end_inset -) via the universal quantifier. -\end_layout - -\end_inset - \end_layout -\begin_layout Standard -We work with a fixed covariant functor -\begin_inset Formula $F$ -\end_inset - - and denote by -\begin_inset Formula $C$ -\end_inset - - the following Church-encoded type: -\begin_inset Formula -\[ -C\triangleq\exists A.\,(A\rightarrow F^{A})\times A\quad. -\] - \end_inset + + + + +\begin_inset Text -We will prove that -\begin_inset Formula $C$ -\end_inset +\begin_layout Plain Layout - is the greatest fixpoint of the type equation -\begin_inset Formula $X\cong F^{X}$ +\size footnotesize +\begin_inset Formula $\mu A.\,\mu B.\,F^{A,B}\cong\mu B.\,F^{B,B}$ \end_inset -; that is, -\begin_inset Formula $C=\nu X.\,F^{X}$ -\end_inset -. - \end_layout -\begin_layout Standard -First, we define some auxiliary functions that work with the type -\begin_inset Formula $C$ \end_inset - - and prove their properties. -\end_layout - -\begin_layout Standard -The function -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -unfold -\end_layout - -\end_inset - - constructs values of type -\begin_inset Formula $C$ -\end_inset - -: -\begin_inset Formula -\begin{align*} - & \text{unfold}:\forall T.\,(T\rightarrow F^{T})\times T\rightarrow C\quad,\\ - & \text{unfold}^{T}(u^{:T\rightarrow F^{T}}\times t^{:T})\triangleq\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times A\rightarrow R}\rightarrow p^{T}(u\times t)\quad. -\end{align*} - +\size footnotesize +\begin_inset Formula $F$ \end_inset -Note that -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -unfold + is any bifunctor \end_layout \end_inset - - is the same as the function -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -pack -\end_layout - -\end_inset - - from Statement +\size footnotesize +Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-identity-law-of-pack" +reference "subsec:Statement-nested-fixpoints" plural "false" caps "false" noprefix "false" \end_inset - if we set -\begin_inset Formula $E=C$ -\end_inset - and -\begin_inset Formula $P^{A}\triangleq(A\rightarrow F^{A})\times A$ +\end_layout + \end_inset + + + + +\begin_inset Text - in the definition of -\begin_inset listings -inline true -status open +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Note Note +status collapsed \begin_layout Plain Layout -pack -\end_layout +\size footnotesize +See +\family typewriter +\size default + +\begin_inset CommandInset href +LatexCommand href +target "https://tex.stackexchange.com/questions/50332/vertical-spacing-of-a-table-cell" +literal "false" \end_inset -. + \end_layout -\begin_layout Standard -By parametricity, the function -\begin_inset listings -inline true -status open +\end_inset + + +\begin_inset Box Frameless +position "c" +hor_pos "c" +has_inner_box 1 +inner_pos "t" +use_parbox 0 +use_makebox 0 +width "0.1mm" +special "none" +height "12mm" +height_special "none" +thickness "0.4pt" +separation "3pt" +shadowsize "4pt" +framecolor "black" +backgroundcolor "none" +status collapsed \begin_layout Plain Layout -unfold \end_layout \end_inset - satisfies a relational naturality law: for all types -\begin_inset Formula $A$ -\end_inset -, -\begin_inset Formula $B$ -\end_inset +\begin_inset Box Frameless +position "c" +hor_pos "c" +has_inner_box 1 +inner_pos "c" +use_parbox 0 +use_makebox 0 +width "43col%" +special "none" +height "1in" +height_special "totalheight" +thickness "0.4pt" +separation "3pt" +shadowsize "4pt" +framecolor "black" +backgroundcolor "none" +status open - and all functions -\begin_inset Formula $f^{:A\rightarrow B}$ +\begin_layout Plain Layout +\align center + +\size footnotesize +\begin_inset Formula $\mu A.\,P^{A,\,\mu B.\,Q^{A,B}}\cong$ \end_inset -, -\begin_inset Formula -\begin{equation} -\text{if}\quad u\bef f^{\uparrow F}=f\bef v\quad\text{then}\quad\text{unfold}^{A}(u^{:A\rightarrow F^{A}}\times a^{:A})=\text{unfold}^{B}(v^{:B\rightarrow F^{B}}\times f(a))\quad.\label{eq:relational-naturality-law-of-unfold} -\end{equation} +\begin_inset Newline newline \end_inset -In category theory, the precondition -\begin_inset Formula $u\bef f^{\uparrow F}=f\bef v$ + +\begin_inset Formula $\forall A.\,\forall B.\,(P^{A,B}\rightarrow A)\times(Q^{A,B}\rightarrow B)\rightarrow A$ \end_inset - is known as the -\begin_inset Quotes eld + +\end_layout + \end_inset -\begin_inset Formula $F$ +\end_layout + \end_inset + + +\begin_inset Text --coalgebra morphism law -\begin_inset Quotes erd +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $P$ \end_inset - of -\begin_inset Formula $f$ +, +\begin_inset Formula $Q$ \end_inset -. - Let us give some definitions for reference: + are any bifunctors \end_layout -\begin_layout Subsubsection -Definition -\begin_inset CommandInset label -LatexCommand label -name "subsec:Definition-F-coalgebra" +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\size footnotesize +Statement +\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Definition-F-coalgebra" +reference "subsec:Statement-nested-fixpoint-under-functor" plural "false" caps "false" noprefix "false" @@ -50445,1753 +50047,1650 @@ noprefix "false" \end_layout -\begin_layout Standard -Given a functor -\begin_inset Formula $F$ -\end_inset - -, a type -\begin_inset Formula $A$ \end_inset + + + + +\begin_inset Text - together with a function -\begin_inset Formula $u:A\rightarrow F^{A}$ -\end_inset +\begin_layout Plain Layout - is called an -\begin_inset Formula $F$ +\size footnotesize +\begin_inset Formula $\forall A.\,F^{A}\rightarrow P\cong P$ \end_inset -\series bold --coalgebra -\series default -. -\begin_inset Index idx -status open - -\begin_layout Plain Layout -\begin_inset Formula $F$ -\end_inset - --coalgebra \end_layout \end_inset + + +\begin_inset Text - The type -\begin_inset Formula $A$ -\end_inset +\begin_layout Plain Layout - is called the -\series bold -carrier -\series default - of the -\begin_inset Formula $F$ +\size footnotesize +If +\begin_inset Formula $F^{A}\neq\bbnum 0$ \end_inset --coalgebra, and the function -\begin_inset Formula $u$ + for some +\begin_inset Formula $A$ \end_inset - is called the -\series bold -structure map -\series default - of the -\begin_inset Formula $F$ -\end_inset --coalgebra. - (Keep in mind that -\begin_inset Formula $u$ -\end_inset +\end_layout - is not universally quantified over -\begin_inset Formula $A$ \end_inset + + +\begin_inset Text -; it is a function that only works with a single, specified type -\begin_inset Formula $A$ -\end_inset +\begin_layout Plain Layout -. - For a given type -\begin_inset Formula $A$ +\size footnotesize +Statement +\begin_inset space ~ \end_inset -, there could be several different structure maps -\begin_inset Formula $u$ -\end_inset -, -\begin_inset Formula $u^{\prime}$ -\end_inset +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-application-full-relation" +plural "false" +caps "false" +noprefix "false" -, and so on; each of them will then define a different -\begin_inset Formula $F$ \end_inset --coalgebra.) +(a) \end_layout -\begin_layout Standard -If -\begin_inset Formula $A$ -\end_inset - - and -\begin_inset Formula $B$ \end_inset + + + + +\begin_inset Text - are two -\begin_inset Formula $F$ -\end_inset +\begin_layout Plain Layout --coalgebras with structure maps -\begin_inset Formula $u:A\rightarrow F^{A}$ +\size footnotesize +\begin_inset Formula $\forall A.\,((A\rightarrow A)\rightarrow A)\rightarrow A\cong\bbnum 1+\bbnum 2+\bbnum 3+...$ \end_inset - and -\begin_inset Formula $v:B\rightarrow F^{B}$ -\end_inset - then a function -\begin_inset Formula $f:A\rightarrow B$ -\end_inset +\end_layout - is called an -\begin_inset Formula $F$ \end_inset + + +\begin_inset Text --coalgebra morphism if this law holds: -\begin_inset Preview - -\begin_layout Standard -\begin_inset Formula -\[ -\xymatrix{\xyScaleY{2.3pc}\xyScaleX{2.5pc}A\ar[d]\sb(0.4){u}\ar[r]\sp(0.5){f} & B\ar[d]\sp(0.4){v}\\ -F^{A}\ar[r]\sp(0.5){f^{\uparrow F}} & F^{B} -} -\] +\begin_layout Plain Layout +\size footnotesize +\begin_inset space ~ \end_inset \end_layout \end_inset + + +\begin_inset Text +\begin_layout Plain Layout -\begin_inset Formula -\[ -u\bef f^{\uparrow F}=f\bef v\quad. -\] - +\size footnotesize +Statement +\begin_inset space ~ \end_inset -This is the -\begin_inset Formula $F$ -\end_inset --coalgebra morphism law of -\begin_inset Formula $f$ -\end_inset +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-advanced-type-equivalence" +plural "false" +caps "false" +noprefix "false" -. - -\begin_inset Formula $\square$ \end_inset \end_layout -\begin_layout Standard -It is also helpful to define a function -\begin_inset listings -inline true -status open +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Box Frameless +position "c" +hor_pos "c" +has_inner_box 1 +inner_pos "t" +use_parbox 0 +use_makebox 0 +width "0.1mm" +special "none" +height "17mm" +height_special "none" +thickness "0.4pt" +separation "3pt" +shadowsize "4pt" +framecolor "black" +backgroundcolor "none" +status open \begin_layout Plain Layout -unfoldF \end_layout \end_inset - that constructs values of type -\begin_inset Formula $F^{C}$ -\end_inset -: -\begin_inset Formula -\begin{align*} - & \text{unfoldF}:\forall T.\,(T\rightarrow F^{T})\times T\rightarrow F^{C}\quad,\\ - & \text{unfoldF}^{T}(u^{:T\rightarrow F^{T}}\times t^{:T})\triangleq t\triangleright u\triangleright\big(a^{:T}\rightarrow\text{unfold}^{T}(u\times a)\big)^{\uparrow F}\quad. -\end{align*} +\begin_inset Box Frameless +position "c" +hor_pos "c" +has_inner_box 1 +inner_pos "c" +use_parbox 0 +use_makebox 0 +width "43col%" +special "none" +height "1in" +height_special "totalheight" +thickness "0.4pt" +separation "3pt" +shadowsize "4pt" +framecolor "black" +backgroundcolor "none" +status open + +\begin_layout Plain Layout +\align center +\size footnotesize +\begin_inset Formula $\forall A.\,(H^{A}\rightarrow A)\rightarrow F^{A}+G^{A}\cong$ \end_inset -\end_layout +\begin_inset Newline newline +\end_inset -\begin_layout Standard -The isomorphism -\begin_inset Formula $C\cong F^{C}$ + +\begin_inset Formula $(\forall A.\:(H^{A}\rightarrow A)\rightarrow F^{A})\,+$ \end_inset - will be implemented via two functions: -\begin_inset Formula -\[ -\text{fix}:F^{C}\rightarrow C\quad,\quad\quad\text{unfix}:C\rightarrow F^{C}\quad, -\] +\begin_inset Newline newline \end_inset -which we define via -\begin_inset listings -inline true -status open -\begin_layout Plain Layout +\begin_inset Formula $(\forall A.\:(H^{A}\rightarrow A)\rightarrow G^{A})$ +\end_inset + -unfold \end_layout \end_inset - and -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout -unfoldF \end_layout \end_inset + + +\begin_inset Text - like this: -\begin_inset Formula -\begin{align*} - & \text{unfix}:C\rightarrow F^{C}\quad,\quad\quad\text{unfix}\triangleq c^{:C}\rightarrow c^{F^{C}}(\forall A.\,\text{unfoldF}^{A})=c^{:C}\rightarrow c^{F^{C}}(\text{unfoldF})\quad,\\ - & \text{fix}:F^{C}\rightarrow C\quad,\quad\quad\text{fix}\triangleq p^{:F^{C}}\rightarrow\text{unfold}^{F^{C}}(\text{unfix}^{\uparrow F}\times p)\quad. -\end{align*} +\begin_layout Plain Layout +\size footnotesize +For any +\begin_inset Formula $F$ \end_inset -Because of these functions, -\begin_inset Formula $C$ +, +\begin_inset Formula $G$ \end_inset - is at the same time an -\begin_inset Formula $F$ +, +\begin_inset Formula $H$ \end_inset --algebra and an -\begin_inset Formula $F$ -\end_inset --coalgebra. \end_layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-coalgebra-morphism-unfold" +\end_inset + + +\begin_inset Text +\begin_layout Plain Layout + +\size footnotesize +Example +\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-coalgebra-morphism-unfold" +reference "subsec:Example-undisjunctive-type-constructors" plural "false" caps "false" noprefix "false" \end_inset - +(c) \end_layout -\begin_layout Standard -For any -\begin_inset Formula $F$ \end_inset + + + + +\begin_inset Text --coalgebra -\begin_inset Formula $A$ -\end_inset +\begin_layout Plain Layout - with a structure map -\begin_inset Formula $u:A\rightarrow F^{A}$ +\size footnotesize +\begin_inset Formula $\forall A.\,\forall B.\,F^{A,B}\cong\forall B.\,\forall A.\,F^{A,B}$ \end_inset -, denote by -\begin_inset Formula $\psi_{u}^{A}$ -\end_inset - the following function of type -\begin_inset Formula $A\rightarrow C$ +\end_layout + \end_inset + + +\begin_inset Text -: -\begin_inset Formula -\[ -\psi_{u}^{A}:A\rightarrow C\quad,\quad\quad\psi_{u}^{A}\triangleq a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\quad. -\] +\begin_layout Plain Layout +\size footnotesize +For any +\begin_inset Formula $F$ \end_inset -Then -\begin_inset Formula $\psi_{u}^{A}$ + +\end_layout + \end_inset + + +\begin_inset Text - is an -\begin_inset Formula $F$ +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ \end_inset --coalgebra morphism of type -\begin_inset Formula $A\rightarrow C$ + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-Fubini-theorem-1" +plural "false" +caps "false" +noprefix "false" + \end_inset -. - -\end_layout -\begin_layout Subparagraph -Proof \end_layout -\begin_layout Standard -Write the -\begin_inset Formula $F$ \end_inset + + + + +\begin_inset Text --coalgebra morphism law for that function: -\begin_inset Formula -\[ -u\bef\big(a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\big)^{\uparrow F}\overset{?}{=}\big(a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\big)\bef v\quad. -\] +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $\forall A.\,(F^{A}+G^{A})\cong(\forall A.\,F^{A})+(\forall A.\,G^{A})$ \end_inset -Apply both sides to an arbitrary value -\begin_inset Formula $t^{:A}$ -\end_inset - and obtain: -\begin_inset Formula -\[ -t\triangleright u\triangleright(a\rightarrow\text{unfold}^{A}(u\times a))^{\uparrow F}\overset{?}{=}\text{unfix}\,(\text{unfold}^{A}(u\times t))\quad. -\] +\end_layout \end_inset + + +\begin_inset Text -Begin with the right-hand side: -\begin_inset Formula -\begin{align*} - & \text{unfix}\,(\text{unfold}^{A}(u\times t))\\ -\text{definition of }\text{unfix}:\quad & =(\text{unfold}^{A}(u\times t))^{F^{C}}(\text{unfoldF})\\ -\text{definition of }\text{unfold}:\quad & =\text{unfoldF}^{A}(u\times t)\\ -\text{definition of }\text{unfoldF}:\quad & =t\triangleright u\triangleright\big(a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\big)^{\uparrow F}\quad. -\end{align*} +\begin_layout Plain Layout +\size footnotesize +For any +\begin_inset Formula $F$ \end_inset -This is now equal to the left-hand side. - -\begin_inset Formula $\square$ +, +\begin_inset Formula $G$ \end_inset \end_layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-identity-law-of-unfold" +\end_inset + + +\begin_inset Text +\begin_layout Plain Layout + +\size footnotesize +Statement +\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-identity-law-of-unfold" +reference "subsec:Statement-general-identities-forall" plural "false" caps "false" noprefix "false" \end_inset - +(a) \end_layout -\begin_layout Standard -The function -\begin_inset listings -inline true -status open +\end_inset + + + + +\begin_inset Text \begin_layout Plain Layout -unfold -\end_layout - +\size footnotesize +\begin_inset Formula $\forall A.\,(F^{A}\times G^{A})\cong(\forall A.\,F^{A})\times(\forall A.\,G^{A})$ \end_inset - satisfies an -\series bold -identity law -\series default -: -\begin_inset Formula -\[ -\text{for all }c^{:C}:\quad\text{unfold}^{C}(\text{unfix}\times c)\overset{?}{=}c\quad. -\] - -\end_inset -This law -\begin_inset Index idx -status open +\end_layout -\begin_layout Plain Layout -identity laws!of -\begin_inset listings -inline true -status open +\end_inset + + +\begin_inset Text \begin_layout Plain Layout -unfold -\end_layout +\size footnotesize +For any +\begin_inset Formula $F$ +\end_inset +, +\begin_inset Formula $G$ \end_inset \end_layout \end_inset - - is similar to the identity law of -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -pack -\end_layout - -\end_inset - - (Statement +\size footnotesize +Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-identity-law-of-pack" +reference "subsec:Statement-general-identities-forall" plural "false" caps "false" noprefix "false" \end_inset -). -\end_layout - -\begin_layout Subparagraph -Proof +(b) \end_layout -\begin_layout Standard -Apply Statement -\begin_inset space ~ \end_inset + + + + +\begin_inset Text +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-identity-law-of-pack" -plural "false" -caps "false" -noprefix "false" - -\end_inset - -, which gives -\begin_inset Formula $e^{E}(\text{pack})=e$ +\size footnotesize +\begin_inset Formula $\forall A.\,R\rightarrow F^{A}\cong R\rightarrow(\forall A.\,F^{A})$ \end_inset -, and substitute -\begin_inset Formula $E=C$ -\end_inset -, -\begin_inset Formula $e=c$ -\end_inset +\end_layout -, -\begin_inset Formula $P^{A}=(A\rightarrow F^{A})\times A$ \end_inset - -, and -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -unfold -\end_layout - +\size footnotesize +Any +\begin_inset Formula $F$ \end_inset - instead of -\begin_inset listings -inline true -status open +, a fixed type +\begin_inset Formula $R$ +\end_inset -\begin_layout Plain Layout -pack \end_layout \end_inset + + +\begin_inset Text -. - We obtain: -\begin_inset Formula -\begin{equation} -c=c^{C}(\text{unfold})\quad.\label{eq:unfold-id-law-derivation1} -\end{equation} - -\end_inset +\begin_layout Plain Layout -Now use the law +\size footnotesize +Statement \begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:surjectivity-of-pack" +reference "subsec:Statement-general-identities-forall" plural "false" caps "false" noprefix "false" \end_inset -) where we substitute -\begin_inset Formula $E=R=C$ -\end_inset +(c) +\end_layout - and -\begin_inset Formula $e=c$ \end_inset + + + + +\begin_inset Text -: -\begin_inset Formula -\[ -\text{for all }r^{:C\rightarrow C}:\quad r(c)=c^{C}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times a^{:A}\rightarrow r(\text{unfold}^{A}(u\times a))\big)\quad. -\] +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $\forall A.\,F^{P^{A}}\cong F^{\forall A.\,P^{A}}$ \end_inset -We will use this law with the function -\begin_inset Formula $r$ + +\end_layout + \end_inset + + +\begin_inset Text - defined by: -\begin_inset Formula -\[ -r:C\rightarrow C\quad,\quad\quad r(c)\triangleq\text{unfold}^{C}(\text{unfix}\times c)\quad. -\] +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $F$ \end_inset -Then we get: -\begin_inset Formula -\begin{align} - & \text{unfold}^{C}(\text{unfix}\times c)=r(c)=c^{C}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times a^{:A}\rightarrow r(\text{unfold}^{A}(u\times a))\big)\nonumber \\ - & =c^{C}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times a^{:A}\rightarrow\text{unfold}^{C}(\text{unfix}\times\text{unfold}^{A}(u\times a)))\big)\quad.\label{eq:unfold-id-law-derivation3} -\end{align} + is strictly positive +\end_layout \end_inset + + +\begin_inset Text -Now we apply the naturality law +\begin_layout Plain Layout + +\size footnotesize +Statement \begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:relational-naturality-law-of-unfold" +reference "subsec:Statement-quantifier-across-functor" plural "false" caps "false" noprefix "false" \end_inset -) with -\begin_inset Formula $B=C$ + +\end_layout + \end_inset + + + + +\begin_inset Text -, -\begin_inset Formula $f=a\rightarrow\text{unfold}^{A}(u\times a)$ +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\forall A.\,F^{A}\cong\bbnum 0$ \end_inset -, and -\begin_inset Formula $v=\text{unfix}$ + when +\begin_inset Formula $F^{\bbnum 0}\cong\bbnum 0$ \end_inset -: -\begin_inset Formula -\begin{equation} -\text{unfold}^{A}(u\times a)=\text{unfold}^{C}(\text{unfix}\times\text{unfold}^{A}(u\times a)))\quad.\label{eq:unfold-id-law-derivation2} -\end{equation} -\end_inset +\end_layout -The precondition of this law ( -\begin_inset Formula $u\bef f^{\uparrow F}\overset{?}{=}f\bef v$ \end_inset + + +\begin_inset Text -) is the +\begin_layout Plain Layout + +\size footnotesize \begin_inset Formula $F$ \end_inset --coalgebra morphism law of -\begin_inset listings -inline true -status open + is such that +\begin_inset Formula $F^{\bbnum 0}\cong\bbnum 0$ +\end_inset -\begin_layout Plain Layout -unfold \end_layout \end_inset + + +\begin_inset Text -, and it has been demonstrated in Statement +\begin_layout Plain Layout + +\size footnotesize +Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-coalgebra-morphism-unfold" +reference "subsec:Statement-Fubini-theorem-1" plural "false" caps "false" noprefix "false" \end_inset -. - So, Eq. -\begin_inset space ~ + +\end_layout + \end_inset + + + + +\begin_inset Text -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:unfold-id-law-derivation2" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $\forall A.\,F^{A\rightarrow A}\cong F^{\bbnum 1}$ \end_inset -) holds. - -\end_layout -\begin_layout Standard -Finally, we can finish the proof: -\begin_inset Formula -\begin{align*} -\text{expect to equal }c:\quad & \text{unfold}^{C}(\text{unfix}\times c)\\ -\text{use Eq.~(\ref{eq:unfold-id-law-derivation3})}:\quad & =c^{C}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times a^{:A}\rightarrow\gunderline{\text{unfold}^{C}(\text{unfix}\times\text{unfold}^{A}(u\times a)))}\big)\\ -\text{use Eq.~(\ref{eq:unfold-id-law-derivation2})}:\quad & =c^{C}\big(\gunderline{\forall A.\,u^{:A\rightarrow F^{A}}\times a^{:A}\rightarrow\text{unfold}^{A}(u\times a)}\big)=c^{C}(\text{unfold})\\ -\text{use Eq.~(\ref{eq:unfold-id-law-derivation1})}:\quad & =c\quad. -\end{align*} +\end_layout \end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $F$ +\end_inset + is strictly positive \end_layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-greatest-fixpoint-church-encoding" +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\size footnotesize +Example +\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-greatest-fixpoint-church-encoding" +reference "subsec:Example-simplify-quantifier-A-A" plural "false" caps "false" noprefix "false" \end_inset - +(a) \end_layout -\begin_layout Standard -The functions -\begin_inset listings -inline true -status open +\end_inset + + + + +\begin_inset Text \begin_layout Plain Layout -fix +\size footnotesize +\begin_inset Formula $\forall A.\,H^{A\rightarrow A}\cong H^{\bbnum 1}$ +\end_inset + + \end_layout \end_inset - - and -\begin_inset listings -inline true -status open + + +\begin_inset Text \begin_layout Plain Layout -unfix -\end_layout - +\size footnotesize +\begin_inset Formula $H$ \end_inset - are inverses to each other. + is a contrafunctor \end_layout -\begin_layout Subparagraph -Proof -\end_layout +\end_inset + + +\begin_inset Text -\begin_layout Standard -Translate the existential quantifier via Eq. +\begin_layout Plain Layout + +\size footnotesize +Example \begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:existential-via-universal-Yoneda" +reference "subsec:Example-simplify-quantifier-A-A" plural "false" caps "false" noprefix "false" \end_inset -) and write -\begin_inset Formula $C$ -\end_inset - - as: -\begin_inset Formula -\[ -C\triangleq\forall R.\,(\forall A.\,(A\rightarrow F^{A})\times A\rightarrow R)\rightarrow R\quad. -\] +(b) +\end_layout \end_inset + + + + +\begin_inset Text -We need to verify that: -\end_layout - -\begin_layout Standard +\begin_layout Plain Layout -\series bold -(1) -\series default - For any -\begin_inset Formula $c:C$ +\size footnotesize +\begin_inset Formula $\forall A.\,((A\rightarrow P)\rightarrow A\rightarrow A\cong P$ \end_inset - we have -\begin_inset Formula $\text{fix}\,(\text{unfix}\,(c))=c$ -\end_inset -. \end_layout -\begin_layout Standard - -\series bold -(2) -\series default - For any -\begin_inset Formula $q:F^{C}$ \end_inset + + +\begin_inset Text - we have -\begin_inset Formula $\text{unfix}\,(\text{fix}\,(q))=q$ +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $P$ \end_inset -. + is a fixed type \end_layout -\begin_layout Standard -To prove item -\series bold -(1) -\series default -: -\begin_inset Formula -\begin{align*} -\text{expect to equal }c:\quad & \gunderline{\text{fix}}\,(\text{unfix}\,(c))\\ -\text{definition of }\text{fix}:\quad & =\text{unfold}^{F^{C}}(\text{unfix}^{\uparrow F}\times\text{unfix}\,(c))\\ -\text{naturality law of }\text{unfold}:\quad & =\text{unfold}^{C}(\text{unfix}\times c)\\ -\text{identity law of }\text{unfold}:\quad & =c\quad. -\end{align*} - \end_inset + + +\begin_inset Text -Here we applied the naturality law +\begin_layout Plain Layout + +\size footnotesize +Exercise \begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:relational-naturality-law-of-unfold" +reference "par:Problem-Peirce-law" plural "false" caps "false" noprefix "false" \end_inset -) with -\begin_inset Formula $A=C$ -\end_inset -, -\begin_inset Formula $B=F^{C}$ -\end_inset +\end_layout -, -\begin_inset Formula $a=c$ \end_inset + + + -, -\begin_inset Formula $f=\text{unfix}$ \end_inset -, -\begin_inset Formula $u=\text{unfix}$ -\end_inset -, and -\begin_inset Formula $v=\text{unfix}^{\uparrow F}$ -\end_inset +\end_layout -. - To verify the precondition of that law, write: -\begin_inset Formula -\[ -u\bef f^{\uparrow F}\overset{?}{=}f\bef v\quad,\quad\text{or equivalently:}\quad\text{unfix}\bef\text{unfix}^{\uparrow F}\overset{?}{=}\text{unfix}\bef\text{unfix}^{\uparrow F}\quad. -\] +\begin_layout Plain Layout +\begin_inset Caption Standard + +\begin_layout Plain Layout +Type identities proved by other parametricity techniques. +\begin_inset CommandInset label +LatexCommand label +name "tab:Type-identities-proved-by-parametricity" \end_inset -This holds trivially. -\end_layout -\begin_layout Standard -To prove item -\series bold -(2) -\series default -, write: -\begin_inset Formula -\begin{align*} -\text{expect to equal }q:\quad & \text{unfix}\,(\gunderline{\text{fix}\,(q)})\\ -\text{definition of }\text{fix}:\quad & =\gunderline{\text{unfix}}\,\big(\text{unfold}^{F^{C}}(\text{unfix}^{\uparrow F}\times q)\big)\\ -\text{definition of }\text{unfold}:\quad & =\text{unfix}\,\big(\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times A\rightarrow R}\rightarrow p^{F^{C}}(\text{unfix}^{\uparrow F}\times q)\big)\\ -\text{definition of }\text{unfix}:\quad & =\big(\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times A\rightarrow R}\rightarrow p^{F^{C}}(\text{unfix}^{\uparrow F}\times q)\big)^{F^{C}}(\text{unfoldF})\\ -\text{apply function}:\quad & =\text{unfoldF}^{F^{C}}(\text{unfix}^{\uparrow F}\times q)\\ -\text{definition of }\text{unfoldF}:\quad & =q\triangleright\gunderline{\text{unfix}^{\uparrow F}\bef\big(a^{:F^{C}}\rightarrow\text{unfold}\,(\text{unfix}^{\uparrow F}\times a)\big)^{\uparrow F}}\\ -\text{composition under }^{\uparrow F}:\quad & =q\triangleright\big(x^{:C}\rightarrow\gunderline{\text{unfold}\,(\text{unfix}^{\uparrow F}\times\text{unfix}\,(x))}\big)^{\uparrow F}\\ -\text{definition of }\text{fix}:\quad & =q\triangleright\big(x^{:C}\rightarrow\gunderline{\text{fix}\,(\text{unfix}\,(x))}\big)^{\uparrow F}\\ -\text{item \textbf{(1)}}:\quad & =q\triangleright\gunderline{(x^{:C}\rightarrow x)^{\uparrow F}}=x\triangleright\text{id}=q\quad. -\end{align*} +\end_layout \end_inset -\begin_inset Formula $\square$ +\end_layout + \end_inset \end_layout \begin_layout Standard -It follows that -\begin_inset Formula $C$ -\end_inset - - is a fixpoint of the type equation -\begin_inset Formula $C\cong F^{C}$ -\end_inset +\begin_inset Float table +placement h +wide false +sideways false +status open + +\begin_layout Plain Layout +\align center +\begin_inset Tabular + + + + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size footnotesize +Identity +\end_layout -. - To show that -\begin_inset Formula $C$ \end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size footnotesize +Assumptions +\end_layout - is indeed the -\emph on -greatest -\emph default - fixpoint, we need to prove that for any other fixpoint -\begin_inset Formula $T$ \end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\series bold +\size footnotesize +Source +\end_layout - there exists a unique fixpoint-preserving morphism -\begin_inset Formula $\psi^{T}:T\rightarrow C$ \end_inset + + + + +\begin_inset Text -. - Similarly to what we saw in Statement -\begin_inset space ~ +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\exists C.\,F^{C}\cong\forall D.\,\big(\forall C.\,(F^{C}\rightarrow D)\big)\rightarrow D$ \end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-fixpoint-preserving-fix" -plural "false" -caps "false" -noprefix "false" +\end_layout \end_inset + + +\begin_inset Text -, it is sufficient to check that -\begin_inset Formula $\psi^{T}$ -\end_inset +\begin_layout Plain Layout - is an +\size footnotesize +For any \begin_inset Formula $F$ \end_inset --coalgebra morphism. -\end_layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-greatest-fixpoint-Church-encoding-morphism" +\end_layout \end_inset + + +\begin_inset Text +\begin_layout Plain Layout + +\size footnotesize +Equation +\begin_inset space ~ +\end_inset +( \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-greatest-fixpoint-Church-encoding-morphism" +reference "eq:existential-via-universal-Yoneda" plural "false" caps "false" noprefix "false" \end_inset - +) \end_layout -\begin_layout Standard -For any -\begin_inset Formula $F$ \end_inset + + + + +\begin_inset Text --coalgebra -\begin_inset Formula $A$ -\end_inset +\begin_layout Plain Layout - with a structure map -\begin_inset Formula $u:A\rightarrow F^{A}$ +\size footnotesize +\begin_inset Formula $(\exists C.\,F^{C})\rightarrow R\cong\forall C.\,(F^{C}\rightarrow R)$ \end_inset -, there exists a unique -\begin_inset Formula $F$ -\end_inset --algebra morphism -\begin_inset Formula $\psi_{u}^{A}$ -\end_inset +\end_layout - of type -\begin_inset Formula $A\rightarrow C$ \end_inset + + +\begin_inset Text -. - The function -\begin_inset Formula $\psi_{u}^{A}$ +\begin_layout Plain Layout + +\size footnotesize +For any +\begin_inset Formula $F$ \end_inset - is known as an -\series bold -anamorphism -\series default +, +\begin_inset Formula $R$ +\end_inset -\begin_inset Index idx -status open -\begin_layout Plain Layout -anamorphism \end_layout \end_inset + + +\begin_inset Text - and was defined as in Statement +\begin_layout Plain Layout + +\size footnotesize +Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-coalgebra-morphism-unfold" +reference "subsec:Statement-function-extension-rule" plural "false" caps "false" noprefix "false" \end_inset -: -\begin_inset Formula -\[ -\psi_{u}^{A}:A\rightarrow C\quad,\quad\quad\psi_{u}^{A}\triangleq a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\quad. -\] + +\end_layout \end_inset + + + + +\begin_inset Text +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\exists A.\,A\cong\bbnum 1$ +\end_inset -\end_layout -\begin_layout Subparagraph -Proof \end_layout -\begin_layout Standard -We know from Statement -\begin_inset space ~ \end_inset + + +\begin_inset Text +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-coalgebra-morphism-unfold" -plural "false" -caps "false" -noprefix "false" +\end_layout \end_inset + + +\begin_inset Text - that -\begin_inset Formula $\psi_{u}^{A}$ -\end_inset +\begin_layout Plain Layout - satisfies the law of -\begin_inset Formula $F$ -\end_inset +\end_layout --coalgebra morphisms. - Let -\begin_inset Formula $f:A\rightarrow C$ \end_inset + + + + +\begin_inset Text - be any other -\begin_inset Formula $F$ -\end_inset +\begin_layout Plain Layout --coalgebra morphism; we need to prove that -\begin_inset Formula $f=\psi_{u}^{A}$ +\size footnotesize +\begin_inset Formula $\exists A.\,F^{A}\cong F^{\bbnum 1}$ \end_inset -. + \end_layout -\begin_layout Standard -We know that -\begin_inset Formula $f$ \end_inset + + +\begin_inset Text - satisfies the +\begin_layout Plain Layout + +\size footnotesize \begin_inset Formula $F$ \end_inset --coalgebra morphism law: -\begin_inset Formula -\[ -u\bef f^{\uparrow F}=f\bef\text{unfix}\quad. -\] + is any functor +\end_layout \end_inset + + +\begin_inset Text -This is the precondition of the relational naturality law +\begin_layout Plain Layout + +\size footnotesize +Statement \begin_inset space ~ \end_inset -( + \begin_inset CommandInset ref LatexCommand ref -reference "eq:relational-naturality-law-of-unfold" +reference "subsec:Statement-co-Yoneda-two-identities-1" plural "false" caps "false" noprefix "false" \end_inset -) of -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout +(a) +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $\exists A.\,H^{A}\cong H^{\bbnum 0}$ +\end_inset + -unfold \end_layout \end_inset + + +\begin_inset Text - if we set -\begin_inset Formula $B=C$ +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $H$ \end_inset - and -\begin_inset Formula $v=\text{unfix}$ + is any contrafunctor +\end_layout + \end_inset + + +\begin_inset Text -. - So, the conclusion of that law holds. - We use that equation as well as Statement +\begin_layout Plain Layout + +\size footnotesize +Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-identity-law-of-unfold" +reference "subsec:Statement-co-Yoneda-two-identities-1" plural "false" caps "false" noprefix "false" \end_inset - and get: -\begin_inset Formula -\begin{align*} -\text{for any }a^{:A}:\quad & \psi_{u}^{A}(a)=\text{unfold}^{A}(u^{:A\rightarrow F^{A}}\times a^{:A})\\ -\text{naturality law of }\text{unfold}:\quad & =\text{unfold}^{C}(\text{unfix}\times f(a))\\ -\text{identity law of }\text{unfold}:\quad & =f(a)\quad. -\end{align*} +(b) +\end_layout \end_inset + + + + +\begin_inset Text -It follows that -\begin_inset Formula $\psi_{u}^{A}=f$ -\end_inset +\begin_layout Plain Layout -. - -\begin_inset Formula $\square$ +\size footnotesize +\begin_inset Formula $\exists A.\,F^{A}\rightarrow A\cong\bbnum 1$ \end_inset \end_layout -\begin_layout Standard -We conclude this Appendix with the proof of a type identity dual to the - Church-Yoneda identity -\begin_inset Index idx -status open +\end_inset + + +\begin_inset Text \begin_layout Plain Layout -Church-co-Yoneda identity + +\size footnotesize +For any +\begin_inset Formula $F$ +\end_inset + + \end_layout \end_inset + + +\begin_inset Text - shown in Statement +\begin_layout Plain Layout + +\size footnotesize +Example \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-Church-Yoneda-identity" +reference "subsec:Example-simple-existential-derivation" plural "false" caps "false" noprefix "false" \end_inset -. - That identity has no accepted name, and this book calls it the -\begin_inset Quotes eld -\end_inset - -Church-co-Yoneda -\begin_inset Quotes erd -\end_inset - identity. \end_layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-Church-co-Yoneda" - \end_inset + + + + +\begin_inset Text +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-Church-co-Yoneda" -plural "false" -caps "false" -noprefix "false" - +\size footnotesize +\begin_inset Formula $\exists A.\,(F^{A}+G^{A})\cong(\exists A.\,F^{A})+(\exists A.\,G^{A})$ \end_inset \end_layout -\begin_layout Standard -For any covariant functors -\begin_inset Formula $F$ -\end_inset - - and -\begin_inset Formula $G$ \end_inset + + +\begin_inset Text -: -\begin_inset Formula -\[ -G^{\nu X.\,F^{X}}\cong\exists A.\,(A\rightarrow F^{A})\times G^{A}\quad. -\] +\begin_layout Plain Layout +\size footnotesize +For any +\begin_inset Formula $F$ \end_inset +, +\begin_inset Formula $G$ +\end_inset -\end_layout -\begin_layout Subparagraph -Proof \end_layout -\begin_layout Standard -Denote for brevity -\begin_inset Formula $C\triangleq\nu X.\,F^{X}$ \end_inset + + +\begin_inset Text -. - The existential type is rewritten as: -\begin_inset Formula -\[ -\exists A.\,(A\rightarrow F^{A})\times G^{A}=\forall R.\,(\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R)\rightarrow R\quad. -\] +\begin_layout Plain Layout +\size footnotesize +Example +\begin_inset space ~ \end_inset -We will demonstrate the isomorphism if we define functions -\begin_inset listings -inline true -status open -\begin_layout Plain Layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-simple-existential-derivation-1-1" +plural "false" +caps "false" +noprefix "false" -toG +\end_inset + +(b) \end_layout \end_inset - - and -\begin_inset listings -inline true -status open + + + + +\begin_inset Text \begin_layout Plain Layout -fromG +\size footnotesize +\begin_inset Formula $\exists A.\,\exists B.\,F^{A,B}\cong\exists B.\,\exists A.\,F^{A,B}$ +\end_inset + + \end_layout \end_inset + + +\begin_inset Text - that are mutual inverses, with type signatures: -\begin_inset Formula -\[ -\text{toG}:(\exists A.\,(A\rightarrow F^{A})\times G^{A})\rightarrow G^{C}\quad,\quad\quad\text{fromG}:G^{C}\rightarrow\exists A.\,(A\rightarrow F^{A})\times G^{A}\quad. -\] +\begin_layout Plain Layout +\size footnotesize +For any +\begin_inset Formula $F$ \end_inset -The first type signature can be implemented as: -\begin_inset Formula -\begin{align*} - & \text{toG}:\big(\forall R.\,(\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R)\rightarrow R\big)\rightarrow G^{C}\quad,\\ - & \text{toG}\triangleq k^{:\forall R.\,(\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R)\rightarrow R}\rightarrow k^{G^{C}}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow g\triangleright(\psi_{u}^{A})^{\uparrow F}\big)\quad, -\end{align*} -\end_inset +\end_layout -where -\begin_inset Formula $\psi_{u}^{A}$ \end_inset + + +\begin_inset Text - is the anamorphism of type -\begin_inset Formula $A\rightarrow C$ -\end_inset +\begin_layout Plain Layout - defined in Statement +\size footnotesize +Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-coalgebra-morphism-unfold" +reference "subsec:Statement-commute-existential" plural "false" caps "false" noprefix "false" \end_inset -. -\end_layout - -\begin_layout Standard -The function -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout -fromG \end_layout \end_inset + + + + +\begin_inset Text - is implemented as: -\begin_inset Formula -\begin{align*} - & \text{fromG}:G^{C}\rightarrow\forall R.\,(\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R)\rightarrow R\quad,\\ - & \text{fromG}\triangleq g^{:G^{C}}\rightarrow\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R}\rightarrow p^{C}(\text{unfix}\times g)\quad. -\end{align*} +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $\nu A.\,F^{A}\cong\exists A.\,(A\rightarrow F^{A})\times A$ \end_inset \end_layout -\begin_layout Standard -It remains to prove the two directions of the isomorphism roundtrip: -\end_layout - -\begin_layout Standard - -\series bold -(1) -\series default - For any -\begin_inset Formula $g:G^{C}$ -\end_inset - - we have: -\begin_inset Formula $\text{toG}\,(\text{fromG}\,(g))=g$ \end_inset + + +\begin_inset Text -. -\end_layout - -\begin_layout Standard - -\series bold -(2) -\series default - For any -\begin_inset Formula $k:\exists A.\,(A\rightarrow F^{A})\times G^{A}$ -\end_inset +\begin_layout Plain Layout - we have: -\begin_inset Formula $\text{fromG}\,(\text{toG}\,(k))=k$ +\size footnotesize +\begin_inset Formula $F$ \end_inset -. + is any functor \end_layout -\begin_layout Standard -To prove item -\series bold -(1) -\series default -: -\begin_inset Formula -\begin{align*} - & \text{toG}\,(\gunderline{\text{fromG}}\,(g))=\gunderline{\text{toG}}\,\big(\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R}\rightarrow p^{C}(\text{unfix}\times g)\big)\\ - & =\big(\forall A.\,u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow g\triangleright(\psi_{u}^{A})^{\uparrow F}\big)^{C}(\text{unfix}\times g)\\ - & =g\triangleright(\psi_{\text{unfix}}^{C})^{\uparrow F}\quad. -\end{align*} - -\end_inset - -We note that -\begin_inset Formula $\psi_{\text{unfix}}^{C}$ -\end_inset - - is the identity function ( -\begin_inset Formula $\text{id}^{:C\rightarrow C}$ -\end_inset - -) because it is the unique -\begin_inset Formula $F$ \end_inset + + +\begin_inset Text --coalgebra morphism of type -\begin_inset Formula $C\rightarrow C$ -\end_inset +\begin_layout Plain Layout - by Statement +\size footnotesize +Section \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-greatest-fixpoint-Church-encoding-morphism" +reference "subsec:The-greatest-fixpoints-and-Church-co-Yoneda" plural "false" caps "false" noprefix "false" \end_inset -. - It follows that: -\begin_inset Formula -\[ -\text{toG}\,(\text{fromG}\,(g))=g\triangleright(\psi_{\text{unfix}}^{C})^{\uparrow F}=g\triangleright\text{id}^{\uparrow F}=g\quad. -\] - -\end_inset - \end_layout -\begin_layout Standard -To prove item -\series bold -(2) -\series default -, apply both sides to a type -\begin_inset Formula $R$ -\end_inset - - and a value -\begin_inset Formula $p^{:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R}$ \end_inset + + + + +\begin_inset Text -: -\begin_inset Formula -\begin{align*} -\text{expect to equal }k^{R}(p):\quad & \big(\text{fromG}\,(\text{toG}\,(k))\big)^{R}(p)=p^{C}(\text{unfix}\times\text{toG}\,(k))\\ - & =p^{C}\big(\text{unfix}\times k^{G^{C}}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow g\triangleright(\psi_{u}^{A})^{\uparrow F}\big)\big)\quad. -\end{align*} - -\end_inset +\begin_layout Plain Layout -To proceed, we need to use the naturality law of -\begin_inset Formula $k$ +\size footnotesize +\begin_inset Formula $G^{\nu A.\,F^{A}}\cong\exists A.\,(A\rightarrow F^{A})\times G^{A}$ \end_inset -: -\begin_inset Formula -\[ -\text{for all }Q,R,f^{:Q\rightarrow R},q^{:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow Q}:\quad k^{R}(\forall A.\:q^{A}\bef f)=f(k^{Q}(q))\quad. -\] - -\end_inset -Setting the following parameters in this law: -\begin_inset Formula -\[ -Q=G^{C}\quad,\quad\quad f=t^{:G^{C}}\rightarrow p^{C}(\text{unfix}\times t)\quad,\quad q=\forall A.\,u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow g\triangleright(\psi_{u}^{A})^{\uparrow F}\quad, -\] +\end_layout \end_inset + + +\begin_inset Text -we obtain: -\begin_inset Formula -\begin{align*} - & k^{R}(\forall A.\:u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow p^{C}(\text{unfix}\times g\triangleright(\psi_{u}^{A})^{\uparrow F}))\\ - & =p^{C}\big(\text{unfix}\times k^{G^{C}}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow g\triangleright(\psi_{u}^{A})^{\uparrow F}\big)\big)\quad. -\end{align*} +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $F$ \end_inset -We expect the left-hand side to equal -\begin_inset Formula $k^{R}(p)$ +, +\begin_inset Formula $G$ \end_inset -, so the remaining difference is: -\begin_inset Formula -\begin{align*} - & p\overset{?}{=}\forall A.\:u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow p^{C}(\text{unfix}\times g\triangleright(\psi_{u}^{A})^{\uparrow F})\quad,\\ -\text{or equivalently}:\quad & p^{A}(u^{:A\rightarrow F^{A}}\times g^{:G^{A}})\overset{?}{=}p^{C}(\text{unfix}\times g\triangleright(\psi_{u}^{A})^{\uparrow F})\quad. -\end{align*} + are any functors +\end_layout \end_inset + + +\begin_inset Text -This should hold for all types -\begin_inset Formula $A$ -\end_inset +\begin_layout Plain Layout - and for all -\begin_inset Formula $g^{:G^{A}}$ +\size footnotesize +Statement +\begin_inset space ~ \end_inset -, -\begin_inset Formula $u^{:A\rightarrow F^{A}}$ -\end_inset -, -\begin_inset Formula $p:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R$ -\end_inset +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-Church-co-Yoneda" +plural "false" +caps "false" +noprefix "false" -. - We may assume that all such -\begin_inset Formula $p$ \end_inset - obey their relational naturality law: -\begin_inset Formula -\[ -\forall A,B,f^{:A\rightarrow B}:\quad\text{if}\quad u^{:A\rightarrow F^{A}}\bef f^{\uparrow F}=f\bef v^{:B\rightarrow F^{B}}\quad\text{then}\quad p^{A}(u\times a)=p^{B}(v\times a\triangleright f^{\uparrow F})\quad. -\] - -\end_inset -We set the following parameters in this law, -\begin_inset Formula -\[ -B=C\quad,\quad a=g\quad,\quad f=\psi_{u}^{A}\quad,\quad v=\text{unfix}\quad, -\] +\end_layout \end_inset + + + + +\begin_inset Text -and obtain: -\begin_inset Formula -\[ -p^{A}(u\times g)=p^{C}(\text{unfix}\times g\triangleright(\psi_{u}^{A})^{\uparrow F})\quad. -\] +\begin_layout Plain Layout +\size footnotesize +\begin_inset Formula $\nu A.\,\nu B.\,F^{A,B}\cong\nu B.\,F^{B,B}$ \end_inset -This will complete the proof of item -\series bold -(2) -\series default - as long as the precondition holds: -\begin_inset Formula -\begin{align*} - & u^{:A\rightarrow F^{A}}\bef f^{\uparrow F}\overset{?}{=}f\bef v^{:B\rightarrow F^{B}}\quad,\\ -\text{or equivalently}:\quad & u\bef(\psi_{u}^{A})^{\uparrow F}\overset{?}{=}\psi_{u}^{A}\bef\text{unfix}\quad. -\end{align*} -\end_inset +\end_layout -This holds by Statement -\begin_inset space ~ \end_inset + + +\begin_inset Text +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-coalgebra-morphism-unfold" -plural "false" -caps "false" -noprefix "false" - -\end_inset - -: it is the +\size footnotesize \begin_inset Formula $F$ \end_inset --coalgebra morphism law of -\begin_inset Formula $\psi_{u}^{A}$ -\end_inset + is any bifunctor +\end_layout -. - -\begin_inset Formula $\square$ \end_inset + + +\begin_inset Text +\begin_layout Plain Layout -\end_layout - -\begin_layout Standard -The Church-co-Yoneda identity can be used to prove the Church encoding formula - for simultaneous greatest fixpoints of several functors, similarly to what - we did in Section +\size footnotesize +Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Least-fixpoints-of-mutually-recursive-types" +reference "subsec:Statement-nested-greatest-fixpoints" plural "false" caps "false" noprefix "false" \end_inset -. - For simplicity, we will now show a proof for just two mutually recursive - types; the proof can be extended to any number of types. - -\end_layout -\begin_layout Standard -We will first prove a property of nested fixpoints. \end_layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-nested-greatest-fixpoints" +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Note Note +status collapsed + +\begin_layout Plain Layout + +\size footnotesize +See +\family typewriter +\size default + +\begin_inset CommandInset href +LatexCommand href +target "https://tex.stackexchange.com/questions/50332/vertical-spacing-of-a-table-cell" +literal "false" \end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-nested-greatest-fixpoints" -plural "false" -caps "false" -noprefix "false" +\end_layout \end_inset +\begin_inset Box Frameless +position "c" +hor_pos "c" +has_inner_box 1 +inner_pos "t" +use_parbox 0 +use_makebox 0 +width "0.1mm" +special "none" +height "12mm" +height_special "none" +thickness "0.4pt" +separation "3pt" +shadowsize "4pt" +framecolor "black" +backgroundcolor "none" +status collapsed + +\begin_layout Plain Layout + \end_layout -\begin_layout Standard -For any bifunctor -\begin_inset Formula $F$ \end_inset -, the following equivalence holds: -\begin_inset Formula -\[ -\nu A.\,(\nu B.\,F^{A,B})\cong\nu B.\,F^{B,B}\quad. -\] +\begin_inset Box Frameless +position "c" +hor_pos "c" +has_inner_box 1 +inner_pos "c" +use_parbox 0 +use_makebox 0 +width "43col%" +special "none" +height "1in" +height_special "totalheight" +thickness "0.4pt" +separation "3pt" +shadowsize "4pt" +framecolor "black" +backgroundcolor "none" +status collapsed + +\begin_layout Plain Layout +\align center + +\size footnotesize +\begin_inset Formula $\nu A.\,F^{A,\,\nu B.\,G^{A,B}}\cong$ +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Formula $\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times A$ \end_inset \end_layout -\begin_layout Subparagraph -Proof +\end_inset + + \end_layout -\begin_layout Standard -Denote -\begin_inset Formula $G^{A,C}\triangleq(A\rightarrow C)\times A$ \end_inset + + +\begin_inset Text - and write the Church encoding for the fixpoints: -\begin_inset Formula -\[ -\nu A.\,(\nu B.\,F^{A,B})=\exists A.\,(A\rightarrow\nu B.\,F^{A,B})\times A=\exists A.\,G^{A,\,\nu B.\,F^{A,B}}\quad. -\] +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $F$ +\end_inset +, +\begin_inset Formula $G$ \end_inset -View -\begin_inset Formula $A$ + are any bifunctors +\end_layout + \end_inset + + +\begin_inset Text - as fixed and use the Church-co-Yoneda identity (Statement +\begin_layout Plain Layout + +\size footnotesize +Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-Church-co-Yoneda" +reference "subsec:Statement-mutually-recursive-greatest-fixpoints" plural "false" caps "false" noprefix "false" \end_inset -): -\begin_inset Formula -\begin{align*} - & G^{A,\,\nu B.\,F^{A,B}}\cong\exists B.\,(B\rightarrow F^{A,B})\times\gunderline{G^{A,B}}\\ - & =\exists B.\,(B\rightarrow F^{A,B})\times(A\rightarrow B)\times A\\ - & =\exists B.\,(A\rightarrow B)\times H^{A,B}\quad, -\end{align*} + +\end_layout \end_inset + + + + +\begin_inset Text -where we defined -\begin_inset Formula $H$ +\begin_layout Plain Layout + +\size footnotesize +\begin_inset Formula $G^{\exists C.\,F^{C}}\cong\forall D.\,(\forall C.\,F^{C}\rightarrow D)\rightarrow G^{D}$ \end_inset - by: -\begin_inset Formula -\[ -H^{A,B}\triangleq(B\rightarrow F^{A,B})\times A\quad. -\] + +\end_layout \end_inset + + +\begin_inset Text -Now we can simplify the nested fixpoints: -\begin_inset Formula -\begin{align*} -\text{expect }\nu B.\,F^{B,B}:\quad & \nu A.\,(\nu B.\,F^{A,B})=\gunderline{\exists A.\,\exists B.}\,(A\rightarrow B)\times H^{A,B}\\ -\text{co-Fubini theorem (Statement~\ref{subsec:Statement-commute-existential})}:\quad & \cong\exists B.\,\exists A.\,(A\rightarrow B)\times H^{A,B}\\ -\text{co-Yoneda identity}:\quad & \cong\exists B.\,\gunderline{H^{B,B}}=\exists B.\,(B\rightarrow F^{B,B})\times B\\ -\text{Church encoding}:\quad & \cong\nu B.\,F^{B,B}\quad. -\end{align*} +\begin_layout Plain Layout + +\size footnotesize +Any +\begin_inset Formula $F$ +\end_inset +, any functor +\begin_inset Formula $G$ \end_inset \end_layout -\begin_layout Subsubsection -Statement -\begin_inset CommandInset label -LatexCommand label -name "subsec:Statement-mutually-recursive-greatest-fixpoints" +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +\size footnotesize +Exercise +\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-mutually-recursive-greatest-fixpoints" +reference "par:Exercise-additional-16-3" plural "false" caps "false" noprefix "false" @@ -52201,835 +51700,924 @@ noprefix "false" \end_layout -\begin_layout Standard -Given any bifunctors -\begin_inset Formula $F$ \end_inset + + + -, -\begin_inset Formula $G$ \end_inset -, define -\begin_inset Formula $T$ -\end_inset - and -\begin_inset Formula $U$ -\end_inset +\end_layout - as the simultaneous greatest fixpoints of two type equations: -\begin_inset Formula -\[ -T=F^{T,U}\quad,\quad\quad U=G^{T,U}\quad. -\] +\begin_layout Plain Layout +\begin_inset Caption Standard -\end_inset +\begin_layout Plain Layout +Type isomorphisms for existential types. +\begin_inset CommandInset label +LatexCommand label +name "tab:Type-identities-for-existential-types" -Then the types -\begin_inset Formula $T$ \end_inset - and -\begin_inset Formula $U$ + +\end_layout + \end_inset - can be expressed as: -\begin_inset Formula -\begin{align*} - & T\cong\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times A\quad,\\ - & U\cong\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times B\quad. -\end{align*} + +\end_layout \end_inset \end_layout -\begin_layout Subparagraph -Proof +\begin_layout Subsection +The Jaskelioff-O'Connor theorem for simple types \end_layout \begin_layout Standard -If -\begin_inset Formula $T$ -\end_inset +The Jaskelioff-O'Connor theorem +\begin_inset Foot +status open - and -\begin_inset Formula $U$ -\end_inset +\begin_layout Plain Layout +See +\family typewriter - are fixed (and equal to the correct greatest fixpoints) then we can write: -\begin_inset Formula -\[ -T=\nu A.\,F^{A,U}\quad,\quad\quad U=\nu B.\,G^{T,B}\quad. -\] +\begin_inset CommandInset href +LatexCommand href +target "https://arxiv.org/abs/1402.1699" +literal "false" \end_inset -Now we can substitute -\begin_inset Formula $U$ -\end_inset - into the equation for -\begin_inset Formula $T$ +\end_layout + \end_inset -: -\begin_inset Formula -\[ -T=\nu A.\,F^{A,\,\nu B.\,G^{T,B}}\quad. -\] + is a type equivalence between certain type constructors quantified over + a typeclass. + This section proves a version of that theorem that holds for simple types + belonging to a +\begin_inset Formula $P$ +\end_inset +-typeclass. + Then the theorem gives a general type formula for the free construction + of any +\begin_inset Formula $P$ \end_inset -The last line is a fixpoint equation involving only -\begin_inset Formula $T$ +-typeclass. +\end_layout + +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-JOC-theorem-simple-types" + \end_inset -, so we may express -\begin_inset Formula $T$ + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-JOC-theorem-simple-types" +plural "false" +caps "false" +noprefix "false" + \end_inset - as the greatest fixpoint of that equation. - Then we get: -\begin_inset Formula -\begin{align*} - & T=\nu C.\,\nu A.\,F^{A,\,\nu B.\,G^{C,B}}\\ -\text{use Statement~\ref{subsec:Statement-nested-greatest-fixpoints} and set }A=C:\quad & \cong\gunderline{\nu A.}\,F^{A,\,\nu B.\,G^{A,B}}\\ -\text{use Church encoding}:\quad & \cong\exists A.\:(A\rightarrow F^{A,\,\nu B.\,G^{A,B}})\times A\\ -\text{define }N^{A,C}\triangleq(A\rightarrow F^{A,C})\times A:\quad & =\exists A.\:N^{A,\,\nu B.\,G^{A,B}}\\ -\text{Church-co-Yoneda identity (Statement~\ref{subsec:Statement-Church-co-Yoneda})}:\quad & \cong\gunderline{\exists A.\,\exists B.}\,(B\rightarrow G^{A,B})\times N^{A,B}\quad. -\end{align*} +\end_layout + +\begin_layout Standard +The free +\begin_inset Formula $P$ \end_inset -Writing out the definition of -\begin_inset Formula $N^{A,B}$ +-typeclass instance +\begin_inset Formula $E^{T}$ \end_inset -, we obtain the claimed Church encoding for + generated by a type \begin_inset Formula $T$ \end_inset -: + is equivalent to the type defined by: \begin_inset Formula -\[ -T\cong\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times A\quad. -\] +\begin{equation} +E^{T}\cong\forall(A\in P\text{-typeclass}).\,(T\rightarrow A)\rightarrow A\quad.\label{eq:free-typeclass-via-church-encoding} +\end{equation} \end_inset - The formula for -\begin_inset Formula $U$ +Here the quantifier goes only over the types +\begin_inset Formula $A$ \end_inset - is derived similarly. - -\begin_inset Formula $\square$ + that belong to the +\begin_inset Formula $P$ \end_inset - -\end_layout - -\begin_layout Subsection -Summary of type isomorphisms -\end_layout - -\begin_layout Standard -This Appendix has developed various parametricity techniques to prove a - number of type isomorphisms. - The results are summarized in Tables +-typeclass. + It is also assumed that the type in the right-hand side of Eq. \begin_inset space ~ \end_inset - +( \begin_inset CommandInset ref LatexCommand ref -reference "tab:Type-identities-proved-by-Yoneda" +reference "eq:free-typeclass-via-church-encoding" plural "false" caps "false" noprefix "false" \end_inset -– -\begin_inset CommandInset ref -LatexCommand ref -reference "tab:Type-identities-for-existential-types" -plural "false" -caps "false" -noprefix "false" - +) admits only functions that satisfy the naturality law with respect to + +\begin_inset Formula $A$ \end_inset . \end_layout -\begin_layout Standard -\begin_inset Float table -placement h -wide false -sideways false -status open - -\begin_layout Plain Layout -\align center -\begin_inset Tabular - - - - - - -\begin_inset Text - -\begin_layout Plain Layout - -\series bold -\size footnotesize -Identity +\begin_layout Subparagraph +Proof \end_layout +\begin_layout Standard +One of the defining properties of the free typeclass constructor +\begin_inset Formula $E$ \end_inset - - -\begin_inset Text - -\begin_layout Plain Layout - -\series bold -\size footnotesize -Assumptions -\end_layout + is the one-to-one correspondence between functions of type +\begin_inset Formula $T\rightarrow A$ \end_inset - - - - -\begin_inset Text -\begin_layout Plain Layout + and +\begin_inset Formula $P$ +\end_inset -\size footnotesize -\begin_inset Formula $\forall A.\,A\rightarrow A\cong\bbnum 1$ +-typeclass morphisms of type +\begin_inset Formula $E^{T}\rightarrow A$ \end_inset +. + Denoting by +\begin_inset Formula $E^{T}\overset{P}{\rightarrow}A$ +\end_inset -\end_layout + the type of those morphisms, we have: +\begin_inset Formula +\[ +\forall(A\in P\text{-typeclass}).\,(T\rightarrow A)\rightarrow A\cong\forall(A\in P\text{-typeclass}).\,(E^{T}\overset{P}{\rightarrow}A)\rightarrow A\quad. +\] \end_inset - - -\begin_inset Text -\begin_layout Plain Layout \end_layout +\begin_layout Standard +All types +\begin_inset Formula $A$ \end_inset - - - - -\begin_inset Text -\begin_layout Plain Layout + belonging to the +\begin_inset Formula $P$ +\end_inset -\size footnotesize -\begin_inset Formula $\forall A.\,A\rightarrow F^{A}\cong F^{\bbnum 1}$ +-typeclass are +\begin_inset Formula $E$ \end_inset +-monad algebras, and those algebras form a category. + Now we use the Yoneda identity in that category: +\begin_inset Formula +\[ +\forall(A\in P\text{-typeclass}).\,(X\overset{P}{\rightarrow}A)\rightarrow A\cong X\quad, +\] -\end_layout +\end_inset +where +\begin_inset Formula $X$ \end_inset - - -\begin_inset Text -\begin_layout Plain Layout + is any fixed type that also belongs to the +\begin_inset Formula $P$ +\end_inset -\size footnotesize -\begin_inset Formula $F$ +-typeclass. + We use this identity with +\begin_inset Formula $X=E^{T}$ \end_inset - is any functor -\end_layout + and obtain: +\begin_inset Formula +\[ +\forall(A\in P\text{-typeclass}).\,(E^{T}\overset{P}{\rightarrow}A)\rightarrow A\cong E^{T}\quad, +\] \end_inset - - - - -\begin_inset Text -\begin_layout Plain Layout - -\size footnotesize -\begin_inset Formula $\forall A.\,A\times A\rightarrow F^{A}\cong F^{\bbnum 2}$ +as required. + +\begin_inset Formula $\square$ \end_inset \end_layout -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout +\begin_layout Subsection +The Jaskelioff-O'Connor theorem for type constructors +\end_layout -\size footnotesize -\begin_inset Formula $F$ +\begin_layout Standard +The full formulation of the theorem involves functor typeclasses instead + of typeclasses for simple types. + The theorem applies to all +\begin_inset Formula $P$ \end_inset - is any functor -\end_layout +-typeclasses for functors. + Those typeclasses have method signatures of the form +\begin_inset Formula $\forall A.\,(P^{F})^{A}\rightarrow F^{A}$ +\end_inset +, where +\begin_inset Formula $P$ \end_inset - - - - -\begin_inset Text -\begin_layout Plain Layout + is a functor on functors (the kind of +\begin_inset Formula $P$ +\end_inset -\size footnotesize -\begin_inset Formula $\forall A.\,A\cong\bbnum 0$ + is +\begin_inset Formula $(*\rightarrow*)\rightarrow*\rightarrow*$ \end_inset +) and functions of type +\begin_inset Formula $(P^{F})^{A}\rightarrow F^{A}$ +\end_inset -\end_layout + are restricted to natural transformations between functors +\begin_inset Formula $P^{F}$ +\end_inset + and +\begin_inset Formula $F$ \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +. + Examples of well-known +\begin_inset Formula $P$ +\end_inset +-typeclasses of that form are pointed functors, filterable functors, applicative + functors, and monads. \end_layout +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-Jaskelioff-OConnor" + \end_inset - - - - -\begin_inset Text -\begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\forall A.\,F^{A}\cong F^{\bbnum 0}$ -\end_inset +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-Jaskelioff-OConnor" +plural "false" +caps "false" +noprefix "false" +\end_inset + (Jaskelioff-O'Connor) \end_layout +\begin_layout Standard +Given any fixed +\begin_inset Formula $P$ \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +-typeclass for functors, denote by +\begin_inset Formula $E$ +\end_inset -\size footnotesize -\begin_inset Formula $F$ + the constructor of free instances of that typeclass: if +\begin_inset Formula $T$ \end_inset - is any functor -\end_layout + is any functor then the functor +\begin_inset Formula $E^{T}$ +\end_inset + is guaranteed to be an instance of the +\begin_inset Formula $P$ \end_inset - - - - -\begin_inset Text -\begin_layout Plain Layout +-typeclass. + Suppose +\begin_inset Formula $A$ +\end_inset -\size footnotesize -\begin_inset Formula $\forall A.\,H^{A}\cong H^{\bbnum 1}$ +, +\begin_inset Formula $B$ \end_inset +, +\begin_inset Formula $C$ +\end_inset -\end_layout + are some fixed types. + Then the following type equivalence holds: +\begin_inset Formula +\begin{align} + & \forall(F\in P\text{-typeclass}).\,(A\rightarrow F^{B})\rightarrow F^{C}\cong(E^{R})^{C}\quad,\label{eq:jaskelioff-o-connor-theorem}\\ +\text{where }R\text{ is defined by}:\quad & R^{T}\triangleq A\times(B\rightarrow T)\quad.\nonumber +\end{align} \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +Here, it is assumed that the type +\begin_inset Formula $(A\rightarrow F^{B})\rightarrow F^{C}$ +\end_inset -\size footnotesize -\begin_inset Formula $H$ + is restricted to functions satisfying the naturality law with respect to + +\begin_inset Formula $F$ \end_inset - is any contrafunctor +. \end_layout -\end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout +\begin_layout Subparagraph +Proof +\end_layout -\size footnotesize -\begin_inset Formula $\forall A.\,(A\rightarrow P)\rightarrow A\rightarrow Q\cong P\rightarrow Q$ +\begin_layout Standard +Denote by +\begin_inset Formula $K\overset{P}{\rightarrow}L$ \end_inset + the type of +\begin_inset Formula $P$ +\end_inset -\end_layout - +-typeclass morphisms between functors +\begin_inset Formula $K$ \end_inset - - -\begin_inset Text -\begin_layout Plain Layout + and +\begin_inset Formula $L$ +\end_inset -\size footnotesize + that belong to the typeclass. + (The full type signature of a \begin_inset Formula $P$ \end_inset -, -\begin_inset Formula $Q$ +-typeclass morphism is +\begin_inset Formula $\forall A.\,K^{A}\overset{P}{\rightarrow}L^{A}$ \end_inset - are fixed types +.) \end_layout +\begin_layout Standard +We will prove the type equivalence +\begin_inset space ~ \end_inset - - - - -\begin_inset Text -\begin_layout Plain Layout +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:jaskelioff-o-connor-theorem" +plural "false" +caps "false" +noprefix "false" -\size footnotesize -\begin_inset Formula $\forall A.\,(P\rightarrow A)\rightarrow Q\rightarrow A\cong Q\rightarrow P$ \end_inset - +) in three steps. \end_layout +\begin_layout Standard + +\series bold +(1) +\series default + Use the Yoneda identity to obtain this type equivalence: +\begin_inset Formula +\[ +A\rightarrow F^{B}\cong\forall X.\,R^{X}\rightarrow F^{X}\quad. +\] + \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +To derive this formula, write: +\begin_inset Formula +\begin{align*} + & A\rightarrow F^{B}\\ +\text{covariant Yoneda identity}:\quad & \cong A\rightarrow\forall X.\,(B\rightarrow X)\rightarrow F^{X}\\ +\text{move }\forall X\text{ to front}:\quad & \cong\forall X.\,A\rightarrow(B\rightarrow X)\rightarrow F^{X}\\ +\text{uncurry the function}:\quad & \cong\forall X.\,A\times(B\rightarrow X)\rightarrow F^{X}=\forall X.\,R^{X}\rightarrow F^{X}\quad. +\end{align*} -\size footnotesize -\begin_inset Formula $P$ \end_inset -, -\begin_inset Formula $Q$ +In the first line of this derivation, we have used the assumption that +\begin_inset Formula $F$ \end_inset - are fixed types + is a (covariant) functor. \end_layout -\end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout +\begin_layout Standard -\size footnotesize -\begin_inset Formula $\forall A.\,((A\rightarrow P)\rightarrow Q)\rightarrow(A\rightarrow S)\rightarrow R\cong((S\rightarrow P)\rightarrow Q)\rightarrow R$ +\series bold +(2) +\series default + By the universal property of the free +\begin_inset Formula $P$ \end_inset +-typeclass runner, for any functor +\begin_inset Formula $F$ +\end_inset -\end_layout - + that belongs to the +\begin_inset Formula $P$ \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +-typeclass and for any functor +\begin_inset Formula $R$ +\end_inset -\size footnotesize + (not necessarily a member of the \begin_inset Formula $P$ \end_inset -, -\begin_inset Formula $Q$ +-typeclass) there is a one-to-one correspondence between +\begin_inset Formula $P$ \end_inset -, -\begin_inset Formula $R$ +-typeclass morphisms +\begin_inset Formula $E^{R}\overset{P}{\rightarrow}F$ \end_inset -, -\begin_inset Formula $S$ + and natural transformations +\begin_inset Formula $R\leadsto F$ \end_inset - are fixed types -\end_layout +. + In other words, there is a type equivalence between the following types + (where we wrote out the full type signatures): +\begin_inset Formula +\[ +\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X}\cong\forall X.\,R^{X}\rightarrow F^{X}\quad. +\] \end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\forall A.\,(P\rightarrow A\times Q)\rightarrow(A+R)\times S\cong$ +Now we set +\begin_inset Formula $R^{T}\triangleq A\times(B\rightarrow T)$ \end_inset + and obtain: +\begin_inset Formula +\[ +(A\rightarrow F^{B})\rightarrow F^{C}\cong(\forall X.\,R^{X}\rightarrow F^{X})\rightarrow F^{C}\cong(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\quad. +\] -\begin_inset Formula $(P\rightarrow Q)\rightarrow(P+R)\times S$ \end_inset - -\end_layout - +So, the left-hand side of Eq. +\begin_inset space ~ \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:jaskelioff-o-connor-theorem" +plural "false" +caps "false" +noprefix "false" -\size footnotesize -\begin_inset Formula $P$ \end_inset -, -\begin_inset Formula $Q$ -\end_inset +) is equivalent to: +\begin_inset Formula +\[ +\forall(F\in P\text{-typeclass}).\,(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\quad. +\] -, -\begin_inset Formula $R$ \end_inset -, -\begin_inset Formula $S$ -\end_inset - are fixed types \end_layout +\begin_layout Standard + +\series bold +(3) +\series default + We use the covariant Yoneda identity in the category of functors that belong + to the +\begin_inset Formula $P$ \end_inset - - - +-typeclass. + As we have found in Section +\begin_inset space ~ \end_inset -\end_layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Imposing-laws-of-P-typeclasses-via-monad-algebras" +plural "false" +caps "false" +noprefix "false" -\begin_layout Plain Layout -\begin_inset Caption Standard +\end_inset -\begin_layout Plain Layout -Type isomorphisms proved via Yoneda identities. -\begin_inset CommandInset label -LatexCommand label -name "tab:Type-identities-proved-by-Yoneda" +, all those functors are +\begin_inset Formula $E$ +\end_inset +-monad algebras, which form a category. + The +\begin_inset Formula $P$ \end_inset +-typeclass morphisms are in one-to-one correspondence with the +\begin_inset Formula $E$ +\end_inset -\end_layout +-monad algebra morphisms. + Therefore, we may write the covariant Yoneda identity for that category + as: +\begin_inset Formula +\[ +\forall(F\in P\text{-typeclass}).\,(\forall X.\,Q^{X}\overset{P}{\rightarrow}F^{X})\rightarrow S^{F}\cong S^{Q}\quad, +\] \end_inset +where +\begin_inset Formula $Q$ +\end_inset -\end_layout + is any fixed functor from the +\begin_inset Formula $P$ +\end_inset +-typeclass, +\begin_inset Formula $S^{F}$ \end_inset + is any type expression that is covariant in +\begin_inset Formula $F$ +\end_inset -\end_layout +, and the naturality law with respect to +\begin_inset Formula $F$ +\end_inset -\begin_layout Standard -\begin_inset Float table -wide false -sideways false -status open + is assumed to hold. + We will use this Yoneda identity with +\begin_inset Formula $Q=E^{R}$ +\end_inset -\begin_layout Plain Layout -\align center -\begin_inset Tabular - - - - - - - -\begin_inset Text +, and set +\begin_inset Formula $S^{F}$ +\end_inset -\begin_layout Plain Layout + to just +\begin_inset Formula $F^{C}$ +\end_inset -\series bold -\size footnotesize -Identity -\end_layout + (the application of +\begin_inset Formula $F$ +\end_inset + to the fixed type +\begin_inset Formula $C$ \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +). + Then we get: +\begin_inset Formula +\[ +\forall(F\in P\text{-typeclass}).\,(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\cong(E^{R})^{C}\quad. +\] -\series bold -\size footnotesize -Assumptions -\end_layout +\end_inset +The last type is the right-hand side of Eq. +\begin_inset space ~ \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:jaskelioff-o-connor-theorem" +plural "false" +caps "false" +noprefix "false" -\series bold -\size footnotesize -Source -\end_layout +\end_inset +). + So, Eq. +\begin_inset space ~ \end_inset - - - - -\begin_inset Text -\begin_layout Plain Layout +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:jaskelioff-o-connor-theorem" +plural "false" +caps "false" +noprefix "false" -\size footnotesize -\begin_inset Formula $\forall A.\,(F^{A}\rightarrow A)\rightarrow A\cong\mu A.\,F^{A}$ \end_inset - +) holds. \end_layout +\begin_layout Standard +Let us now derive the code that implements the type equivalence +\begin_inset space ~ \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:jaskelioff-o-connor-theorem" +plural "false" +caps "false" +noprefix "false" -\size footnotesize -\begin_inset Formula $F$ \end_inset - is any functor -\end_layout - +) in the direction of right-to-left. + Suppose we are given a value +\begin_inset Formula $q$ \end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -Section + of the type in the right-hand side of Eq. \begin_inset space ~ \end_inset - +( \begin_inset CommandInset ref LatexCommand ref -reference "subsec:The-Church-encoding-of-recursive-types" +reference "eq:jaskelioff-o-connor-theorem" plural "false" caps "false" noprefix "false" \end_inset - -\end_layout +): +\begin_inset Formula +\[ +q:(E^{R})^{C}\quad. +\] \end_inset - - - - -\begin_inset Text -\begin_layout Plain Layout +We need to retrace step +\series bold +(3) +\series default + above and convert this +\begin_inset Formula $q$ +\end_inset -\size footnotesize -\begin_inset Formula $\forall A.\,(H^{A}\rightarrow A)\rightarrow A\cong H^{\bbnum 1}$ + to a function +\begin_inset Formula $f$ \end_inset + of type: +\begin_inset Formula +\[ +f:\forall(F\in P\text{-typeclass}).\,(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\quad. +\] -\end_layout +\end_inset +The required function +\begin_inset Formula $f$ \end_inset - - -\begin_inset Text -\begin_layout Plain Layout + is defined by: +\begin_inset Formula +\[ +f^{F}\big(k^{:\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X}}\big)\triangleq k^{C}(q)\quad. +\] -\size footnotesize -\begin_inset Formula $H$ \end_inset - is any contrafunctor + \end_layout +\begin_layout Standard +Continue by retracing step +\series bold +(2) +\series default +, converting +\begin_inset Formula $f$ \end_inset - - -\begin_inset Text -\begin_layout Plain Layout + to a function +\begin_inset Formula $g$ +\end_inset + + of type: +\begin_inset Formula +\[ +g:\forall(F\in P\text{-typeclass}).\,(\forall X.\,R^{X}\rightarrow F^{X})\rightarrow F^{C}\quad. +\] -\size footnotesize -Statement -\begin_inset space ~ \end_inset +The function +\begin_inset Formula $g$ +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Example-simplify-quantifier-1-1" -plural "false" -caps "false" -noprefix "false" + is defined by: +\begin_inset Formula +\[ +g^{F}\big(k^{:\forall X.\,R^{X}\rightarrow F^{X}}\big)\triangleq f^{F}\big(\forall Y.\,r^{:(E^{R})^{Y}}\rightarrow\text{run}_{E}^{R,Y}(k)(r)\big)\quad, +\] + +\end_inset + +where the universal runner ( +\begin_inset Formula $\text{run}_{E}^{T,Y}$ +\end_inset + +) has type: +\begin_inset Formula +\[ +\text{run}_{E}^{T,Y}:(\forall X.\,T^{X}\rightarrow F^{X})\rightarrow(E^{T})^{Y}\rightarrow F^{Y}\quad. +\] \end_inset \end_layout +\begin_layout Standard +It remains to retrace step +\series bold +(1) +\series default + and define a function +\begin_inset Formula $h$ \end_inset - - - - -\begin_inset Text -\begin_layout Plain Layout + of type: +\begin_inset Formula +\[ +h:\forall(F\in P\text{-typeclass}).\,(A\rightarrow F^{B})\rightarrow F^{C}\quad. +\] -\size footnotesize -\begin_inset Formula $\forall A.\,(A\rightarrow A)\rightarrow H^{A}\cong H^{\bbnum 1}$ \end_inset +We implement +\begin_inset Formula $h$ +\end_inset -\end_layout + via this code: +\begin_inset Formula +\[ +h^{F}(k^{:A\rightarrow F^{B}})\triangleq g^{F}\big(\forall X.\,a^{:A}\times t^{:B\rightarrow X}\rightarrow k(a)\triangleright t^{\uparrow F}\big)\quad. +\] \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +This completes the code that transforms +\begin_inset Formula $q$ +\end_inset -\size footnotesize -\begin_inset Formula $H$ + into +\begin_inset Formula $h$ \end_inset - is any contrafunctor +. + +\begin_inset Formula $\square$ +\end_inset + + \end_layout -\end_inset - - -\begin_inset Text +\begin_layout Standard +We will now apply the Jaskelioff-O'Connor theorem to prove some useful type + equivalences. +\end_layout -\begin_layout Plain Layout +\begin_layout Subsubsection +Statement +\begin_inset CommandInset label +LatexCommand label +name "subsec:Statement-identity-monad-morphism" -\size footnotesize -Example -\begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Example-strong-dinaturality-show-void" +reference "subsec:Statement-identity-monad-morphism" plural "false" caps "false" noprefix "false" \end_inset -(b) + \end_layout +\begin_layout Standard +Denote by +\begin_inset Formula $F\xrightarrow{\text{Monad}}G$ \end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\forall A.\,(F^{A}\rightarrow A)\rightarrow G^{A}\cong G^{\mu A.\,F^{A}}$ + (more verbosely, +\begin_inset Formula $\forall X.\,F^{X}\xrightarrow{\text{Monad}}G^{X}$ \end_inset +) the type of monad morphisms between monads +\begin_inset Formula $F$ +\end_inset -\end_layout - + and +\begin_inset Formula $G$ \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +. + Those are natural transformations of type +\begin_inset Formula $\forall X.\,F^{X}\rightarrow G^{X}$ +\end_inset -\size footnotesize -\begin_inset Formula $F$ + that additionally satisfy the laws of monad morphisms. + Denote by +\begin_inset Formula $\text{Id}$ \end_inset -, -\begin_inset Formula $G$ + the identity monad ( +\begin_inset Formula $\text{Id}^{A}\triangleq A$ \end_inset - are any functors +). + \end_layout +\begin_layout Standard + +\series bold +(a) +\series default + The standard monad method +\begin_inset Formula $\text{pu}_{M}:\forall A.\,A\rightarrow M^{A}$ \end_inset - - -\begin_inset Text -\begin_layout Plain Layout + is the only monad morphism of type +\begin_inset Formula $\text{Id}\xrightarrow{\text{Monad}}M$ +\end_inset -\size footnotesize -Statement -\begin_inset space ~ + that works in the same way for all monads +\begin_inset Formula $M$ \end_inset +. +\begin_inset Foot +status open -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-Church-Yoneda-identity" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout +See +\family typewriter + +\begin_inset CommandInset href +LatexCommand href +target "https://cstheory.stackexchange.com/questions/53389/" +literal "false" \end_inset @@ -53037,83 +52625,46 @@ noprefix "false" \end_layout \end_inset - - - - -\begin_inset Text -\begin_layout Plain Layout + We can express this as a type equivalence: +\begin_inset Formula +\[ +\forall M^{:\text{Monad}}.\,\text{Id}\xrightarrow{\text{Monad}}M\cong\bbnum 1\quad. +\] -\size footnotesize -\begin_inset Formula $\mu A.\,\mu B.\,F^{A,B}\cong\mu B.\,F^{B,B}$ \end_inset \end_layout -\end_inset - - -\begin_inset Text +\begin_layout Standard -\begin_layout Plain Layout +\series bold +(b) +\series default + The identity function of type +\begin_inset Formula $\forall X.\,M^{X}\rightarrow M^{X}$ +\end_inset -\size footnotesize -\begin_inset Formula $F$ + is the only monad morphism of type +\begin_inset Formula $M\xrightarrow{\text{Monad}}M$ \end_inset - is any bifunctor -\end_layout - -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout - -\size footnotesize -Statement -\begin_inset space ~ -\end_inset - - -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-nested-fixpoints" -plural "false" -caps "false" -noprefix "false" - -\end_inset - - -\end_layout - + that works in the same way for all monads +\begin_inset Formula $M$ \end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -\begin_inset Note Note -status collapsed +. +\begin_inset Foot +status open \begin_layout Plain Layout - -\size footnotesize See \family typewriter -\size default \begin_inset CommandInset href LatexCommand href -target "https://tex.stackexchange.com/questions/50332/vertical-spacing-of-a-table-cell" +target "https://stackoverflow.com/questions/61444425/" literal "false" \end_inset @@ -53123,1798 +52674,2584 @@ literal "false" \end_inset + We can express this as a type equivalence: +\begin_inset Formula +\[ +\forall M^{:\text{Monad}}.\,M\xrightarrow{\text{Monad}}M\cong\bbnum 1\quad. +\] -\begin_inset Box Frameless -position "c" -hor_pos "c" -has_inner_box 1 -inner_pos "t" -use_parbox 0 -use_makebox 0 -width "0.1mm" -special "none" -height "12mm" -height_special "none" -thickness "0.4pt" -separation "3pt" -shadowsize "4pt" -framecolor "black" -backgroundcolor "none" -status collapsed +\end_inset -\begin_layout Plain Layout \end_layout -\end_inset - +\begin_layout Subparagraph +Proof +\end_layout -\begin_inset Box Frameless -position "c" -hor_pos "c" -has_inner_box 1 -inner_pos "c" -use_parbox 0 -use_makebox 0 -width "43col%" -special "none" -height "1in" -height_special "totalheight" -thickness "0.4pt" -separation "3pt" -shadowsize "4pt" -framecolor "black" -backgroundcolor "none" +\begin_layout Standard +The +\begin_inset listings +inline true status open \begin_layout Plain Layout -\align center - -\size footnotesize -\begin_inset Formula $\mu A.\,P^{A,\,\mu B.\,Q^{A,B}}\cong$ -\end_inset - - -\begin_inset Newline newline -\end_inset - - -\begin_inset Formula $\forall A.\,\forall B.\,(P^{A,B}\rightarrow A)\times(Q^{A,B}\rightarrow B)\rightarrow A$ -\end_inset - +Monad \end_layout \end_inset - -\end_layout - + typeclass has methods in the form of a +\begin_inset Formula $P$ \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +-typeclass for functors +\begin_inset Formula $K$ +\end_inset -\size footnotesize + if we define \begin_inset Formula $P$ \end_inset -, -\begin_inset Formula $Q$ + by +\begin_inset Formula $(P^{K})^{A}\triangleq A+K^{K^{A}}$ \end_inset - are any bifunctors -\end_layout - -\end_inset - - -\begin_inset Text +. + Then the methods of the +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -Statement -\begin_inset space ~ +Monad +\end_layout + \end_inset + typeclass are represented by a single value of type: +\begin_inset Formula +\[ +\forall A.\,(P^{K})^{A}\rightarrow K^{A}=\forall A.\,A+K^{K^{A}}\rightarrow K^{A}\cong(\forall A.\,A\rightarrow K^{A})\times(\forall A.\,K^{K^{A}}\rightarrow K^{A})\quad. +\] -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-nested-fixpoint-under-functor" -plural "false" -caps "false" -noprefix "false" +\end_inset +This is a tuple type describing the type signatures of +\begin_inset Formula $K$ \end_inset +'s +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +pure \end_layout \end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\forall A.\,F^{A}\rightarrow P\cong P$ -\end_inset + and +\begin_inset listings +inline true +status open +\begin_layout Plain Layout +flatten \end_layout \end_inset - - -\begin_inset Text -\begin_layout Plain Layout - -\size footnotesize -If -\begin_inset Formula $F^{A}\neq\bbnum 0$ + methods when +\begin_inset Formula $K$ \end_inset - for some -\begin_inset Formula $A$ -\end_inset + is a monad. + So, the Jaskelioff-O'Connor theorem applies to the +\begin_inset listings +inline true +status open +\begin_layout Plain Layout +Monad \end_layout \end_inset - - -\begin_inset Text -\begin_layout Plain Layout - -\size footnotesize -Statement -\begin_inset space ~ + typeclass. + The free monad constructor ( +\begin_inset Formula $E$ \end_inset - -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-application-full-relation" -plural "false" -caps "false" -noprefix "false" - +) is defined recursively as +\begin_inset Formula $(E^{F})^{A}\triangleq A+F^{(E^{F})^{A}}$ \end_inset -(a) -\end_layout +, making +\begin_inset Formula $E^{F}$ +\end_inset + a monad when +\begin_inset Formula $F$ \end_inset - - - - -\begin_inset Text -\begin_layout Plain Layout + is any functor. + The free monad's universal runner is defined by: +\begin_inset Formula +\begin{align*} + & \text{run}_{E}^{F,A}:(\forall X.\,F^{X}\rightarrow M^{X})\rightarrow(E^{F})^{A}\rightarrow M^{A}\quad,\\ + & \text{run}_{E}^{F,A}\big(k^{:\forall X.\,F^{X}\rightarrow M^{X}}\big)\triangleq\,\begin{array}{|c||c|} + & M^{A}\\ +\hline A & \text{pu}_{M}\\ +F^{(E^{F})^{A}} & k^{(E^{F})^{A}}\bef\text{flm}_{M}\big(\overline{\text{run}}_{E}^{F,A}(k)\big) +\end{array}\quad. +\end{align*} -\size footnotesize -\begin_inset Formula $\forall A.\,((A\rightarrow A)\rightarrow A)\rightarrow A\cong\bbnum 1+\bbnum 2+\bbnum 3+...$ \end_inset \end_layout -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout +\begin_layout Standard -\size footnotesize -\begin_inset space ~ +\series bold +(a) +\series default + Monad morphisms are natural transformations that satisfy additional laws. + We first consider the given type without restricting the functions of type + +\begin_inset Formula $A\rightarrow M^{A}$ \end_inset + to monad morphisms but still assuming that they are natural transformations: +\begin_inset Formula +\[ +\forall M^{:\text{Monad}}.\,\forall A.\,A\rightarrow M^{A}\quad. +\] + +\end_inset -\end_layout +By the Yoneda identity, we get the type equivalence: +\begin_inset Formula +\[ +\forall A.\,A\rightarrow M^{A}\cong M^{\bbnum 1}\quad. +\] \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +So, we have reduced the type to +\begin_inset Formula $\forall M^{:\text{Monad}}.\,M^{\bbnum 1}$ +\end_inset -\size footnotesize -Statement +. + This type will be in the form suitable for the Jaskelioff-O'Connor theorem \begin_inset space ~ \end_inset - +( \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-advanced-type-equivalence" +reference "eq:jaskelioff-o-connor-theorem" plural "false" caps "false" noprefix "false" \end_inset - -\end_layout - +) if we set +\begin_inset Formula $F=M$ \end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout - -\size footnotesize -\begin_inset Box Frameless -position "c" -hor_pos "c" -has_inner_box 1 -inner_pos "t" -use_parbox 0 -use_makebox 0 -width "0.1mm" -special "none" -height "17mm" -height_special "none" -thickness "0.4pt" -separation "3pt" -shadowsize "4pt" -framecolor "black" -backgroundcolor "none" -status open -\begin_layout Plain Layout +, +\begin_inset Formula $A=\bbnum 0$ +\end_inset -\end_layout +, +\begin_inset Formula $C=\bbnum 1$ +\end_inset +; the parameter +\begin_inset Formula $B$ \end_inset + remains unused since +\begin_inset Formula $A\rightarrow M^{B}=\bbnum 0\rightarrow M^{B}\cong\bbnum 1$ +\end_inset -\begin_inset Box Frameless -position "c" -hor_pos "c" -has_inner_box 1 -inner_pos "c" -use_parbox 0 -use_makebox 0 -width "43col%" -special "none" -height "1in" -height_special "totalheight" -thickness "0.4pt" -separation "3pt" -shadowsize "4pt" -framecolor "black" -backgroundcolor "none" -status open +. + Then Eq. +\begin_inset space ~ +\end_inset -\begin_layout Plain Layout -\align center +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:jaskelioff-o-connor-theorem" +plural "false" +caps "false" +noprefix "false" -\size footnotesize -\begin_inset Formula $\forall A.\,(H^{A}\rightarrow A)\rightarrow F^{A}+G^{A}\cong$ \end_inset +) gives: +\begin_inset Formula +\[ +\forall M^{:\text{Monad}}.\,M^{\bbnum 1}\cong\forall M^{:\text{Monad}}.\,(\bbnum 0\rightarrow M^{B})\rightarrow M^{\bbnum 1}\cong(E^{R})^{\bbnum 1}\quad, +\] -\begin_inset Newline newline \end_inset +where we must define +\begin_inset Formula $R^{X}=A\times(B\rightarrow X)$ +\end_inset -\begin_inset Formula $(\forall A.\:(H^{A}\rightarrow A)\rightarrow F^{A})\,+$ +. + However, setting +\begin_inset Formula $A=\bbnum 0$ \end_inset + gives also +\begin_inset Formula $R=\bbnum 0$ +\end_inset -\begin_inset Newline newline +. + Then the free monad +\begin_inset Formula $E^{R}$ \end_inset + is the identity functor: +\begin_inset Formula +\[ +(E^{R})^{C}=C+R^{(E^{R})^{C}}=C+\bbnum 0\cong C\quad. +\] -\begin_inset Formula $(\forall A.\:(H^{A}\rightarrow A)\rightarrow G^{A})$ \end_inset +Finally, we obtain +\begin_inset Formula $(E^{R})^{\bbnum 1}=\bbnum 1$ +\end_inset -\end_layout +, and so: +\begin_inset Formula +\[ +\forall M^{:\text{Monad}}.\,\forall A.\,A\rightarrow M^{A}\cong\bbnum 1\quad. +\] \end_inset \end_layout -\end_inset - - -\begin_inset Text - -\begin_layout Plain Layout +\begin_layout Standard +We conclude that +\emph on +without +\emph default + restricting to monad morphisms there is only a single function of the given + type. + It remains to derive the code for that function and to verify that it is + indeed a monad morphism. +\end_layout -\size footnotesize -For any -\begin_inset Formula $F$ +\begin_layout Standard +We begin with a unit value (that we denote by +\begin_inset Formula $1$ \end_inset -, -\begin_inset Formula $G$ +) viewed as a value of type +\begin_inset Formula $(E^{R})^{C}$ \end_inset -, -\begin_inset Formula $H$ + in the right-hand side of Eq. +\begin_inset space ~ \end_inset - -\end_layout +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:jaskelioff-o-connor-theorem" +plural "false" +caps "false" +noprefix "false" \end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -Example +). + We follow the proof of Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Example-undisjunctive-type-constructors" +reference "subsec:Statement-Jaskelioff-OConnor" plural "false" caps "false" noprefix "false" \end_inset -(c) -\end_layout +. + The first step is to convert the value of type +\begin_inset Formula $(E^{R})^{C}$ +\end_inset + into a function +\begin_inset Formula $f$ \end_inset - - - - -\begin_inset Text -\begin_layout Plain Layout + of type: +\begin_inset Formula +\[ +f:\forall M^{:\text{Monad}}.\,\big(\forall X.\,(E^{R})^{X}\xrightarrow{\text{Monad}}M^{X}\big)\rightarrow M^{C}\quad. +\] -\size footnotesize -\begin_inset Formula $\forall A.\,\forall B.\,F^{A,B}\cong\forall B.\,\forall A.\,F^{A,B}$ \end_inset - -\end_layout +In our case, this function is simplified to: +\begin_inset Formula +\begin{align*} + & f:\forall M^{:\text{Monad}}.\,\big(\forall X.\,\text{Id}^{X}\xrightarrow{\text{Monad}}M^{X}\big)\rightarrow M^{\bbnum 1}\quad,\\ + & f^{M}\big(k^{:\forall X.\,\text{Id}^{X}\xrightarrow{\text{Monad}}M^{X}}\big)\triangleq k^{\bbnum 1}(1)\quad. +\end{align*} \end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -For any -\begin_inset Formula $F$ +The next step is to convert +\begin_inset Formula $f$ \end_inset + to a function +\begin_inset Formula $g$ +\end_inset -\end_layout + of type: +\begin_inset Formula +\[ +g:\forall M^{:\text{Monad}}.\,(\forall X.\,R^{X}\rightarrow M^{X})\rightarrow M^{C}\quad. +\] \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +In our case, +\begin_inset Formula $R^{X}=\bbnum 0$ +\end_inset -\size footnotesize -Statement + and +\begin_inset Formula $R^{X}\rightarrow M^{X}\cong\bbnum 1$ +\end_inset + +, so this function is simplified to: +\begin_inset Formula +\begin{align*} + & g:\forall M^{:\text{Monad}}.\,\bbnum 1\rightarrow M^{\bbnum 1}\quad,\\ + & g^{M}(k^{:\bbnum 1})\triangleq f^{M}\big(\forall Y.\,r^{:(E^{R})^{Y}}\rightarrow\text{run}_{E}^{R,Y}(k)(r)\big)\\ + & \quad=f^{M}(\forall Y.\,r^{:Y}\rightarrow\text{pu}_{M}^{Y}(r))=\text{pu}_{M}^{\bbnum 1}(1)\quad. +\end{align*} + +\end_inset + +Finally, we convert +\begin_inset Formula $g$ +\end_inset + + to a function +\begin_inset Formula $h$ +\end_inset + + of type: +\begin_inset Formula +\begin{align*} + & h:\forall M^{:\text{Monad}}.\,(A\rightarrow M^{B})\rightarrow M^{C}\\ + & =\forall M^{:\text{Monad}}.\,(\bbnum 0\rightarrow M^{B})\rightarrow M^{\bbnum 1}\quad.\\ + & \cong\forall M^{:\text{Monad}}.\,\bbnum 1\rightarrow M^{\bbnum 1}\cong\forall M^{:\text{Monad}}.\,M^{\bbnum 1}\quad. +\end{align*} + +\end_inset + + There exists only one value of type +\begin_inset Formula $\forall M^{:\text{Monad}}.\,M^{\bbnum 1}$ +\end_inset + +, and that value is +\begin_inset Formula $\text{pu}_{M}(1)$ +\end_inset + +. + Converting that to the type signature +\begin_inset Formula $\forall A.\:A\rightarrow M^{A}$ +\end_inset + +, we recover just the standard monad method +\begin_inset Formula $\text{pu}_{M}$ +\end_inset + +. + We know that +\begin_inset Formula $\text{pu}_{M}$ +\end_inset + + gives a monad morphism between the identity monad and +\begin_inset Formula $M$ +\end_inset + + (see Statement \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-Fubini-theorem-1" +reference "subsec:Statement-pure-M-is-monad-morphism" plural "false" caps "false" noprefix "false" \end_inset +). + So, we have proved that there exists a unique monad morphism of type +\begin_inset Formula $\forall M^{:\text{Monad}}.\,\text{Id}\xrightarrow{\text{Monad}}M$ +\end_inset +. + \end_layout +\begin_layout Standard + +\series bold +(b) +\series default + Again, we first consider the given type without restricting the functions + of type +\begin_inset Formula $M^{X}\rightarrow M^{X}$ \end_inset - - - - -\begin_inset Text -\begin_layout Plain Layout + to monad morphisms (but still assuming that they are natural transformations): +\begin_inset Formula +\[ +\forall M^{:\text{Monad}}.\,\forall X.\,M^{X}\rightarrow M^{X}\quad. +\] -\size footnotesize -\begin_inset Formula $\forall A.\,(F^{A}+G^{A})\cong(\forall A.\,F^{A})+(\forall A.\,G^{A})$ \end_inset +This type will be in the form suitable for the Jaskelioff-O'Connor theorem +\begin_inset space ~ +\end_inset -\end_layout +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:jaskelioff-o-connor-theorem" +plural "false" +caps "false" +noprefix "false" \end_inset - - -\begin_inset Text -\begin_layout Plain Layout - -\size footnotesize -For any -\begin_inset Formula $F$ +) if we set +\begin_inset Formula $F=M$ \end_inset , +\begin_inset Formula $A=\bbnum 1$ +\end_inset + +, and +\begin_inset Formula $B=C=X$ +\end_inset + +. + The functor +\begin_inset Formula $R$ +\end_inset + + is then defined by: +\begin_inset Formula +\[ +R^{T}\triangleq A\times(B\rightarrow T)\cong X\rightarrow T\quad, +\] + +\end_inset + +and the functor +\begin_inset Formula $E^{R}$ +\end_inset + + (the free monad on +\begin_inset Formula $R$ +\end_inset + +) is defined recursively by: +\begin_inset Formula +\[ +(E^{R})^{T}\triangleq T+\big(X\rightarrow(E^{R})^{T}\big)\quad. +\] + +\end_inset + + With these definitions, Eq. +\begin_inset space ~ +\end_inset + +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:jaskelioff-o-connor-theorem" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +) gives: +\begin_inset Formula +\[ +\forall M^{:\text{Monad}}.\,\forall X.\,M^{X}\rightarrow M^{X}\cong\forall X.\,(E^{R})^{X}\quad. +\] + +\end_inset + +We are using the functor +\begin_inset Formula $(E^{R})^{T}$ +\end_inset + + with the type parameter +\begin_inset Formula $T=X$ +\end_inset + +; however, +\begin_inset Formula $E^{R}$ +\end_inset + + also contains +\begin_inset Formula $X$ +\end_inset + + through the definition of +\begin_inset Formula $R$ +\end_inset + +. + To avoid confusion and to simplify notation, let us write +\begin_inset Formula $G^{X}$ +\end_inset + + instead of +\begin_inset Formula $(E^{R})^{X}$ +\end_inset + +, where the type constructor +\begin_inset Formula $G$ +\end_inset + + is defined recursively by: +\begin_inset Formula +\[ +G^{X}\triangleq X+(X\rightarrow G^{X})\quad. +\] + +\end_inset + +(Note that \begin_inset Formula $G$ +\end_inset + + is neither covariant nor contravariant.) With this definition, we obtain: +\begin_inset Formula +\[ +\forall M^{:\text{Monad}}.\,\forall X.\,M^{X}\rightarrow M^{X}\cong\forall X.\,G^{X}\quad. +\] + \end_inset \end_layout +\begin_layout Standard +To simpify the type +\begin_inset Formula $\forall X.\,G^{X}$ \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +, begin by expanding the recursive type +\begin_inset Formula $G^{X}$ +\end_inset -\size footnotesize -Statement +: +\begin_inset Formula +\begin{align*} + & \forall X.\,G^{X}\cong\forall X.\,X+(X\rightarrow G^{X})\\ +\text{non-disjunctivity}:\quad & \cong(\forall X.\,X)+(\forall X.\,X\rightarrow G^{X})\\ +\text{use }\forall X.\,X\cong\bbnum 0:\quad & \cong\forall X.\,X\rightarrow G^{X}\quad. +\end{align*} + +\end_inset + +Here we used the non-disjunctivity property from Example \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref -reference "subsec:Statement-general-identities-forall" +reference "subsec:Example-undisjunctive-type-constructors" plural "false" caps "false" noprefix "false" \end_inset -(a) +(e). \end_layout +\begin_layout Standard +Continue expanding the recursive type: +\begin_inset Formula +\begin{align*} + & \forall X.\,X\rightarrow G^{X}\cong\forall X.\,X\rightarrow(X+(X\rightarrow G^{X}))\\ +\text{non-disjunctivity}:\quad & \cong(\gunderline{\forall X.\,X\rightarrow X})+\big(\forall X.\,X\rightarrow X\rightarrow G^{X}\big)\\ + & \cong\bbnum 1+\forall X.\,X\times X\rightarrow G^{X}\quad. +\end{align*} + \end_inset - - - - -\begin_inset Text + +The relevant non-disjunctivity property was shown in Example +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-undisjunctive-type-constructors" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +(f). + Expand further, using the same non-disjunctivity property: +\begin_inset Formula +\begin{align*} + & \forall X.\,G^{X}\cong\bbnum 1+\forall X.\,X\times X\rightarrow G^{X}\\ + & \cong\bbnum 1+\forall X.\,X\times X\rightarrow(X+(X\rightarrow G^{X}))\\ +\text{non-disjunctivity}:\quad & \cong\bbnum 1+(\gunderline{\forall X.\,X\times X\rightarrow X})+\big(\forall X.\,X\times X\rightarrow X\rightarrow G^{X}\big)\\ + & \cong\bbnum 1+\bbnum 2+\forall X.\,X\times X\times X\rightarrow G^{X}\quad. +\end{align*} + +\end_inset + +Proceeding similarly, we obtain: +\begin_inset Formula +\[ +\forall X.\,\underbrace{X\times...\times X}_{n\text{ times}}\rightarrow G^{X}\cong\underbrace{\bbnum 1+...+\bbnum 1}_{n\text{ times}}+\forall X.\,\underbrace{X\times...\times X}_{n+1\text{ times}}\rightarrow G^{X}\quad. +\] + +\end_inset + +It follows by induction that +\begin_inset Formula $\forall X.\,G^{X}$ +\end_inset + + is equivalent to an +\begin_inset Quotes eld +\end_inset + +infinite +\begin_inset Quotes erd +\end_inset + + sum type: +\begin_inset Formula +\[ +\forall X.\,G^{X}\cong\bbnum 1+\bbnum 2+\bbnum 3+... +\] + +\end_inset + +Values of that type may be described by pairs +\begin_inset Formula $\left(n,k\right)$ +\end_inset + + of natural numbers such that +\begin_inset Formula $1\le k\le n$ +\end_inset + +. + The number +\begin_inset Formula $n$ +\end_inset + + chooses the part +\begin_inset Quotes eld +\end_inset + + +\begin_inset Formula $\bbnum n$ +\end_inset + + +\begin_inset Quotes erd +\end_inset + + within the disjunctive type +\begin_inset Formula $\bbnum 1+\bbnum 2+\bbnum 3+...$ +\end_inset + +, where we denoted by +\begin_inset Quotes eld +\end_inset + + +\begin_inset Formula $\bbnum n$ +\end_inset + + +\begin_inset Quotes erd +\end_inset + + the type +\begin_inset Formula $\underbrace{\bbnum 1+...+\bbnum 1}_{n\text{ times}}$ +\end_inset + +. + The number +\begin_inset Formula $k$ +\end_inset + + chooses a specific unit value within +\begin_inset Formula $\underbrace{\bbnum 1+...+\bbnum 1}_{n\text{ times}}$ +\end_inset + +. +\end_layout + +\begin_layout Standard +The next step is to convert values +\begin_inset Formula $\left(n,k\right)$ +\end_inset + + of that type into functions of type +\begin_inset Formula $M^{X}\rightarrow M^{X}$ +\end_inset + + that work in the same way for all monads +\begin_inset Formula $M$ +\end_inset + + and all types +\begin_inset Formula $X$ +\end_inset + +. + We have to find out whether any of those functions obey the laws of monad + morphisms. + For that, we need to derive the specific code of those functions. + We follow the steps outlined in the proof of Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-Jaskelioff-OConnor" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +. +\end_layout + +\begin_layout Standard +First, we translate pairs +\begin_inset Formula $\left(n,k\right)$ +\end_inset + + into values of type +\begin_inset Formula $\forall X.\,G^{X}$ +\end_inset + + that we will denote by +\begin_inset Formula $q_{n,k}$ +\end_inset + +. + To achieve that, we need to retrace the way we expanded the recursive type + +\begin_inset Formula $G^{X}$ +\end_inset + +. + As an example, consider the pair +\begin_inset Formula $\left(n=2,k=1\right)$ +\end_inset + +. + The value +\begin_inset Formula $n=2$ +\end_inset + + corresponds to the type +\begin_inset Formula $\bbnum 2$ +\end_inset + +, which was obtained from +\begin_inset Formula $\forall X.\,X\rightarrow X\rightarrow X$ +\end_inset + + during expansion of +\begin_inset Formula $\forall X.\,G^{X}$ +\end_inset + +. + The type +\begin_inset Formula $\forall X.\,X\rightarrow X\rightarrow X$ +\end_inset + + has only two distinct values, which are functions that return the first + or the second argument of type +\begin_inset Formula $X$ +\end_inset + +. + The index +\begin_inset Formula $k=1$ +\end_inset + + selects the first of those values, which is a function whose code is written + as +\begin_inset Formula $x_{1}^{:X}\rightarrow x_{2}^{:X}\rightarrow x_{1}$ +\end_inset + +. + +\end_layout + +\begin_layout Standard +To simplify notation, let us temporarily fix the type parameter +\begin_inset Formula $X$ +\end_inset + +; we will restore the quantifier +\begin_inset Formula $\forall X$ +\end_inset + + at the end of the derivation. +\end_layout + +\begin_layout Standard +The type +\begin_inset Formula $X\rightarrow X\rightarrow X$ +\end_inset + + was found during expansion of the recursive type +\begin_inset Formula $G^{X}$ +\end_inset + + as: +\begin_inset Formula +\[ +G^{X}=X+(X\rightarrow(X+(X\rightarrow(X+...))))\quad. +\] + +\end_inset + +So, the pair +\begin_inset Formula $\left(n=2,k=1\right)$ +\end_inset + + corresponds to the function +\begin_inset Formula $q_{2,1}^{X}:G^{X}$ +\end_inset + + written as: +\begin_inset Formula +\begin{align*} + & q_{2,1}^{X}:X+(X\rightarrow(X+(X\rightarrow(X+(X\rightarrow G^{X})))))\quad,\\ + & q_{2,1}^{X}\triangleq\bbnum 0^{:X}+(x_{1}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{2}^{:X}\rightarrow(x_{1}+\bbnum 0^{:X\rightarrow G^{X}}))))\quad. +\end{align*} + +\end_inset + +In a similar way, we define the functions +\begin_inset Formula $q_{n,k}$ +\end_inset + + for any +\begin_inset Formula $1\le k\le n$ +\end_inset + +: +\begin_inset Formula +\[ +q_{n,k}^{X}\triangleq\bbnum 0^{:X}+(x_{1}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{2}^{:X}\rightarrow...\rightarrow(\bbnum 0^{:X}+(x_{n}^{:X}\rightarrow(x_{k}+\bbnum 0^{:X\rightarrow G^{X}})))...)))\quad. +\] + +\end_inset + +To make this code description rigorous, let us define +\begin_inset Formula $u_{i,n,k}$ +\end_inset + + and +\begin_inset Formula $v_{i,n}$ +\end_inset + + like this: +\begin_inset Formula +\begin{align*} + & u_{i,n,k}\triangleq\bbnum 0^{:X}+(x_{i}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{i+1}^{:X}\rightarrow...\rightarrow(x_{n}^{:X}\rightarrow(x_{k}+\bbnum 0^{:X\rightarrow G^{X}}))...))),\\ + & v_{i,n}(x_{0})\triangleq\bbnum 0^{:X}+(x_{i}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{i+1}^{:X}\rightarrow...\rightarrow(x_{n}^{:X}\rightarrow(x_{0}+\bbnum 0^{:X\rightarrow G^{X}}))...))). +\end{align*} + +\end_inset + +These formulas hold for +\begin_inset Formula $1\le i\le k\le n$ +\end_inset + +. + An inductive definition of +\begin_inset Formula $q_{n,k}^{X}$ +\end_inset + +, +\begin_inset Formula $u_{i,n,k}$ +\end_inset + +, and +\begin_inset Formula $v_{i,n}$ +\end_inset + + is: +\begin_inset Formula +\begin{align*} + & q_{n,k}^{X}=u_{1,n,k}\quad,\quad\quad u_{i,n,k}:G^{X}\quad,\quad\quad v_{i,n}:X\rightarrow G^{X}\quad,\\ +\text{for }1\le i m.flatMap { x_2 => pure(x_1) + } } +\end_layout + +\end_inset + +This code can be rewritten as a functor block, making its logic more visually + clear: +\begin_inset listings +inline false +status open \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\forall A.\,(F^{A}\times G^{A})\cong(\forall A.\,F^{A})\times(\forall A.\,G^{A})$ -\end_inset +def h_2_1(m: M[X]): M[X] = for { +\end_layout +\begin_layout Plain Layout + x_1 <- m \end_layout -\end_inset - - -\begin_inset Text - \begin_layout Plain Layout -\size footnotesize -For any -\begin_inset Formula $F$ -\end_inset - -, -\begin_inset Formula $G$ -\end_inset + x_2 <- m +\end_layout +\begin_layout Plain Layout +} yield x_1 \end_layout \end_inset - - -\begin_inset Text + +The code runs two effects of +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -Statement -\begin_inset space ~ -\end_inset +m +\end_layout +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-general-identities-forall" -plural "false" -caps "false" -noprefix "false" + but returns the first value ( +\begin_inset listings +inline true +status open -\end_inset +\begin_layout Plain Layout -(b) +x_1 \end_layout \end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\forall A.\,R\rightarrow F^{A}\cong R\rightarrow(\forall A.\,F^{A})$ -\end_inset +), ignoring +\begin_inset listings +inline true +status open +\begin_layout Plain Layout +x_2 \end_layout \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +. +\end_layout -\size footnotesize -Any -\begin_inset Formula $F$ +\begin_layout Standard +Now we can generalize the code pattern from +\begin_inset Formula $h_{2,1}$ \end_inset -, a fixed type -\begin_inset Formula $R$ + to +\begin_inset Formula $h_{n,k}$ \end_inset + and write symbolically: +\begin_inset listings +inline false +status open -\end_layout +\begin_layout Plain Layout -\end_inset - - -\begin_inset Text +def h_n_k(m: M[X]): M[X] = for { +\end_layout \begin_layout Plain Layout -\size footnotesize -Statement -\begin_inset space ~ -\end_inset + x_1 <- m +\end_layout +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-general-identities-forall" -plural "false" -caps "false" -noprefix "false" + x_2 <- m +\end_layout -\end_inset +\begin_layout Plain Layout -(c) + ... \end_layout -\end_inset - - - - -\begin_inset Text - \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\forall A.\,F^{P^{A}}\cong F^{\forall A.\,P^{A}}$ -\end_inset + x_n <- m +\end_layout +\begin_layout Plain Layout +} yield x_k \end_layout \end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $F$ -\end_inset - is strictly positive \end_layout +\begin_layout Standard +To prove that this is indeed the correct code for +\begin_inset Formula $h_{n,k}^{M}(m)$ \end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -Statement -\begin_inset space ~ +, we need to use induction in +\begin_inset Formula $n$ \end_inset +. + We rewrite +\begin_inset Formula $q_{n,k}^{X}=u_{1,n,k}$ +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-quantifier-across-functor" -plural "false" -caps "false" -noprefix "false" + and compute +\begin_inset Formula $\text{run}_{E}^{R,X}(p)(q_{n,k})=\text{run}_{E}^{R,X}(p)(u_{1,n,k})$ +\end_inset +. + Using the code of +\begin_inset Formula $\text{run}_{E}$ \end_inset +, we obtain the following inductive code definitions: +\begin_inset Formula +\begin{align*} +\text{for }1\le i - - - -\begin_inset Text -\begin_layout Plain Layout + is indeed of the form: +\begin_inset Formula +\[ +m\triangleright\text{flm}_{M}(x_{1}^{:X}\rightarrow m\triangleright\text{flm}_{M}(x_{2}^{:X}\rightarrow...\rightarrow m\triangleright\text{flm}_{M}(x_{n}^{:X}\rightarrow\text{pu}_{M}(x_{k}))...))\quad. +\] -\size footnotesize -\begin_inset Formula $\forall A.\,F^{A}\cong\bbnum 0$ \end_inset - when -\begin_inset Formula $F^{\bbnum 0}\cong\bbnum 0$ -\end_inset +This exactly corresponds to the schematic Scala code for +\begin_inset listings +inline true +status open +\begin_layout Plain Layout +h_n_k \end_layout \end_inset - - -\begin_inset Text -\begin_layout Plain Layout + we just showed. +\end_layout -\size footnotesize -\begin_inset Formula $F$ +\begin_layout Standard +It remains to check whether the functions +\begin_inset Formula $h_{n,k}$ \end_inset - is such that -\begin_inset Formula $F^{\bbnum 0}\cong\bbnum 0$ + are monad morphisms. + We note that +\begin_inset Formula $h_{1,1}$ \end_inset + is an identity function, due to the monad +\begin_inset Formula $M$ +\end_inset -\end_layout +'s identity law: +\begin_inset Formula +\[ +h_{1,1}^{M}(m)=m\triangleright\text{flm}_{M}(\gunderline{x_{1}^{:X}\rightarrow\text{pu}_{M}(x_{1})})=m\triangleright\gunderline{\text{flm}_{M}(\text{pu}_{M})}=m\quad. +\] \end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -Statement -\begin_inset space ~ +So, +\begin_inset Formula $h_{1,1}$ \end_inset + is (trivially) a monad morphism. + We will now show that +\begin_inset Formula $h_{n,k}$ +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-Fubini-theorem-1" -plural "false" -caps "false" -noprefix "false" + for +\begin_inset Formula $n\ge2$ +\end_inset + are +\emph on +not +\emph default + monad morphisms. + It is sufficient to choose a specific monad +\begin_inset Formula $M$ \end_inset + and to show that a specific monad morphism law fails. + We will check the monad morphism composition law: for any value +\begin_inset Formula $q:M^{M^{X}}$ +\end_inset -\end_layout +, +\begin_inset Formula +\[ +h_{n,k}(\text{ftn}_{M}(q))\overset{?}{=}\text{ftn}_{M}(h_{n,k}(q\triangleright h_{n,k}^{\uparrow M}))\quad. +\] \end_inset - - - - -\begin_inset Text -\begin_layout Plain Layout - -\size footnotesize -\begin_inset Formula $\forall A.\,F^{A\rightarrow A}\cong F^{\bbnum 1}$ +We choose +\begin_inset Formula $M$ \end_inset + as the standard +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +State \end_layout \end_inset - - -\begin_inset Text -\begin_layout Plain Layout + monad with the internal state of type +\begin_inset listings +inline true +status open -\size footnotesize -\begin_inset Formula $F$ -\end_inset +\begin_layout Plain Layout - is strictly positive +Int \end_layout \end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -Example -\begin_inset space ~ +. + To show a counterexample that disproves the composition law, we will use + a specially chosen value +\begin_inset Formula $q$ \end_inset + of type +\begin_inset listings +inline true +status open -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Example-simplify-quantifier-A-A" -plural "false" -caps "false" -noprefix "false" - -\end_inset +\begin_layout Plain Layout -(a) +State[Int, State[Int, Unit]] \end_layout \end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\forall A.\,H^{A\rightarrow A}\cong H^{\bbnum 1}$ -\end_inset +: +\begin_inset listings +inline false +status open +\begin_layout Plain Layout +type M[A] = Int => (A, Int) \end_layout -\end_inset - - -\begin_inset Text - \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $H$ -\end_inset - - is a contrafunctor +val q: M[M[Unit]] = { s => ( { t => ((), s + 1) }, s) } \end_layout \end_inset - - -\begin_inset Text -\begin_layout Plain Layout -\size footnotesize -Example -\begin_inset space ~ -\end_inset +\begin_inset Formula +\[ +M^{A}\triangleq\text{Int}\rightarrow A\times\text{Int}\quad,\quad\quad q:M^{M^{\bbnum 1}}\quad,\quad q\triangleq s^{:\text{Int}}\rightarrow(\_^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}})\times s\quad. +\] +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Example-simplify-quantifier-A-A" -plural "false" -caps "false" -noprefix "false" +For more intuition, let us express +\begin_inset listings +inline true +status open -\end_inset +\begin_layout Plain Layout -(b) +q \end_layout \end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\forall A.\,((A\rightarrow P)\rightarrow A\rightarrow A\cong P$ -\end_inset + via the +\begin_inset listings +inline true +status open +\begin_layout Plain Layout +State \end_layout \end_inset - - -\begin_inset Text -\begin_layout Plain Layout + monad operations +\begin_inset listings +inline true +status open -\size footnotesize -\begin_inset Formula $P$ -\end_inset +\begin_layout Plain Layout - is a fixed type +get \end_layout \end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -Exercise -\begin_inset space ~ -\end_inset + and +\begin_inset listings +inline true +status open +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "par:Problem-Peirce-law" -plural "false" -caps "false" -noprefix "false" +set +\end_layout \end_inset +: +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout +val get: M[Int] = s => (s, s) \end_layout -\end_inset - - - +\begin_layout Plain Layout -\end_inset +val set: Int => M[Unit] = x => s => ((), x) +\end_layout +\begin_layout Plain Layout +// Assuming that map and flatMap are defined for M: \end_layout \begin_layout Plain Layout -\begin_inset Caption Standard + +val q: M[M[Unit]] = for { +\end_layout \begin_layout Plain Layout -Type identities proved by other parametricity techniques. -\begin_inset CommandInset label -LatexCommand label -name "tab:Type-identities-proved-by-parametricity" -\end_inset + s <- get +\end_layout +\begin_layout Plain Layout +} yield set(s + 1) \end_layout \end_inset +Now we compute the two sides of the composition law, step by step. + First, we will use Scala's functor block syntax. + The +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +flatten \end_layout \end_inset + method can be written as: +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout +def flatten[A](mm: M[M[A]]): M[A] = for { \end_layout -\begin_layout Standard -\begin_inset Float table -placement h -wide false -sideways false -status open +\begin_layout Plain Layout + + m <- mm +\end_layout \begin_layout Plain Layout -\align center -\begin_inset Tabular - - - - - - - -\begin_inset Text + + x <- m +\end_layout \begin_layout Plain Layout -\series bold -\size footnotesize -Identity +} yield x \end_layout \end_inset - - -\begin_inset Text + +Substituting the value +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\series bold -\size footnotesize -Assumptions +q \end_layout \end_inset - - -\begin_inset Text + + defined above, we get: +\begin_inset listings +inline false +status open \begin_layout Plain Layout -\series bold -\size footnotesize -Source +val flatten_q: M[Unit] = for { // This is flatten(q). \end_layout -\end_inset - - - - -\begin_inset Text - \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\exists C.\,F^{C}\cong\forall D.\,\big(\forall C.\,(F^{C}\rightarrow D)\big)\rightarrow D$ -\end_inset + m <- for { +\end_layout +\begin_layout Plain Layout + s <- get \end_layout -\end_inset - - -\begin_inset Text +\begin_layout Plain Layout + + } yield set(s + 1) +\end_layout \begin_layout Plain Layout -\size footnotesize -For any -\begin_inset Formula $F$ -\end_inset + x <- m +\end_layout +\begin_layout Plain Layout +} yield x \end_layout \end_inset - - -\begin_inset Text + +Eliminate the nested +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -Equation -\begin_inset space ~ +for +\end_layout + \end_inset -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:existential-via-universal-Yoneda" -plural "false" -caps "false" -noprefix "false" + and obtain: +\begin_inset listings +inline false +status open -\end_inset +\begin_layout Plain Layout -) +val flatten_q: M[Unit] = for { \end_layout -\end_inset - - - - -\begin_inset Text - \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $(\exists C.\,F^{C})\rightarrow R\cong\forall C.\,(F^{C}\rightarrow R)$ -\end_inset + s <- get +\end_layout +\begin_layout Plain Layout + m = set(s + 1) \end_layout -\end_inset - - -\begin_inset Text +\begin_layout Plain Layout + + x <- m +\end_layout \begin_layout Plain Layout -\size footnotesize -For any -\begin_inset Formula $F$ -\end_inset +} yield x +\end_layout -, -\begin_inset Formula $R$ \end_inset +Or equivalently (as the returned value is always a unit value): +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout +val flatten_q: M[Unit] = for { \end_layout -\end_inset - - -\begin_inset Text +\begin_layout Plain Layout + + s <- get +\end_layout \begin_layout Plain Layout -\size footnotesize -Statement -\begin_inset space ~ -\end_inset + _ <- set(s + 1) +\end_layout +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-function-extension-rule" -plural "false" -caps "false" -noprefix "false" +} yield () +\end_layout \end_inset +Applying +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +h_n_k \end_layout \end_inset - - - - -\begin_inset Text + + to this value means writing code of the form: +\begin_inset listings +inline false +status open \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\exists A.\,A\cong\bbnum 1$ -\end_inset +val h_flatten_q: M[Unit] = for { +\end_layout +\begin_layout Plain Layout + x_1 <- flatten_q \end_layout -\end_inset - - -\begin_inset Text - \begin_layout Plain Layout + ... \end_layout -\end_inset - - -\begin_inset Text +\begin_layout Plain Layout + + x_n <- flatten_q +\end_layout \begin_layout Plain Layout +} yield x_k \end_layout \end_inset - - - - -\begin_inset Text + +The returned value in +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\exists A.\,F^{A}\cong F^{\bbnum 1}$ +x_k +\end_layout + \end_inset + is in any case the unit value, so let us focus on the state updates. + Each +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +flatten_q \end_layout \end_inset - - -\begin_inset Text + + has the effect of reading the state value +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $F$ +s +\end_layout + \end_inset - is any functor + and storing the incremented value +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +s + 1 \end_layout \end_inset - - -\begin_inset Text + +. + The function +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -Statement -\begin_inset space ~ +h_n_k +\end_layout + \end_inset + repeats +\begin_inset Formula $n$ +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-co-Yoneda-two-identities-1" -plural "false" -caps "false" -noprefix "false" + times the effect of +\begin_inset listings +inline true +status open -\end_inset +\begin_layout Plain Layout -(a) +flatten_q \end_layout \end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\exists A.\,H^{A}\cong H^{\bbnum 0}$ +. + This increments the internal state +\begin_inset Formula $n$ \end_inset + times. + So, the left-hand side of the law is equivalent to: +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout +val lhs: M[Unit] = for { // This is h_flatten_q === h_n_k(flatten(q)). \end_layout -\end_inset - - -\begin_inset Text - \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $H$ -\end_inset - - is any contrafunctor + s <- get \end_layout -\end_inset - - -\begin_inset Text - \begin_layout Plain Layout -\size footnotesize -Statement -\begin_inset space ~ -\end_inset + _ <- set(s + n) +\end_layout +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-co-Yoneda-two-identities-1" -plural "false" -caps "false" -noprefix "false" +} yield () +\end_layout \end_inset -(b) + \end_layout +\begin_layout Standard +Turning now to the right-hand side of the law, we write the first sub-expression + ( +\begin_inset Formula $q\triangleright h_{n,k}^{\uparrow M}$ \end_inset - - - - -\begin_inset Text + +, or in Scala, +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\exists A.\,F^{A}\rightarrow A\cong\bbnum 1$ +q.map(h_n_k) +\end_layout + \end_inset +) as the following Scala code: +\begin_inset listings +inline false +status open -\end_layout +\begin_layout Plain Layout -\end_inset - - -\begin_inset Text +val q_map_h: M[M[Unit]] = for { +\end_layout \begin_layout Plain Layout -\size footnotesize -For any -\begin_inset Formula $F$ -\end_inset + m <- q +\end_layout +\begin_layout Plain Layout +} yield h_n_k(m) \end_layout \end_inset - - -\begin_inset Text + +Substituting the code of +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -Example -\begin_inset space ~ +q +\end_layout + \end_inset + (but not yet expanding +\begin_inset listings +inline true +status open -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Example-simple-existential-derivation" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout + +h_n_k +\end_layout \end_inset +), we find: +\begin_inset listings +inline false +status open -\end_layout +\begin_layout Plain Layout -\end_inset - - - - -\begin_inset Text +val q_map_h: M[M[Unit]] = for { +\end_layout \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\exists A.\,(F^{A}+G^{A})\cong(\exists A.\,F^{A})+(\exists A.\,G^{A})$ -\end_inset + s <- get +\end_layout +\begin_layout Plain Layout +} yield h_n_k(set(s + 1)) \end_layout \end_inset - - -\begin_inset Text + +The function call +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -For any -\begin_inset Formula $F$ +h_n_k(set(s + 1)) +\end_layout + \end_inset -, -\begin_inset Formula $G$ + repeats +\begin_inset Formula $n$ \end_inset + times the effect of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +set(s + 1) \end_layout \end_inset - - -\begin_inset Text + +, but +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -Example -\begin_inset space ~ -\end_inset +s +\end_layout +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Example-simple-existential-derivation-1-1" -plural "false" -caps "false" -noprefix "false" + is a fixed value in that scope, so the result is equal to just a single + effect: +\begin_inset listings +inline false +status open -\end_inset +\begin_layout Plain Layout -(b) +val q_map_h: M[M[Unit]] = for { \end_layout -\end_inset - - - - -\begin_inset Text - \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\exists A.\,\exists B.\,F^{A,B}\cong\exists B.\,\exists A.\,F^{A,B}$ -\end_inset + s <- get +\end_layout +\begin_layout Plain Layout +} yield set(s + 1) \end_layout \end_inset - - -\begin_inset Text + +This is the same value as +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -For any -\begin_inset Formula $F$ +q +\end_layout + \end_inset + itself. +\end_layout + +\begin_layout Standard +The next sub-expression is +\begin_inset listings +inline true +status open +\begin_layout Plain Layout + +h_n_k(q_map_h) \end_layout \end_inset - - -\begin_inset Text + +, which equals +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -Statement -\begin_inset space ~ +h_n_k(q) +\end_layout + \end_inset +: +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +val h_q_map_h: M[M[Unit]] = for { +\end_layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-commute-existential" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout -\end_inset + x_1 <- q +\end_layout +\begin_layout Plain Layout + ... \end_layout -\end_inset - - - - -\begin_inset Text - \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\nu A.\,F^{A}\cong\exists A.\,(A\rightarrow F^{A})\times A$ -\end_inset + x_n <- q +\end_layout +\begin_layout Plain Layout +} yield x_k \end_layout \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +Substituting the code for +\begin_inset listings +inline true +status open -\size footnotesize -\begin_inset Formula $F$ -\end_inset +\begin_layout Plain Layout - is any functor +q \end_layout \end_inset - - -\begin_inset Text -\begin_layout Plain Layout +, we get: +\begin_inset listings +inline false +status open -\size footnotesize -Section -\begin_inset space ~ -\end_inset +\begin_layout Plain Layout +val h_q_map_h: M[M[Unit]] = for { +\end_layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:The-greatest-fixpoints-and-Church-co-Yoneda" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout -\end_inset + x_1 <- for { +\end_layout +\begin_layout Plain Layout + s <- get \end_layout -\end_inset - - - - -\begin_inset Text +\begin_layout Plain Layout + + } yield set(s + 1) +\end_layout \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $G^{\nu A.\,F^{A}}\cong\exists A.\,(A\rightarrow F^{A})\times G^{A}$ -\end_inset + ... +\end_layout +\begin_layout Plain Layout + x_n <- for { \end_layout -\end_inset - - -\begin_inset Text +\begin_layout Plain Layout + + s <- get +\end_layout \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $F$ -\end_inset + } yield set(s + 1) +\end_layout -, -\begin_inset Formula $G$ -\end_inset +\begin_layout Plain Layout - are any functors +} yield x_k \end_layout \end_inset - - -\begin_inset Text + +Eliminate the nested +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -Statement -\begin_inset space ~ +for +\end_layout + \end_inset + and obtain: +\begin_inset listings +inline false +status open -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-Church-co-Yoneda" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout -\end_inset +val h_q_map_h: M[M[Unit]] = for { +\end_layout +\begin_layout Plain Layout + s <- get \end_layout -\end_inset - - - - -\begin_inset Text - \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $\nu A.\,\nu B.\,F^{A,B}\cong\nu B.\,F^{B,B}$ -\end_inset + x_1 = set(s + 1) +\end_layout +\begin_layout Plain Layout + ... \end_layout -\end_inset - - -\begin_inset Text +\begin_layout Plain Layout + + s <- get +\end_layout \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $F$ -\end_inset + x_n = set(s + 1) +\end_layout - is any bifunctor +\begin_layout Plain Layout + +} yield x_k \end_layout \end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -Statement -\begin_inset space ~ +The code runs +\begin_inset Formula $n$ \end_inset + times the effect of +\begin_inset listings +inline true +status open -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-nested-greatest-fixpoints" -plural "false" -caps "false" -noprefix "false" +\begin_layout Plain Layout + +get +\end_layout \end_inset + but actually never runs the effect of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +set \end_layout \end_inset - - - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -\begin_inset Note Note -status collapsed +; the unevaluated effectful value +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -See -\family typewriter -\size default - -\begin_inset CommandInset href -LatexCommand href -target "https://tex.stackexchange.com/questions/50332/vertical-spacing-of-a-table-cell" -literal "false" +set(s + 1) +\end_layout \end_inset + is merely assigned to each +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +x_i \end_layout \end_inset + and then returned. + So, the code is equivalent to: +\begin_inset listings +inline false +status open -\begin_inset Box Frameless -position "c" -hor_pos "c" -has_inner_box 1 -inner_pos "t" -use_parbox 0 -use_makebox 0 -width "0.1mm" -special "none" -height "12mm" -height_special "none" -thickness "0.4pt" -separation "3pt" -shadowsize "4pt" -framecolor "black" -backgroundcolor "none" -status collapsed +\begin_layout Plain Layout + +val h_q_map_h: M[M[Unit]] = for { +\end_layout + +\begin_layout Plain Layout + + s <- get +\end_layout \begin_layout Plain Layout +} yield set(s + 1) \end_layout \end_inset - -\begin_inset Box Frameless -position "c" -hor_pos "c" -has_inner_box 1 -inner_pos "c" -use_parbox 0 -use_makebox 0 -width "43col%" -special "none" -height "1in" -height_special "totalheight" -thickness "0.4pt" -separation "3pt" -shadowsize "4pt" -framecolor "black" -backgroundcolor "none" -status collapsed +This is again just equal to +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\align center -\size footnotesize -\begin_inset Formula $\nu A.\,F^{A,\,\nu B.\,G^{A,B}}\cong$ +q +\end_layout + \end_inset +. +\end_layout -\begin_inset Newline newline -\end_inset +\begin_layout Standard +It remains to apply +\begin_inset listings +inline true +status open +\begin_layout Plain Layout + +flatten +\end_layout -\begin_inset Formula $\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times A$ \end_inset + to +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +h_q_map_h \end_layout \end_inset +, which is the same as +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +flatten(q) \end_layout \end_inset - - -\begin_inset Text + + and was already computed as +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $F$ -\end_inset +flatten_q +\end_layout -, -\begin_inset Formula $G$ \end_inset - are any bifunctors + above: +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +val rhs: M[Unit] = for { // This is flatten(h_q_map_h) === flatten(q). \end_layout -\end_inset - - -\begin_inset Text +\begin_layout Plain Layout + + s <- get +\end_layout \begin_layout Plain Layout -\size footnotesize -Statement -\begin_inset space ~ -\end_inset + _ <- set(s + 1) +\end_layout +\begin_layout Plain Layout -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Statement-mutually-recursive-greatest-fixpoints" -plural "false" -caps "false" -noprefix "false" +} yield () +\end_layout \end_inset \end_layout -\end_inset - - - - -\begin_inset Text +\begin_layout Standard +The left-hand side and the right-hand side of the law differ only in the + +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -\begin_inset Formula $G^{\exists C.\,F^{C}}\cong\forall D.\,(\forall C.\,F^{C}\rightarrow D)\rightarrow G^{D}$ +set +\end_layout + \end_inset + operation ( +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +set(s + n) \end_layout \end_inset - - -\begin_inset Text + + vs. +\begin_inset space ~ +\end_inset + + +\begin_inset listings +inline true +status open \begin_layout Plain Layout -\size footnotesize -Any -\begin_inset Formula $F$ +set(s + 1) +\end_layout + \end_inset -, any functor -\begin_inset Formula $G$ +). + So, they are equal only when +\begin_inset Formula $n=1$ \end_inset + (that is, for +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +h_1_1 \end_layout \end_inset - - -\begin_inset Text - -\begin_layout Plain Layout -\size footnotesize -Exercise -\begin_inset space ~ +). + It follows that, for all +\begin_inset Formula $n\ge2$ \end_inset + and for all +\begin_inset Formula $1\le k\le n$ +\end_inset -\begin_inset CommandInset ref -LatexCommand ref -reference "par:Exercise-additional-16-3" -plural "false" -caps "false" -noprefix "false" +, the function +\begin_inset Formula $h_{n,k}$ +\end_inset + of type +\begin_inset Formula $M^{X}\rightarrow M^{X}$ \end_inset + violates the composition law of monad morphisms when applied to the chosen + value +\begin_inset Formula $q:M^{M^{X}}$ +\end_inset +. \end_layout +\begin_layout Standard +Let us now summarize this derivation in code notation. + The left-hand side of the composition law is: +\begin_inset Formula +\begin{align*} + & \text{ftn}_{M}(q)=s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}}\quad,\\ + & h_{n,k}(\text{ftn}_{M}(q))=s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+n)^{:\text{Int}}\quad. +\end{align*} + +\end_inset + +Here we used the fact that +\begin_inset Formula $h_{n,k}(m)$ \end_inset - - - + repeats +\begin_inset Formula $n$ +\end_inset + + times the effect of +\begin_inset Formula $m$ \end_inset + (and that effect increments the value +\begin_inset Formula $s$ +\end_inset +). + \end_layout -\begin_layout Plain Layout -\begin_inset Caption Standard +\begin_layout Standard +Turn to the right-hand side of the law and calculate: +\begin_inset Formula +\begin{align*} + & q\triangleright h_{n,k}^{\uparrow M}=s^{:\text{Int}}\rightarrow(\_^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}})\times s=q\quad,\\ + & h_{n,k}(q\triangleright h_{n,k}^{\uparrow M})=s^{:\text{Int}}\rightarrow(\_^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}})\times s=q\quad,\\ + & \text{ftn}_{M}(q)=s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}}\quad. +\end{align*} -\begin_layout Plain Layout -Type isomorphisms for existential types. -\begin_inset CommandInset label -LatexCommand label -name "tab:Type-identities-for-existential-types" +\end_inset + +The condition for the two sides of the law to be equal is: +\begin_inset Formula +\[ +s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+n)^{:\text{Int}}\overset{?}{=}s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}}\quad. +\] \end_inset +This holds only if +\begin_inset Formula $n=1$ +\end_inset +. \end_layout +\begin_layout Standard +It follows that +\begin_inset Formula $h_{1,1}$ \end_inset + (which is an identity function of type +\begin_inset Formula $M^{X}\rightarrow M^{X}$ +\end_inset -\end_layout - +) is the only monad morphism that fits the required type. + +\begin_inset Formula $\square$ \end_inset diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 7d353a08a..0dc5c210f 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -6314,15 +6314,15 @@ can be generalized to the following isomorphism, \end_inset -where the type constructor +as long as the type constructor \begin_inset Formula $P$ \end_inset - must satisfy the property we call + is, in our terminology, \begin_inset Quotes eld \end_inset -non-disjunctivity +non-disjunctive \begin_inset Quotes erd \end_inset @@ -6343,7 +6343,8 @@ noprefix "false" gives a formal definition of that property and goes through structural analysis, discovering what type constructors are non-disjunctive. - Several examples of non-disjunctive type constructors are shown in Example + Some recipes for building non-disjunctive type constructors are shown in + Example \begin_inset space ~ \end_inset @@ -6355,14 +6356,80 @@ plural "false" caps "false" noprefix "false" +\end_inset + + and are generalized in Table +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Non-disjunctive-type-constructions" +plural "false" +caps "false" +noprefix "false" + \end_inset . \end_layout +\begin_layout Standard +We turn to a brief study of existentially quantified types. + Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Existential-type-quantifiers" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + proves the two co-Yoneda identities and establishes some fundamental properties + of existential types. + Then Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:The-greatest-fixpoints-and-Church-co-Yoneda" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + shows that the greatest fixpoints are given by the Church encoding: +\begin_inset Formula +\[ +\nu A.\,F^{A}\cong\exists A.\,(A\rightarrow F^{A})\times A\quad, +\] + +\end_inset + +and proves the Church-co-Yoneda identity: +\begin_inset Formula +\[ +G^{\nu A.\,F^{A}}\cong\exists A.\,(A\rightarrow F^{A})\times G^{A}\quad. +\] + +\end_inset + +This identity allows us to derive the nested fixpoint lemma and the mutual + recursion formula for the greatest fixpoints. +\end_layout + \begin_layout Standard These techniques allow us to derive a number of properties of types with - universal quantifiers. + universal and existential quantifiers. Tables \begin_inset space ~ \end_inset @@ -6426,58 +6493,6 @@ noprefix "false" law. \end_layout -\begin_layout Standard -We turn to a brief study of existentially quantified types. - Section -\begin_inset space ~ -\end_inset - - -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Existential-type-quantifiers" -plural "false" -caps "false" -noprefix "false" - -\end_inset - - proves the two co-Yoneda identities and establishes some fundamental properties - of existential types. - Then Section -\begin_inset space ~ -\end_inset - - -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:The-greatest-fixpoints-and-Church-co-Yoneda" -plural "false" -caps "false" -noprefix "false" - -\end_inset - - shows that the greatest fixpoints are given by the Church encoding: -\begin_inset Formula -\[ -\nu A.\,F^{A}\cong\exists A.\,(A\rightarrow F^{A})\times A\quad, -\] - -\end_inset - -and proves the Church-co-Yoneda identity: -\begin_inset Formula -\[ -G^{\nu A.\,F^{A}}\cong\exists A.\,(A\rightarrow F^{A})\times G^{A}\quad. -\] - -\end_inset - -This identity allows us to derive the nested fixpoint lemma and the mutual - recursion formula for the greatest fixpoints. -\end_layout - \begin_layout Standard \begin_inset ERT status open diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index fe69fa147e7851ffe01fd87414cfe3538a28ab82..a030f488dd7335611eaa5c17e200611608e5c368 100644 GIT binary patch delta 147 zcmX?Ra?E7I8WB#*5F;Zi6C*35$y-H?ka!lbN%Lv!SJ(4Ivei HwWXv16*DH2 delta 147 zcmX?Ra?E7I8WB$O5JPh-Lo+Mm$y-H?ka! Any! in Scala: +\begin{lstlisting} +def toAny[T](t: T): Any = t +\end{lstlisting} + This is just an identity function that relabels the types. So, this +function establishes the subtyping relation \lstinline!T <: Any!. + +\textbf{(2)} The type equivalence $\exists X.\,X\cong\bbnum 1$ may +appear counterintuitive. The unit type has only one distinct value; +but there are infinitely many ways of creating a value of type $\exists X.\,X$. +We may take any value $t:T$ of any type $T$ and \textsf{``}pack\textsf{''} that +value into a value of type $\exists X.\,X$ by hiding the type $T$, +similarly to the function \lstinline!toAny!. +\begin{lstlisting}[mathescape=true] +sealed trait ExistsX // Implements the type $\color{dkgreen}\exists X.\,X$. +final case class ExistsX0[X](x: X) +def hide[T](t: T): ExistsX = ExistsX0[T](t) +val x1: ExistsX = hide(123) +val x2: ExistsX = hide(124) +val x3: ExistsX = hide("abc") +\end{lstlisting} +This code may suggest that we are able to create many different values +of type \lstinline!ExistsX!. How can it be that \lstinline!ExistsX! +is equivalent to a unit type with a single distinct value? The reason +is that no fully parametric functions will be able to detect any difference +between all those values. A fully parametric function may pattern-match +on \lstinline!ExistsX0(x)! but must treat the type of \lstinline!x! +as arbitrary and unknown, with no operations available for computing +anything out of \lstinline!x!. So, there will be no way to determine +the actual type and value of \lstinline!x! and to make any decisions +based on them. A computer\textsf{'}s memory will probably store different bit +patterns when representing \lstinline!hide(123)! and \lstinline!hide(124)!. +But that difference remains unobservable in fully parametric code. +$\square$ + +We may use Eq.~(\ref{eq:existential-via-universal-Yoneda}) to replace +the existential quantifier by the universal one when proving properties +of existentially quantified types. + +\subsubsection{Example \label{subsec:Example-simple-existential-derivation}\ref{subsec:Example-simple-existential-derivation}\index{examples}} + +Show that $\exists A.\,F^{A}\rightarrow A\cong\bbnum 1$ for any type +constructor $F$. + +\subparagraph{Solution} + +Use Eq.~(\ref{eq:existential-via-universal-Yoneda}) and write: \[ -(A\rightarrow F^{B})\rightarrow F^{C}\cong(\forall X.\,R^{X}\rightarrow F^{X})\rightarrow F^{C}\cong(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\quad. +\exists A.\,F^{A}\rightarrow A=\forall B.\,(\forall A.\,(F^{A}\rightarrow A)\rightarrow B)\rightarrow B\quad. \] -So, the left-hand side of Eq.~(\ref{eq:jaskelioff-o-connor-theorem}) -is equivalent to: +Statement~\ref{subsec:Statement-application-full-relation} with +$P^{A}\triangleq F^{A}\rightarrow A$ and $K\triangleq B$ shows that +$\forall A.\,(F^{A}\rightarrow A)\rightarrow B\cong B$ as the type +constructor $F^{A}\rightarrow A$ is \textsf{``}lifting-to-full\textsf{''} by Statement~\ref{subsec:Statement-undisjunctive-type-constructors-structural}(c, +d). So, we get: \[ -\forall(F\in P\text{-typeclass}).\,(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\quad. +\exists A.\,F^{A}\rightarrow A=\forall B.\,B\rightarrow B\cong\bbnum 1\quad. \] -\textbf{(3)} We use the covariant Yoneda identity in the category -of functors that belong to the $P$-typeclass. As we have found in -Section~\ref{subsec:Imposing-laws-of-P-typeclasses-via-monad-algebras}, -all those functors are $E$-monad algebras, which form a category. -The $P$-typeclass morphisms are in one-to-one correspondence with -the $E$-monad algebra morphisms. Therefore, we may write the covariant -Yoneda identity for that category as: + +\subsubsection{Example \label{subsec:Example-simple-existential-derivation-1-1}\ref{subsec:Example-simple-existential-derivation-1-1}} + +Let $P$ and $Q$ be any type constructors. + +\textbf{(a)} If $P^{A}\cong Q^{A}$ for all $A$ then $\exists A.\,P^{A}\cong\exists A.\,Q^{A}$. + +\textbf{(b)} For arbitrary $P$ and $Q$: \[ -\forall(F\in P\text{-typeclass}).\,(\forall X.\,Q^{X}\overset{P}{\rightarrow}F^{X})\rightarrow S^{F}\cong S^{Q}\quad, +\exists A.\,P^{A}+Q^{A}\cong(\exists A.\,P^{A})+(\exists A.\,Q^{A})\quad. \] -where $Q$ is any fixed functor from the $P$-typeclass, $S^{F}$ -is any type expression that is covariant in $F$, and the naturality -law with respect to $F$ is assumed to hold. We will use this Yoneda -identity with $Q=E^{R}$, and set $S^{F}$ to just $F^{C}$ (the application -of $F$ to the fixed type $C$). Then we get: -\[ -\forall(F\in P\text{-typeclass}).\,(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\cong(E^{R})^{C}\quad. -\] -The last type is the right-hand side of Eq.~(\ref{eq:jaskelioff-o-connor-theorem}). -So, Eq.~(\ref{eq:jaskelioff-o-connor-theorem}) holds. -Let us now derive the code that implements the type equivalence~(\ref{eq:jaskelioff-o-connor-theorem}) -in the direction of right-to-left. Suppose we are given a value $q$ -of the type in the right-hand side of Eq.~(\ref{eq:jaskelioff-o-connor-theorem}): -\[ -q:(E^{R})^{C}\quad. -\] -We need to retrace step \textbf{(3)} above and convert this $q$ to -a function $f$ of type: -\[ -f:\forall(F\in P\text{-typeclass}).\,(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\quad. -\] -The required function $f$ is defined by: -\[ -f^{F}\big(k^{:\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X}}\big)\triangleq k^{C}(q)\quad. -\] +\textbf{(c)} Show that following type identities do \emph{not} hold +in general: +\begin{align*} + & \exists A.\,P^{A}\times Q^{A}\not\cong(\exists A.\,P^{A})\times(\exists A.\,Q^{A})\quad,\\ + & R\rightarrow(\exists A.\,P^{A})\not\cong\exists A.\,R\rightarrow P^{A}\quad. +\end{align*} +(Similar identities do hold for the universal quantifiers; see Statement~\ref{subsec:Statement-general-identities-forall}.) -Continue by retracing step \textbf{(2)}, converting $f$ to a function -$g$ of type: +\subparagraph{Solution} + +\textbf{(a)} Suppose we have an isomorphism: \[ -g:\forall(F\in P\text{-typeclass}).\,(\forall X.\,R^{X}\rightarrow F^{X})\rightarrow F^{C}\quad. +f^{A}:P^{A}\rightarrow Q^{A}\quad,\quad\quad g^{A}:Q^{A}\rightarrow P^{A}\quad. \] -The function $g$ is defined by: +The types $\exists A.\,P^{A}$ and $\exists A.\,Q^{A}$ are equivalent +to some type expressions involving only universal quantifiers and +the type constructors $P$, $Q$. +\begin{align*} + & \exists A.\,P^{A}\cong\exists A.\,Q^{A}\\ +{\color{greenunder}\text{is the same as}:}\quad & \forall D.\,(\forall A.\,P^{A}\rightarrow D)\rightarrow D\cong\forall D.\,(\forall A.\,Q^{A}\rightarrow D)\rightarrow D\quad. +\end{align*} +Then we can apply Statement~\ref{subsec:Statement-isomorphism-under-type-constructor} +repeatedly to show that those type expressions are isomorphic as types: +\begin{align*} + & \forall A.\,P^{A}\rightarrow D\cong\forall A.\,Q^{A}\rightarrow D\quad,\\ + & (\forall A.\,P^{A}\rightarrow D)\rightarrow D\cong(\forall A.\,Q^{A}\rightarrow D)\rightarrow D\quad,\\ + & \forall D.\,(\forall A.\,P^{A}\rightarrow D)\rightarrow D\cong\forall D.\,(\forall A.\,Q^{A}\rightarrow D)\rightarrow D\quad. +\end{align*} + +\textbf{(b)} Use Eq.~(\ref{eq:existential-via-universal-Yoneda}) +and write: +\begin{align*} + & \exists A.\,P^{A}+Q^{A}=\forall B.\,(\forall A.\,\gunderline{P^{A}+Q^{A}\rightarrow B})\rightarrow B\\ + & =\forall B.\,(\forall A.\,(P^{A}\rightarrow B)\times(Q^{A}\rightarrow B))\rightarrow B\\ + & =\forall B.\,(\gunderline{\forall A.\,P^{A}\rightarrow B})\times(\gunderline{\forall A.\,Q^{A}\rightarrow B})\rightarrow B\\ +{\color{greenunder}\text{use Eq.\,(\ref{eq:existential-via-universal})}:}\quad & =\forall B.\,(\gunderline{(\exists A.\,P^{A})\rightarrow B)\times((\exists A.\,Q^{A})\rightarrow B})\rightarrow B\\ + & =\forall B.\,\big((\exists A.\,P^{A})+(\exists A.\,Q^{A})\,\gunderline{\rightarrow B\big)\rightarrow B}\\ +{\color{greenunder}\text{Yoneda identity}:}\quad & =(\exists A.\,P^{A})+(\exists A.\,Q^{A})\quad. +\end{align*} + +\textbf{(c)} The first counter-example is found via the co-Yoneda +identity itself: \[ -g^{F}\big(k^{:\forall X.\,R^{X}\rightarrow F^{X}}\big)\triangleq f^{F}\big(\forall Y.\,r^{:(E^{R})^{Y}}\rightarrow\text{run}_{E}^{R,Y}(k)(r)\big)\quad, +\exists A.\,(A\rightarrow R)\times F^{A}\cong F^{R}\quad. \] -where the universal runner ($\text{run}_{E}^{T,Y}$) has type: +Splitting the left-hand side into a product of two existential types, +we get: \[ -\text{run}_{E}^{T,Y}:(\forall X.\,T^{X}\rightarrow F^{X})\rightarrow(E^{T})^{Y}\rightarrow F^{Y}\quad. +(\exists A.\,(A\rightarrow R))\times(\exists A.\,F^{A})\cong\bbnum 1\times F^{\bbnum 1}\cong F^{\bbnum 1}\quad. \] +But the last type is not equivalent to $F^{R}$. -It remains to retrace step \textbf{(1)} and define a function $h$ -of type: +The second counter-example is with the following type: \[ -h:\forall(F\in P\text{-typeclass}).\,(A\rightarrow F^{B})\rightarrow F^{C}\quad. +P^{A}\triangleq(A\rightarrow Q)\times A\quad. \] -We implement $h$ via this code: +Here $Q$ is a fixed type. By the co-Yoneda identity, we have $\exists A.\,P^{A}\cong Q$ +and so $R\rightarrow(\exists A.\,P^{A})\cong R\rightarrow Q$. Now +let us simplify the other side: +\begin{align*} + & \exists A.\,R\rightarrow P^{A}=\exists A.\,R\rightarrow(A\rightarrow Q)\times A\\ + & \quad\cong\exists A.\,(R\rightarrow A\rightarrow Q)\times(R\rightarrow A)\\ +{\color{greenunder}\text{co-Yoneda identity}:}\quad & \quad\cong R\rightarrow R\rightarrow Q\quad. +\end{align*} +The last type is not equivalent to $R\rightarrow Q$. $\square$ + +\subsubsection{Statement \label{subsec:Statement-commute-existential}\ref{subsec:Statement-commute-existential} +(co-Fubini theorem)} + +For any type constructor $P$ with two parameters (not necessarily +covariant or contravariant): \[ -h^{F}(k^{:A\rightarrow F^{B}})\triangleq g^{F}\big(\forall X.\,a^{:A}\times t^{:B\rightarrow X}\rightarrow k(a)\triangleright t^{\uparrow F}\big)\quad. +\exists A.\,\exists B.\,P^{A,B}\cong\exists B.\,\exists A.\,P^{A,B}\quad. \] -This completes the code that transforms $q$ into $h$. $\square$ - -We will now apply the Jaskelioff-O\textsf{'}Connor theorem to prove some useful -type equivalences. -\subsubsection{Statement \label{subsec:Statement-identity-monad-morphism}\ref{subsec:Statement-identity-monad-morphism}} -Denote by $F\xrightarrow{\text{Monad}}G$ (more verbosely, $\forall X.\,F^{X}\xrightarrow{\text{Monad}}G^{X}$) -the type of monad morphisms between monads $F$ and $G$. Those are -natural transformations of type $\forall X.\,F^{X}\rightarrow G^{X}$ -that additionally satisfy the laws of monad morphisms. Denote by $\text{Id}$ -the identity monad ($\text{Id}^{A}\triangleq A$). +\subparagraph{Proof} -\textbf{(a)} The standard monad method $\text{pu}_{M}:\forall A.\,A\rightarrow M^{A}$ -is the only monad morphism of type $\text{Id}\xrightarrow{\text{Monad}}M$ -that works in the same way for all monads $M$.\footnote{See \texttt{\href{https://cstheory.stackexchange.com/questions/53389/}{https://cstheory.stackexchange.com/questions/53389/}}} -We can express this as a type equivalence: +We rewrite $\exists A.\,\exists B.\,P^{A,B}$ via universal quantifiers: +\begin{align*} + & \gunderline{\exists A.}\,\exists B.\,P^{A,B}\\ +{\color{greenunder}\text{use Eq.\,(\ref{eq:existential-via-universal-Yoneda})}:}\quad & \cong\forall D.\,\big(\forall A.\,\gunderline{(\exists B.\,P^{A,B})\rightarrow D})\rightarrow D\\ +{\color{greenunder}\text{use Eq.\,(\ref{eq:existential-via-universal})}:}\quad & \cong\forall D.\,\big(\forall A.\,\forall B.\,P^{A,B}\rightarrow D)\rightarrow D\quad. +\end{align*} +If we rewrite $\exists B.\,\exists A.\,P^{A,B}$ similarly, we will +get: \[ -\forall M^{:\text{Monad}}.\,\text{Id}\xrightarrow{\text{Monad}}M\cong\bbnum 1\quad. +\exists B.\,\exists A.\,P^{A,B}\cong\forall D.\,\big(\forall B.\,\forall A.\,P^{A,B}\rightarrow D)\rightarrow D\quad. \] +Statement~\ref{subsec:Statement-Fubini-theorem} gives $\forall A.\,\forall B.\,P^{A,B}\cong\forall B.\,\forall A.\,P^{A,B}$, +completing the proof. $\square$ -\textbf{(b)} The identity function of type $\forall X.\,M^{X}\rightarrow M^{X}$ -is the only monad morphism of type $M\xrightarrow{\text{Monad}}M$ -that works in the same way for all monads $M$.\footnote{See \texttt{\href{https://stackoverflow.com/questions/61444425/}{https://stackoverflow.com/questions/61444425/}}} -We can express this as a type equivalence: +Now we will prove some more technical properties of existential types. + +In the next two statements, we work with a fixed type constructor +$P$, which is not assumed to be covariant or contravariant. For brevity, +we denote: \[ -\forall M^{:\text{Monad}}.\,M\xrightarrow{\text{Monad}}M\cong\bbnum 1\quad. +E\triangleq\forall B.\,(\forall A.\,P^{A}\rightarrow B)\rightarrow B\quad. \] -\subparagraph{Proof} +\subsubsection{Statement \label{subsec:Statement-identity-law-of-pack}\ref{subsec:Statement-identity-law-of-pack}} -The \lstinline!Monad! typeclass has methods in the form of a $P$-typeclass -for functors $K$ if we define $P$ by $(P^{K})^{A}\triangleq A+K^{K^{A}}$. -Then the methods of the \lstinline!Monad! typeclass are represented -by a single value of type: -\[ -\forall A.\,(P^{K})^{A}\rightarrow K^{A}=\forall A.\,A+K^{K^{A}}\rightarrow K^{A}\cong(\forall A.\,A\rightarrow K^{A})\times(\forall A.\,K^{K^{A}}\rightarrow K^{A})\quad. -\] -This is a tuple type describing the type signatures of $K$\textsf{'}s \lstinline!pure! -and \lstinline!flatten! methods when $K$ is a monad. So, the Jaskelioff-O\textsf{'}Connor -theorem applies to the \lstinline!Monad! typeclass. The free monad -constructor ($E$) is defined recursively as $(E^{F})^{A}\triangleq A+F^{(E^{F})^{A}}$, -making $E^{F}$ a monad when $F$ is any functor. The free monad\textsf{'}s -universal runner is defined by: +Values of type $E$ are constructed via the standard function \lstinline!pack! +that has the following type signature: \begin{align*} - & \text{run}_{E}^{F,A}:(\forall X.\,F^{X}\rightarrow M^{X})\rightarrow(E^{F})^{A}\rightarrow M^{A}\quad,\\ - & \text{run}_{E}^{F,A}\big(k^{:\forall X.\,F^{X}\rightarrow M^{X}}\big)\triangleq\,\begin{array}{|c||c|} - & M^{A}\\ -\hline A & \text{pu}_{M}\\ -F^{(E^{F})^{A}} & k^{(E^{F})^{A}}\bef\text{flm}_{M}\big(\overline{\text{run}}_{E}^{F,A}(k)\big) -\end{array}\quad. + & \text{pack}:\forall T.\,P^{T}\rightarrow E\quad,\\ +{\color{greenunder}\text{or equivalently}:}\quad & \text{pack}:\forall T.\,P^{T}\rightarrow\forall B.\,(\forall A.\,P^{A}\rightarrow B)\rightarrow B\quad,\\ + & \text{pack}^{T}(p^{:P^{T}})\triangleq\forall B.\,\big(k^{:\forall A.\,P^{A}\rightarrow B}\big)\rightarrow k^{T}(p)\quad. +\end{align*} +Then the \textbf{identity law} of\index{identity laws!of pack@of \lstinline!pack!} +\lstinline!pack! holds: for any value $e:E$, +\begin{equation} +e^{E}(\text{pack})=e\quad.\label{eq:identity-law-of-pack} +\end{equation} +It is assumed that all values $e^{:E}$ obey their naturality law: +\begin{equation} +\text{for all }f^{:B\rightarrow C},k^{:\forall A.\,P^{A}\rightarrow B}:\quad f(e^{B}(k))=e^{C}(\forall A.\,k^{A}\bef f)\quad.\label{eq:naturality-law-of-e-derivation1} +\end{equation} + + +\subparagraph{Proof\protect\footnote{The author thanks \index{Dan Doel}Dan Doel for assistance with the +proof of this statement. See the discussion at \texttt{\protect\href{https://cstheory.stackexchange.com/questions/54124}{https://cstheory.stackexchange.com/questions/54124}}}} + +Both sides of Eq.~(\ref{eq:identity-law-of-pack}) have type $E$. +Since $E$ is a type of functions with a type parameter, the two sides +can be applied to an arbitrary type $U$ and an arbitrary value $u:\forall A.\,P^{A}\rightarrow U$ +to get two values of type $U$: +\begin{align*} +{\color{greenunder}\text{both sides of}:}\quad & e^{E}(\text{pack})\overset{?}{=}e\\ +{\color{greenunder}\text{can be applied to }U\text{ and }u\text{ and yield}:}\quad & \big(e^{E}(\text{pack})\big)^{U}(u)\overset{?}{=}e^{U}(u)\quad. \end{align*} -\textbf{(a)} Monad morphisms are natural transformations that satisfy -additional laws. We first consider the given type without restricting -the functions of type $A\rightarrow M^{A}$ to monad morphisms but -still assuming that they are natural transformations: +So, let us prove that for all types $U$ and all values $u:\forall A.\,P^{A}\rightarrow U$, +\begin{equation} +\big(e^{E}(\text{pack})\big)^{U}(u)\overset{?}{=}e^{U}(u)\quad.\label{eq:identity-law-of-pack-derivation1} +\end{equation} +To prove the last equation, we will rewrite it in the form of the +naturality law~(\ref{eq:naturality-law-of-e-derivation1}) by finding +suitable parameters $B$, $C$, $f$, and $k$. Once we manage to +do that, the proof of Eq.~(\ref{eq:identity-law-of-pack}) will be +completed. + +The left-hand side of Eq.~(\ref{eq:identity-law-of-pack-derivation1}) +will match the left-hand side of Eq.~(\ref{eq:naturality-law-of-e-derivation1}) +if we assign $B=E$, $k=\text{pack}$, and $f(e)\triangleq e^{U}(u)$. +The type of $f$ must be $B\rightarrow C$; since $f(e)$ has type +$U$, we need to set $C=U$. With these assignments, the right-hand +side of Eq.~(\ref{eq:naturality-law-of-e-derivation1}) becomes: \[ -\forall M^{:\text{Monad}}.\,\forall A.\,A\rightarrow M^{A}\quad. +e^{C}(k\bef f)=e^{U}(\forall A.\,\text{pack}^{A}\bef f)\quad. \] -By the Yoneda identity, we get the type equivalence: +This will be equal to the right-hand side $e^{U}(u)$ of Eq.~(\ref{eq:identity-law-of-pack-derivation1}) +if we show that: \[ -\forall A.\,A\rightarrow M^{A}\cong M^{\bbnum 1}\quad. +\forall A.\,\text{pack}^{A}\bef f\overset{?}{=}u\quad. \] -So, we have reduced the type to $\forall M^{:\text{Monad}}.\,M^{\bbnum 1}$. -This type will be in the form suitable for the Jaskelioff-O\textsf{'}Connor -theorem~(\ref{eq:jaskelioff-o-connor-theorem}) if we set $F=M$, -$A=\bbnum 0$, $C=\bbnum 1$; the parameter $B$ remains unused since -$A\rightarrow M^{B}=\bbnum 0\rightarrow M^{B}\cong\bbnum 1$. Then -Eq.~(\ref{eq:jaskelioff-o-connor-theorem}) gives: +Substitute the definitions of \lstinline!pack! and $f$, renaming +$A$ to $T$: \[ -\forall M^{:\text{Monad}}.\,M^{\bbnum 1}\cong\forall M^{:\text{Monad}}.\,(\bbnum 0\rightarrow M^{B})\rightarrow M^{\bbnum 1}\cong(E^{R})^{\bbnum 1}\quad, +\forall T.\,\text{pack}^{T}\bef f=\forall T.\,p^{:P^{T}}\rightarrow f\big(\forall B.\,\big(q^{:\forall A.\,P^{A}\rightarrow B}\big)\rightarrow q^{T}(p)\big)\quad. \] -where we must define $R^{X}=A\times(B\rightarrow X)$. However, setting -$A=\bbnum 0$ gives also $R=\bbnum 0$. Then the free monad $E^{R}$ -is the identity functor: +The function $f$ substitutes $B=U$ and $q=u$ into its function +parameter: \[ -(E^{R})^{C}=C+R^{(E^{R})^{C}}=C+\bbnum 0\cong C\quad. +f\big(\forall B.\,\big(q^{:\forall A.\,P^{A}\rightarrow B}\big)\rightarrow q^{T}(p)\big)=\big(\forall B.\,\big(q^{:\forall A.\,P^{A}\rightarrow B}\big)\rightarrow q^{T}(p)\big)^{U}(u)=u^{T}(p)\quad. \] -Finally, we obtain $(E^{R})^{\bbnum 1}=\bbnum 1$, and so: +So, we find: \[ -\forall M^{:\text{Monad}}.\,\forall A.\,A\rightarrow M^{A}\cong\bbnum 1\quad. +\forall T.\,\text{pack}^{T}\bef f=\forall T.\,p^{:P^{T}}\rightarrow u^{T}(p)=\forall T.\,u^{T}=u\quad. \] +This completes the proof. $\square$ -We conclude that \emph{without} restricting to monad morphisms there -is only a single function of the given type. It remains to derive -the code for that function and to verify that it is indeed a monad -morphism. +Finally, here is the key property required for proving the equivalence +of two formulations of existential types, Eq.~(\ref{eq:existential-via-universal}) +and Eq.~(\ref{eq:existential-via-universal-Yoneda}). -We begin with a unit value (that we denote by $1$) viewed as a value -of type $(E^{R})^{C}$ in the right-hand side of Eq.~(\ref{eq:jaskelioff-o-connor-theorem}). -We follow the proof of Statement~\ref{subsec:Statement-Jaskelioff-OConnor}. -The first step is to convert the value of type $(E^{R})^{C}$ into -a function $f$ of type: -\[ -f:\forall M^{:\text{Monad}}.\,\big(\forall X.\,(E^{R})^{X}\xrightarrow{\text{Monad}}M^{X}\big)\rightarrow M^{C}\quad. -\] -In our case, this function is simplified to: +\subsubsection{Statement \label{subsec:Statement-function-extension-rule}\ref{subsec:Statement-function-extension-rule}} + +The following type isomorphism holds: \begin{align*} - & f:\forall M^{:\text{Monad}}.\,\big(\forall X.\,\text{Id}^{X}\xrightarrow{\text{Monad}}M^{X}\big)\rightarrow M^{\bbnum 1}\quad,\\ - & f^{M}\big(k^{:\forall X.\,\text{Id}^{X}\xrightarrow{\text{Monad}}M^{X}}\big)\triangleq k^{\bbnum 1}(1)\quad. + & E\rightarrow R=(\exists A.\,P^{A})\rightarrow R\cong\forall C.\,P^{C}\rightarrow R\quad,\\ +{\color{greenunder}\text{or equivalently}:}\quad & \big(\forall B.\,(\forall A.\,P^{A}\rightarrow B)\rightarrow B\big)\rightarrow R\cong\forall C.\,P^{C}\rightarrow R\quad, \end{align*} -The next step is to convert $f$ to a function $g$ of type: -\[ -g:\forall M^{:\text{Monad}}.\,(\forall X.\,R^{X}\rightarrow M^{X})\rightarrow M^{C}\quad. -\] -In our case, $R^{X}=\bbnum 0$ and $R^{X}\rightarrow M^{X}\cong\bbnum 1$, -so this function is simplified to: +where $R$ is a fixed type. In this isomorphism, it is assumed that +the type $E$ contains only functions $e^{:E}$ that obey the naturality +law~(\ref{eq:naturality-law-of-e-derivation1}). + +This isomorphism can be also formulated via code like this: +\begin{equation} +\text{for all }e^{:E}\text{ and }r^{:E\rightarrow R}:\quad r(e)=e^{R}(\forall C.\,\text{pack}^{C}\bef r)\quad,\label{eq:surjectivity-of-pack} +\end{equation} +where the standard function \lstinline!pack! was defined in the proof +of Statement~\ref{subsec:Statement-identity-law-of-pack}. Any function +$r$ that consumes values of type $e$ can be expressed via application +of $r$ to values constructed via \lstinline!pack!. + +\subparagraph{Proof} + +The isomorphism is shown by defining two functions (\lstinline!inF! +and \lstinline!outF!): \begin{align*} - & g:\forall M^{:\text{Monad}}.\,\bbnum 1\rightarrow M^{\bbnum 1}\quad,\\ - & g^{M}(k^{:\bbnum 1})\triangleq f^{M}\big(\forall Y.\,r^{:(E^{R})^{Y}}\rightarrow\text{run}_{E}^{R,Y}(k)(r)\big)\\ - & \quad=f^{M}(\forall Y.\,r^{:Y}\rightarrow\text{pu}_{M}^{Y}(r))=\text{pu}_{M}^{\bbnum 1}(1)\quad. + & \text{inF}:(\forall C.\,P^{C}\rightarrow R)\rightarrow E\rightarrow R\quad,\\ + & \text{inF}\triangleq k^{:\forall C.\,P^{C}\rightarrow R}\rightarrow e^{:E}\rightarrow e^{R}(k)\quad,\\ + & \text{outF}:(E\rightarrow R)\rightarrow\forall C.\,P^{C}\rightarrow R\quad,\\ + & \text{outF}\triangleq r^{:E\rightarrow R}\rightarrow\forall C.\,p^{:P^{C}}\rightarrow r(\text{pack}^{C}(p))=r^{:E\rightarrow R}\rightarrow\forall C.\,\text{pack}^{C}\bef r\quad, \end{align*} -Finally, we convert $g$ to a function $h$ of type: +and by proving that those functions are inverses of each other. + +Without the type annotations, the code of \lstinline!inF! and \lstinline!outF! +is: +\[ +\text{inF}=k\rightarrow q\rightarrow q(k)\quad,\quad\quad\text{outF}=r\rightarrow p\rightarrow r(k\rightarrow k(p))\quad. +\] +Now it is quick to prove one direction of isomorphism ($\text{inF}\bef\text{outF}\overset{?}{=}\text{id}$): \begin{align*} - & h:\forall M^{:\text{Monad}}.\,(A\rightarrow M^{B})\rightarrow M^{C}\\ - & =\forall M^{:\text{Monad}}.\,(\bbnum 0\rightarrow M^{B})\rightarrow M^{\bbnum 1}\quad.\\ - & \cong\forall M^{:\text{Monad}}.\,\bbnum 1\rightarrow M^{\bbnum 1}\cong\forall M^{:\text{Monad}}.\,M^{\bbnum 1}\quad. +{\color{greenunder}\text{expect to equal }\text{id}:}\quad & \text{inF}\bef\text{outF}=k\rightarrow\text{outF}\,(q\rightarrow q(k))\\ + & =k\rightarrow p\rightarrow(q\rightarrow q(k))(k\rightarrow k(p))\\ + & =k\rightarrow\gunderline{p\rightarrow k(p)}=k\rightarrow k=\text{id}\quad. \end{align*} - There exists only one value of type $\forall M^{:\text{Monad}}.\,M^{\bbnum 1}$, -and that value is $\text{pu}_{M}(1)$. Converting that to the type -signature $\forall A.\:A\rightarrow M^{A}$, we recover just the standard -monad method $\text{pu}_{M}$. We know that $\text{pu}_{M}$ gives -a monad morphism between the identity monad and $M$ (see Statement~\ref{subsec:Statement-pure-M-is-monad-morphism}). -So, we have proved that there exists a unique monad morphism of type -$\forall M^{:\text{Monad}}.\,\text{Id}\xrightarrow{\text{Monad}}M$. -\textbf{(b)} Again, we first consider the given type without restricting -the functions of type $M^{X}\rightarrow M^{X}$ to monad morphisms -(but still assuming that they are natural transformations): +The other direction ($\text{outF}\bef\text{inF}\overset{?}{=}\text{id}$) +requires more work. The argument of the function $\text{outF}\bef\text{inF}$ +has type $E\rightarrow R$, and we need to show that for any function +$r^{:E\rightarrow R}$ the following equation holds: \[ -\forall M^{:\text{Monad}}.\,\forall X.\,M^{X}\rightarrow M^{X}\quad. +\text{inF}\,(\text{outF}\,(r))\overset{?}{=}r\quad,\quad\text{or equivalently}:\quad r\triangleright\text{outF}\triangleright\text{inF}\overset{?}{=}r\quad. \] -This type will be in the form suitable for the Jaskelioff-O\textsf{'}Connor -theorem~(\ref{eq:jaskelioff-o-connor-theorem}) if we set $F=M$, -$A=\bbnum 1$, and $B=C=X$. The functor $R$ is then defined by: +The last equation is between functions of type $E\rightarrow R$; +we may apply both sides to an arbitrary value $e^{:E}$ and require +that the results (of type $R$) should be equal: \[ -R^{T}\triangleq A\times(B\rightarrow T)\cong X\rightarrow T\quad, +\big(r\triangleright\text{outF}\triangleright\text{inF}\big)(e)\overset{?}{=}r(e)\quad. \] -and the functor $E^{R}$ (the free monad on $R$) is defined recursively -by: +We begin by subtituting the definitions of \lstinline!inF! and \lstinline!outF!: +\begin{align*} +{\color{greenunder}\text{expect to equal }r(e):}\quad & e\triangleright\big(r\triangleright\text{outF}\triangleright\text{inF}\big)=e\triangleright\big((\forall A.\,p^{:P^{A}}\rightarrow r(\text{pack}^{A}(p)))\triangleright\text{inF}\big)\\ + & =e^{R}\big(\forall A.\,p^{:P^{A}}\rightarrow r(\text{pack}^{A}(p))\big)=e^{R}(\forall A.\,\text{pack}^{A}\bef r)\quad. +\end{align*} +Since $e$ is unknown and arbitrary, we can make progress in the proof +only if we use the naturality law of $e$ as given by Eq.~(\ref{eq:naturality-law-of-e-derivation1}). +We assign $B=E$, $C=R$, $f=r$, $k=\text{pack}$ in that law and +obtain: \[ -(E^{R})^{T}\triangleq T+\big(X\rightarrow(E^{R})^{T}\big)\quad. +r(e^{E}(\text{pack}))=e^{R}(\forall A.\,\text{pack}^{A}\bef r)\quad. \] - With these definitions, Eq.~(\ref{eq:jaskelioff-o-connor-theorem}) -gives: +By the identity law of pack (Statement~\ref{subsec:Statement-identity-law-of-pack}), +$e^{E}(\text{pack})=e$. So, we conclude the derivation: +\begin{align*} +{\color{greenunder}\text{expect to equal }r(e):}\quad & e\triangleright\big(r\triangleright\text{outF}\triangleright\text{inF}\big)=\gunderline{e^{R}(\forall A.\,\text{pack}^{A}\bef r)}\\ +{\color{greenunder}\text{naturality law of }e:}\quad & =r(\gunderline{e^{E}(\text{pack})})\\ +{\color{greenunder}\text{identity law of }\text{pack}:}\quad & =r(e)\quad. +\end{align*} +We have proved the isomorphism and also verified Eq.~(\ref{eq:surjectivity-of-pack}). +$\square$ + +\subsection{Greatest fixpoints and the Church-co-Yoneda identity\label{subsec:The-greatest-fixpoints-and-Church-co-Yoneda}} + +We have seen that the least fixpoints of functors are expressed via +the Church encoding type that involves a universally quantified higher-order +function. An analogous encoding (with an existentially quantified +type) exists for greatest fixpoints. We will now prove some properties +of that encoding.\footnote{This section follows the logic given in P.~Wadler\textsf{'}s paper \textsf{``}Recursive +types for free\textsf{''}, except that we \emph{define} existential types +by Eq.~(\ref{eq:existential-via-universal-Yoneda}) via the universal +quantifier.} + +We work with a fixed covariant functor $F$ and denote by $C$ the +following Church-encoded type: \[ -\forall M^{:\text{Monad}}.\,\forall X.\,M^{X}\rightarrow M^{X}\cong\forall X.\,(E^{R})^{X}\quad. +C\triangleq\exists A.\,(A\rightarrow F^{A})\times A\quad. \] -We are using the functor $(E^{R})^{T}$ with the type parameter $T=X$; -however, $E^{R}$ also contains $X$ through the definition of $R$. -To avoid confusion and to simplify notation, let us write $G^{X}$ -instead of $(E^{R})^{X}$, where the type constructor $G$ is defined -recursively by: +We will prove that $C$ is the greatest fixpoint of the type equation +$X\cong F^{X}$; that is, $C=\nu X.\,F^{X}$. + +First, we define some auxiliary functions that work with the type +$C$ and prove their properties. + +The function \lstinline!unfold! constructs values of type $C$: +\begin{align*} + & \text{unfold}:\forall T.\,(T\rightarrow F^{T})\times T\rightarrow C\quad,\\ + & \text{unfold}^{T}(u^{:T\rightarrow F^{T}}\times t^{:T})\triangleq\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times A\rightarrow R}\rightarrow p^{T}(u\times t)\quad. +\end{align*} +Note that \lstinline!unfold! is the same as the function \lstinline!pack! +from Statement~\ref{subsec:Statement-identity-law-of-pack} if we +set $E=C$ and $P^{A}\triangleq(A\rightarrow F^{A})\times A$ in the +definition of \lstinline!pack!. + +By parametricity, the function \lstinline!unfold! satisfies a relational +naturality law: for all types $A$, $B$ and all functions $f^{:A\rightarrow B}$, +\begin{equation} +\text{if}\quad u\bef f^{\uparrow F}=f\bef v\quad\text{then}\quad\text{unfold}^{A}(u^{:A\rightarrow F^{A}}\times a^{:A})=\text{unfold}^{B}(v^{:B\rightarrow F^{B}}\times f(a))\quad.\label{eq:relational-naturality-law-of-unfold} +\end{equation} +In category theory, the precondition $u\bef f^{\uparrow F}=f\bef v$ +is known as the \textsf{``}$F$-coalgebra morphism law\textsf{''} of $f$. Let us +give some definitions for reference: + +\subsubsection{Definition \label{subsec:Definition-F-coalgebra}\ref{subsec:Definition-F-coalgebra}} + +Given a functor $F$, a type $A$ together with a function $u:A\rightarrow F^{A}$ +is called an $F$\textbf{-coalgebra}.\index{$F$-coalgebra} The type +$A$ is called the \textbf{carrier} of the $F$-coalgebra, and the +function $u$ is called the \textbf{structure map} of the $F$-coalgebra. +(Keep in mind that $u$ is not universally quantified over $A$; it +is a function that only works with a single, specified type $A$. +For a given type $A$, there could be several different structure +maps $u$, $u^{\prime}$, and so on; each of them will then define +a different $F$-coalgebra.) + +If $A$ and $B$ are two $F$-coalgebras with structure maps $u:A\rightarrow F^{A}$ +and $v:B\rightarrow F^{B}$ then a function $f:A\rightarrow B$ is +called an $F$-coalgebra morphism if this law holds: \[ -G^{X}\triangleq X+(X\rightarrow G^{X})\quad. +\xymatrix{\xyScaleY{2.3pc}\xyScaleX{2.5pc}A\ar[d]\sb(0.4){u}\ar[r]\sp(0.5){f} & B\ar[d]\sp(0.4){v}\\ +F^{A}\ar[r]\sp(0.5){f^{\uparrow F}} & F^{B} +} \] -(Note that $G$ is neither covariant nor contravariant.) With this -definition, we obtain: \[ -\forall M^{:\text{Monad}}.\,\forall X.\,M^{X}\rightarrow M^{X}\cong\forall X.\,G^{X}\quad. +u\bef f^{\uparrow F}=f\bef v\quad. \] +This is the $F$-coalgebra morphism law of $f$. $\square$ -To simpify the type $\forall X.\,G^{X}$, begin by expanding the recursive -type $G^{X}$: +It is also helpful to define a function \lstinline!unfoldF! that +constructs values of type $F^{C}$: \begin{align*} - & \forall X.\,G^{X}\cong\forall X.\,X+(X\rightarrow G^{X})\\ -{\color{greenunder}\text{non-disjunctivity}:}\quad & \cong(\forall X.\,X)+(\forall X.\,X\rightarrow G^{X})\\ -{\color{greenunder}\text{use }\forall X.\,X\cong\bbnum 0:}\quad & \cong\forall X.\,X\rightarrow G^{X}\quad. + & \text{unfoldF}:\forall T.\,(T\rightarrow F^{T})\times T\rightarrow F^{C}\quad,\\ + & \text{unfoldF}^{T}(u^{:T\rightarrow F^{T}}\times t^{:T})\triangleq t\triangleright u\triangleright\big(a^{:T}\rightarrow\text{unfold}^{T}(u\times a)\big)^{\uparrow F}\quad. \end{align*} -Here we used the non-disjunctivity property from Example~\ref{subsec:Example-undisjunctive-type-constructors}(e). -Continue expanding the recursive type: -\begin{align*} - & \forall X.\,X\rightarrow G^{X}\cong\forall X.\,X\rightarrow(X+(X\rightarrow G^{X}))\\ -{\color{greenunder}\text{non-disjunctivity}:}\quad & \cong(\gunderline{\forall X.\,X\rightarrow X})+\big(\forall X.\,X\rightarrow X\rightarrow G^{X}\big)\\ - & \cong\bbnum 1+\forall X.\,X\times X\rightarrow G^{X}\quad. -\end{align*} -The relevant non-disjunctivity property was shown in Example~\ref{subsec:Example-undisjunctive-type-constructors}(f). -Expand further, using the same non-disjunctivity property: -\begin{align*} - & \forall X.\,G^{X}\cong\bbnum 1+\forall X.\,X\times X\rightarrow G^{X}\\ - & \cong\bbnum 1+\forall X.\,X\times X\rightarrow(X+(X\rightarrow G^{X}))\\ -{\color{greenunder}\text{non-disjunctivity}:}\quad & \cong\bbnum 1+(\gunderline{\forall X.\,X\times X\rightarrow X})+\big(\forall X.\,X\times X\rightarrow X\rightarrow G^{X}\big)\\ - & \cong\bbnum 1+\bbnum 2+\forall X.\,X\times X\times X\rightarrow G^{X}\quad. -\end{align*} -Proceeding similarly, we obtain: -\[ -\forall X.\,\underbrace{X\times...\times X}_{n\text{ times}}\rightarrow G^{X}\cong\underbrace{\bbnum 1+...+\bbnum 1}_{n\text{ times}}+\forall X.\,\underbrace{X\times...\times X}_{n+1\text{ times}}\rightarrow G^{X}\quad. -\] -It follows by induction that $\forall X.\,G^{X}$ is equivalent to -an \textsf{``}infinite\textsf{''} sum type: +The isomorphism $C\cong F^{C}$ will be implemented via two functions: \[ -\forall X.\,G^{X}\cong\bbnum 1+\bbnum 2+\bbnum 3+... +\text{fix}:F^{C}\rightarrow C\quad,\quad\quad\text{unfix}:C\rightarrow F^{C}\quad, \] -Values of that type may be described by pairs $\left(n,k\right)$ -of natural numbers such that $1\le k\le n$. The number $n$ chooses -the part \textsf{``}$\bbnum n$\textsf{''} within the disjunctive type $\bbnum 1+\bbnum 2+\bbnum 3+...$, -where we denoted by \textsf{``}$\bbnum n$\textsf{''} the type $\underbrace{\bbnum 1+...+\bbnum 1}_{n\text{ times}}$. -The number $k$ chooses a specific unit value within $\underbrace{\bbnum 1+...+\bbnum 1}_{n\text{ times}}$. +which we define via \lstinline!unfold! and \lstinline!unfoldF! like +this: +\begin{align*} + & \text{unfix}:C\rightarrow F^{C}\quad,\quad\quad\text{unfix}\triangleq c^{:C}\rightarrow c^{F^{C}}(\forall A.\,\text{unfoldF}^{A})=c^{:C}\rightarrow c^{F^{C}}(\text{unfoldF})\quad,\\ + & \text{fix}:F^{C}\rightarrow C\quad,\quad\quad\text{fix}\triangleq p^{:F^{C}}\rightarrow\text{unfold}^{F^{C}}(\text{unfix}^{\uparrow F}\times p)\quad. +\end{align*} +Because of these functions, $C$ is at the same time an $F$-algebra +and an $F$-coalgebra. -The next step is to convert values $\left(n,k\right)$ of that type -into functions of type $M^{X}\rightarrow M^{X}$ that work in the -same way for all monads $M$ and all types $X$. We have to find out -whether any of those functions obey the laws of monad morphisms. For -that, we need to derive the specific code of those functions. We follow -the steps outlined in the proof of Statement~\ref{subsec:Statement-Jaskelioff-OConnor}. +\subsubsection{Statement \label{subsec:Statement-coalgebra-morphism-unfold}\ref{subsec:Statement-coalgebra-morphism-unfold}} -First, we translate pairs $\left(n,k\right)$ into values of type -$\forall X.\,G^{X}$ that we will denote by $q_{n,k}$. To achieve -that, we need to retrace the way we expanded the recursive type $G^{X}$. -As an example, consider the pair $\left(n=2,k=1\right)$. The value -$n=2$ corresponds to the type $\bbnum 2$, which was obtained from -$\forall X.\,X\rightarrow X\rightarrow X$ during expansion of $\forall X.\,G^{X}$. -The type $\forall X.\,X\rightarrow X\rightarrow X$ has only two distinct -values, which are functions that return the first or the second argument -of type $X$. The index $k=1$ selects the first of those values, -which is a function whose code is written as $x_{1}^{:X}\rightarrow x_{2}^{:X}\rightarrow x_{1}$. +For any $F$-coalgebra $A$ with a structure map $u:A\rightarrow F^{A}$, +denote by $\psi_{u}^{A}$ the following function of type $A\rightarrow C$: +\[ +\psi_{u}^{A}:A\rightarrow C\quad,\quad\quad\psi_{u}^{A}\triangleq a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\quad. +\] +Then $\psi_{u}^{A}$ is an $F$-coalgebra morphism of type $A\rightarrow C$. -To simplify notation, let us temporarily fix the type parameter $X$; -we will restore the quantifier $\forall X$ at the end of the derivation. +\subparagraph{Proof} -The type $X\rightarrow X\rightarrow X$ was found during expansion -of the recursive type $G^{X}$ as: +Write the $F$-coalgebra morphism law for that function: \[ -G^{X}=X+(X\rightarrow(X+(X\rightarrow(X+...))))\quad. +u\bef\big(a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\big)^{\uparrow F}\overset{?}{=}\big(a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\big)\bef v\quad. \] -So, the pair $\left(n=2,k=1\right)$ corresponds to the function $q_{2,1}^{X}:G^{X}$ -written as: -\begin{align*} - & q_{2,1}^{X}:X+(X\rightarrow(X+(X\rightarrow(X+(X\rightarrow G^{X})))))\quad,\\ - & q_{2,1}^{X}\triangleq\bbnum 0^{:X}+(x_{1}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{2}^{:X}\rightarrow(x_{1}+\bbnum 0^{:X\rightarrow G^{X}}))))\quad. -\end{align*} -In a similar way, we define the functions $q_{n,k}$ for any $1\le k\le n$: +Apply both sides to an arbitrary value $t^{:A}$ and obtain: \[ -q_{n,k}^{X}\triangleq\bbnum 0^{:X}+(x_{1}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{2}^{:X}\rightarrow...\rightarrow(\bbnum 0^{:X}+(x_{n}^{:X}\rightarrow(x_{k}+\bbnum 0^{:X\rightarrow G^{X}})))...)))\quad. +t\triangleright u\triangleright(a\rightarrow\text{unfold}^{A}(u\times a))^{\uparrow F}\overset{?}{=}\text{unfix}\,(\text{unfold}^{A}(u\times t))\quad. \] -To make this code description rigorous, let us define $u_{i,n,k}$ -and $v_{i,n}$ like this: +Begin with the right-hand side: \begin{align*} - & u_{i,n,k}\triangleq\bbnum 0^{:X}+(x_{i}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{i+1}^{:X}\rightarrow...\rightarrow(x_{n}^{:X}\rightarrow(x_{k}+\bbnum 0^{:X\rightarrow G^{X}}))...))),\\ - & v_{i,n}(x_{0})\triangleq\bbnum 0^{:X}+(x_{i}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{i+1}^{:X}\rightarrow...\rightarrow(x_{n}^{:X}\rightarrow(x_{0}+\bbnum 0^{:X\rightarrow G^{X}}))...))). -\end{align*} -These formulas hold for $1\le i\le k\le n$. An inductive definition -of $q_{n,k}^{X}$, $u_{i,n,k}$, and $v_{i,n}$ is: -\begin{align*} - & q_{n,k}^{X}=u_{1,n,k}\quad,\quad\quad u_{i,n,k}:G^{X}\quad,\quad\quad v_{i,n}:X\rightarrow G^{X}\quad,\\ -{\color{greenunder}\text{for }1\le i m.flatMap { x_2 => pure(x_1) } } -\end{lstlisting} -This code can be rewritten as a functor block, making its logic more -visually clear: -\begin{lstlisting} -def h_2_1(m: M[X]): M[X] = for { - x_1 <- m - x_2 <- m -} yield x_1 -\end{lstlisting} -The code runs two effects of \lstinline!m! but returns the first -value (\lstinline!x_1!), ignoring \lstinline!x_2!. - -Now we can generalize the code pattern from $h_{2,1}$ to $h_{n,k}$ -and write symbolically: -\begin{lstlisting} -def h_n_k(m: M[X]): M[X] = for { - x_1 <- m - x_2 <- m - ... - x_n <- m -} yield x_k -\end{lstlisting} -To prove that this is indeed the correct code for $h_{n,k}^{M}(m)$, -we need to use induction in $n$. We rewrite $q_{n,k}^{X}=u_{1,n,k}$ -and compute $\text{run}_{E}^{R,X}(p)(q_{n,k})=\text{run}_{E}^{R,X}(p)(u_{1,n,k})$. -Using the code of $\text{run}_{E}$, we obtain the following inductive -code definitions: +To prove item \textbf{(2)}, apply both sides to a type $R$ and a +value $p^{:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R}$: \begin{align*} -{\color{greenunder}\text{for }1\le i (A, Int) -val q: M[M[Unit]] = { s => ( { t => ((), s + 1) }, s) } -\end{lstlisting} +We set the following parameters in this law, \[ -M^{A}\triangleq\text{Int}\rightarrow A\times\text{Int}\quad,\quad\quad q:M^{M^{\bbnum 1}}\quad,\quad q\triangleq s^{:\text{Int}}\rightarrow(\_^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}})\times s\quad. +B=C\quad,\quad a=g\quad,\quad f=\psi_{u}^{A}\quad,\quad v=\text{unfix}\quad, \] -For more intuition, let us express \lstinline!q! via the \lstinline!State! -monad operations \lstinline!get! and \lstinline!set!: -\begin{lstlisting} -val get: M[Int] = s => (s, s) -val set: Int => M[Unit] = x => s => ((), x) -// Assuming that map and flatMap are defined for M: -val q: M[M[Unit]] = for { - s <- get -} yield set(s + 1) -\end{lstlisting} -Now we compute the two sides of the composition law, step by step. -First, we will use Scala\textsf{'}s functor block syntax. The \lstinline!flatten! -method can be written as: -\begin{lstlisting} -def flatten[A](mm: M[M[A]]): M[A] = for { - m <- mm - x <- m -} yield x -\end{lstlisting} -Substituting the value \lstinline!q! defined above, we get: -\begin{lstlisting} -val flatten_q: M[Unit] = for { // This is flatten(q). - m <- for { - s <- get - } yield set(s + 1) - x <- m -} yield x -\end{lstlisting} -Eliminate the nested \lstinline!for! and obtain: -\begin{lstlisting} -val flatten_q: M[Unit] = for { - s <- get - m = set(s + 1) - x <- m -} yield x -\end{lstlisting} -Or equivalently (as the returned value is always a unit value): -\begin{lstlisting} -val flatten_q: M[Unit] = for { - s <- get - _ <- set(s + 1) -} yield () -\end{lstlisting} -Applying \lstinline!h_n_k! to this value means writing code of the -form: -\begin{lstlisting} -val h_flatten_q: M[Unit] = for { - x_1 <- flatten_q - ... - x_n <- flatten_q -} yield x_k -\end{lstlisting} -The returned value in \lstinline!x_k! is in any case the unit value, -so let us focus on the state updates. Each \lstinline!flatten_q! -has the effect of reading the state value \lstinline!s! and storing -the incremented value \lstinline!s + 1!. The function \lstinline!h_n_k! -repeats $n$ times the effect of \lstinline!flatten_q!. This increments -the internal state $n$ times. So, the left-hand side of the law is -equivalent to: -\begin{lstlisting} -val lhs: M[Unit] = for { // This is h_flatten_q === h_n_k(flatten(q)). - s <- get - _ <- set(s + n) -} yield () -\end{lstlisting} +and obtain: +\[ +p^{A}(u\times g)=p^{C}(\text{unfix}\times g\triangleright(\psi_{u}^{A})^{\uparrow F})\quad. +\] +This will complete the proof of item \textbf{(2)} as long as the precondition +holds: +\begin{align*} + & u^{:A\rightarrow F^{A}}\bef f^{\uparrow F}\overset{?}{=}f\bef v^{:B\rightarrow F^{B}}\quad,\\ +{\color{greenunder}\text{or equivalently}:}\quad & u\bef(\psi_{u}^{A})^{\uparrow F}\overset{?}{=}\psi_{u}^{A}\bef\text{unfix}\quad. +\end{align*} +This holds by Statement~\ref{subsec:Statement-coalgebra-morphism-unfold}: +it is the $F$-coalgebra morphism law of $\psi_{u}^{A}$. $\square$ -Turning now to the right-hand side of the law, we write the first -sub-expression ($q\triangleright h_{n,k}^{\uparrow M}$, or in Scala, -\lstinline!q.map(h_n_k)!) as the following Scala code: -\begin{lstlisting} -val q_map_h: M[M[Unit]] = for { - m <- q -} yield h_n_k(m) -\end{lstlisting} -Substituting the code of \lstinline!q! (but not yet expanding \lstinline!h_n_k!), -we find: -\begin{lstlisting} -val q_map_h: M[M[Unit]] = for { - s <- get -} yield h_n_k(set(s + 1)) -\end{lstlisting} -The function call \lstinline!h_n_k(set(s + 1))! repeats $n$ times -the effect of \lstinline!set(s + 1)!, but \lstinline!s! is a fixed -value in that scope, so the result is equal to just a single effect: -\begin{lstlisting} -val q_map_h: M[M[Unit]] = for { - s <- get -} yield set(s + 1) -\end{lstlisting} -This is the same value as \lstinline!q! itself. +The Church-co-Yoneda identity can be used to prove the Church encoding +formula for simultaneous greatest fixpoints of several functors, similarly +to what we did in Section~\ref{subsec:Least-fixpoints-of-mutually-recursive-types}. +For simplicity, we will now show a proof for just two mutually recursive +types; the proof can be extended to any number of types. -The next sub-expression is \lstinline!h_n_k(q_map_h)!, which equals -\lstinline!h_n_k(q)!: -\begin{lstlisting} -val h_q_map_h: M[M[Unit]] = for { - x_1 <- q - ... - x_n <- q -} yield x_k -\end{lstlisting} -Substituting the code for \lstinline!q!, we get: -\begin{lstlisting} -val h_q_map_h: M[M[Unit]] = for { - x_1 <- for { - s <- get - } yield set(s + 1) - ... - x_n <- for { - s <- get - } yield set(s + 1) -} yield x_k -\end{lstlisting} -Eliminate the nested \lstinline!for! and obtain: -\begin{lstlisting} -val h_q_map_h: M[M[Unit]] = for { - s <- get - x_1 = set(s + 1) - ... - s <- get - x_n = set(s + 1) -} yield x_k -\end{lstlisting} -The code runs $n$ times the effect of \lstinline!get! but actually -never runs the effect of \lstinline!set!; the unevaluated effectful -value \lstinline!set(s + 1)! is merely assigned to each \lstinline!x_i! -and then returned. So, the code is equivalent to: -\begin{lstlisting} -val h_q_map_h: M[M[Unit]] = for { - s <- get -} yield set(s + 1) -\end{lstlisting} -This is again just equal to \lstinline!q!. +We will first prove a property of nested fixpoints. -It remains to apply \lstinline!flatten! to \lstinline!h_q_map_h!, -which is the same as \lstinline!flatten(q)! and was already computed -as \lstinline!flatten_q! above: -\begin{lstlisting} -val rhs: M[Unit] = for { // This is flatten(h_q_map_h) === flatten(q). - s <- get - _ <- set(s + 1) -} yield () -\end{lstlisting} +\subsubsection{Statement \label{subsec:Statement-nested-greatest-fixpoints}\ref{subsec:Statement-nested-greatest-fixpoints}} -The left-hand side and the right-hand side of the law differ only -in the \lstinline!set! operation (\lstinline!set(s + n)! vs.~\lstinline!set(s + 1)!). -So, they are equal only when $n=1$ (that is, for \lstinline!h_1_1!). -It follows that, for all $n\ge2$ and for all $1\le k\le n$, the -function $h_{n,k}$ of type $M^{X}\rightarrow M^{X}$ violates the -composition law of monad morphisms when applied to the chosen value -$q:M^{M^{X}}$. +For any bifunctor $F$, the following equivalence holds: +\[ +\nu A.\,(\nu B.\,F^{A,B})\cong\nu B.\,F^{B,B}\quad. +\] -Let us now summarize this derivation in code notation. The left-hand -side of the composition law is: -\begin{align*} - & \text{ftn}_{M}(q)=s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}}\quad,\\ - & h_{n,k}(\text{ftn}_{M}(q))=s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+n)^{:\text{Int}}\quad. -\end{align*} -Here we used the fact that $h_{n,k}(m)$ repeats $n$ times the effect -of $m$ (and that effect increments the value $s$). - -Turn to the right-hand side of the law and calculate: -\begin{align*} - & q\triangleright h_{n,k}^{\uparrow M}=s^{:\text{Int}}\rightarrow(\_^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}})\times s=q\quad,\\ - & h_{n,k}(q\triangleright h_{n,k}^{\uparrow M})=s^{:\text{Int}}\rightarrow(\_^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}})\times s=q\quad,\\ - & \text{ftn}_{M}(q)=s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}}\quad. -\end{align*} -The condition for the two sides of the law to be equal is: -\[ -s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+n)^{:\text{Int}}\overset{?}{=}s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}}\quad. -\] -This holds only if $n=1$. - -It follows that $h_{1,1}$ (which is an identity function of type -$M^{X}\rightarrow M^{X}$) is the only monad morphism that fits the -required type. $\square$ - -\subsection{Existential type quantifiers. Co-Yoneda identities} -The Yoneda identities allow us in many cases to simplify type expressions -with universal quantifiers. Similar identities hold for existentially -quantified types. +\subparagraph{Proof} -For the purposes of this and the following sections, we define the -existential quantifier via Eq.~(\ref{eq:existential-via-universal-Yoneda}): +Denote $G^{A,C}\triangleq(A\rightarrow C)\times A$ and write the +Church encoding for the fixpoints: \[ -\exists C.\,F^{C}\cong\forall D.\,\big(\forall C.\,(F^{C}\rightarrow D)\big)\rightarrow D\quad. +\nu A.\,(\nu B.\,F^{A,B})=\exists A.\,(A\rightarrow\nu B.\,F^{A,B})\times A=\exists A.\,G^{A,\,\nu B.\,F^{A,B}}\quad. \] -Here $F$ is any type constructor (not necessarily covariant or contravariant). - -\subsubsection{Statement \label{subsec:Statement-co-Yoneda-two-identities}\ref{subsec:Statement-co-Yoneda-two-identities}} - -For any functor $F$ and any contrafunctor $H$, the following identities -hold: -\begin{align*} -{\color{greenunder}\text{\textbf{(a)} }\text{covariant co-Yoneda identity}:}\quad & \exists A.\,(A\rightarrow R)\times F^{A}\cong F^{R}\quad,\\ -{\color{greenunder}\text{\textbf{(b)} }\text{contravariant co-Yoneda identity}:}\quad & \exists A.\,(R\rightarrow A)\times H^{A}\cong H^{R}\quad. -\end{align*} - - -\subparagraph{Proof} - -We use Eq.~(\ref{eq:existential-via-universal-Yoneda}) to express -$\exists A$ via $\forall A$. - -\textbf{(a)} We write: +View $A$ as fixed and use the Church-co-Yoneda identity (Statement~\ref{subsec:Statement-Church-co-Yoneda}): \begin{align*} -{\color{greenunder}\text{expect to equal }F^{R}:}\quad & \exists A.\,(A\rightarrow R)\times F^{A}\\ -{\color{greenunder}\text{definition of }\exists\text{ in Eq.~}(\ref{eq:existential-via-universal-Yoneda}):}\quad & \cong\forall B.\,\big(\forall A.\,\gunderline{(A\rightarrow R)\times F^{A}}\rightarrow B\big)\rightarrow B\\ -{\color{greenunder}\text{uncurry arguments}:}\quad & \cong\forall B.\,\big(\gunderline{\forall A.\,(A\rightarrow R)\rightarrow F^{A}\rightarrow B}\big)\rightarrow B\\ -{\color{greenunder}\text{contravariant Yoneda identity}:}\quad & \cong\gunderline{\forall B.\,\big(F^{R}\rightarrow B\big)\rightarrow B}\\ -{\color{greenunder}\text{covariant Yoneda identity}:}\quad & \cong F^{R}\quad. + & G^{A,\,\nu B.\,F^{A,B}}\cong\exists B.\,(B\rightarrow F^{A,B})\times\gunderline{G^{A,B}}\\ + & =\exists B.\,(B\rightarrow F^{A,B})\times(A\rightarrow B)\times A\\ + & =\exists B.\,(A\rightarrow B)\times H^{A,B}\quad, \end{align*} - -\textbf{(b)} We write: +where we defined $H$ by: +\[ +H^{A,B}\triangleq(B\rightarrow F^{A,B})\times A\quad. +\] +Now we can simplify the nested fixpoints: \begin{align*} -{\color{greenunder}\text{expect to equal }H^{R}:}\quad & \exists A.\,(R\rightarrow A)\times H^{A}\\ -{\color{greenunder}\text{definition of }\exists\text{ in Eq.~}(\ref{eq:existential-via-universal-Yoneda}):}\quad & \cong\forall B.\,\big(\forall A.\,\gunderline{(R\rightarrow A)\times H^{A}}\rightarrow B\big)\rightarrow B\\ -{\color{greenunder}\text{uncurry arguments}:}\quad & \cong\forall B.\,\big(\gunderline{\forall A.\,(R\rightarrow A)\rightarrow H^{A}\rightarrow B}\big)\rightarrow B\\ -{\color{greenunder}\text{covariant Yoneda identity}:}\quad & \cong\gunderline{\forall B.\,\big(H^{R}\rightarrow B\big)\rightarrow B}\\ -{\color{greenunder}\text{covariant Yoneda identity}:}\quad & \cong H^{R}\quad. +{\color{greenunder}\text{expect }\nu B.\,F^{B,B}:}\quad & \nu A.\,(\nu B.\,F^{A,B})=\gunderline{\exists A.\,\exists B.}\,(A\rightarrow B)\times H^{A,B}\\ +{\color{greenunder}\text{co-Fubini theorem (Statement~\ref{subsec:Statement-commute-existential})}:}\quad & \cong\exists B.\,\exists A.\,(A\rightarrow B)\times H^{A,B}\\ +{\color{greenunder}\text{co-Yoneda identity}:}\quad & \cong\exists B.\,\gunderline{H^{B,B}}=\exists B.\,(B\rightarrow F^{B,B})\times B\\ +{\color{greenunder}\text{Church encoding}:}\quad & \cong\nu B.\,F^{B,B}\quad. \end{align*} -$\square$ -To build up intuition, let us substitute $R=\bbnum 0$ and $R=\bbnum 1$ -into the co-Yoneda identities: -\subsubsection{Statement \label{subsec:Statement-co-Yoneda-two-identities-1}\ref{subsec:Statement-co-Yoneda-two-identities-1}} +\subsubsection{Statement \label{subsec:Statement-mutually-recursive-greatest-fixpoints}\ref{subsec:Statement-mutually-recursive-greatest-fixpoints}} -The following type equivalences hold: +Given any bifunctors $F$, $G$, define $T$ and $U$ as the simultaneous +greatest fixpoints of two type equations: +\[ +T=F^{T,U}\quad,\quad\quad U=G^{T,U}\quad. +\] +Then the types $T$ and $U$ can be expressed as: \begin{align*} -{\color{greenunder}\text{\textbf{(a)} for any functor }F:}\quad & \exists A.\,F^{A}\cong F^{\bbnum 1}\quad,\\ -{\color{greenunder}\text{\textbf{(b)} for any contrafunctor }F:}\quad & \exists A.\,H^{A}\cong H^{\bbnum 0}\quad. + & T\cong\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times A\quad,\\ + & U\cong\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times B\quad. \end{align*} \subparagraph{Proof} -For \textbf{(a)}, set $R=\bbnum 1$ in the covariant co-Yoneda identity: -\begin{align*} -{\color{greenunder}\text{left-hand side}:}\quad & \exists A.\,(\gunderline{A\rightarrow\bbnum 1})\times F^{A}\cong\exists A.\,\bbnum 1\times F^{A}\cong\exists A.\,F^{A}\quad,\\ -{\color{greenunder}\text{right-hand side}:}\quad & F^{\bbnum 1}\quad. -\end{align*} - -For \textbf{(b)}, set $R=\bbnum 0$ in the contravariant co-Yoneda -identity: -\begin{align*} -{\color{greenunder}\text{left-hand side}:}\quad & \exists A.\,(\gunderline{\bbnum 0\rightarrow A})\times H^{A}\cong\exists A.\,\bbnum 1\times H^{A}\cong\exists A.\,H^{A}\quad,\\ -{\color{greenunder}\text{right-hand side}:}\quad & H^{\bbnum 0}\quad. -\end{align*} - $\square$ - -With these properties, we get the following examples of type equivalences: -\begin{align*} - & \exists A.\,A\cong\bbnum 1\quad,\quad\quad\exists A.\,A\rightarrow R\cong\bbnum 1\quad,\quad\quad\exists A.\,A+R\cong\bbnum 1+R\quad,\\ - & \exists A.\,(R\rightarrow A)\times(A\rightarrow S)\cong R\rightarrow S\quad,\quad\quad\exists A.\,(A\rightarrow R)\times A\times A\cong R\times R\quad. -\end{align*} - - -\paragraph{Remarks} - -\textbf{(1)} The Scala type \lstinline!Any! closely corresponds to -the type $\exists X.\,X$, which is equivalent to \lstinline!Unit!. -The advantage of using \lstinline!Any! instead of \lstinline!Unit! -is that \lstinline!Any! is understood by the Scala compiler as a -supertype of \emph{all} Scala types (while \lstinline!Unit! is not). -Indeed, for any type $T$ there is an injective function $T\rightarrow\exists X.\,X$, -which corresponds to a function of type \lstinline!T => Any! in Scala: -\begin{lstlisting} -def toAny[T](t: T): Any = t -\end{lstlisting} - This is just an identity function that relabels the types. So, this -function establishes the subtyping relation \lstinline!T <: Any!. - -\textbf{(2)} The type equivalence $\exists X.\,X\cong\bbnum 1$ may -appear counterintuitive. The unit type has only one distinct value; -but there are infinitely many ways of creating a value of type $\exists X.\,X$. -We may take any value $t:T$ of any type $T$ and \textsf{``}pack\textsf{''} that -value into a value of type $\exists X.\,X$ by hiding the type $T$, -similarly to the function \lstinline!toAny!. -\begin{lstlisting}[mathescape=true] -sealed trait ExistsX // Implements the type $\color{dkgreen}\exists X.\,X$. -final case class ExistsX0[X](x: X) -def hide[T](t: T): ExistsX = ExistsX0[T](t) -val x1: ExistsX = hide(123) -val x2: ExistsX = hide(124) -val x3: ExistsX = hide("abc") -\end{lstlisting} -This code may suggest that we are able to create many different values -of type \lstinline!ExistsX!. How can it be that \lstinline!ExistsX! -is equivalent to a unit type with a single distinct value? The reason -is that no fully parametric functions will be able to detect any difference -between all those values. A fully parametric function may pattern-match -on \lstinline!ExistsX0(x)! but must treat the type of \lstinline!x! -as arbitrary and unknown, with no operations available for computing -anything out of \lstinline!x!. So, there will be no way to determine -the actual type and value of \lstinline!x! and to make any decisions -based on them. A computer\textsf{'}s memory will probably store different bit -patterns when representing \lstinline!hide(123)! and \lstinline!hide(124)!. -But that difference remains unobservable in fully parametric code. -$\square$ - -We may use Eq.~(\ref{eq:existential-via-universal-Yoneda}) to replace -the existential quantifier by the universal one when proving properties -of existentially quantified types. - -\subsubsection{Example \label{subsec:Example-simple-existential-derivation}\ref{subsec:Example-simple-existential-derivation}\index{examples}} - -Show that $\exists A.\,F^{A}\rightarrow A\cong\bbnum 1$ for any type -constructor $F$. - -\subparagraph{Solution} - -Use Eq.~(\ref{eq:existential-via-universal-Yoneda}) and write: -\[ -\exists A.\,F^{A}\rightarrow A=\forall B.\,(\forall A.\,(F^{A}\rightarrow A)\rightarrow B)\rightarrow B\quad. -\] -Statement~\ref{subsec:Statement-application-full-relation} with -$P^{A}\triangleq F^{A}\rightarrow A$ and $K\triangleq B$ shows that -$\forall A.\,(F^{A}\rightarrow A)\rightarrow B\cong B$ as the type -constructor $F^{A}\rightarrow A$ is \textsf{``}lifting-to-full\textsf{''} by Statement~\ref{subsec:Statement-undisjunctive-type-constructors-structural}(c, -d). So, we get: +If $T$ and $U$ are fixed (and equal to the correct greatest fixpoints) +then we can write: \[ -\exists A.\,F^{A}\rightarrow A=\forall B.\,B\rightarrow B\cong\bbnum 1\quad. +T=\nu A.\,F^{A,U}\quad,\quad\quad U=\nu B.\,G^{T,B}\quad. \] - - -\subsubsection{Example \label{subsec:Example-simple-existential-derivation-1-1}\ref{subsec:Example-simple-existential-derivation-1-1}} - -Let $P$ and $Q$ be any type constructors. - -\textbf{(a)} If $P^{A}\cong Q^{A}$ for all $A$ then $\exists A.\,P^{A}\cong\exists A.\,Q^{A}$. - -\textbf{(b)} For arbitrary $P$ and $Q$: +Now we can substitute $U$ into the equation for $T$: \[ -\exists A.\,P^{A}+Q^{A}\cong(\exists A.\,P^{A})+(\exists A.\,Q^{A})\quad. +T=\nu A.\,F^{A,\,\nu B.\,G^{T,B}}\quad. \] - -\textbf{(c)} Show that following type identities do \emph{not} hold -in general: +The last line is a fixpoint equation involving only $T$, so we may +express $T$ as the greatest fixpoint of that equation. Then we get: \begin{align*} - & \exists A.\,P^{A}\times Q^{A}\not\cong(\exists A.\,P^{A})\times(\exists A.\,Q^{A})\quad,\\ - & R\rightarrow(\exists A.\,P^{A})\not\cong\exists A.\,R\rightarrow P^{A}\quad. + & T=\nu C.\,\nu A.\,F^{A,\,\nu B.\,G^{C,B}}\\ +{\color{greenunder}\text{use Statement~\ref{subsec:Statement-nested-greatest-fixpoints} and set }A=C:}\quad & \cong\gunderline{\nu A.}\,F^{A,\,\nu B.\,G^{A,B}}\\ +{\color{greenunder}\text{use Church encoding}:}\quad & \cong\exists A.\:(A\rightarrow F^{A,\,\nu B.\,G^{A,B}})\times A\\ +{\color{greenunder}\text{define }N^{A,C}\triangleq(A\rightarrow F^{A,C})\times A:}\quad & =\exists A.\:N^{A,\,\nu B.\,G^{A,B}}\\ +{\color{greenunder}\text{Church-co-Yoneda identity (Statement~\ref{subsec:Statement-Church-co-Yoneda})}:}\quad & \cong\gunderline{\exists A.\,\exists B.}\,(B\rightarrow G^{A,B})\times N^{A,B}\quad. \end{align*} -(Similar identities do hold for the universal quantifiers; see Statement~\ref{subsec:Statement-general-identities-forall}.) - -\subparagraph{Solution} - -\textbf{(a)} Suppose we have an isomorphism: +Writing out the definition of $N^{A,B}$, we obtain the claimed Church +encoding for $T$: \[ -f^{A}:P^{A}\rightarrow Q^{A}\quad,\quad\quad g^{A}:Q^{A}\rightarrow P^{A}\quad. +T\cong\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times A\quad. \] -The types $\exists A.\,P^{A}$ and $\exists A.\,Q^{A}$ are equivalent -to some type expressions involving only universal quantifiers and -the type constructors $P$, $Q$. -\begin{align*} - & \exists A.\,P^{A}\cong\exists A.\,Q^{A}\\ -{\color{greenunder}\text{is the same as}:}\quad & \forall D.\,(\forall A.\,P^{A}\rightarrow D)\rightarrow D\cong\forall D.\,(\forall A.\,Q^{A}\rightarrow D)\rightarrow D\quad. -\end{align*} -Then we can apply Statement~\ref{subsec:Statement-isomorphism-under-type-constructor} -repeatedly to show that those type expressions are isomorphic as types: -\begin{align*} - & \forall A.\,P^{A}\rightarrow D\cong\forall A.\,Q^{A}\rightarrow D\quad,\\ - & (\forall A.\,P^{A}\rightarrow D)\rightarrow D\cong(\forall A.\,Q^{A}\rightarrow D)\rightarrow D\quad,\\ - & \forall D.\,(\forall A.\,P^{A}\rightarrow D)\rightarrow D\cong\forall D.\,(\forall A.\,Q^{A}\rightarrow D)\rightarrow D\quad. -\end{align*} + The formula for $U$ is derived similarly. $\square$ -\textbf{(b)} Use Eq.~(\ref{eq:existential-via-universal-Yoneda}) -and write: -\begin{align*} - & \exists A.\,P^{A}+Q^{A}=\forall B.\,(\forall A.\,\gunderline{P^{A}+Q^{A}\rightarrow B})\rightarrow B\\ - & =\forall B.\,(\forall A.\,(P^{A}\rightarrow B)\times(Q^{A}\rightarrow B))\rightarrow B\\ - & =\forall B.\,(\gunderline{\forall A.\,P^{A}\rightarrow B})\times(\gunderline{\forall A.\,Q^{A}\rightarrow B})\rightarrow B\\ -{\color{greenunder}\text{use Eq.\,(\ref{eq:existential-via-universal})}:}\quad & =\forall B.\,(\gunderline{(\exists A.\,P^{A})\rightarrow B)\times((\exists A.\,Q^{A})\rightarrow B})\rightarrow B\\ - & =\forall B.\,\big((\exists A.\,P^{A})+(\exists A.\,Q^{A})\,\gunderline{\rightarrow B\big)\rightarrow B}\\ -{\color{greenunder}\text{Yoneda identity}:}\quad & =(\exists A.\,P^{A})+(\exists A.\,Q^{A})\quad. -\end{align*} +\subsection{Summary of type isomorphisms} -\textbf{(c)} The first counter-example is found via the co-Yoneda -identity itself: -\[ -\exists A.\,(A\rightarrow R)\times F^{A}\cong F^{R}\quad. -\] -Splitting the left-hand side into a product of two existential types, -we get: -\[ -(\exists A.\,(A\rightarrow R))\times(\exists A.\,F^{A})\cong\bbnum 1\times F^{\bbnum 1}\cong F^{\bbnum 1}\quad. -\] -But the last type is not equivalent to $F^{R}$. - -The second counter-example is with the following type: -\[ -P^{A}\triangleq(A\rightarrow Q)\times A\quad. -\] -Here $Q$ is a fixed type. By the co-Yoneda identity, we have $\exists A.\,P^{A}\cong Q$ -and so $R\rightarrow(\exists A.\,P^{A})\cong R\rightarrow Q$. Now -let us simplify the other side: -\begin{align*} - & \exists A.\,R\rightarrow P^{A}=\exists A.\,R\rightarrow(A\rightarrow Q)\times A\\ - & \quad\cong\exists A.\,(R\rightarrow A\rightarrow Q)\times(R\rightarrow A)\\ -{\color{greenunder}\text{co-Yoneda identity}:}\quad & \quad\cong R\rightarrow R\rightarrow Q\quad. -\end{align*} -The last type is not equivalent to $R\rightarrow Q$. $\square$ - -\subsubsection{Statement \label{subsec:Statement-commute-existential}\ref{subsec:Statement-commute-existential} -(co-Fubini theorem)} - -For any type constructor $P$ with two parameters (not necessarily -covariant or contravariant): -\[ -\exists A.\,\exists B.\,P^{A,B}\cong\exists B.\,\exists A.\,P^{A,B}\quad. -\] +This Appendix has developed various parametricity techniques to prove +a number of type isomorphisms. The results are summarized in Tables~\ref{tab:Type-identities-proved-by-Yoneda}\textendash \ref{tab:Type-identities-for-existential-types}. +\begin{table}[h] +\begin{centering} +\begin{tabular}{|c|c|} +\hline +\textbf{\footnotesize{}Identity} & \textbf{\footnotesize{}Assumptions}\tabularnewline +\hline +\hline +{\footnotesize{}$\forall A.\,A\rightarrow A\cong\bbnum 1$} & \tabularnewline +\hline +{\footnotesize{}$\forall A.\,A\rightarrow F^{A}\cong F^{\bbnum 1}$} & {\footnotesize{}$F$ is any functor}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,A\times A\rightarrow F^{A}\cong F^{\bbnum 2}$} & {\footnotesize{}$F$ is any functor}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,A\cong\bbnum 0$} & \tabularnewline +\hline +{\footnotesize{}$\forall A.\,F^{A}\cong F^{\bbnum 0}$} & {\footnotesize{}$F$ is any functor}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,H^{A}\cong H^{\bbnum 1}$} & {\footnotesize{}$H$ is any contrafunctor}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,(A\rightarrow P)\rightarrow A\rightarrow Q\cong P\rightarrow Q$} & {\footnotesize{}$P$, $Q$ are fixed types}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,(P\rightarrow A)\rightarrow Q\rightarrow A\cong Q\rightarrow P$} & {\footnotesize{}$P$, $Q$ are fixed types}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,((A\rightarrow P)\rightarrow Q)\rightarrow(A\rightarrow S)\rightarrow R\cong((S\rightarrow P)\rightarrow Q)\rightarrow R$} & {\footnotesize{}$P$, $Q$, $R$, $S$ are fixed types}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,(P\rightarrow A\times Q)\rightarrow(A+R)\times S\cong$$(P\rightarrow Q)\rightarrow(P+R)\times S$} & {\footnotesize{}$P$, $Q$, $R$, $S$ are fixed types}\tabularnewline +\hline +\end{tabular} +\par\end{centering} +\caption{Type isomorphisms proved via Yoneda identities.\label{tab:Type-identities-proved-by-Yoneda}} +\end{table} -\subparagraph{Proof} +\begin{table} +\begin{centering} +\begin{tabular}{|c|c|c|} +\hline +\textbf{\footnotesize{}Identity} & \textbf{\footnotesize{}Assumptions} & \textbf{\footnotesize{}Source}\tabularnewline +\hline +\hline +{\footnotesize{}$\forall A.\,(F^{A}\rightarrow A)\rightarrow A\cong\mu A.\,F^{A}$} & {\footnotesize{}$F$ is any functor} & {\footnotesize{}Section~\ref{subsec:The-Church-encoding-of-recursive-types}}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,(H^{A}\rightarrow A)\rightarrow A\cong H^{\bbnum 1}$} & {\footnotesize{}$H$ is any contrafunctor} & {\footnotesize{}Statement~\ref{subsec:Example-simplify-quantifier-1-1}}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,(A\rightarrow A)\rightarrow H^{A}\cong H^{\bbnum 1}$} & {\footnotesize{}$H$ is any contrafunctor} & {\footnotesize{}Example~\ref{subsec:Example-strong-dinaturality-show-void}(b)}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,(F^{A}\rightarrow A)\rightarrow G^{A}\cong G^{\mu A.\,F^{A}}$} & {\footnotesize{}$F$, $G$ are any functors} & {\footnotesize{}Statement~\ref{subsec:Statement-Church-Yoneda-identity}}\tabularnewline +\hline +{\footnotesize{}$\mu A.\,\mu B.\,F^{A,B}\cong\mu B.\,F^{B,B}$} & {\footnotesize{}$F$ is any bifunctor} & {\footnotesize{}Statement~\ref{subsec:Statement-nested-fixpoints}}\tabularnewline +\hline +{\footnotesize{}}% +\begin{minipage}[c][12mm][t]{0.1mm}% +% +\end{minipage}{\footnotesize{}}% +\begin{minipage}[c]{0.43\columnwidth}% +\begin{center} +{\footnotesize{}$\mu A.\,P^{A,\,\mu B.\,Q^{A,B}}\cong$}\\ +{\footnotesize{}$\forall A.\,\forall B.\,(P^{A,B}\rightarrow A)\times(Q^{A,B}\rightarrow B)\rightarrow A$} +\par\end{center}% +\end{minipage} & {\footnotesize{}$P$, $Q$ are any bifunctors} & {\footnotesize{}Statement~\ref{subsec:Statement-nested-fixpoint-under-functor}}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,F^{A}\rightarrow P\cong P$} & {\footnotesize{}If $F^{A}\neq\bbnum 0$ for some $A$} & {\footnotesize{}Statement~\ref{subsec:Statement-application-full-relation}(a)}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,((A\rightarrow A)\rightarrow A)\rightarrow A\cong\bbnum 1+\bbnum 2+\bbnum 3+...$} & {\footnotesize{}~} & {\footnotesize{}Statement~\ref{subsec:Statement-advanced-type-equivalence}}\tabularnewline +\hline +{\footnotesize{}}% +\begin{minipage}[c][17mm][t]{0.1mm}% +% +\end{minipage}{\footnotesize{}}% +\begin{minipage}[c]{0.43\columnwidth}% +\begin{center} +{\footnotesize{}$\forall A.\,(H^{A}\rightarrow A)\rightarrow F^{A}+G^{A}\cong$}\\ +{\footnotesize{}$(\forall A.\:(H^{A}\rightarrow A)\rightarrow F^{A})\,+$}\\ +{\footnotesize{}$(\forall A.\:(H^{A}\rightarrow A)\rightarrow G^{A})$} +\par\end{center}% +\end{minipage} & {\footnotesize{}For any $F$, $G$, $H$} & {\footnotesize{}Example~\ref{subsec:Example-undisjunctive-type-constructors}(c)}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,\forall B.\,F^{A,B}\cong\forall B.\,\forall A.\,F^{A,B}$} & {\footnotesize{}For any $F$} & {\footnotesize{}Statement~\ref{subsec:Statement-Fubini-theorem-1}}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,(F^{A}+G^{A})\cong(\forall A.\,F^{A})+(\forall A.\,G^{A})$} & {\footnotesize{}For any $F$, $G$} & {\footnotesize{}Statement~\ref{subsec:Statement-general-identities-forall}(a)}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,(F^{A}\times G^{A})\cong(\forall A.\,F^{A})\times(\forall A.\,G^{A})$} & {\footnotesize{}For any $F$, $G$} & {\footnotesize{}Statement~\ref{subsec:Statement-general-identities-forall}(b)}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,R\rightarrow F^{A}\cong R\rightarrow(\forall A.\,F^{A})$} & {\footnotesize{}Any $F$, a fixed type $R$} & {\footnotesize{}Statement~\ref{subsec:Statement-general-identities-forall}(c)}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,F^{P^{A}}\cong F^{\forall A.\,P^{A}}$} & {\footnotesize{}$F$ is strictly positive} & {\footnotesize{}Statement~\ref{subsec:Statement-quantifier-across-functor}}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,F^{A}\cong\bbnum 0$ when $F^{\bbnum 0}\cong\bbnum 0$} & {\footnotesize{}$F$ is such that $F^{\bbnum 0}\cong\bbnum 0$} & {\footnotesize{}Statement~\ref{subsec:Statement-Fubini-theorem-1}}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,F^{A\rightarrow A}\cong F^{\bbnum 1}$} & {\footnotesize{}$F$ is strictly positive} & {\footnotesize{}Example~\ref{subsec:Example-simplify-quantifier-A-A}(a)}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,H^{A\rightarrow A}\cong H^{\bbnum 1}$} & {\footnotesize{}$H$ is a contrafunctor} & {\footnotesize{}Example~\ref{subsec:Example-simplify-quantifier-A-A}(b)}\tabularnewline +\hline +{\footnotesize{}$\forall A.\,((A\rightarrow P)\rightarrow A\rightarrow A\cong P$} & {\footnotesize{}$P$ is a fixed type} & {\footnotesize{}Exercise~\ref{par:Problem-Peirce-law}}\tabularnewline +\hline +\end{tabular} +\par\end{centering} +\caption{Type identities proved by other parametricity techniques.\label{tab:Type-identities-proved-by-parametricity}} +\end{table} -We rewrite $\exists A.\,\exists B.\,P^{A,B}$ via universal quantifiers: -\begin{align*} - & \gunderline{\exists A.}\,\exists B.\,P^{A,B}\\ -{\color{greenunder}\text{use Eq.\,(\ref{eq:existential-via-universal-Yoneda})}:}\quad & \cong\forall D.\,\big(\forall A.\,\gunderline{(\exists B.\,P^{A,B})\rightarrow D})\rightarrow D\\ -{\color{greenunder}\text{use Eq.\,(\ref{eq:existential-via-universal})}:}\quad & \cong\forall D.\,\big(\forall A.\,\forall B.\,P^{A,B}\rightarrow D)\rightarrow D\quad. -\end{align*} -If we rewrite $\exists B.\,\exists A.\,P^{A,B}$ similarly, we will -get: -\[ -\exists B.\,\exists A.\,P^{A,B}\cong\forall D.\,\big(\forall B.\,\forall A.\,P^{A,B}\rightarrow D)\rightarrow D\quad. -\] -Statement~\ref{subsec:Statement-Fubini-theorem} gives $\forall A.\,\forall B.\,P^{A,B}\cong\forall B.\,\forall A.\,P^{A,B}$, -completing the proof. $\square$ +\begin{table}[h] +\begin{centering} +\begin{tabular}{|c|c|c|} +\hline +\textbf{\footnotesize{}Identity} & \textbf{\footnotesize{}Assumptions} & \textbf{\footnotesize{}Source}\tabularnewline +\hline +\hline +{\footnotesize{}$\exists C.\,F^{C}\cong\forall D.\,\big(\forall C.\,(F^{C}\rightarrow D)\big)\rightarrow D$} & {\footnotesize{}For any $F$} & {\footnotesize{}Equation~(\ref{eq:existential-via-universal-Yoneda})}\tabularnewline +\hline +{\footnotesize{}$(\exists C.\,F^{C})\rightarrow R\cong\forall C.\,(F^{C}\rightarrow R)$} & {\footnotesize{}For any $F$, $R$} & {\footnotesize{}Statement~\ref{subsec:Statement-function-extension-rule}}\tabularnewline +\hline +{\footnotesize{}$\exists A.\,A\cong\bbnum 1$} & & \tabularnewline +\hline +{\footnotesize{}$\exists A.\,F^{A}\cong F^{\bbnum 1}$} & {\footnotesize{}$F$ is any functor} & {\footnotesize{}Statement~\ref{subsec:Statement-co-Yoneda-two-identities-1}(a)}\tabularnewline +\hline +{\footnotesize{}$\exists A.\,H^{A}\cong H^{\bbnum 0}$} & {\footnotesize{}$H$ is any contrafunctor} & {\footnotesize{}Statement~\ref{subsec:Statement-co-Yoneda-two-identities-1}(b)}\tabularnewline +\hline +{\footnotesize{}$\exists A.\,F^{A}\rightarrow A\cong\bbnum 1$} & {\footnotesize{}For any $F$} & {\footnotesize{}Example~\ref{subsec:Example-simple-existential-derivation}}\tabularnewline +\hline +{\footnotesize{}$\exists A.\,(F^{A}+G^{A})\cong(\exists A.\,F^{A})+(\exists A.\,G^{A})$} & {\footnotesize{}For any $F$, $G$} & {\footnotesize{}Example~\ref{subsec:Example-simple-existential-derivation-1-1}(b)}\tabularnewline +\hline +{\footnotesize{}$\exists A.\,\exists B.\,F^{A,B}\cong\exists B.\,\exists A.\,F^{A,B}$} & {\footnotesize{}For any $F$} & {\footnotesize{}Statement~\ref{subsec:Statement-commute-existential}}\tabularnewline +\hline +{\footnotesize{}$\nu A.\,F^{A}\cong\exists A.\,(A\rightarrow F^{A})\times A$} & {\footnotesize{}$F$ is any functor} & {\footnotesize{}Section~\ref{subsec:The-greatest-fixpoints-and-Church-co-Yoneda}}\tabularnewline +\hline +{\footnotesize{}$G^{\nu A.\,F^{A}}\cong\exists A.\,(A\rightarrow F^{A})\times G^{A}$} & {\footnotesize{}$F$, $G$ are any functors} & {\footnotesize{}Statement~\ref{subsec:Statement-Church-co-Yoneda}}\tabularnewline +\hline +{\footnotesize{}$\nu A.\,\nu B.\,F^{A,B}\cong\nu B.\,F^{B,B}$} & {\footnotesize{}$F$ is any bifunctor} & {\footnotesize{}Statement~\ref{subsec:Statement-nested-greatest-fixpoints}}\tabularnewline +\hline +{\footnotesize{}}% +\begin{minipage}[c][12mm][t]{0.1mm}% +% +\end{minipage}{\footnotesize{}}% +\begin{minipage}[c]{0.43\columnwidth}% +\begin{center} +{\footnotesize{}$\nu A.\,F^{A,\,\nu B.\,G^{A,B}}\cong$}\\ +{\footnotesize{}$\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times A$} +\par\end{center}% +\end{minipage} & {\footnotesize{}$F$, $G$ are any bifunctors} & {\footnotesize{}Statement~\ref{subsec:Statement-mutually-recursive-greatest-fixpoints}}\tabularnewline +\hline +{\footnotesize{}$G^{\exists C.\,F^{C}}\cong\forall D.\,(\forall C.\,F^{C}\rightarrow D)\rightarrow G^{D}$} & {\footnotesize{}Any $F$, any functor $G$} & {\footnotesize{}Exercise~\ref{par:Exercise-additional-16-3}}\tabularnewline +\hline +\end{tabular} +\par\end{centering} +\caption{Type isomorphisms for existential types.\label{tab:Type-identities-for-existential-types}} +\end{table} -Now we will prove some more technical properties of existential types. -In the next two statements, we work with a fixed type constructor -$P$, which is not assumed to be covariant or contravariant. For brevity, -we denote: -\[ -E\triangleq\forall B.\,(\forall A.\,P^{A}\rightarrow B)\rightarrow B\quad. -\] +\subsection{The Jaskelioff-O\textsf{'}Connor theorem for simple types} +The Jaskelioff-O\textsf{'}Connor theorem\footnote{See \texttt{\href{https://arxiv.org/abs/1402.1699}{https://arxiv.org/abs/1402.1699}}} +is a type equivalence between certain type constructors quantified +over a typeclass. This section proves a version of that theorem that +holds for simple types belonging to a $P$-typeclass. Then the theorem +gives a general type formula for the free construction of any $P$-typeclass. -\subsubsection{Statement \label{subsec:Statement-identity-law-of-pack}\ref{subsec:Statement-identity-law-of-pack}} +\subsubsection{Statement \label{subsec:Statement-JOC-theorem-simple-types}\ref{subsec:Statement-JOC-theorem-simple-types}} -Values of type $E$ are constructed via the standard function \lstinline!pack! -that has the following type signature: -\begin{align*} - & \text{pack}:\forall T.\,P^{T}\rightarrow E\quad,\\ -{\color{greenunder}\text{or equivalently}:}\quad & \text{pack}:\forall T.\,P^{T}\rightarrow\forall B.\,(\forall A.\,P^{A}\rightarrow B)\rightarrow B\quad,\\ - & \text{pack}^{T}(p^{:P^{T}})\triangleq\forall B.\,\big(k^{:\forall A.\,P^{A}\rightarrow B}\big)\rightarrow k^{T}(p)\quad. -\end{align*} -Then the \textbf{identity law} of\index{identity laws!of pack@of \lstinline!pack!} -\lstinline!pack! holds: for any value $e:E$, -\begin{equation} -e^{E}(\text{pack})=e\quad.\label{eq:identity-law-of-pack} -\end{equation} -It is assumed that all values $e^{:E}$ obey their naturality law: +The free $P$-typeclass instance $E^{T}$ generated by a type $T$ +is equivalent to the type defined by: \begin{equation} -\text{for all }f^{:B\rightarrow C},k^{:\forall A.\,P^{A}\rightarrow B}:\quad f(e^{B}(k))=e^{C}(\forall A.\,k^{A}\bef f)\quad.\label{eq:naturality-law-of-e-derivation1} +E^{T}\cong\forall(A\in P\text{-typeclass}).\,(T\rightarrow A)\rightarrow A\quad.\label{eq:free-typeclass-via-church-encoding} \end{equation} +Here the quantifier goes only over the types $A$ that belong to the +$P$-typeclass. It is also assumed that the type in the right-hand +side of Eq.~(\ref{eq:free-typeclass-via-church-encoding}) admits +only functions that satisfy the naturality law with respect to $A$. +\subparagraph{Proof} -\subparagraph{Proof\protect\footnote{The author thanks \index{Dan Doel}Dan Doel for assistance with the -proof of this statement. See the discussion at \texttt{\protect\href{https://cstheory.stackexchange.com/questions/54124}{https://cstheory.stackexchange.com/questions/54124}}}} - -Both sides of Eq.~(\ref{eq:identity-law-of-pack}) have type $E$. -Since $E$ is a type of functions with a type parameter, the two sides -can be applied to an arbitrary type $U$ and an arbitrary value $u:\forall A.\,P^{A}\rightarrow U$ -to get two values of type $U$: -\begin{align*} -{\color{greenunder}\text{both sides of}:}\quad & e^{E}(\text{pack})\overset{?}{=}e\\ -{\color{greenunder}\text{can be applied to }U\text{ and }u\text{ and yield}:}\quad & \big(e^{E}(\text{pack})\big)^{U}(u)\overset{?}{=}e^{U}(u)\quad. -\end{align*} - -So, let us prove that for all types $U$ and all values $u:\forall A.\,P^{A}\rightarrow U$, -\begin{equation} -\big(e^{E}(\text{pack})\big)^{U}(u)\overset{?}{=}e^{U}(u)\quad.\label{eq:identity-law-of-pack-derivation1} -\end{equation} -To prove the last equation, we will rewrite it in the form of the -naturality law~(\ref{eq:naturality-law-of-e-derivation1}) by finding -suitable parameters $B$, $C$, $f$, and $k$. Once we manage to -do that, the proof of Eq.~(\ref{eq:identity-law-of-pack}) will be -completed. - -The left-hand side of Eq.~(\ref{eq:identity-law-of-pack-derivation1}) -will match the left-hand side of Eq.~(\ref{eq:naturality-law-of-e-derivation1}) -if we assign $B=E$, $k=\text{pack}$, and $f(e)\triangleq e^{U}(u)$. -The type of $f$ must be $B\rightarrow C$; since $f(e)$ has type -$U$, we need to set $C=U$. With these assignments, the right-hand -side of Eq.~(\ref{eq:naturality-law-of-e-derivation1}) becomes: +One of the defining properties of the free typeclass constructor $E$ +is the one-to-one correspondence between functions of type $T\rightarrow A$ +and $P$-typeclass morphisms of type $E^{T}\rightarrow A$. Denoting +by $E^{T}\overset{P}{\rightarrow}A$ the type of those morphisms, +we have: \[ -e^{C}(k\bef f)=e^{U}(\forall A.\,\text{pack}^{A}\bef f)\quad. +\forall(A\in P\text{-typeclass}).\,(T\rightarrow A)\rightarrow A\cong\forall(A\in P\text{-typeclass}).\,(E^{T}\overset{P}{\rightarrow}A)\rightarrow A\quad. \] -This will be equal to the right-hand side $e^{U}(u)$ of Eq.~(\ref{eq:identity-law-of-pack-derivation1}) -if we show that: + +All types $A$ belonging to the $P$-typeclass are $E$-monad algebras, +and those algebras form a category. Now we use the Yoneda identity +in that category: \[ -\forall A.\,\text{pack}^{A}\bef f\overset{?}{=}u\quad. +\forall(A\in P\text{-typeclass}).\,(X\overset{P}{\rightarrow}A)\rightarrow A\cong X\quad, \] -Substitute the definitions of \lstinline!pack! and $f$, renaming -$A$ to $T$: +where $X$ is any fixed type that also belongs to the $P$-typeclass. +We use this identity with $X=E^{T}$ and obtain: \[ -\forall T.\,\text{pack}^{T}\bef f=\forall T.\,p^{:P^{T}}\rightarrow f\big(\forall B.\,\big(q^{:\forall A.\,P^{A}\rightarrow B}\big)\rightarrow q^{T}(p)\big)\quad. +\forall(A\in P\text{-typeclass}).\,(E^{T}\overset{P}{\rightarrow}A)\rightarrow A\cong E^{T}\quad, \] -The function $f$ substitutes $B=U$ and $q=u$ into its function -parameter: -\[ -f\big(\forall B.\,\big(q^{:\forall A.\,P^{A}\rightarrow B}\big)\rightarrow q^{T}(p)\big)=\big(\forall B.\,\big(q^{:\forall A.\,P^{A}\rightarrow B}\big)\rightarrow q^{T}(p)\big)^{U}(u)=u^{T}(p)\quad. -\] -So, we find: -\[ -\forall T.\,\text{pack}^{T}\bef f=\forall T.\,p^{:P^{T}}\rightarrow u^{T}(p)=\forall T.\,u^{T}=u\quad. -\] -This completes the proof. $\square$ +as required. $\square$ -Finally, here is the key property required for proving the equivalence -of two formulations of existential types, Eq.~(\ref{eq:existential-via-universal}) -and Eq.~(\ref{eq:existential-via-universal-Yoneda}). +\subsection{The Jaskelioff-O\textsf{'}Connor theorem for type constructors} -\subsubsection{Statement \label{subsec:Statement-function-extension-rule}\ref{subsec:Statement-function-extension-rule}} +The full formulation of the theorem involves functor typeclasses instead +of typeclasses for simple types. The theorem applies to all $P$-typeclasses +for functors. Those typeclasses have method signatures of the form +$\forall A.\,(P^{F})^{A}\rightarrow F^{A}$, where $P$ is a functor +on functors (the kind of $P$ is $(*\rightarrow*)\rightarrow*\rightarrow*$) +and functions of type $(P^{F})^{A}\rightarrow F^{A}$ are restricted +to natural transformations between functors $P^{F}$ and $F$. Examples +of well-known $P$-typeclasses of that form are pointed functors, +filterable functors, applicative functors, and monads. -The following type isomorphism holds: -\begin{align*} - & E\rightarrow R=(\exists A.\,P^{A})\rightarrow R\cong\forall C.\,P^{C}\rightarrow R\quad,\\ -{\color{greenunder}\text{or equivalently}:}\quad & \big(\forall B.\,(\forall A.\,P^{A}\rightarrow B)\rightarrow B\big)\rightarrow R\cong\forall C.\,P^{C}\rightarrow R\quad, -\end{align*} -where $R$ is a fixed type. In this isomorphism, it is assumed that -the type $E$ contains only functions $e^{:E}$ that obey the naturality -law~(\ref{eq:naturality-law-of-e-derivation1}). +\subsubsection{Statement \label{subsec:Statement-Jaskelioff-OConnor}\ref{subsec:Statement-Jaskelioff-OConnor} +(Jaskelioff-O\textsf{'}Connor)} -This isomorphism can be also formulated via code like this: -\begin{equation} -\text{for all }e^{:E}\text{ and }r^{:E\rightarrow R}:\quad r(e)=e^{R}(\forall C.\,\text{pack}^{C}\bef r)\quad,\label{eq:surjectivity-of-pack} -\end{equation} -where the standard function \lstinline!pack! was defined in the proof -of Statement~\ref{subsec:Statement-identity-law-of-pack}. Any function -$r$ that consumes values of type $e$ can be expressed via application -of $r$ to values constructed via \lstinline!pack!. +Given any fixed $P$-typeclass for functors, denote by $E$ the constructor +of free instances of that typeclass: if $T$ is any functor then the +functor $E^{T}$ is guaranteed to be an instance of the $P$-typeclass. +Suppose $A$, $B$, $C$ are some fixed types. Then the following +type equivalence holds: +\begin{align} + & \forall(F\in P\text{-typeclass}).\,(A\rightarrow F^{B})\rightarrow F^{C}\cong(E^{R})^{C}\quad,\label{eq:jaskelioff-o-connor-theorem}\\ +{\color{greenunder}\text{where }R\text{ is defined by}:}\quad & R^{T}\triangleq A\times(B\rightarrow T)\quad.\nonumber +\end{align} +Here, it is assumed that the type $(A\rightarrow F^{B})\rightarrow F^{C}$ +is restricted to functions satisfying the naturality law with respect +to $F$. \subparagraph{Proof} -The isomorphism is shown by defining two functions (\lstinline!inF! -and \lstinline!outF!): -\begin{align*} - & \text{inF}:(\forall C.\,P^{C}\rightarrow R)\rightarrow E\rightarrow R\quad,\\ - & \text{inF}\triangleq k^{:\forall C.\,P^{C}\rightarrow R}\rightarrow e^{:E}\rightarrow e^{R}(k)\quad,\\ - & \text{outF}:(E\rightarrow R)\rightarrow\forall C.\,P^{C}\rightarrow R\quad,\\ - & \text{outF}\triangleq r^{:E\rightarrow R}\rightarrow\forall C.\,p^{:P^{C}}\rightarrow r(\text{pack}^{C}(p))=r^{:E\rightarrow R}\rightarrow\forall C.\,\text{pack}^{C}\bef r\quad, -\end{align*} -and by proving that those functions are inverses of each other. +Denote by $K\overset{P}{\rightarrow}L$ the type of $P$-typeclass +morphisms between functors $K$ and $L$ that belong to the typeclass. +(The full type signature of a $P$-typeclass morphism is $\forall A.\,K^{A}\overset{P}{\rightarrow}L^{A}$.) -Without the type annotations, the code of \lstinline!inF! and \lstinline!outF! -is: +We will prove the type equivalence~(\ref{eq:jaskelioff-o-connor-theorem}) +in three steps. + +\textbf{(1)} Use the Yoneda identity to obtain this type equivalence: \[ -\text{inF}=k\rightarrow q\rightarrow q(k)\quad,\quad\quad\text{outF}=r\rightarrow p\rightarrow r(k\rightarrow k(p))\quad. +A\rightarrow F^{B}\cong\forall X.\,R^{X}\rightarrow F^{X}\quad. \] -Now it is quick to prove one direction of isomorphism ($\text{inF}\bef\text{outF}\overset{?}{=}\text{id}$): +To derive this formula, write: \begin{align*} -{\color{greenunder}\text{expect to equal }\text{id}:}\quad & \text{inF}\bef\text{outF}=k\rightarrow\text{outF}\,(q\rightarrow q(k))\\ - & =k\rightarrow p\rightarrow(q\rightarrow q(k))(k\rightarrow k(p))\\ - & =k\rightarrow\gunderline{p\rightarrow k(p)}=k\rightarrow k=\text{id}\quad. + & A\rightarrow F^{B}\\ +{\color{greenunder}\text{covariant Yoneda identity}:}\quad & \cong A\rightarrow\forall X.\,(B\rightarrow X)\rightarrow F^{X}\\ +{\color{greenunder}\text{move }\forall X\text{ to front}:}\quad & \cong\forall X.\,A\rightarrow(B\rightarrow X)\rightarrow F^{X}\\ +{\color{greenunder}\text{uncurry the function}:}\quad & \cong\forall X.\,A\times(B\rightarrow X)\rightarrow F^{X}=\forall X.\,R^{X}\rightarrow F^{X}\quad. \end{align*} +In the first line of this derivation, we have used the assumption +that $F$ is a (covariant) functor. -The other direction ($\text{outF}\bef\text{inF}\overset{?}{=}\text{id}$) -requires more work. The argument of the function $\text{outF}\bef\text{inF}$ -has type $E\rightarrow R$, and we need to show that for any function -$r^{:E\rightarrow R}$ the following equation holds: +\textbf{(2)} By the universal property of the free $P$-typeclass +runner, for any functor $F$ that belongs to the $P$-typeclass and +for any functor $R$ (not necessarily a member of the $P$-typeclass) +there is a one-to-one correspondence between $P$-typeclass morphisms +$E^{R}\overset{P}{\rightarrow}F$ and natural transformations $R\leadsto F$. +In other words, there is a type equivalence between the following +types (where we wrote out the full type signatures): \[ -\text{inF}\,(\text{outF}\,(r))\overset{?}{=}r\quad,\quad\text{or equivalently}:\quad r\triangleright\text{outF}\triangleright\text{inF}\overset{?}{=}r\quad. +\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X}\cong\forall X.\,R^{X}\rightarrow F^{X}\quad. \] -The last equation is between functions of type $E\rightarrow R$; -we may apply both sides to an arbitrary value $e^{:E}$ and require -that the results (of type $R$) should be equal: +Now we set $R^{T}\triangleq A\times(B\rightarrow T)$ and obtain: \[ -\big(r\triangleright\text{outF}\triangleright\text{inF}\big)(e)\overset{?}{=}r(e)\quad. +(A\rightarrow F^{B})\rightarrow F^{C}\cong(\forall X.\,R^{X}\rightarrow F^{X})\rightarrow F^{C}\cong(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\quad. \] -We begin by subtituting the definitions of \lstinline!inF! and \lstinline!outF!: -\begin{align*} -{\color{greenunder}\text{expect to equal }r(e):}\quad & e\triangleright\big(r\triangleright\text{outF}\triangleright\text{inF}\big)=e\triangleright\big((\forall A.\,p^{:P^{A}}\rightarrow r(\text{pack}^{A}(p)))\triangleright\text{inF}\big)\\ - & =e^{R}\big(\forall A.\,p^{:P^{A}}\rightarrow r(\text{pack}^{A}(p))\big)=e^{R}(\forall A.\,\text{pack}^{A}\bef r)\quad. -\end{align*} -Since $e$ is unknown and arbitrary, we can make progress in the proof -only if we use the naturality law of $e$ as given by Eq.~(\ref{eq:naturality-law-of-e-derivation1}). -We assign $B=E$, $C=R$, $f=r$, $k=\text{pack}$ in that law and -obtain: +So, the left-hand side of Eq.~(\ref{eq:jaskelioff-o-connor-theorem}) +is equivalent to: \[ -r(e^{E}(\text{pack}))=e^{R}(\forall A.\,\text{pack}^{A}\bef r)\quad. +\forall(F\in P\text{-typeclass}).\,(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\quad. \] -By the identity law of pack (Statement~\ref{subsec:Statement-identity-law-of-pack}), -$e^{E}(\text{pack})=e$. So, we conclude the derivation: -\begin{align*} -{\color{greenunder}\text{expect to equal }r(e):}\quad & e\triangleright\big(r\triangleright\text{outF}\triangleright\text{inF}\big)=\gunderline{e^{R}(\forall A.\,\text{pack}^{A}\bef r)}\\ -{\color{greenunder}\text{naturality law of }e:}\quad & =r(\gunderline{e^{E}(\text{pack})})\\ -{\color{greenunder}\text{identity law of }\text{pack}:}\quad & =r(e)\quad. -\end{align*} -We have proved the isomorphism and also verified Eq.~(\ref{eq:surjectivity-of-pack}). -$\square$ - -\subsection{Greatest fixpoints and the Church-co-Yoneda identity\label{subsec:The-greatest-fixpoints-and-Church-co-Yoneda}} - -We have seen that the least fixpoints of functors are expressed via -the Church encoding type that involves a universally quantified higher-order -function. An analogous encoding (with an existentially quantified -type) exists for greatest fixpoints. We will now prove some properties -of that encoding.\footnote{This section follows the logic given in P.~Wadler\textsf{'}s paper \textsf{``}Recursive -types for free\textsf{''}, except that we \emph{define} existential types -by Eq.~(\ref{eq:existential-via-universal-Yoneda}) via the universal -quantifier.} -We work with a fixed covariant functor $F$ and denote by $C$ the -following Church-encoded type: +\textbf{(3)} We use the covariant Yoneda identity in the category +of functors that belong to the $P$-typeclass. As we have found in +Section~\ref{subsec:Imposing-laws-of-P-typeclasses-via-monad-algebras}, +all those functors are $E$-monad algebras, which form a category. +The $P$-typeclass morphisms are in one-to-one correspondence with +the $E$-monad algebra morphisms. Therefore, we may write the covariant +Yoneda identity for that category as: \[ -C\triangleq\exists A.\,(A\rightarrow F^{A})\times A\quad. +\forall(F\in P\text{-typeclass}).\,(\forall X.\,Q^{X}\overset{P}{\rightarrow}F^{X})\rightarrow S^{F}\cong S^{Q}\quad, \] -We will prove that $C$ is the greatest fixpoint of the type equation -$X\cong F^{X}$; that is, $C=\nu X.\,F^{X}$. - -First, we define some auxiliary functions that work with the type -$C$ and prove their properties. - -The function \lstinline!unfold! constructs values of type $C$: -\begin{align*} - & \text{unfold}:\forall T.\,(T\rightarrow F^{T})\times T\rightarrow C\quad,\\ - & \text{unfold}^{T}(u^{:T\rightarrow F^{T}}\times t^{:T})\triangleq\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times A\rightarrow R}\rightarrow p^{T}(u\times t)\quad. -\end{align*} -Note that \lstinline!unfold! is the same as the function \lstinline!pack! -from Statement~\ref{subsec:Statement-identity-law-of-pack} if we -set $E=C$ and $P^{A}\triangleq(A\rightarrow F^{A})\times A$ in the -definition of \lstinline!pack!. - -By parametricity, the function \lstinline!unfold! satisfies a relational -naturality law: for all types $A$, $B$ and all functions $f^{:A\rightarrow B}$, -\begin{equation} -\text{if}\quad u\bef f^{\uparrow F}=f\bef v\quad\text{then}\quad\text{unfold}^{A}(u^{:A\rightarrow F^{A}}\times a^{:A})=\text{unfold}^{B}(v^{:B\rightarrow F^{B}}\times f(a))\quad.\label{eq:relational-naturality-law-of-unfold} -\end{equation} -In category theory, the precondition $u\bef f^{\uparrow F}=f\bef v$ -is known as the \textsf{``}$F$-coalgebra morphism law\textsf{''} of $f$. Let us -give some definitions for reference: - -\subsubsection{Definition \label{subsec:Definition-F-coalgebra}\ref{subsec:Definition-F-coalgebra}} - -Given a functor $F$, a type $A$ together with a function $u:A\rightarrow F^{A}$ -is called an $F$\textbf{-coalgebra}.\index{$F$-coalgebra} The type -$A$ is called the \textbf{carrier} of the $F$-coalgebra, and the -function $u$ is called the \textbf{structure map} of the $F$-coalgebra. -(Keep in mind that $u$ is not universally quantified over $A$; it -is a function that only works with a single, specified type $A$. -For a given type $A$, there could be several different structure -maps $u$, $u^{\prime}$, and so on; each of them will then define -a different $F$-coalgebra.) +where $Q$ is any fixed functor from the $P$-typeclass, $S^{F}$ +is any type expression that is covariant in $F$, and the naturality +law with respect to $F$ is assumed to hold. We will use this Yoneda +identity with $Q=E^{R}$, and set $S^{F}$ to just $F^{C}$ (the application +of $F$ to the fixed type $C$). Then we get: +\[ +\forall(F\in P\text{-typeclass}).\,(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\cong(E^{R})^{C}\quad. +\] +The last type is the right-hand side of Eq.~(\ref{eq:jaskelioff-o-connor-theorem}). +So, Eq.~(\ref{eq:jaskelioff-o-connor-theorem}) holds. -If $A$ and $B$ are two $F$-coalgebras with structure maps $u:A\rightarrow F^{A}$ -and $v:B\rightarrow F^{B}$ then a function $f:A\rightarrow B$ is -called an $F$-coalgebra morphism if this law holds: +Let us now derive the code that implements the type equivalence~(\ref{eq:jaskelioff-o-connor-theorem}) +in the direction of right-to-left. Suppose we are given a value $q$ +of the type in the right-hand side of Eq.~(\ref{eq:jaskelioff-o-connor-theorem}): \[ -\xymatrix{\xyScaleY{2.3pc}\xyScaleX{2.5pc}A\ar[d]\sb(0.4){u}\ar[r]\sp(0.5){f} & B\ar[d]\sp(0.4){v}\\ -F^{A}\ar[r]\sp(0.5){f^{\uparrow F}} & F^{B} -} +q:(E^{R})^{C}\quad. \] +We need to retrace step \textbf{(3)} above and convert this $q$ to +a function $f$ of type: \[ -u\bef f^{\uparrow F}=f\bef v\quad. +f:\forall(F\in P\text{-typeclass}).\,(\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X})\rightarrow F^{C}\quad. \] -This is the $F$-coalgebra morphism law of $f$. $\square$ - -It is also helpful to define a function \lstinline!unfoldF! that -constructs values of type $F^{C}$: -\begin{align*} - & \text{unfoldF}:\forall T.\,(T\rightarrow F^{T})\times T\rightarrow F^{C}\quad,\\ - & \text{unfoldF}^{T}(u^{:T\rightarrow F^{T}}\times t^{:T})\triangleq t\triangleright u\triangleright\big(a^{:T}\rightarrow\text{unfold}^{T}(u\times a)\big)^{\uparrow F}\quad. -\end{align*} - -The isomorphism $C\cong F^{C}$ will be implemented via two functions: +The required function $f$ is defined by: \[ -\text{fix}:F^{C}\rightarrow C\quad,\quad\quad\text{unfix}:C\rightarrow F^{C}\quad, +f^{F}\big(k^{:\forall X.\,(E^{R})^{X}\overset{P}{\rightarrow}F^{X}}\big)\triangleq k^{C}(q)\quad. \] -which we define via \lstinline!unfold! and \lstinline!unfoldF! like -this: -\begin{align*} - & \text{unfix}:C\rightarrow F^{C}\quad,\quad\quad\text{unfix}\triangleq c^{:C}\rightarrow c^{F^{C}}(\forall A.\,\text{unfoldF}^{A})=c^{:C}\rightarrow c^{F^{C}}(\text{unfoldF})\quad,\\ - & \text{fix}:F^{C}\rightarrow C\quad,\quad\quad\text{fix}\triangleq p^{:F^{C}}\rightarrow\text{unfold}^{F^{C}}(\text{unfix}^{\uparrow F}\times p)\quad. -\end{align*} -Because of these functions, $C$ is at the same time an $F$-algebra -and an $F$-coalgebra. - -\subsubsection{Statement \label{subsec:Statement-coalgebra-morphism-unfold}\ref{subsec:Statement-coalgebra-morphism-unfold}} -For any $F$-coalgebra $A$ with a structure map $u:A\rightarrow F^{A}$, -denote by $\psi_{u}^{A}$ the following function of type $A\rightarrow C$: +Continue by retracing step \textbf{(2)}, converting $f$ to a function +$g$ of type: \[ -\psi_{u}^{A}:A\rightarrow C\quad,\quad\quad\psi_{u}^{A}\triangleq a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\quad. +g:\forall(F\in P\text{-typeclass}).\,(\forall X.\,R^{X}\rightarrow F^{X})\rightarrow F^{C}\quad. \] -Then $\psi_{u}^{A}$ is an $F$-coalgebra morphism of type $A\rightarrow C$. - -\subparagraph{Proof} - -Write the $F$-coalgebra morphism law for that function: +The function $g$ is defined by: \[ -u\bef\big(a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\big)^{\uparrow F}\overset{?}{=}\big(a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\big)\bef v\quad. +g^{F}\big(k^{:\forall X.\,R^{X}\rightarrow F^{X}}\big)\triangleq f^{F}\big(\forall Y.\,r^{:(E^{R})^{Y}}\rightarrow\text{run}_{E}^{R,Y}(k)(r)\big)\quad, \] -Apply both sides to an arbitrary value $t^{:A}$ and obtain: +where the universal runner ($\text{run}_{E}^{T,Y}$) has type: \[ -t\triangleright u\triangleright(a\rightarrow\text{unfold}^{A}(u\times a))^{\uparrow F}\overset{?}{=}\text{unfix}\,(\text{unfold}^{A}(u\times t))\quad. +\text{run}_{E}^{T,Y}:(\forall X.\,T^{X}\rightarrow F^{X})\rightarrow(E^{T})^{Y}\rightarrow F^{Y}\quad. \] -Begin with the right-hand side: -\begin{align*} - & \text{unfix}\,(\text{unfold}^{A}(u\times t))\\ -{\color{greenunder}\text{definition of }\text{unfix}:}\quad & =(\text{unfold}^{A}(u\times t))^{F^{C}}(\text{unfoldF})\\ -{\color{greenunder}\text{definition of }\text{unfold}:}\quad & =\text{unfoldF}^{A}(u\times t)\\ -{\color{greenunder}\text{definition of }\text{unfoldF}:}\quad & =t\triangleright u\triangleright\big(a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\big)^{\uparrow F}\quad. -\end{align*} -This is now equal to the left-hand side. $\square$ - -\subsubsection{Statement \label{subsec:Statement-identity-law-of-unfold}\ref{subsec:Statement-identity-law-of-unfold}} - -The function \lstinline!unfold! satisfies an \textbf{identity law}: -\[ -\text{for all }c^{:C}:\quad\text{unfold}^{C}(\text{unfix}\times c)\overset{?}{=}c\quad. -\] -This law\index{identity laws!of unfold@of \lstinline!unfold!} is -similar to the identity law of \lstinline!pack! (Statement~\ref{subsec:Statement-identity-law-of-pack}). - -\subparagraph{Proof} -Apply Statement~\ref{subsec:Statement-identity-law-of-pack}, which -gives $e^{E}(\text{pack})=e$, and substitute $E=C$, $e=c$, $P^{A}=(A\rightarrow F^{A})\times A$, -and \lstinline!unfold! instead of \lstinline!pack!. We obtain: -\begin{equation} -c=c^{C}(\text{unfold})\quad.\label{eq:unfold-id-law-derivation1} -\end{equation} -Now use the law~(\ref{eq:surjectivity-of-pack}) where we substitute -$E=R=C$ and $e=c$: +It remains to retrace step \textbf{(1)} and define a function $h$ +of type: \[ -\text{for all }r^{:C\rightarrow C}:\quad r(c)=c^{C}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times a^{:A}\rightarrow r(\text{unfold}^{A}(u\times a))\big)\quad. +h:\forall(F\in P\text{-typeclass}).\,(A\rightarrow F^{B})\rightarrow F^{C}\quad. \] -We will use this law with the function $r$ defined by: +We implement $h$ via this code: \[ -r:C\rightarrow C\quad,\quad\quad r(c)\triangleq\text{unfold}^{C}(\text{unfix}\times c)\quad. +h^{F}(k^{:A\rightarrow F^{B}})\triangleq g^{F}\big(\forall X.\,a^{:A}\times t^{:B\rightarrow X}\rightarrow k(a)\triangleright t^{\uparrow F}\big)\quad. \] -Then we get: -\begin{align} - & \text{unfold}^{C}(\text{unfix}\times c)=r(c)=c^{C}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times a^{:A}\rightarrow r(\text{unfold}^{A}(u\times a))\big)\nonumber \\ - & =c^{C}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times a^{:A}\rightarrow\text{unfold}^{C}(\text{unfix}\times\text{unfold}^{A}(u\times a)))\big)\quad.\label{eq:unfold-id-law-derivation3} -\end{align} -Now we apply the naturality law~(\ref{eq:relational-naturality-law-of-unfold}) -with $B=C$, $f=a\rightarrow\text{unfold}^{A}(u\times a)$, and $v=\text{unfix}$: -\begin{equation} -\text{unfold}^{A}(u\times a)=\text{unfold}^{C}(\text{unfix}\times\text{unfold}^{A}(u\times a)))\quad.\label{eq:unfold-id-law-derivation2} -\end{equation} -The precondition of this law ($u\bef f^{\uparrow F}\overset{?}{=}f\bef v$) -is the $F$-coalgebra morphism law of \lstinline!unfold!, and it -has been demonstrated in Statement~\ref{subsec:Statement-coalgebra-morphism-unfold}. -So, Eq.~(\ref{eq:unfold-id-law-derivation2}) holds. - -Finally, we can finish the proof: -\begin{align*} -{\color{greenunder}\text{expect to equal }c:}\quad & \text{unfold}^{C}(\text{unfix}\times c)\\ -{\color{greenunder}\text{use Eq.~(\ref{eq:unfold-id-law-derivation3})}:}\quad & =c^{C}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times a^{:A}\rightarrow\gunderline{\text{unfold}^{C}(\text{unfix}\times\text{unfold}^{A}(u\times a)))}\big)\\ -{\color{greenunder}\text{use Eq.~(\ref{eq:unfold-id-law-derivation2})}:}\quad & =c^{C}\big(\gunderline{\forall A.\,u^{:A\rightarrow F^{A}}\times a^{:A}\rightarrow\text{unfold}^{A}(u\times a)}\big)=c^{C}(\text{unfold})\\ -{\color{greenunder}\text{use Eq.~(\ref{eq:unfold-id-law-derivation1})}:}\quad & =c\quad. -\end{align*} +This completes the code that transforms $q$ into $h$. $\square$ +We will now apply the Jaskelioff-O\textsf{'}Connor theorem to prove some useful +type equivalences. -\subsubsection{Statement \label{subsec:Statement-greatest-fixpoint-church-encoding}\ref{subsec:Statement-greatest-fixpoint-church-encoding}} +\subsubsection{Statement \label{subsec:Statement-identity-monad-morphism}\ref{subsec:Statement-identity-monad-morphism}} -The functions \lstinline!fix! and \lstinline!unfix! are inverses -to each other. +Denote by $F\xrightarrow{\text{Monad}}G$ (more verbosely, $\forall X.\,F^{X}\xrightarrow{\text{Monad}}G^{X}$) +the type of monad morphisms between monads $F$ and $G$. Those are +natural transformations of type $\forall X.\,F^{X}\rightarrow G^{X}$ +that additionally satisfy the laws of monad morphisms. Denote by $\text{Id}$ +the identity monad ($\text{Id}^{A}\triangleq A$). -\subparagraph{Proof} +\textbf{(a)} The standard monad method $\text{pu}_{M}:\forall A.\,A\rightarrow M^{A}$ +is the only monad morphism of type $\text{Id}\xrightarrow{\text{Monad}}M$ +that works in the same way for all monads $M$.\footnote{See \texttt{\href{https://cstheory.stackexchange.com/questions/53389/}{https://cstheory.stackexchange.com/questions/53389/}}} +We can express this as a type equivalence: +\[ +\forall M^{:\text{Monad}}.\,\text{Id}\xrightarrow{\text{Monad}}M\cong\bbnum 1\quad. +\] -Translate the existential quantifier via Eq.~(\ref{eq:existential-via-universal-Yoneda}) -and write $C$ as: +\textbf{(b)} The identity function of type $\forall X.\,M^{X}\rightarrow M^{X}$ +is the only monad morphism of type $M\xrightarrow{\text{Monad}}M$ +that works in the same way for all monads $M$.\footnote{See \texttt{\href{https://stackoverflow.com/questions/61444425/}{https://stackoverflow.com/questions/61444425/}}} +We can express this as a type equivalence: \[ -C\triangleq\forall R.\,(\forall A.\,(A\rightarrow F^{A})\times A\rightarrow R)\rightarrow R\quad. +\forall M^{:\text{Monad}}.\,M\xrightarrow{\text{Monad}}M\cong\bbnum 1\quad. \] -We need to verify that: -\textbf{(1)} For any $c:C$ we have $\text{fix}\,(\text{unfix}\,(c))=c$. -\textbf{(2)} For any $q:F^{C}$ we have $\text{unfix}\,(\text{fix}\,(q))=q$. +\subparagraph{Proof} -To prove item \textbf{(1)}: -\begin{align*} -{\color{greenunder}\text{expect to equal }c:}\quad & \gunderline{\text{fix}}\,(\text{unfix}\,(c))\\ -{\color{greenunder}\text{definition of }\text{fix}:}\quad & =\text{unfold}^{F^{C}}(\text{unfix}^{\uparrow F}\times\text{unfix}\,(c))\\ -{\color{greenunder}\text{naturality law of }\text{unfold}:}\quad & =\text{unfold}^{C}(\text{unfix}\times c)\\ -{\color{greenunder}\text{identity law of }\text{unfold}:}\quad & =c\quad. -\end{align*} -Here we applied the naturality law~(\ref{eq:relational-naturality-law-of-unfold}) -with $A=C$, $B=F^{C}$, $a=c$, $f=\text{unfix}$, $u=\text{unfix}$, -and $v=\text{unfix}^{\uparrow F}$. To verify the precondition of -that law, write: +The \lstinline!Monad! typeclass has methods in the form of a $P$-typeclass +for functors $K$ if we define $P$ by $(P^{K})^{A}\triangleq A+K^{K^{A}}$. +Then the methods of the \lstinline!Monad! typeclass are represented +by a single value of type: \[ -u\bef f^{\uparrow F}\overset{?}{=}f\bef v\quad,\quad\text{or equivalently:}\quad\text{unfix}\bef\text{unfix}^{\uparrow F}\overset{?}{=}\text{unfix}\bef\text{unfix}^{\uparrow F}\quad. +\forall A.\,(P^{K})^{A}\rightarrow K^{A}=\forall A.\,A+K^{K^{A}}\rightarrow K^{A}\cong(\forall A.\,A\rightarrow K^{A})\times(\forall A.\,K^{K^{A}}\rightarrow K^{A})\quad. \] -This holds trivially. - -To prove item \textbf{(2)}, write: +This is a tuple type describing the type signatures of $K$\textsf{'}s \lstinline!pure! +and \lstinline!flatten! methods when $K$ is a monad. So, the Jaskelioff-O\textsf{'}Connor +theorem applies to the \lstinline!Monad! typeclass. The free monad +constructor ($E$) is defined recursively as $(E^{F})^{A}\triangleq A+F^{(E^{F})^{A}}$, +making $E^{F}$ a monad when $F$ is any functor. The free monad\textsf{'}s +universal runner is defined by: \begin{align*} -{\color{greenunder}\text{expect to equal }q:}\quad & \text{unfix}\,(\gunderline{\text{fix}\,(q)})\\ -{\color{greenunder}\text{definition of }\text{fix}:}\quad & =\gunderline{\text{unfix}}\,\big(\text{unfold}^{F^{C}}(\text{unfix}^{\uparrow F}\times q)\big)\\ -{\color{greenunder}\text{definition of }\text{unfold}:}\quad & =\text{unfix}\,\big(\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times A\rightarrow R}\rightarrow p^{F^{C}}(\text{unfix}^{\uparrow F}\times q)\big)\\ -{\color{greenunder}\text{definition of }\text{unfix}:}\quad & =\big(\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times A\rightarrow R}\rightarrow p^{F^{C}}(\text{unfix}^{\uparrow F}\times q)\big)^{F^{C}}(\text{unfoldF})\\ -{\color{greenunder}\text{apply function}:}\quad & =\text{unfoldF}^{F^{C}}(\text{unfix}^{\uparrow F}\times q)\\ -{\color{greenunder}\text{definition of }\text{unfoldF}:}\quad & =q\triangleright\gunderline{\text{unfix}^{\uparrow F}\bef\big(a^{:F^{C}}\rightarrow\text{unfold}\,(\text{unfix}^{\uparrow F}\times a)\big)^{\uparrow F}}\\ -{\color{greenunder}\text{composition under }^{\uparrow F}:}\quad & =q\triangleright\big(x^{:C}\rightarrow\gunderline{\text{unfold}\,(\text{unfix}^{\uparrow F}\times\text{unfix}\,(x))}\big)^{\uparrow F}\\ -{\color{greenunder}\text{definition of }\text{fix}:}\quad & =q\triangleright\big(x^{:C}\rightarrow\gunderline{\text{fix}\,(\text{unfix}\,(x))}\big)^{\uparrow F}\\ -{\color{greenunder}\text{item \textbf{(1)}}:}\quad & =q\triangleright\gunderline{(x^{:C}\rightarrow x)^{\uparrow F}}=x\triangleright\text{id}=q\quad. + & \text{run}_{E}^{F,A}:(\forall X.\,F^{X}\rightarrow M^{X})\rightarrow(E^{F})^{A}\rightarrow M^{A}\quad,\\ + & \text{run}_{E}^{F,A}\big(k^{:\forall X.\,F^{X}\rightarrow M^{X}}\big)\triangleq\,\begin{array}{|c||c|} + & M^{A}\\ +\hline A & \text{pu}_{M}\\ +F^{(E^{F})^{A}} & k^{(E^{F})^{A}}\bef\text{flm}_{M}\big(\overline{\text{run}}_{E}^{F,A}(k)\big) +\end{array}\quad. \end{align*} -$\square$ - -It follows that $C$ is a fixpoint of the type equation $C\cong F^{C}$. -To show that $C$ is indeed the \emph{greatest} fixpoint, we need -to prove that for any other fixpoint $T$ there exists a unique fixpoint-preserving -morphism $\psi^{T}:T\rightarrow C$. Similarly to what we saw in Statement~\ref{subsec:Statement-fixpoint-preserving-fix}, -it is sufficient to check that $\psi^{T}$ is an $F$-coalgebra morphism. - -\subsubsection{Statement \label{subsec:Statement-greatest-fixpoint-Church-encoding-morphism}\ref{subsec:Statement-greatest-fixpoint-Church-encoding-morphism}} -For any $F$-coalgebra $A$ with a structure map $u:A\rightarrow F^{A}$, -there exists a unique $F$-algebra morphism $\psi_{u}^{A}$ of type -$A\rightarrow C$. The function $\psi_{u}^{A}$ is known as an \textbf{anamorphism}\index{anamorphism} -and was defined as in Statement~\ref{subsec:Statement-coalgebra-morphism-unfold}: +\textbf{(a)} Monad morphisms are natural transformations that satisfy +additional laws. We first consider the given type without restricting +the functions of type $A\rightarrow M^{A}$ to monad morphisms but +still assuming that they are natural transformations: \[ -\psi_{u}^{A}:A\rightarrow C\quad,\quad\quad\psi_{u}^{A}\triangleq a^{:A}\rightarrow\text{unfold}^{A}(u\times a)\quad. +\forall M^{:\text{Monad}}.\,\forall A.\,A\rightarrow M^{A}\quad. \] - - -\subparagraph{Proof} - -We know from Statement~\ref{subsec:Statement-coalgebra-morphism-unfold} -that $\psi_{u}^{A}$ satisfies the law of $F$-coalgebra morphisms. -Let $f:A\rightarrow C$ be any other $F$-coalgebra morphism; we need -to prove that $f=\psi_{u}^{A}$. - -We know that $f$ satisfies the $F$-coalgebra morphism law: +By the Yoneda identity, we get the type equivalence: \[ -u\bef f^{\uparrow F}=f\bef\text{unfix}\quad. +\forall A.\,A\rightarrow M^{A}\cong M^{\bbnum 1}\quad. \] -This is the precondition of the relational naturality law~(\ref{eq:relational-naturality-law-of-unfold}) -of \lstinline!unfold! if we set $B=C$ and $v=\text{unfix}$. So, -the conclusion of that law holds. We use that equation as well as -Statement~\ref{subsec:Statement-identity-law-of-unfold} and get: -\begin{align*} -{\color{greenunder}\text{for any }a^{:A}:}\quad & \psi_{u}^{A}(a)=\text{unfold}^{A}(u^{:A\rightarrow F^{A}}\times a^{:A})\\ -{\color{greenunder}\text{naturality law of }\text{unfold}:}\quad & =\text{unfold}^{C}(\text{unfix}\times f(a))\\ -{\color{greenunder}\text{identity law of }\text{unfold}:}\quad & =f(a)\quad. -\end{align*} -It follows that $\psi_{u}^{A}=f$. $\square$ - -We conclude this Appendix with the proof of a type identity dual to -the Church-Yoneda identity\index{Church-co-Yoneda identity} shown -in Statement~\ref{subsec:Statement-Church-Yoneda-identity}. That -identity has no accepted name, and this book calls it the \textsf{``}Church-co-Yoneda\textsf{''} -identity. - -\subsubsection{Statement \label{subsec:Statement-Church-co-Yoneda}\ref{subsec:Statement-Church-co-Yoneda}} - -For any covariant functors $F$ and $G$: +So, we have reduced the type to $\forall M^{:\text{Monad}}.\,M^{\bbnum 1}$. +This type will be in the form suitable for the Jaskelioff-O\textsf{'}Connor +theorem~(\ref{eq:jaskelioff-o-connor-theorem}) if we set $F=M$, +$A=\bbnum 0$, $C=\bbnum 1$; the parameter $B$ remains unused since +$A\rightarrow M^{B}=\bbnum 0\rightarrow M^{B}\cong\bbnum 1$. Then +Eq.~(\ref{eq:jaskelioff-o-connor-theorem}) gives: \[ -G^{\nu X.\,F^{X}}\cong\exists A.\,(A\rightarrow F^{A})\times G^{A}\quad. +\forall M^{:\text{Monad}}.\,M^{\bbnum 1}\cong\forall M^{:\text{Monad}}.\,(\bbnum 0\rightarrow M^{B})\rightarrow M^{\bbnum 1}\cong(E^{R})^{\bbnum 1}\quad, \] - - -\subparagraph{Proof} - -Denote for brevity $C\triangleq\nu X.\,F^{X}$. The existential type -is rewritten as: +where we must define $R^{X}=A\times(B\rightarrow X)$. However, setting +$A=\bbnum 0$ gives also $R=\bbnum 0$. Then the free monad $E^{R}$ +is the identity functor: \[ -\exists A.\,(A\rightarrow F^{A})\times G^{A}=\forall R.\,(\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R)\rightarrow R\quad. +(E^{R})^{C}=C+R^{(E^{R})^{C}}=C+\bbnum 0\cong C\quad. \] -We will demonstrate the isomorphism if we define functions \lstinline!toG! -and \lstinline!fromG! that are mutual inverses, with type signatures: +Finally, we obtain $(E^{R})^{\bbnum 1}=\bbnum 1$, and so: \[ -\text{toG}:(\exists A.\,(A\rightarrow F^{A})\times G^{A})\rightarrow G^{C}\quad,\quad\quad\text{fromG}:G^{C}\rightarrow\exists A.\,(A\rightarrow F^{A})\times G^{A}\quad. +\forall M^{:\text{Monad}}.\,\forall A.\,A\rightarrow M^{A}\cong\bbnum 1\quad. \] -The first type signature can be implemented as: -\begin{align*} - & \text{toG}:\big(\forall R.\,(\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R)\rightarrow R\big)\rightarrow G^{C}\quad,\\ - & \text{toG}\triangleq k^{:\forall R.\,(\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R)\rightarrow R}\rightarrow k^{G^{C}}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow g\triangleright(\psi_{u}^{A})^{\uparrow F}\big)\quad, -\end{align*} -where $\psi_{u}^{A}$ is the anamorphism of type $A\rightarrow C$ -defined in Statement~\ref{subsec:Statement-coalgebra-morphism-unfold}. - -The function \lstinline!fromG! is implemented as: -\begin{align*} - & \text{fromG}:G^{C}\rightarrow\forall R.\,(\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R)\rightarrow R\quad,\\ - & \text{fromG}\triangleq g^{:G^{C}}\rightarrow\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R}\rightarrow p^{C}(\text{unfix}\times g)\quad. -\end{align*} - -It remains to prove the two directions of the isomorphism roundtrip: - -\textbf{(1)} For any $g:G^{C}$ we have: $\text{toG}\,(\text{fromG}\,(g))=g$. -\textbf{(2)} For any $k:\exists A.\,(A\rightarrow F^{A})\times G^{A}$ -we have: $\text{fromG}\,(\text{toG}\,(k))=k$. +We conclude that \emph{without} restricting to monad morphisms there +is only a single function of the given type. It remains to derive +the code for that function and to verify that it is indeed a monad +morphism. -To prove item \textbf{(1)}: -\begin{align*} - & \text{toG}\,(\gunderline{\text{fromG}}\,(g))=\gunderline{\text{toG}}\,\big(\forall R.\,p^{:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R}\rightarrow p^{C}(\text{unfix}\times g)\big)\\ - & =\big(\forall A.\,u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow g\triangleright(\psi_{u}^{A})^{\uparrow F}\big)^{C}(\text{unfix}\times g)\\ - & =g\triangleright(\psi_{\text{unfix}}^{C})^{\uparrow F}\quad. -\end{align*} -We note that $\psi_{\text{unfix}}^{C}$ is the identity function ($\text{id}^{:C\rightarrow C}$) -because it is the unique $F$-coalgebra morphism of type $C\rightarrow C$ -by Statement~\ref{subsec:Statement-greatest-fixpoint-Church-encoding-morphism}. -It follows that: +We begin with a unit value (that we denote by $1$) viewed as a value +of type $(E^{R})^{C}$ in the right-hand side of Eq.~(\ref{eq:jaskelioff-o-connor-theorem}). +We follow the proof of Statement~\ref{subsec:Statement-Jaskelioff-OConnor}. +The first step is to convert the value of type $(E^{R})^{C}$ into +a function $f$ of type: \[ -\text{toG}\,(\text{fromG}\,(g))=g\triangleright(\psi_{\text{unfix}}^{C})^{\uparrow F}=g\triangleright\text{id}^{\uparrow F}=g\quad. +f:\forall M^{:\text{Monad}}.\,\big(\forall X.\,(E^{R})^{X}\xrightarrow{\text{Monad}}M^{X}\big)\rightarrow M^{C}\quad. \] - -To prove item \textbf{(2)}, apply both sides to a type $R$ and a -value $p^{:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R}$: +In our case, this function is simplified to: \begin{align*} -{\color{greenunder}\text{expect to equal }k^{R}(p):}\quad & \big(\text{fromG}\,(\text{toG}\,(k))\big)^{R}(p)=p^{C}(\text{unfix}\times\text{toG}\,(k))\\ - & =p^{C}\big(\text{unfix}\times k^{G^{C}}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow g\triangleright(\psi_{u}^{A})^{\uparrow F}\big)\big)\quad. + & f:\forall M^{:\text{Monad}}.\,\big(\forall X.\,\text{Id}^{X}\xrightarrow{\text{Monad}}M^{X}\big)\rightarrow M^{\bbnum 1}\quad,\\ + & f^{M}\big(k^{:\forall X.\,\text{Id}^{X}\xrightarrow{\text{Monad}}M^{X}}\big)\triangleq k^{\bbnum 1}(1)\quad. \end{align*} -To proceed, we need to use the naturality law of $k$: -\[ -\text{for all }Q,R,f^{:Q\rightarrow R},q^{:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow Q}:\quad k^{R}(\forall A.\:q^{A}\bef f)=f(k^{Q}(q))\quad. -\] -Setting the following parameters in this law: +The next step is to convert $f$ to a function $g$ of type: \[ -Q=G^{C}\quad,\quad\quad f=t^{:G^{C}}\rightarrow p^{C}(\text{unfix}\times t)\quad,\quad q=\forall A.\,u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow g\triangleright(\psi_{u}^{A})^{\uparrow F}\quad, +g:\forall M^{:\text{Monad}}.\,(\forall X.\,R^{X}\rightarrow M^{X})\rightarrow M^{C}\quad. \] -we obtain: +In our case, $R^{X}=\bbnum 0$ and $R^{X}\rightarrow M^{X}\cong\bbnum 1$, +so this function is simplified to: \begin{align*} - & k^{R}(\forall A.\:u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow p^{C}(\text{unfix}\times g\triangleright(\psi_{u}^{A})^{\uparrow F}))\\ - & =p^{C}\big(\text{unfix}\times k^{G^{C}}\big(\forall A.\,u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow g\triangleright(\psi_{u}^{A})^{\uparrow F}\big)\big)\quad. + & g:\forall M^{:\text{Monad}}.\,\bbnum 1\rightarrow M^{\bbnum 1}\quad,\\ + & g^{M}(k^{:\bbnum 1})\triangleq f^{M}\big(\forall Y.\,r^{:(E^{R})^{Y}}\rightarrow\text{run}_{E}^{R,Y}(k)(r)\big)\\ + & \quad=f^{M}(\forall Y.\,r^{:Y}\rightarrow\text{pu}_{M}^{Y}(r))=\text{pu}_{M}^{\bbnum 1}(1)\quad. \end{align*} -We expect the left-hand side to equal $k^{R}(p)$, so the remaining -difference is: +Finally, we convert $g$ to a function $h$ of type: \begin{align*} - & p\overset{?}{=}\forall A.\:u^{:A\rightarrow F^{A}}\times g^{:G^{A}}\rightarrow p^{C}(\text{unfix}\times g\triangleright(\psi_{u}^{A})^{\uparrow F})\quad,\\ -{\color{greenunder}\text{or equivalently}:}\quad & p^{A}(u^{:A\rightarrow F^{A}}\times g^{:G^{A}})\overset{?}{=}p^{C}(\text{unfix}\times g\triangleright(\psi_{u}^{A})^{\uparrow F})\quad. + & h:\forall M^{:\text{Monad}}.\,(A\rightarrow M^{B})\rightarrow M^{C}\\ + & =\forall M^{:\text{Monad}}.\,(\bbnum 0\rightarrow M^{B})\rightarrow M^{\bbnum 1}\quad.\\ + & \cong\forall M^{:\text{Monad}}.\,\bbnum 1\rightarrow M^{\bbnum 1}\cong\forall M^{:\text{Monad}}.\,M^{\bbnum 1}\quad. \end{align*} -This should hold for all types $A$ and for all $g^{:G^{A}}$, $u^{:A\rightarrow F^{A}}$, -$p:\forall A.\,(A\rightarrow F^{A})\times G^{A}\rightarrow R$. We -may assume that all such $p$ obey their relational naturality law: + There exists only one value of type $\forall M^{:\text{Monad}}.\,M^{\bbnum 1}$, +and that value is $\text{pu}_{M}(1)$. Converting that to the type +signature $\forall A.\:A\rightarrow M^{A}$, we recover just the standard +monad method $\text{pu}_{M}$. We know that $\text{pu}_{M}$ gives +a monad morphism between the identity monad and $M$ (see Statement~\ref{subsec:Statement-pure-M-is-monad-morphism}). +So, we have proved that there exists a unique monad morphism of type +$\forall M^{:\text{Monad}}.\,\text{Id}\xrightarrow{\text{Monad}}M$. + +\textbf{(b)} Again, we first consider the given type without restricting +the functions of type $M^{X}\rightarrow M^{X}$ to monad morphisms +(but still assuming that they are natural transformations): \[ -\forall A,B,f^{:A\rightarrow B}:\quad\text{if}\quad u^{:A\rightarrow F^{A}}\bef f^{\uparrow F}=f\bef v^{:B\rightarrow F^{B}}\quad\text{then}\quad p^{A}(u\times a)=p^{B}(v\times a\triangleright f^{\uparrow F})\quad. +\forall M^{:\text{Monad}}.\,\forall X.\,M^{X}\rightarrow M^{X}\quad. \] -We set the following parameters in this law, +This type will be in the form suitable for the Jaskelioff-O\textsf{'}Connor +theorem~(\ref{eq:jaskelioff-o-connor-theorem}) if we set $F=M$, +$A=\bbnum 1$, and $B=C=X$. The functor $R$ is then defined by: \[ -B=C\quad,\quad a=g\quad,\quad f=\psi_{u}^{A}\quad,\quad v=\text{unfix}\quad, +R^{T}\triangleq A\times(B\rightarrow T)\cong X\rightarrow T\quad, \] -and obtain: +and the functor $E^{R}$ (the free monad on $R$) is defined recursively +by: \[ -p^{A}(u\times g)=p^{C}(\text{unfix}\times g\triangleright(\psi_{u}^{A})^{\uparrow F})\quad. +(E^{R})^{T}\triangleq T+\big(X\rightarrow(E^{R})^{T}\big)\quad. \] -This will complete the proof of item \textbf{(2)} as long as the precondition -holds: + With these definitions, Eq.~(\ref{eq:jaskelioff-o-connor-theorem}) +gives: +\[ +\forall M^{:\text{Monad}}.\,\forall X.\,M^{X}\rightarrow M^{X}\cong\forall X.\,(E^{R})^{X}\quad. +\] +We are using the functor $(E^{R})^{T}$ with the type parameter $T=X$; +however, $E^{R}$ also contains $X$ through the definition of $R$. +To avoid confusion and to simplify notation, let us write $G^{X}$ +instead of $(E^{R})^{X}$, where the type constructor $G$ is defined +recursively by: +\[ +G^{X}\triangleq X+(X\rightarrow G^{X})\quad. +\] +(Note that $G$ is neither covariant nor contravariant.) With this +definition, we obtain: +\[ +\forall M^{:\text{Monad}}.\,\forall X.\,M^{X}\rightarrow M^{X}\cong\forall X.\,G^{X}\quad. +\] + +To simpify the type $\forall X.\,G^{X}$, begin by expanding the recursive +type $G^{X}$: \begin{align*} - & u^{:A\rightarrow F^{A}}\bef f^{\uparrow F}\overset{?}{=}f\bef v^{:B\rightarrow F^{B}}\quad,\\ -{\color{greenunder}\text{or equivalently}:}\quad & u\bef(\psi_{u}^{A})^{\uparrow F}\overset{?}{=}\psi_{u}^{A}\bef\text{unfix}\quad. + & \forall X.\,G^{X}\cong\forall X.\,X+(X\rightarrow G^{X})\\ +{\color{greenunder}\text{non-disjunctivity}:}\quad & \cong(\forall X.\,X)+(\forall X.\,X\rightarrow G^{X})\\ +{\color{greenunder}\text{use }\forall X.\,X\cong\bbnum 0:}\quad & \cong\forall X.\,X\rightarrow G^{X}\quad. \end{align*} -This holds by Statement~\ref{subsec:Statement-coalgebra-morphism-unfold}: -it is the $F$-coalgebra morphism law of $\psi_{u}^{A}$. $\square$ - -The Church-co-Yoneda identity can be used to prove the Church encoding -formula for simultaneous greatest fixpoints of several functors, similarly -to what we did in Section~\ref{subsec:Least-fixpoints-of-mutually-recursive-types}. -For simplicity, we will now show a proof for just two mutually recursive -types; the proof can be extended to any number of types. - -We will first prove a property of nested fixpoints. - -\subsubsection{Statement \label{subsec:Statement-nested-greatest-fixpoints}\ref{subsec:Statement-nested-greatest-fixpoints}} +Here we used the non-disjunctivity property from Example~\ref{subsec:Example-undisjunctive-type-constructors}(e). -For any bifunctor $F$, the following equivalence holds: +Continue expanding the recursive type: +\begin{align*} + & \forall X.\,X\rightarrow G^{X}\cong\forall X.\,X\rightarrow(X+(X\rightarrow G^{X}))\\ +{\color{greenunder}\text{non-disjunctivity}:}\quad & \cong(\gunderline{\forall X.\,X\rightarrow X})+\big(\forall X.\,X\rightarrow X\rightarrow G^{X}\big)\\ + & \cong\bbnum 1+\forall X.\,X\times X\rightarrow G^{X}\quad. +\end{align*} +The relevant non-disjunctivity property was shown in Example~\ref{subsec:Example-undisjunctive-type-constructors}(f). +Expand further, using the same non-disjunctivity property: +\begin{align*} + & \forall X.\,G^{X}\cong\bbnum 1+\forall X.\,X\times X\rightarrow G^{X}\\ + & \cong\bbnum 1+\forall X.\,X\times X\rightarrow(X+(X\rightarrow G^{X}))\\ +{\color{greenunder}\text{non-disjunctivity}:}\quad & \cong\bbnum 1+(\gunderline{\forall X.\,X\times X\rightarrow X})+\big(\forall X.\,X\times X\rightarrow X\rightarrow G^{X}\big)\\ + & \cong\bbnum 1+\bbnum 2+\forall X.\,X\times X\times X\rightarrow G^{X}\quad. +\end{align*} +Proceeding similarly, we obtain: \[ -\nu A.\,(\nu B.\,F^{A,B})\cong\nu B.\,F^{B,B}\quad. +\forall X.\,\underbrace{X\times...\times X}_{n\text{ times}}\rightarrow G^{X}\cong\underbrace{\bbnum 1+...+\bbnum 1}_{n\text{ times}}+\forall X.\,\underbrace{X\times...\times X}_{n+1\text{ times}}\rightarrow G^{X}\quad. +\] +It follows by induction that $\forall X.\,G^{X}$ is equivalent to +an \textsf{``}infinite\textsf{''} sum type: +\[ +\forall X.\,G^{X}\cong\bbnum 1+\bbnum 2+\bbnum 3+... \] +Values of that type may be described by pairs $\left(n,k\right)$ +of natural numbers such that $1\le k\le n$. The number $n$ chooses +the part \textsf{``}$\bbnum n$\textsf{''} within the disjunctive type $\bbnum 1+\bbnum 2+\bbnum 3+...$, +where we denoted by \textsf{``}$\bbnum n$\textsf{''} the type $\underbrace{\bbnum 1+...+\bbnum 1}_{n\text{ times}}$. +The number $k$ chooses a specific unit value within $\underbrace{\bbnum 1+...+\bbnum 1}_{n\text{ times}}$. +The next step is to convert values $\left(n,k\right)$ of that type +into functions of type $M^{X}\rightarrow M^{X}$ that work in the +same way for all monads $M$ and all types $X$. We have to find out +whether any of those functions obey the laws of monad morphisms. For +that, we need to derive the specific code of those functions. We follow +the steps outlined in the proof of Statement~\ref{subsec:Statement-Jaskelioff-OConnor}. -\subparagraph{Proof} +First, we translate pairs $\left(n,k\right)$ into values of type +$\forall X.\,G^{X}$ that we will denote by $q_{n,k}$. To achieve +that, we need to retrace the way we expanded the recursive type $G^{X}$. +As an example, consider the pair $\left(n=2,k=1\right)$. The value +$n=2$ corresponds to the type $\bbnum 2$, which was obtained from +$\forall X.\,X\rightarrow X\rightarrow X$ during expansion of $\forall X.\,G^{X}$. +The type $\forall X.\,X\rightarrow X\rightarrow X$ has only two distinct +values, which are functions that return the first or the second argument +of type $X$. The index $k=1$ selects the first of those values, +which is a function whose code is written as $x_{1}^{:X}\rightarrow x_{2}^{:X}\rightarrow x_{1}$. -Denote $G^{A,C}\triangleq(A\rightarrow C)\times A$ and write the -Church encoding for the fixpoints: +To simplify notation, let us temporarily fix the type parameter $X$; +we will restore the quantifier $\forall X$ at the end of the derivation. + +The type $X\rightarrow X\rightarrow X$ was found during expansion +of the recursive type $G^{X}$ as: \[ -\nu A.\,(\nu B.\,F^{A,B})=\exists A.\,(A\rightarrow\nu B.\,F^{A,B})\times A=\exists A.\,G^{A,\,\nu B.\,F^{A,B}}\quad. +G^{X}=X+(X\rightarrow(X+(X\rightarrow(X+...))))\quad. \] -View $A$ as fixed and use the Church-co-Yoneda identity (Statement~\ref{subsec:Statement-Church-co-Yoneda}): +So, the pair $\left(n=2,k=1\right)$ corresponds to the function $q_{2,1}^{X}:G^{X}$ +written as: \begin{align*} - & G^{A,\,\nu B.\,F^{A,B}}\cong\exists B.\,(B\rightarrow F^{A,B})\times\gunderline{G^{A,B}}\\ - & =\exists B.\,(B\rightarrow F^{A,B})\times(A\rightarrow B)\times A\\ - & =\exists B.\,(A\rightarrow B)\times H^{A,B}\quad, + & q_{2,1}^{X}:X+(X\rightarrow(X+(X\rightarrow(X+(X\rightarrow G^{X})))))\quad,\\ + & q_{2,1}^{X}\triangleq\bbnum 0^{:X}+(x_{1}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{2}^{:X}\rightarrow(x_{1}+\bbnum 0^{:X\rightarrow G^{X}}))))\quad. \end{align*} -where we defined $H$ by: +In a similar way, we define the functions $q_{n,k}$ for any $1\le k\le n$: \[ -H^{A,B}\triangleq(B\rightarrow F^{A,B})\times A\quad. +q_{n,k}^{X}\triangleq\bbnum 0^{:X}+(x_{1}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{2}^{:X}\rightarrow...\rightarrow(\bbnum 0^{:X}+(x_{n}^{:X}\rightarrow(x_{k}+\bbnum 0^{:X\rightarrow G^{X}})))...)))\quad. \] -Now we can simplify the nested fixpoints: +To make this code description rigorous, let us define $u_{i,n,k}$ +and $v_{i,n}$ like this: \begin{align*} -{\color{greenunder}\text{expect }\nu B.\,F^{B,B}:}\quad & \nu A.\,(\nu B.\,F^{A,B})=\gunderline{\exists A.\,\exists B.}\,(A\rightarrow B)\times H^{A,B}\\ -{\color{greenunder}\text{co-Fubini theorem (Statement~\ref{subsec:Statement-commute-existential})}:}\quad & \cong\exists B.\,\exists A.\,(A\rightarrow B)\times H^{A,B}\\ -{\color{greenunder}\text{co-Yoneda identity}:}\quad & \cong\exists B.\,\gunderline{H^{B,B}}=\exists B.\,(B\rightarrow F^{B,B})\times B\\ -{\color{greenunder}\text{Church encoding}:}\quad & \cong\nu B.\,F^{B,B}\quad. + & u_{i,n,k}\triangleq\bbnum 0^{:X}+(x_{i}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{i+1}^{:X}\rightarrow...\rightarrow(x_{n}^{:X}\rightarrow(x_{k}+\bbnum 0^{:X\rightarrow G^{X}}))...))),\\ + & v_{i,n}(x_{0})\triangleq\bbnum 0^{:X}+(x_{i}^{:X}\rightarrow(\bbnum 0^{:X}+(x_{i+1}^{:X}\rightarrow...\rightarrow(x_{n}^{:X}\rightarrow(x_{0}+\bbnum 0^{:X\rightarrow G^{X}}))...))). \end{align*} - - -\subsubsection{Statement \label{subsec:Statement-mutually-recursive-greatest-fixpoints}\ref{subsec:Statement-mutually-recursive-greatest-fixpoints}} - -Given any bifunctors $F$, $G$, define $T$ and $U$ as the simultaneous -greatest fixpoints of two type equations: -\[ -T=F^{T,U}\quad,\quad\quad U=G^{T,U}\quad. -\] -Then the types $T$ and $U$ can be expressed as: +These formulas hold for $1\le i\le k\le n$. An inductive definition +of $q_{n,k}^{X}$, $u_{i,n,k}$, and $v_{i,n}$ is: \begin{align*} - & T\cong\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times A\quad,\\ - & U\cong\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times B\quad. + & q_{n,k}^{X}=u_{1,n,k}\quad,\quad\quad u_{i,n,k}:G^{X}\quad,\quad\quad v_{i,n}:X\rightarrow G^{X}\quad,\\ +{\color{greenunder}\text{for }1\le i m.flatMap { x_2 => pure(x_1) } } +\end{lstlisting} +This code can be rewritten as a functor block, making its logic more +visually clear: +\begin{lstlisting} +def h_2_1(m: M[X]): M[X] = for { + x_1 <- m + x_2 <- m +} yield x_1 +\end{lstlisting} +The code runs two effects of \lstinline!m! but returns the first +value (\lstinline!x_1!), ignoring \lstinline!x_2!. -\begin{table} -\begin{centering} -\begin{tabular}{|c|c|c|} -\hline -\textbf{\footnotesize{}Identity} & \textbf{\footnotesize{}Assumptions} & \textbf{\footnotesize{}Source}\tabularnewline -\hline -\hline -{\footnotesize{}$\forall A.\,(F^{A}\rightarrow A)\rightarrow A\cong\mu A.\,F^{A}$} & {\footnotesize{}$F$ is any functor} & {\footnotesize{}Section~\ref{subsec:The-Church-encoding-of-recursive-types}}\tabularnewline -\hline -{\footnotesize{}$\forall A.\,(H^{A}\rightarrow A)\rightarrow A\cong H^{\bbnum 1}$} & {\footnotesize{}$H$ is any contrafunctor} & {\footnotesize{}Statement~\ref{subsec:Example-simplify-quantifier-1-1}}\tabularnewline -\hline -{\footnotesize{}$\forall A.\,(F^{A}\rightarrow A)\rightarrow G^{A}\cong G^{\mu A.\,F^{A}}$} & {\footnotesize{}$F$, $G$ are any functors} & {\footnotesize{}Statement~\ref{subsec:Statement-Church-Yoneda-identity}}\tabularnewline -\hline -{\footnotesize{}$\mu A.\,\mu B.\,F^{A,B}\cong\mu B.\,F^{B,B}$} & {\footnotesize{}$F$ is any bifunctor} & {\footnotesize{}Statement~\ref{subsec:Statement-nested-fixpoints}}\tabularnewline -\hline -{\footnotesize{}}% -\begin{minipage}[c][12mm][t]{0.1mm}% -% -\end{minipage}{\footnotesize{}}% -\begin{minipage}[c]{0.43\columnwidth}% -\begin{center} -{\footnotesize{}$\mu A.\,P^{A,\,\mu B.\,Q^{A,B}}\cong$}\\ -{\footnotesize{}$\forall A.\,\forall B.\,(P^{A,B}\rightarrow A)\times(Q^{A,B}\rightarrow B)\rightarrow A$} -\par\end{center}% -\end{minipage} & {\footnotesize{}$P$, $Q$ are any bifunctors} & {\footnotesize{}Statement~\ref{subsec:Statement-nested-fixpoint-under-functor}}\tabularnewline -\hline -{\footnotesize{}$\forall A.\,F^{A}\rightarrow P\cong P$} & {\footnotesize{}If $F^{A}\neq\bbnum 0$ for some $A$} & {\footnotesize{}Statement~\ref{subsec:Statement-application-full-relation}(a)}\tabularnewline -\hline -{\footnotesize{}$\forall A.\,((A\rightarrow A)\rightarrow A)\rightarrow A\cong\bbnum 1+\bbnum 2+\bbnum 3+...$} & {\footnotesize{}~} & {\footnotesize{}Statement~\ref{subsec:Statement-advanced-type-equivalence}}\tabularnewline -\hline -{\footnotesize{}}% -\begin{minipage}[c][17mm][t]{0.1mm}% -% -\end{minipage}{\footnotesize{}}% -\begin{minipage}[c]{0.43\columnwidth}% -\begin{center} -{\footnotesize{}$\forall A.\,(H^{A}\rightarrow A)\rightarrow F^{A}+G^{A}\cong$}\\ -{\footnotesize{}$(\forall A.\:(H^{A}\rightarrow A)\rightarrow F^{A})\,+$}\\ -{\footnotesize{}$(\forall A.\:(H^{A}\rightarrow A)\rightarrow G^{A})$} -\par\end{center}% -\end{minipage} & {\footnotesize{}For any $F$, $G$, $H$} & {\footnotesize{}Example~\ref{subsec:Example-undisjunctive-type-constructors}(c)}\tabularnewline -\hline -{\footnotesize{}$\forall A.\,\forall B.\,F^{A,B}\cong\forall B.\,\forall A.\,F^{A,B}$} & {\footnotesize{}For any $F$} & {\footnotesize{}Statement~\ref{subsec:Statement-Fubini-theorem-1}}\tabularnewline -\hline -{\footnotesize{}$\forall A.\,(F^{A}+G^{A})\cong(\forall A.\,F^{A})+(\forall A.\,G^{A})$} & {\footnotesize{}For any $F$, $G$} & {\footnotesize{}Statement~\ref{subsec:Statement-general-identities-forall}(a)}\tabularnewline -\hline -{\footnotesize{}$\forall A.\,(F^{A}\times G^{A})\cong(\forall A.\,F^{A})\times(\forall A.\,G^{A})$} & {\footnotesize{}For any $F$, $G$} & {\footnotesize{}Statement~\ref{subsec:Statement-general-identities-forall}(b)}\tabularnewline -\hline -{\footnotesize{}$\forall A.\,R\rightarrow F^{A}\cong R\rightarrow(\forall A.\,F^{A})$} & {\footnotesize{}Any $F$, a fixed type $R$} & {\footnotesize{}Statement~\ref{subsec:Statement-general-identities-forall}(c)}\tabularnewline -\hline -{\footnotesize{}$\forall A.\,F^{P^{A}}\cong F^{\forall A.\,P^{A}}$} & {\footnotesize{}$F$ is strictly positive} & {\footnotesize{}Statement~\ref{subsec:Statement-quantifier-across-functor}}\tabularnewline -\hline -{\footnotesize{}$\forall A.\,F^{A}\cong\bbnum 0$ when $F^{\bbnum 0}\cong\bbnum 0$} & {\footnotesize{}$F$ is such that $F^{\bbnum 0}\cong\bbnum 0$} & {\footnotesize{}Statement~\ref{subsec:Statement-Fubini-theorem-1}}\tabularnewline -\hline -{\footnotesize{}$\forall A.\,F^{A\rightarrow A}\cong F^{\bbnum 1}$} & {\footnotesize{}$F$ is strictly positive} & {\footnotesize{}Example~\ref{subsec:Example-simplify-quantifier-A-A}(a)}\tabularnewline -\hline -{\footnotesize{}$\forall A.\,H^{A\rightarrow A}\cong H^{\bbnum 1}$} & {\footnotesize{}$H$ is a contrafunctor} & {\footnotesize{}Example~\ref{subsec:Example-simplify-quantifier-A-A}(b)}\tabularnewline -\hline -{\footnotesize{}$\forall A.\,((A\rightarrow P)\rightarrow A\rightarrow A\cong P$} & {\footnotesize{}$P$ is a fixed type} & {\footnotesize{}Exercise~\ref{par:Problem-Peirce-law}}\tabularnewline -\hline -\end{tabular} -\par\end{centering} -\caption{Type identities proved by other parametricity techniques.\label{tab:Type-identities-proved-by-parametricity}} -\end{table} +Now we can generalize the code pattern from $h_{2,1}$ to $h_{n,k}$ +and write symbolically: +\begin{lstlisting} +def h_n_k(m: M[X]): M[X] = for { + x_1 <- m + x_2 <- m + ... + x_n <- m +} yield x_k +\end{lstlisting} -\begin{table}[h] -\begin{centering} -\begin{tabular}{|c|c|c|} -\hline -\textbf{\footnotesize{}Identity} & \textbf{\footnotesize{}Assumptions} & \textbf{\footnotesize{}Source}\tabularnewline -\hline -\hline -{\footnotesize{}$\exists C.\,F^{C}\cong\forall D.\,\big(\forall C.\,(F^{C}\rightarrow D)\big)\rightarrow D$} & {\footnotesize{}For any $F$} & {\footnotesize{}Equation~(\ref{eq:existential-via-universal-Yoneda})}\tabularnewline -\hline -{\footnotesize{}$(\exists C.\,F^{C})\rightarrow R\cong\forall C.\,(F^{C}\rightarrow R)$} & {\footnotesize{}For any $F$, $R$} & {\footnotesize{}Statement~\ref{subsec:Statement-function-extension-rule}}\tabularnewline -\hline -{\footnotesize{}$\exists A.\,A\cong\bbnum 1$} & & \tabularnewline -\hline -{\footnotesize{}$\exists A.\,F^{A}\cong F^{\bbnum 1}$} & {\footnotesize{}$F$ is any functor} & {\footnotesize{}Statement~\ref{subsec:Statement-co-Yoneda-two-identities-1}(a)}\tabularnewline -\hline -{\footnotesize{}$\exists A.\,H^{A}\cong H^{\bbnum 0}$} & {\footnotesize{}$H$ is any contrafunctor} & {\footnotesize{}Statement~\ref{subsec:Statement-co-Yoneda-two-identities-1}(b)}\tabularnewline -\hline -{\footnotesize{}$\exists A.\,F^{A}\rightarrow A\cong\bbnum 1$} & {\footnotesize{}For any $F$} & {\footnotesize{}Example~\ref{subsec:Example-simple-existential-derivation}}\tabularnewline -\hline -{\footnotesize{}$\exists A.\,(F^{A}+G^{A})\cong(\exists A.\,F^{A})+(\exists A.\,G^{A})$} & {\footnotesize{}For any $F$, $G$} & {\footnotesize{}Example~\ref{subsec:Example-simple-existential-derivation-1-1}(b)}\tabularnewline -\hline -{\footnotesize{}$\exists A.\,\exists B.\,F^{A,B}\cong\exists B.\,\exists A.\,F^{A,B}$} & {\footnotesize{}For any $F$} & {\footnotesize{}Statement~\ref{subsec:Statement-commute-existential}}\tabularnewline -\hline -{\footnotesize{}$\nu A.\,F^{A}\cong\exists A.\,(A\rightarrow F^{A})\times A$} & {\footnotesize{}$F$ is any functor} & {\footnotesize{}Section~\ref{subsec:The-greatest-fixpoints-and-Church-co-Yoneda}}\tabularnewline -\hline -{\footnotesize{}$G^{\nu A.\,F^{A}}\cong\exists A.\,(A\rightarrow F^{A})\times G^{A}$} & {\footnotesize{}$F$, $G$ are any functors} & {\footnotesize{}Statement~\ref{subsec:Statement-Church-co-Yoneda}}\tabularnewline -\hline -{\footnotesize{}$\nu A.\,\nu B.\,F^{A,B}\cong\nu B.\,F^{B,B}$} & {\footnotesize{}$F$ is any bifunctor} & {\footnotesize{}Statement~\ref{subsec:Statement-nested-greatest-fixpoints}}\tabularnewline -\hline -{\footnotesize{}}% -\begin{minipage}[c][12mm][t]{0.1mm}% -% -\end{minipage}{\footnotesize{}}% -\begin{minipage}[c]{0.43\columnwidth}% -\begin{center} -{\footnotesize{}$\nu A.\,F^{A,\,\nu B.\,G^{A,B}}\cong$}\\ -{\footnotesize{}$\exists A.\,\exists B.\,(A\rightarrow F^{A,B})\times(B\rightarrow G^{A,B})\times A$} -\par\end{center}% -\end{minipage} & {\footnotesize{}$F$, $G$ are any bifunctors} & {\footnotesize{}Statement~\ref{subsec:Statement-mutually-recursive-greatest-fixpoints}}\tabularnewline -\hline -{\footnotesize{}$G^{\exists C.\,F^{C}}\cong\forall D.\,(\forall C.\,F^{C}\rightarrow D)\rightarrow G^{D}$} & {\footnotesize{}Any $F$, any functor $G$} & {\footnotesize{}Exercise~\ref{par:Exercise-additional-16-3}}\tabularnewline -\hline -\end{tabular} -\par\end{centering} -\caption{Type isomorphisms for existential types.\label{tab:Type-identities-for-existential-types}} -\end{table} +To prove that this is indeed the correct code for $h_{n,k}^{M}(m)$, +we need to use induction in $n$. We rewrite $q_{n,k}^{X}=u_{1,n,k}$ +and compute $\text{run}_{E}^{R,X}(p)(q_{n,k})=\text{run}_{E}^{R,X}(p)(u_{1,n,k})$. +Using the code of $\text{run}_{E}$, we obtain the following inductive +code definitions: +\begin{align*} +{\color{greenunder}\text{for }1\le i (A, Int) +val q: M[M[Unit]] = { s => ( { t => ((), s + 1) }, s) } +\end{lstlisting} +\[ +M^{A}\triangleq\text{Int}\rightarrow A\times\text{Int}\quad,\quad\quad q:M^{M^{\bbnum 1}}\quad,\quad q\triangleq s^{:\text{Int}}\rightarrow(\_^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}})\times s\quad. +\] +For more intuition, let us express \lstinline!q! via the \lstinline!State! +monad operations \lstinline!get! and \lstinline!set!: +\begin{lstlisting} +val get: M[Int] = s => (s, s) +val set: Int => M[Unit] = x => s => ((), x) +// Assuming that map and flatMap are defined for M: +val q: M[M[Unit]] = for { + s <- get +} yield set(s + 1) +\end{lstlisting} +Now we compute the two sides of the composition law, step by step. +First, we will use Scala\textsf{'}s functor block syntax. The \lstinline!flatten! +method can be written as: +\begin{lstlisting} +def flatten[A](mm: M[M[A]]): M[A] = for { + m <- mm + x <- m +} yield x +\end{lstlisting} +Substituting the value \lstinline!q! defined above, we get: +\begin{lstlisting} +val flatten_q: M[Unit] = for { // This is flatten(q). + m <- for { + s <- get + } yield set(s + 1) + x <- m +} yield x +\end{lstlisting} +Eliminate the nested \lstinline!for! and obtain: +\begin{lstlisting} +val flatten_q: M[Unit] = for { + s <- get + m = set(s + 1) + x <- m +} yield x +\end{lstlisting} +Or equivalently (as the returned value is always a unit value): +\begin{lstlisting} +val flatten_q: M[Unit] = for { + s <- get + _ <- set(s + 1) +} yield () +\end{lstlisting} +Applying \lstinline!h_n_k! to this value means writing code of the +form: +\begin{lstlisting} +val h_flatten_q: M[Unit] = for { + x_1 <- flatten_q + ... + x_n <- flatten_q +} yield x_k +\end{lstlisting} +The returned value in \lstinline!x_k! is in any case the unit value, +so let us focus on the state updates. Each \lstinline!flatten_q! +has the effect of reading the state value \lstinline!s! and storing +the incremented value \lstinline!s + 1!. The function \lstinline!h_n_k! +repeats $n$ times the effect of \lstinline!flatten_q!. This increments +the internal state $n$ times. So, the left-hand side of the law is +equivalent to: +\begin{lstlisting} +val lhs: M[Unit] = for { // This is h_flatten_q === h_n_k(flatten(q)). + s <- get + _ <- set(s + n) +} yield () +\end{lstlisting} + +Turning now to the right-hand side of the law, we write the first +sub-expression ($q\triangleright h_{n,k}^{\uparrow M}$, or in Scala, +\lstinline!q.map(h_n_k)!) as the following Scala code: +\begin{lstlisting} +val q_map_h: M[M[Unit]] = for { + m <- q +} yield h_n_k(m) +\end{lstlisting} +Substituting the code of \lstinline!q! (but not yet expanding \lstinline!h_n_k!), +we find: +\begin{lstlisting} +val q_map_h: M[M[Unit]] = for { + s <- get +} yield h_n_k(set(s + 1)) +\end{lstlisting} +The function call \lstinline!h_n_k(set(s + 1))! repeats $n$ times +the effect of \lstinline!set(s + 1)!, but \lstinline!s! is a fixed +value in that scope, so the result is equal to just a single effect: +\begin{lstlisting} +val q_map_h: M[M[Unit]] = for { + s <- get +} yield set(s + 1) +\end{lstlisting} +This is the same value as \lstinline!q! itself. +The next sub-expression is \lstinline!h_n_k(q_map_h)!, which equals +\lstinline!h_n_k(q)!: +\begin{lstlisting} +val h_q_map_h: M[M[Unit]] = for { + x_1 <- q + ... + x_n <- q +} yield x_k +\end{lstlisting} +Substituting the code for \lstinline!q!, we get: +\begin{lstlisting} +val h_q_map_h: M[M[Unit]] = for { + x_1 <- for { + s <- get + } yield set(s + 1) + ... + x_n <- for { + s <- get + } yield set(s + 1) +} yield x_k +\end{lstlisting} +Eliminate the nested \lstinline!for! and obtain: +\begin{lstlisting} +val h_q_map_h: M[M[Unit]] = for { + s <- get + x_1 = set(s + 1) + ... + s <- get + x_n = set(s + 1) +} yield x_k +\end{lstlisting} +The code runs $n$ times the effect of \lstinline!get! but actually +never runs the effect of \lstinline!set!; the unevaluated effectful +value \lstinline!set(s + 1)! is merely assigned to each \lstinline!x_i! +and then returned. So, the code is equivalent to: +\begin{lstlisting} +val h_q_map_h: M[M[Unit]] = for { + s <- get +} yield set(s + 1) +\end{lstlisting} +This is again just equal to \lstinline!q!. + +It remains to apply \lstinline!flatten! to \lstinline!h_q_map_h!, +which is the same as \lstinline!flatten(q)! and was already computed +as \lstinline!flatten_q! above: +\begin{lstlisting} +val rhs: M[Unit] = for { // This is flatten(h_q_map_h) === flatten(q). + s <- get + _ <- set(s + 1) +} yield () +\end{lstlisting} + +The left-hand side and the right-hand side of the law differ only +in the \lstinline!set! operation (\lstinline!set(s + n)! vs.~\lstinline!set(s + 1)!). +So, they are equal only when $n=1$ (that is, for \lstinline!h_1_1!). +It follows that, for all $n\ge2$ and for all $1\le k\le n$, the +function $h_{n,k}$ of type $M^{X}\rightarrow M^{X}$ violates the +composition law of monad morphisms when applied to the chosen value +$q:M^{M^{X}}$. + +Let us now summarize this derivation in code notation. The left-hand +side of the composition law is: +\begin{align*} + & \text{ftn}_{M}(q)=s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}}\quad,\\ + & h_{n,k}(\text{ftn}_{M}(q))=s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+n)^{:\text{Int}}\quad. +\end{align*} +Here we used the fact that $h_{n,k}(m)$ repeats $n$ times the effect +of $m$ (and that effect increments the value $s$). + +Turn to the right-hand side of the law and calculate: +\begin{align*} + & q\triangleright h_{n,k}^{\uparrow M}=s^{:\text{Int}}\rightarrow(\_^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}})\times s=q\quad,\\ + & h_{n,k}(q\triangleright h_{n,k}^{\uparrow M})=s^{:\text{Int}}\rightarrow(\_^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}})\times s=q\quad,\\ + & \text{ftn}_{M}(q)=s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}}\quad. +\end{align*} +The condition for the two sides of the law to be equal is: +\[ +s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+n)^{:\text{Int}}\overset{?}{=}s^{:\text{Int}}\rightarrow1^{:\bbnum 1}\times(s+1)^{:\text{Int}}\quad. +\] +This holds only if $n=1$. + +It follows that $h_{1,1}$ (which is an identity function of type +$M^{X}\rightarrow M^{X}$) is the only monad morphism that fits the +required type. $\square$ \chapter{Solutions for selected exercises} diff --git a/sofp-src/tex/sofp-back-cover-no-bg.tex b/sofp-src/tex/sofp-back-cover-no-bg.tex index 6d4e8b230..7cd865857 100644 --- a/sofp-src/tex/sofp-back-cover-no-bg.tex +++ b/sofp-src/tex/sofp-back-cover-no-bg.tex @@ -28,7 +28,7 @@ developed in excruciating detail through 1981 Scala code snippets, 233 statements with step-by-step derivations, 105 diagrams, 237 examples -with tested Scala code, and 314 exercises. Discussions +with tested Scala code, and 315 exercises. Discussions build upon each chapter\textsf{'}s material further. Beginners in FP will find tutorials about the \texttt{map}/\texttt{reduce} diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index 88ef7993d..dee2bd60d 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -833,17 +833,80 @@ \subsection{Appendix~\ref{app:Proofs-of-naturality-parametricity}} involving covariant and contravariant functors. Another version is a Yoneda identity for type constructors (Section~\ref{subsec:The-Yoneda-identities-for-type-constructors}). -{*}{*}{*} - -A number of resulting type isomorphisms can be found in Tables~\ref{tab:Type-identities-proved-by-Yoneda}\textendash \ref{tab:Type-identities-for-existential-types}. +We turn to further applications of parametricity that go beyond what +the Yoneda identities can achieve. Section~\ref{subsec:The-Church-encoding-of-recursive-types} +gives full proofs of the Church encoding of a recursive type defined +as the least fixpoint ($\mu A.\,F^{A}$) of a pattern functor $F$. +It is also shown (Statement~\ref{subsec:Statement-existence-of-church-encoding-type}) +that the least fixpoint is non-void if and only if the type $F^{\bbnum 0}$ +is non-void. This section develops the machinery of $F$-functor algebras, +catamorphisms, and defining the recursive type $\mu A.\,F^{A}$ via +the standard functions \lstinline!fix! and \lstinline!unfix!. + +Section~\ref{subsec:The-Church-Yoneda-identity} proves a useful +isomorphism that generalizes both the Church encoding and the Yoneda +identity: +\[ +G^{\mu A.\,F^{A}}\cong\forall A.\,(F^{A}\rightarrow A)\rightarrow G^{A}\quad. +\] +In this book, this is called the \textsf{``}Church-Yoneda\textsf{''} identity. One +application of that identity is in proving the \textsf{``}nested fixpoint +lemma\textsf{''} (Statement~\ref{subsec:Statement-nested-fixpoints}): +\[ +\mu A.\,(\mu B.\,N^{A,B})\cong\mu B.\,N^{B,B}\quad. +\] +Another is to establish the formula for the Church encoding of mutually +recursive types (Section~\ref{subsec:Least-fixpoints-of-mutually-recursive-types}). -{*}{*}{*} +A general property of universal quantifiers is distributivity with +respect to products, co-products, and function types (Statement~\ref{subsec:Statement-general-identities-forall}). +Distributivity with respect to co-products, +\[ +\forall A.\,F^{A}+G^{A}\cong(\forall A.\,F^{A})+(\forall A.\,G^{A})\quad, +\] +can be generalized to the following isomorphism, +\[ +\forall A.\,P^{A}\rightarrow F^{A}+G^{A}\cong(\forall A.\,P^{A}\rightarrow F^{A})+(\forall A.\,P^{A}\rightarrow G^{A})\quad, +\] +as long as the type constructor $P$ is, in our terminology, \textsf{``}non-disjunctive\textsf{''}. +Section~\ref{subsec:Non-disjunctive-type-constructors} gives a formal +definition of that property and goes through structural analysis, +discovering what type constructors are non-disjunctive. Known patterns +for building non-disjunctive type constructors are shown in Example~\ref{subsec:Example-undisjunctive-type-constructors} +and are generalized in Table~\ref{tab:Non-disjunctive-type-constructions}. + +We turn to a brief study of existentially quantified types. Section~\ref{subsec:Existential-type-quantifiers} +proves the two co-Yoneda identities and establishes some fundamental +properties of existential types. Then Section~\ref{subsec:The-greatest-fixpoints-and-Church-co-Yoneda} +shows that the greatest fixpoints are given by the Church encoding: +\[ +\nu A.\,F^{A}\cong\exists A.\,(A\rightarrow F^{A})\times A\quad, +\] +and proves the Church-co-Yoneda identity: +\[ +G^{\nu A.\,F^{A}}\cong\exists A.\,(A\rightarrow F^{A})\times G^{A}\quad. +\] +This identity allows us to derive the nested fixpoint lemma and the +mutual recursion formula for the greatest fixpoints. + +These techniques allow us to derive a number of properties of types +with universal and existential quantifiers. Tables~\ref{tab:Type-identities-proved-by-Yoneda}\textendash \ref{tab:Type-identities-for-existential-types} +summarize the type isomorphisms proved in this Appendix by those techniques. + +The final sections of the Appendix study the Jaskelioff-O\textsf{'}Connor theorem +and its applications to problems raised in this book. One of those +applications is a proof that the identity function of type $\forall A.\,M^{A}\rightarrow M^{A}$ +is the only monad morphism between a monad $M$ and itself that obeys +the monadic naturality law with respect to $M$. This property means +that the non-degeneracy law of base runners (derived in Chapter~\ref{chap:monad-transformers}) +is always satisfied automatically, and so we do not need to verify +that law. \setcounter{secnumdepth}{3}% \begin{comment} Restore the normal numbering of subsections and subsubsections \end{comment} - +) \section{Topics not covered in this book} @@ -1365,6 +1428,22 @@ \subsubsection{Exercise \label{par:Exercise-additional-16-3}\ref{par:Exercise-ad \] +\subsubsection{Exercise \label{par:Exercise-additional-16-3-1}\ref{par:Exercise-additional-16-3-1}} + +This is a generalization of Example~\ref{subsec:Example-strong-dinaturality-show-void}. + +\textbf{(a)} For any (covariant) functors $F$ and $G$, show that: +\[ +\forall A.\,(A\times G^{A}\rightarrow A)\rightarrow F^{A}\cong F^{\bbnum 0}\quad. +\] + +\textbf{(b)} For any contrafunctor $H$ and a type constructor $G$ +that is either covariant or contravariant, show that: +\[ +\forall A.\,(G^{A}\rightarrow A)\rightarrow H^{A}\cong H^{\bbnum 1}\quad. +\] + + \subsubsection{Exercise \label{par:Exercise-additional-16}\ref{par:Exercise-additional-16}} Define a monad transformer $\text{Cod}_{F}^{L}\varangle M$ for the diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 46a0e546e..e6341a695 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): b43d0d17c2f973432a5c7d08f6f0968c0a3998ac5b93e2f1d9b7afac611a021f}\\ -{\scriptsize{}Git commit: 548cc8f5d0465b7f4eac634f9cb1c4195b183f0c}\\ -{\scriptsize{}PDF file built on Mon, 27 Oct 2025 17:16:51 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 5db8540016b621593d8248b5fb0901dfd8e1c41f1e2e27af2e08badef20c3503}\\ +{\scriptsize{}Git commit: f31bad889f111a005acc97c441d660b5dea21d5d}\\ +{\scriptsize{}PDF file built on Wed, 29 Oct 2025 22:42:44 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, @@ -377,7 +377,7 @@ developed in excruciating detail through 1981 Scala code snippets, 233 statements with step-by-step derivations, 105 diagrams, 237 examples with tested Scala -code, and 314 exercises. Discussions build upon each +code, and 315 exercises. Discussions build upon each chapter's material further.}\\ {\scriptsize{}}\\ {\scriptsize{}Beginners in FP will find tutorials about the map/reduce From 04366f66bc223bac269de59d96d2e453bf55873d Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Wed, 29 Oct 2025 23:26:35 +0100 Subject: [PATCH 16/42] wip --- sofp-src/lyx/sofp-appendices.lyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sofp-src/lyx/sofp-appendices.lyx b/sofp-src/lyx/sofp-appendices.lyx index e7f13a5f8..edb197ac6 100644 --- a/sofp-src/lyx/sofp-appendices.lyx +++ b/sofp-src/lyx/sofp-appendices.lyx @@ -41347,7 +41347,7 @@ For any \begin_layout Plain Layout \size footnotesize -\begin_inset Formula $F^{A}\triangleq(Z+G^{A}\rightarrow A\times H^{A})\rightarrow K^{A}$ +\begin_inset Formula $F^{A}\triangleq(Z+K^{A}\rightarrow A\times G^{A})\rightarrow H^{A}$ \end_inset @@ -41390,7 +41390,7 @@ For any \begin_layout Plain Layout \size footnotesize -\begin_inset Formula $F^{A}\triangleq((L^{A}\rightarrow Z+G^{A})\rightarrow A\times H^{A})\rightarrow K^{A}$ +\begin_inset Formula $F^{A}\triangleq((L^{A}\rightarrow Z+K^{A})\rightarrow A\times G^{A})\rightarrow H^{A}$ \end_inset From 24b2b45f90d56a8de5daaeaeccd6b94897ed6059 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Thu, 30 Oct 2025 10:42:44 +0100 Subject: [PATCH 17/42] more detail about non-lifting-to-empty --- sofp-src/lyx/sofp-appendices.lyx | 583 ++++++++++++++++++++++-------- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-appendices.tex | 143 +++++--- sofp-src/tex/sofp-summary.tex | 2 +- sofp-src/tex/sofp.tex | 6 +- 5 files changed, 528 insertions(+), 206 deletions(-) diff --git a/sofp-src/lyx/sofp-appendices.lyx b/sofp-src/lyx/sofp-appendices.lyx index edb197ac6..ad21974c2 100644 --- a/sofp-src/lyx/sofp-appendices.lyx +++ b/sofp-src/lyx/sofp-appendices.lyx @@ -40064,12 +40064,12 @@ A type constructor \end_inset . - (Compare with item + (Item \series bold (b) \series default - to see that a type constructor can be lifting-to-full and lifting-to-empty - at the same time.) + shows that the same type constructor can be lifting-to-full and lifting-to-empt +y.) \end_layout \begin_layout Standard @@ -40116,6 +40116,74 @@ not is lifting-to-empty. \end_layout +\begin_layout Standard +A type constructor +\begin_inset Formula $P$ +\end_inset + + is +\emph on +not +\emph default + lifting-to-empty when: +\end_layout + +\begin_layout Standard + +\series bold +(i) +\series default + +\begin_inset Formula $P^{A}\triangleq A\rightarrow A$ +\end_inset + +. +\end_layout + +\begin_layout Standard + +\series bold +(j) +\series default + +\begin_inset Formula $P^{A}\triangleq Z+K^{A}$ +\end_inset + + where +\begin_inset Formula $K$ +\end_inset + + is arbitrary and +\begin_inset Formula $Z\neq\bbnum 0$ +\end_inset + + is a fixed type. +\end_layout + +\begin_layout Standard + +\series bold +(k) +\series default + +\begin_inset Formula $P^{A}\triangleq K^{A}\rightarrow L^{A}$ +\end_inset + + where +\begin_inset Formula $K$ +\end_inset + + is arbitrary and +\begin_inset Formula $L$ +\end_inset + + is +\emph on +not +\emph default + lifting-to-empty. +\end_layout + \begin_layout Subparagraph Proof \end_layout @@ -40182,7 +40250,7 @@ Proof \end_inset -where +Here \begin_inset Formula $q:A\rightarrow Q^{A}$ \end_inset @@ -40190,13 +40258,20 @@ where \begin_inset Formula $r:A\rightarrow R^{A}$ \end_inset - are some functions (that we could assume to exist, for the purpose of this - example). + are some functions that will exist for some +\begin_inset Formula $Q$ +\end_inset + + and +\begin_inset Formula $R$ +\end_inset + +. The function \begin_inset Formula $f$ \end_inset - returns different parts of the disjunction + returns different parts of the disjunctive type \begin_inset Formula $Q^{A}+R^{A}$ \end_inset @@ -40217,7 +40292,8 @@ disjunctive information \begin_inset Quotes erd \end_inset -; that is, +. + We say that \begin_inset Formula $P$ \end_inset @@ -40476,11 +40552,11 @@ any \begin_inset Formula $r^{:A\leftrightarrow B}$ \end_inset - is lifted to a relation -\begin_inset Formula $r^{\updownarrow K}$ + is lifted to a non-empty relation +\begin_inset Formula $r^{\updownarrow K}\neq\emptyset$ \end_inset - that is non-empty. +. As \begin_inset Formula $L$ \end_inset @@ -40528,6 +40604,287 @@ noprefix "false" \begin_inset Formula $r^{\updownarrow K}\ogreaterthan\emptyset=\emptyset$ \end_inset +. +\end_layout + +\begin_layout Standard + +\series bold +(i) +\series default + To show that +\begin_inset Formula $P$ +\end_inset + + is not lifting-to-empty, we need to prove that for any relation +\begin_inset Formula $r^{:A\leftrightarrow B}$ +\end_inset + + there exist +\begin_inset Formula $x^{:P^{A}}$ +\end_inset + + and +\begin_inset Formula $y^{:P^{B}}$ +\end_inset + + such that +\begin_inset Formula $(x,y)\in r^{\updownarrow P}$ +\end_inset + +. + Write out the condition +\begin_inset Formula $(x,y)\in r^{\updownarrow P}$ +\end_inset + +: +\begin_inset Formula +\[ +(x,y)\in r^{\updownarrow P}\quad\text{means}\quad\text{if}\quad(a^{:A},b^{:B})\in r\quad\text{then}\quad(x(a),y(b))\in r\quad. +\] + +\end_inset + +If we choose +\begin_inset Formula $x\triangleq\text{id}^{:A\rightarrow A}$ +\end_inset + + and +\begin_inset Formula $y\triangleq\text{id}^{:B\rightarrow B}$ +\end_inset + +, we will have +\begin_inset Formula $(x(a),y(b))=(a,b)$ +\end_inset + +. + Then the condition becomes: if +\begin_inset Formula $(a,b)\in r$ +\end_inset + + then +\begin_inset Formula $(a,b)\in r$ +\end_inset + +. + This holds for any +\begin_inset Formula $r$ +\end_inset + +. + So, for any +\begin_inset Formula $r$ +\end_inset + + there exist +\begin_inset Formula $x$ +\end_inset + +, +\begin_inset Formula $y$ +\end_inset + + such that +\begin_inset Formula $(x,y)\in r^{\updownarrow P}$ +\end_inset + +. +\end_layout + +\begin_layout Standard + +\series bold +(j) +\series default + Lifting any relation +\begin_inset Formula $r^{:A\leftrightarrow B}$ +\end_inset + + to +\begin_inset Formula $P$ +\end_inset + +, we find: +\begin_inset Formula +\[ +r^{\updownarrow P}=\text{id}^{:Z\leftrightarrow Z}\boxplus r^{\updownarrow K}\quad. +\] + +\end_inset + +By assumption +\begin_inset Formula $Z\neq\bbnum 0$ +\end_inset + +, so we may choose a value +\begin_inset Formula $z^{:Z}$ +\end_inset + + and set +\begin_inset Formula $x^{:P^{A}}\triangleq z+\bbnum 0^{:A}$ +\end_inset + + and +\begin_inset Formula $y^{:P^{B}}\triangleq z+\bbnum 0^{:B}$ +\end_inset + +. + The values +\begin_inset Formula $x$ +\end_inset + +, +\begin_inset Formula $y$ +\end_inset + + are always in the relation +\begin_inset Formula $\text{id}^{:Z\leftrightarrow Z}\boxplus r^{\updownarrow K}$ +\end_inset + + for any +\begin_inset Formula $r$ +\end_inset + +. + It follows that +\begin_inset Formula $r^{\updownarrow P}$ +\end_inset + + is not empty for any +\begin_inset Formula $r$ +\end_inset + +. + +\end_layout + +\begin_layout Standard + +\series bold +(k) +\series default + We need to show that for any types +\begin_inset Formula $A$ +\end_inset + +, +\begin_inset Formula $B$ +\end_inset + + and for any +\begin_inset Formula $r^{:A\leftrightarrow B}$ +\end_inset + + there exist values +\begin_inset Formula $x^{:P^{A}}$ +\end_inset + +, +\begin_inset Formula $y^{:P^{B}}$ +\end_inset + + such that +\begin_inset Formula $(x,y)\in r^{\updownarrow P}$ +\end_inset + +. + By assumption, +\begin_inset Formula $L$ +\end_inset + + is +\emph on +not +\emph default + lifting-to-empty, so for any types +\begin_inset Formula $A$ +\end_inset + +, +\begin_inset Formula $B$ +\end_inset + + and for any +\begin_inset Formula $r^{:A\leftrightarrow B}$ +\end_inset + + there exist values +\begin_inset Formula $p^{:L^{A}}$ +\end_inset + +, +\begin_inset Formula $q^{:L^{B}}$ +\end_inset + + such that +\begin_inset Formula $(p,q)\in r^{\updownarrow L}$ +\end_inset + +. + We choose +\begin_inset Formula $x\triangleq\_^{:K^{A}}\rightarrow p$ +\end_inset + + and +\begin_inset Formula $y\triangleq\_^{:K^{B}}\rightarrow q$ +\end_inset + +. + We will now show that +\begin_inset Formula $(x,y)\in r^{\updownarrow P}$ +\end_inset + +. + Since +\begin_inset Formula $P^{A}=K^{A}\rightarrow L^{A}$ +\end_inset + +, the lifting to +\begin_inset Formula $P$ +\end_inset + + is given via the pair mapper: +\begin_inset Formula +\[ +(x,y)\in r^{\updownarrow P}\quad\text{means}\quad\forall(a^{:K^{A}},b^{:K^{B}}):\quad\text{if}\quad(a,b)\in r^{\updownarrow K}\quad\text{then}\quad(x(a),y(b))\in r^{\updownarrow L}\quad. +\] + +\end_inset + +We have defined +\begin_inset Formula $x$ +\end_inset + + and +\begin_inset Formula $y$ +\end_inset + + as constant functions that always return +\begin_inset Formula $p$ +\end_inset + + and +\begin_inset Formula $q$ +\end_inset + +. + So, we always have +\begin_inset Formula $(x(a),y(b))\in r^{\updownarrow L}$ +\end_inset + + for any +\begin_inset Formula $a$ +\end_inset + +, +\begin_inset Formula $b$ +\end_inset + +. + It follows that +\begin_inset Formula $(x,y)\in r^{\updownarrow P}$ +\end_inset + . \begin_inset Formula $\square$ @@ -40577,14 +40934,14 @@ examples (a) \series default Show that -\begin_inset Formula $P^{A}\triangleq A\rightarrow A$ +\begin_inset Formula $P^{A}\triangleq A\times F^{A}\rightarrow A$ \end_inset - is lifting-to-full but -\emph on -not -\emph default - lifting-to-empty. + is lifting-to-full for any +\begin_inset Formula $F$ +\end_inset + +. \end_layout \begin_layout Standard @@ -40593,10 +40950,14 @@ not (b) \series default Show that -\begin_inset Formula $P^{A}\triangleq\bbnum 1+A\rightarrow A$ +\begin_inset Formula $P^{A}\triangleq\bbnum 1+F^{A}\rightarrow A$ \end_inset - is both lifting-to-full and lifting-to-empty. + is both lifting-to-full and lifting-to-empty for any +\begin_inset Formula $F$ +\end_inset + +. \end_layout \begin_layout Standard @@ -40642,12 +41003,16 @@ noprefix "false" \end_inset - that all those type constructors denoted by + that all the above type constructors denoted by \begin_inset Formula $P$ \end_inset are non-disjunctive. - Then, for any type constructors + +\end_layout + +\begin_layout Standard +For any type constructors \begin_inset Formula $F$ \end_inset @@ -40725,83 +41090,18 @@ noprefix "false" \end_inset (d) with -\begin_inset Formula $K^{A}\triangleq L^{A}\triangleq A$ -\end_inset - - that -\begin_inset Formula $P$ -\end_inset - - is also lifting-to-full. -\end_layout - -\begin_layout Standard -To show that -\begin_inset Formula $P$ -\end_inset - - is not lifting-to-empty, it is sufficient to demonstrate that for any relation - -\begin_inset Formula $r^{:A\leftrightarrow B}$ -\end_inset - - there exist -\begin_inset Formula $x^{:P^{A}}$ -\end_inset - - and -\begin_inset Formula $y^{:P^{B}}$ -\end_inset - - such that -\begin_inset Formula $(x,y)\in r^{\updownarrow P}$ -\end_inset - -. - Write out the condition -\begin_inset Formula $(x,y)\in r^{\updownarrow P}$ -\end_inset - -: -\begin_inset Formula -\[ -(x,y)\in r^{\updownarrow P}\quad\text{means}\quad\text{if}\quad(a^{:A},b^{:B})\in r\quad\text{then}\quad(x(a),y(b))\in r\quad. -\] - -\end_inset - -If we choose -\begin_inset Formula $x\triangleq\text{id}^{:A\rightarrow A}$ +\begin_inset Formula $K^{A}\triangleq A\times F^{A}$ \end_inset and -\begin_inset Formula $y\triangleq\text{id}^{:B\rightarrow B}$ -\end_inset - -, we will have -\begin_inset Formula $(x(a),y(b))=(a,b)$ -\end_inset - -. - Then the condition becomes: if -\begin_inset Formula $(a,b)\in r$ -\end_inset - - then -\begin_inset Formula $(a,b)\in r$ -\end_inset - -. - This is true for any -\begin_inset Formula $r$ +\begin_inset Formula $L^{A}\triangleq A$ \end_inset -. - So, -\begin_inset Formula $(x,y)\in r^{\updownarrow P}$ + that +\begin_inset Formula $P$ \end_inset - holds. + is also lifting-to-full. \end_layout \begin_layout Standard @@ -40843,7 +41143,7 @@ noprefix "false" \end_inset (d) with -\begin_inset Formula $K^{A}\triangleq\bbnum 1+A$ +\begin_inset Formula $K^{A}\triangleq\bbnum 1+F^{A}$ \end_inset and @@ -40873,7 +41173,11 @@ noprefix "false" \end_inset -(h) if we prove that +(j) with +\begin_inset Formula $Z=\bbnum 1$ +\end_inset + + to see that \begin_inset Formula $K^{A}$ \end_inset @@ -40881,42 +41185,30 @@ noprefix "false" \emph on not \emph default - lifting-to-empty. - Lifting any relation -\begin_inset Formula $r^{:A\leftrightarrow B}$ -\end_inset - - to -\begin_inset Formula $K$ + lifting-to-empty, while we know that +\begin_inset Formula $L^{A}$ \end_inset -, we find: -\begin_inset Formula -\[ -r^{\updownarrow K}=\text{id}^{:\bbnum 1\leftrightarrow\bbnum 1}\boxplus r\quad. -\] - + is lifting-to-empty. + It follows from Statement +\begin_inset space ~ \end_inset -The pair of values -\begin_inset Formula $x^{:K^{A}}\triangleq1+\bbnum 0^{:A}$ -\end_inset - and -\begin_inset Formula $y^{:K^{B}}\triangleq1+\bbnum 0^{:B}$ -\end_inset +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-undisjunctive-type-constructors-structural" +plural "false" +caps "false" +noprefix "false" - are always in the relation -\begin_inset Formula $\text{id}\boxplus r$ \end_inset -. - In this way, we have shown that -\begin_inset Formula $r^{\updownarrow K}$ +(h) that +\begin_inset Formula $K$ \end_inset - is not empty. - + is lifting-to-empty. \end_layout \begin_layout Standard @@ -40944,14 +41236,24 @@ noprefix "false" \begin_layout Standard Note that the type expression -\begin_inset Formula $\bbnum 1+A\rightarrow A$ +\begin_inset Formula $\bbnum 1+F^{A}\rightarrow A$ \end_inset - contains a disjunctive type but can be rewritten equivalently as -\begin_inset Formula $P^{A}\cong(\bbnum 1\rightarrow A)\times(A\rightarrow A)$ + appears to contain a disjunctive type but can be rewritten equivalently + as +\begin_inset Formula $P^{A}\cong(\bbnum 1\rightarrow A)\times(F^{A}\rightarrow A)$ \end_inset , which no longer contains a disjunctive type. + (If +\begin_inset Formula $F^{A}$ +\end_inset + + is disjunctive then +\begin_inset Formula $F^{A}\rightarrow A$ +\end_inset + + can be rewritten similarly.) \end_layout \begin_layout Standard @@ -41143,8 +41445,8 @@ noprefix "false" \end_inset - shows some formulas for non-disjunctive type constructors that follow from - Statement + shows some general formulas for non-disjunctive type constructors that + follow from Statement \begin_inset space ~ \end_inset @@ -41156,20 +41458,6 @@ plural "false" caps "false" noprefix "false" -\end_inset - - and Example -\begin_inset space ~ -\end_inset - - -\begin_inset CommandInset ref -LatexCommand ref -reference "subsec:Example-undisjunctive-type-constructors" -plural "false" -caps "false" -noprefix "false" - \end_inset . @@ -41291,15 +41579,14 @@ For any \begin_layout Plain Layout \size footnotesize -For any -\begin_inset Formula $G^{A}$ +\begin_inset Formula $H$ \end_inset - and any lifting-to-full -\begin_inset Formula $H^{A}$ + is lifting-to-full, +\begin_inset Formula $G$ \end_inset - + is any type constructor \end_layout \end_inset @@ -41330,7 +41617,7 @@ For any \begin_inset Formula $G^{A}$ \end_inset - and + and for any \begin_inset Formula $H^{A}$ \end_inset @@ -41373,8 +41660,8 @@ For any \begin_inset Formula $K^{A}$ \end_inset -, and any fixed type -\begin_inset Formula $Z$ +, and a fixed type +\begin_inset Formula $Z\neq\bbnum 0$ \end_inset @@ -41420,8 +41707,8 @@ For any \begin_inset Formula $L^{A}$ \end_inset -, and any fixed type -\begin_inset Formula $Z$ +, and +\begin_inset Formula $Z\neq\bbnum 0$ \end_inset diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index a030f488dd7335611eaa5c17e200611608e5c368..0ede01a8457af9af33c3157261c144024d425fa6 100644 GIT binary patch delta 156 zcmX?Ra?E7IY7uT@gAhXlD-#1N1B=PqL<~^)A4Q(!zky8f< Date: Thu, 30 Oct 2025 12:55:01 +0100 Subject: [PATCH 18/42] wip --- sofp-src/lyx/sofp-summary.lyx | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 0dc5c210f..0f9756711 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -6391,8 +6391,8 @@ noprefix "false" \end_inset - proves the two co-Yoneda identities and establishes some fundamental properties - of existential types. + proves the two co-Yoneda identities and establishes some other fundamental + properties of existential types. Then Section \begin_inset space ~ \end_inset @@ -6407,7 +6407,11 @@ noprefix "false" \end_inset - shows that the greatest fixpoints are given by the Church encoding: + shows that the greatest fixpoint of a functor +\begin_inset Formula $F$ +\end_inset + + is given by the Church encoding: \begin_inset Formula \[ \nu A.\,F^{A}\cong\exists A.\,(A\rightarrow F^{A})\times A\quad, @@ -6415,7 +6419,15 @@ noprefix "false" \end_inset -and proves the Church-co-Yoneda identity: +and also proves the Church-co-Yoneda identity: for any functors +\begin_inset Formula $F$ +\end_inset + + and +\begin_inset Formula $G$ +\end_inset + +, \begin_inset Formula \[ G^{\nu A.\,F^{A}}\cong\exists A.\,(A\rightarrow F^{A})\times G^{A}\quad. @@ -6428,7 +6440,7 @@ This identity allows us to derive the nested fixpoint lemma and the mutual \end_layout \begin_layout Standard -These techniques allow us to derive a number of properties of types with +These techniques allow us to derive a number of properties for types with universal and existential quantifiers. Tables \begin_inset space ~ @@ -6454,7 +6466,7 @@ noprefix "false" \end_inset - summarize the type isomorphisms proved in this Appendix by those techniques. + summarize the type isomorphisms proved in this Appendix by various techniques. \end_layout \begin_layout Standard @@ -6489,8 +6501,8 @@ noprefix "false" \end_inset -) is always satisfied automatically, and so we do not need to verify that - law. +) is always satisfied automatically and does not need to be verified separately + for each monad transformer. \end_layout \begin_layout Standard From 6c6d0b1658b3fb05dd9aa80958ffb2ac705f975d Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Thu, 30 Oct 2025 14:14:53 +0100 Subject: [PATCH 19/42] gix build error --- sofp-src/lyx/sofp-appendices.lyx | 58 ++++++++++++++++++++++++------ sofp-src/lyx/sofp-summary.lyx | 40 +++++++++++++++++---- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-appendices.tex | 25 ++++++------- sofp-src/tex/sofp-summary.tex | 35 ++++++++++-------- sofp-src/tex/sofp.tex | 6 ++-- 6 files changed, 118 insertions(+), 46 deletions(-) diff --git a/sofp-src/lyx/sofp-appendices.lyx b/sofp-src/lyx/sofp-appendices.lyx index ad21974c2..b40f361c5 100644 --- a/sofp-src/lyx/sofp-appendices.lyx +++ b/sofp-src/lyx/sofp-appendices.lyx @@ -52225,6 +52225,13 @@ as required. \begin_layout Subsection The Jaskelioff-O'Connor theorem for type constructors +\begin_inset CommandInset label +LatexCommand label +name "subsec:The-Jaskelioff-OConnor-theorem" + +\end_inset + + \end_layout \begin_layout Standard @@ -52310,11 +52317,11 @@ Given any fixed \begin_inset Formula $E^{T}$ \end_inset - is guaranteed to be an instance of the + is an instance of the \begin_inset Formula $P$ \end_inset --typeclass. +-typeclass satisfying the properties of free typeclass constructors. Suppose \begin_inset Formula $A$ \end_inset @@ -52341,8 +52348,11 @@ Here, it is assumed that the type \begin_inset Formula $(A\rightarrow F^{B})\rightarrow F^{C}$ \end_inset - is restricted to functions satisfying the naturality law with respect to - + is restricted to functions satisfying the +\begin_inset Formula $P$ +\end_inset + +-typeclass naturality law with respect to \begin_inset Formula $F$ \end_inset @@ -54789,7 +54799,7 @@ flatten_q \end_inset - has the effect of reading the state value + has the effect of reading a state value \begin_inset listings inline true status open @@ -54843,12 +54853,12 @@ flatten_q \end_inset . - This increments the internal state + This increments the state \begin_inset Formula $n$ \end_inset times. - So, the left-hand side of the law is equivalent to: + So, the left-hand side of the law becomes: \begin_inset listings inline false status open @@ -55245,7 +55255,11 @@ set \end_inset -; the unevaluated effectful value +: the +\emph on +unevaluated +\emph default + effectful value \begin_inset listings inline true status open @@ -55269,8 +55283,32 @@ x_i \end_inset - and then returned. - So, the code is equivalent to: + and then returned under a monad wrapper. + So, the code shown above for +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +h_q_map_h +\end_layout + +\end_inset + + can be simplified to just a single +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +get +\end_layout + +\end_inset + +: \begin_inset listings inline false status open diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 0f9756711..465da0e4c 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -6098,11 +6098,19 @@ noprefix "false" \end_layout \begin_layout Standard -The Yoneda identities are an important application of category theory, which - proves an abstract version of the Yoneda identity for all categories. - The most important application to programming are the two Yoneda identities - involving covariant and contravariant functors. - Another version is a Yoneda identity for type constructors (Section +Category theory proves abstract version of the Yoneda identity (the +\begin_inset Quotes eld +\end_inset + +Yoneda lemma +\begin_inset Quotes erd +\end_inset + +) for all categories. + The two Yoneda identities involving covariant and contravariant functors + are the most important practical application of the Yoneda lemma to programming. + Other applications used in this book are Yoneda identities for type constructor +s (see Section \begin_inset space ~ \end_inset @@ -6116,7 +6124,25 @@ noprefix "false" \end_inset -). +) and for lawful +\begin_inset Formula $P$ +\end_inset + +-typeclasses (used in Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:The-Jaskelioff-OConnor-theorem" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + in the proof of the Jaskelioff-O'Connor theorem). \end_layout \begin_layout Standard @@ -6342,7 +6368,7 @@ noprefix "false" \end_inset gives a formal definition of that property and goes through structural - analysis, discovering what type constructors are non-disjunctive. + analysis, discovering various type constructors that are non-disjunctive. Some recipes for building non-disjunctive type constructors are shown in Example \begin_inset space ~ diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 0ede01a8457af9af33c3157261c144024d425fa6..d851abc44f016fde8430cfee5d5c6285e6a4358d 100644 GIT binary patch delta 142 zcmX?Ra?E7IdJ%SGD?<}21LMitL`>l9k0MWa%`Hum43bkUbW>9j%{D(0l9k0MWa(=3uxQVr6QbyHI;4K_a# Date: Sat, 1 Nov 2025 16:24:15 +0100 Subject: [PATCH 20/42] overview of the transformer chapter --- sofp-src/lyx/sofp-appendices.lyx | 14 +- sofp-src/lyx/sofp-summary.lyx | 1645 +++++++++++++++++++++++++++- sofp-src/lyx/sofp-transformers.lyx | 92 +- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-appendices.tex | 4 +- sofp-src/tex/sofp-summary.tex | 336 +++++- sofp-src/tex/sofp-transformers.tex | 53 +- sofp-src/tex/sofp.tex | 6 +- 8 files changed, 1978 insertions(+), 172 deletions(-) diff --git a/sofp-src/lyx/sofp-appendices.lyx b/sofp-src/lyx/sofp-appendices.lyx index b40f361c5..113012d87 100644 --- a/sofp-src/lyx/sofp-appendices.lyx +++ b/sofp-src/lyx/sofp-appendices.lyx @@ -12173,13 +12173,6 @@ name "sec:Parametricity-theorem-for-relations" \end_inset -\begin_inset CommandInset label -LatexCommand label -name "subsec:Relations-between-types" - -\end_inset - - \end_layout \begin_layout Standard @@ -12591,6 +12584,13 @@ must be an identity function. \begin_layout Subsection Relations between values of different types +\begin_inset CommandInset label +LatexCommand label +name "subsec:Relations-between-types" + +\end_inset + + \end_layout \begin_layout Standard diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 465da0e4c..8667436ff 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -5648,7 +5648,1444 @@ noprefix "false" \end_layout \begin_layout Standard -*** +This chapter is an in-depth study of monad transformers. +\end_layout + +\begin_layout Standard +To motivate monad transformers, we begin by trying to use two different + monads in a single functor block and we find that the code becomes hard + to work with. + The code can be simplified if we manage to combine two monads into a single + larger monad. + One way of combining monads is by functor composition, for example as +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Future[Option[A]] +\end_layout + +\end_inset + +. + Table +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Correct-and-incorrect-compositions" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + shows some examples of working and non-working functor composition of monads. + In some cases (such as Future and State), functor composition completely + fails. +\end_layout + +\begin_layout Standard +This suggests a different approach where one monad is fixed (the +\begin_inset Quotes eld +\end_inset + +base monad +\begin_inset Quotes erd +\end_inset + + +\begin_inset Formula $L$ +\end_inset + +) and the other ( +\begin_inset Quotes eld +\end_inset + +foreign +\begin_inset Quotes erd +\end_inset + +) monad +\begin_inset Formula $M$ +\end_inset + + is considered as a parameter. + This is known as the +\begin_inset Quotes eld +\end_inset + +monad transformer +\begin_inset Quotes erd +\end_inset + + approach. + The result of combining +\begin_inset Formula $L$ +\end_inset + + and +\begin_inset Formula $M$ +\end_inset + + is a +\begin_inset Quotes eld +\end_inset + +larger +\begin_inset Quotes erd +\end_inset + + monad (denoted by +\begin_inset Formula $L\varangle M$ +\end_inset + + in this book) that can express the effects of both monads +\begin_inset Formula $L$ +\end_inset + +, +\begin_inset Formula $M$ +\end_inset + +. + The +\begin_inset Quotes eld +\end_inset + +monad transformer +\begin_inset Quotes erd +\end_inset + + of the base monad +\begin_inset Formula $L$ +\end_inset + + is the operation +\begin_inset Formula $L\varangle$ +\end_inset + + that can be applied to any foreign monad +\begin_inset Formula $M$ +\end_inset + + to obtain the new monad +\begin_inset Formula $L\varangle M$ +\end_inset + +. + The code of +\begin_inset Formula $L\varangle$ +\end_inset + + is written once for every base monad +\begin_inset Formula $L$ +\end_inset + +; the same code will then work for all foreign monads +\begin_inset Formula $M$ +\end_inset + +. + This avoids the need for writing custom code that combines every pair of + monads. + Monad transformer code is written only once per base monad. + +\end_layout + +\begin_layout Standard +Table +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Known-monad-transformers" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + shows the types of monad transformers for a number of known monads. + Then we go through some examples, showing how monad transformers are implemente +d in practice. +\end_layout + +\begin_layout Standard +In addition to having the code for the transformed monad +\begin_inset Formula $L\varangle M$ +\end_inset + +, in practice one needs to be able to use the effects of each of the two + monads ( +\begin_inset Formula $L$ +\end_inset + +, +\begin_inset Formula $M$ +\end_inset + +) within a functor block of type +\begin_inset Formula $L\varangle M$ +\end_inset + +. + For that, we need functions that transform values of types +\begin_inset Formula $L^{A}$ +\end_inset + + and +\begin_inset Formula $M^{A}$ +\end_inset + + into values of type +\begin_inset Formula $(L\varangle M)^{A}$ +\end_inset + +. + Those functions are called the +\begin_inset Quotes eld +\end_inset + +base lift +\begin_inset Quotes erd +\end_inset + + ( +\begin_inset Formula $L\leadsto L\varangle M$ +\end_inset + +) and the +\begin_inset Quotes eld +\end_inset + +foreign lift +\begin_inset Quotes erd +\end_inset + + ( +\begin_inset Formula $M\leadsto L\varangle M$ +\end_inset + +). + +\end_layout + +\begin_layout Standard +In order to extract final results from monadic programs, one uses functions + called +\begin_inset Quotes eld +\end_inset + +runners +\begin_inset Quotes erd +\end_inset + +. + Those functions execute a monad's effects and deliver resulting values, + sometimes wrapped in another, simpler monad. + If we have runners for +\begin_inset Formula $L$ +\end_inset + + and +\begin_inset Formula $M$ +\end_inset + +, we would need a way to obtain the corresponding runners for the combined + monad +\begin_inset Formula $L\varangle M$ +\end_inset + +. + Showing examples with the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Reader +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +List +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +State +\end_layout + +\end_inset + +, and some other monad transformers, we motivate introducing a +\begin_inset Quotes eld +\end_inset + +base runner +\begin_inset Quotes erd +\end_inset + + ( +\begin_inset Formula $L\varangle M\leadsto M$ +\end_inset + +) and a +\begin_inset Quotes eld +\end_inset + +foreign runner +\begin_inset Quotes erd +\end_inset + + ( +\begin_inset Formula $L\varangle M\leadsto L\varangle N$ +\end_inset + +). + Those runners execute the effects of one monad while keeping the effects + of another. + +\end_layout + +\begin_layout Standard +Not all transformers support both lifts and both runners. + For instance, we show that the continuation monad's transformer does not + allow us to implement a base lift or any runners. +\end_layout + +\begin_layout Standard +The properties required for a monad transformer can be formulated by defining + a typeclass we denote +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +MTrans +\end_layout + +\end_inset + + (Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:A-typeclass-for-monad-transformers" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). +\end_layout + +\begin_layout Standard +We turn to combining more than two monads, noticing that monad transformers + can be applied one after another; for example, as +\begin_inset Formula $K\varangle(L\varangle M)$ +\end_inset + + or as +\begin_inset Formula $K\varangle(L\varangle(M\varangle N))$ +\end_inset + +. + The resulting combined monad is called a +\begin_inset Quotes eld +\end_inset + +monad stack +\begin_inset Quotes erd +\end_inset + +. + It is a new, +\begin_inset Quotes eld +\end_inset + +larger +\begin_inset Quotes erd +\end_inset + + monad that can describe the effects of all its constituent monads ( +\begin_inset Formula $K$ +\end_inset + +, +\begin_inset Formula $L$ +\end_inset + +, +\begin_inset Formula $M$ +\end_inset + +, ...). +\end_layout + +\begin_layout Standard +We define monad transformer for the monad +\begin_inset Formula $K\varangle L$ +\end_inset + + by +\begin_inset Formula $(K\varangle L)\varangle M\triangleq K\varangle(L\varangle M)$ +\end_inset + +. + This makes the operation +\begin_inset Formula $\varangle$ +\end_inset + + associative, meaning that we may write +\begin_inset Formula $K\varangle L\varangle M$ +\end_inset + + without ambiguity. + We also motivate the properties +\begin_inset Formula $\text{Id}\varangle M\cong M$ +\end_inset + + and +\begin_inset Formula $M\varangle\text{Id}\cong M$ +\end_inset + +. + Later in this chapter we will rigorously prove those properties for all + known monad transformers. +\end_layout + +\begin_layout Standard +Building a monad stack in a different order ( +\begin_inset Formula $K\varangle L$ +\end_inset + + or +\begin_inset Formula $L\varangle K$ +\end_inset + +) will, as a rule, produce inequivalent monads. + Table +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:Examples-of-monad-stacks" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + shows some examples where transformers are applied in different orders. +\end_layout + +\begin_layout Standard +To write code in a large monad stack +\begin_inset Formula $P\triangleq M_{1}\varangle M_{2}\varangle...\varangle M_{k}$ +\end_inset + +, we need functions that can lift any of the monads +\begin_inset Formula $M_{i}$ +\end_inset + + to the stack, as well as functions that run the effects of a certain monad + +\begin_inset Formula $M_{i}$ +\end_inset + + while keeping all other effects. + We can construct the necessary lifts if all monads in the stack (except + possibly the last one, +\begin_inset Formula $M_{k}$ +\end_inset + +) have transformers supporting their individual lift functions. + However, the resulting code is difficult to write because it is a composition + of up to +\begin_inset Formula $k$ +\end_inset + + individual lifts that have to be combined in exactly correct way. + +\end_layout + +\begin_layout Standard +To make working with monad stacks easier, there are several techniques that + generate the necessary lifts automatically. + The first of these techniques (Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Constructing-lifts-via-type-relations" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +) obtains lifts from a type relation constructed automatically via typeclass + derivation. + The second of these techniques is known as MTL-style programming ( +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Combining-monads-via-mtl-style" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). + It requires the programmer to define a typeclass for each monad, encapsulating + the +\begin_inset Quotes eld +\end_inset + +operations +\begin_inset Quotes erd +\end_inset + + that characterize working with that monad. + (Table +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "tab:effectful-operations-for-some-monads" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + shows what those +\begin_inset Quotes eld +\end_inset + +operations +\begin_inset Quotes erd +\end_inset + + are for a few well-known monads.) The programmer needs to write all code + in terms of those typeclasses and operations, rather than in terms of specific + monads. +\end_layout + +\begin_layout Standard +We turn to formulating the laws required of monad transformers. + We motivate those laws via examples of practical use. + Having obtained a large number of laws, we simplify and streamline their + formulations, using inspiration from category theory. + The result is a quip: +\begin_inset Quotes eld +\end_inset + +a monad transformer is a pointed endofunctor in the category of monads +\begin_inset Quotes erd +\end_inset + + (Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Category-theoretic-properties-of-lifts-and-runners-functors-in-category-of-monads" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). + This formula expresses concisely the 18 laws of monad transformers that + we summarize in more detail in Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Laws-of-monad-transformers" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +. +\end_layout + +\begin_layout Standard +The formulated laws can be verified for any given construction that is claimed + to give a monad transformer. + To illustrate that a law violation means failing to provide a required + functionality, we show a number of examples that do not satisfy the laws + of monad transformers. + In Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Examples-of-failure-of-generic-monad-transformer" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + we list several failing attempts to construct a general monad transformer + that could work for all monads at once. + Only one construction (the Church-encoded co-product in the category of + monads) satisfies all laws of a general transformer, but is unfortunately + unusable in mainstream programming languages due to lack of first-class + support for typeclass laws. +\end_layout + +\begin_layout Standard +In Sections +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Stacking-two-monads" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +– +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Stacking-any-number-of-monads" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + we prove that all laws hold for monad stacks involving any number of monads, + assuming that all the constituent monad transformers are lawful. +\end_layout + +\begin_layout Standard +The next sections embark on proving the laws for monad transformers of the + individual monads. + We begin with the +\begin_inset Quotes eld +\end_inset + +compositional +\begin_inset Quotes erd +\end_inset + + transformers that work by composing the foreign monad as a functor either + inside or outside the base monad. + Both kinds of compositional transformers have common properties that we + begin to study in Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "sec:Monad-transformers-that-use-composition" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +. + The key to simplifying the proofs for compositional transformers is to + consider the special +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +swap +\end_layout + +\end_inset + + function (Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Motivation-for-the-swap-function" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). + The required laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +swap +\end_layout + +\end_inset + + are motivated and derived in Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Deriving-the-necessary-laws-for-swap" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +. + The laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +swap +\end_layout + +\end_inset + + are easier to verify for specific monads. + We show in Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Deriving-swap-from-flatten" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + that the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +swap +\end_layout + +\end_inset + + function is type-isomorphic to the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatten +\end_layout + +\end_inset + + method of the composed monad (either +\begin_inset Formula $L\circ M$ +\end_inset + + or +\begin_inset Formula $M\circ L$ +\end_inset + +), assuming that their respective laws hold. + +\end_layout + +\begin_layout Standard +We proceed to prove the laws of compositional monad transformers by assuming + that the laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +swap +\end_layout + +\end_inset + + already hold. + This proves at once the validity of all composed-inside and composed-outside + monad transformers. + It remains to verify the laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +swap +\end_layout + +\end_inset + + for specific monads. + +\end_layout + +\begin_layout Standard +Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "sec:transformers-linear-monads" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + considers +\begin_inset Quotes eld +\end_inset + +linear monads +\begin_inset Quotes erd +\end_inset + + (in the sense of being linear polynomials as functors) and proves that + the laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +swap +\end_layout + +\end_inset + + hold for those monads. + This covers +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Option +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Either +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Writer +\end_layout + +\end_inset + +, and their compositions. +\end_layout + +\begin_layout Standard +Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "sec:transformers-rigid-monads" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + turns to monads whose transformers compose the foreign monad outside the + base monad. + Those monads are called +\begin_inset Quotes eld +\end_inset + +rigid +\begin_inset Quotes erd +\end_inset + + in this book. +\begin_inset Foot +status open + +\begin_layout Plain Layout +See the discussion here: +\family typewriter + +\begin_inset CommandInset href +LatexCommand href +target "https://stackoverflow.com/questions/39649497/" +literal "false" + +\end_inset + + +\end_layout + +\end_inset + + The only well-known example of a rigid monad is +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Reader +\end_layout + +\end_inset + +. + To build up intuition, we show some type constructions that create new + rigid monads and obtain further examples. + Then we prove that the laws of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +swap +\end_layout + +\end_inset + + hold for all rigid monads. + This ensures the correctness of their monad transformers. +\end_layout + +\begin_layout Standard +Apart from functor composition, transformers for other monads do not follow + any general patterns. + The rest of the chapter goes over various known constructions that work + for specific kinds of monads. + The known patterns will be summarized in Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Summary-of-monad-transformer-constructions" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +. +\end_layout + +\begin_layout Standard +Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "sec:Transformers-for-products-and-free-pointed" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + proves the laws for transformers of product monads (see Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-monad-semimonad-product" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +) and the +\begin_inset Quotes eld +\end_inset + +free pointed +\begin_inset Quotes erd +\end_inset + + monads (see Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-co-product-with-identity-monad" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). + +\end_layout + +\begin_layout Standard +Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "sec:Transformers-for-recursive-monads" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + proves the laws for transformers of two recursively defined monads. + One such monad is the +\begin_inset Quotes eld +\end_inset + +free monad +\begin_inset Quotes erd +\end_inset + + on a given functor (see Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-monad-construction-4-free-monad" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). + We also prove (Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-free-monad-transformer-coproduct" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +) that two free monads combine via their transformers to a free monad on + a co-product of functors. + This is an important property that makes free monads easier to combine. +\end_layout + +\begin_layout Standard +The other recursive monad is the standard +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +List +\end_layout + +\end_inset + + monad whose associativity law was verified in Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-flatten-verify-for-monad-1-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +. + The +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +List +\end_layout + +\end_inset + + monad's transformer is complicated, and a proof of its laws takes some + work (Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Transformer-for-the-List-monad" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). +\end_layout + +\begin_layout Standard +We now turn to +\begin_inset Quotes eld +\end_inset + +incomplete +\begin_inset Quotes erd +\end_inset + + monad transformers that lack certain features. + +\end_layout + +\begin_layout Standard +The first of those is the transformer for the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +State +\end_layout + +\end_inset + + monad (Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Statement-state-monad-transformer" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). + The only deficiency of the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +StateT +\end_layout + +\end_inset + + transformer is the violation of monad morphism laws by the base runner. + (This means that the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +StateT +\end_layout + +\end_inset + + transformer is a pointed but +\emph on +not +\emph default + a co-pointed endofunctor in the category of monads.) Accordingly, running + a monadic program involving a +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +StateT +\end_layout + +\end_inset + + must run all +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +State +\end_layout + +\end_inset + + effects at once; it is incorrect to run the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +State +\end_layout + +\end_inset + + effects for parts of a program and then compose the results. +\end_layout + +\begin_layout Standard +The next sections prove the laws of the monad transformers for the continuation, + search, and codensity monads. + Those transformers do not support base runners or foreign runners at all; + they are not endofunctors in the category of monads. + Accordingly, programmers can use those monads only in the deepest position + in monad stacks; in that case, all effects can be still lifted to the stack. +\end_layout + +\begin_layout Standard +The chapter concludes by considering several directions of developing the + theory further: +\end_layout + +\begin_layout Itemize +Show examples of monads that have more than one transformer. + As a rule, one transformer is complete and all others are incomplete. +\end_layout + +\begin_layout Itemize +Prove some general properties of monad morphisms that are useful for proofs + of laws of monad transformers. +\end_layout + +\begin_layout Itemize +\begin_inset Quotes eld +\end_inset + +Rigid +\begin_inset Quotes erd +\end_inset + + monad transformers are built via +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +swap +\end_layout + +\end_inset + + functions. + Do compositions of arbitrary rigid monads always have a corresponding +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +swap +\end_layout + +\end_inset + + function? This question is not yet fully answered (Problem +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "par:Problem-monads-5-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). +\end_layout + +\begin_layout Itemize +The requirements for +\begin_inset Quotes eld +\end_inset + +rigid +\begin_inset Quotes erd +\end_inset + + monads can be relaxed to yield +\begin_inset Quotes eld +\end_inset + +rigid +\begin_inset Quotes erd +\end_inset + + functors. + We outline their properties and show some applications: the +\begin_inset Quotes eld +\end_inset + +functor-valued +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + + +\begin_inset Quotes erd +\end_inset + + and the +\begin_inset Quotes eld +\end_inset + +refactor-to-monad +\begin_inset Quotes erd +\end_inset + + transformation. +\end_layout + +\begin_layout Itemize +The +\begin_inset Quotes eld +\end_inset + +MTL-style +\begin_inset Quotes erd +\end_inset + + monadic programming can be made more general via the +\begin_inset Quotes eld +\end_inset + +monadically natural lifting +\begin_inset Quotes erd +\end_inset + + of monad operations to monad stacks. + We prove the theoretical results underlying this technique. \end_layout \begin_layout Subsection @@ -5689,13 +7126,13 @@ in the same way \end_inset for all types. - This appendix develops the necessary theory and technique to prove a number - of results used in other parts of the book. + This appendix develops the necessary theory and technique to show how one + can prove a number of results used in other parts of the book. \end_layout \begin_layout Standard -We show that a given type constructor may have at most one fully parametric - and lawful implementation of the +First, we show that a given type constructor may have at most one fully + parametric and lawful implementation of the \begin_inset listings inline true status open @@ -5778,8 +7215,8 @@ noprefix "false" \end_layout \begin_layout Standard -The lifting methods of any fully parametric bifunctor or profunctor obey - the commutativity law such as Eq. +We show that the lifting methods of any fully parametric bifunctor or profunctor + will automatically obey the commutativity law such as Eq. \begin_inset space ~ \end_inset @@ -5798,12 +7235,35 @@ noprefix "false" \end_layout \begin_layout Standard -The a central theorem from which all applications of parametricity will - follow says that any fully parametric expression +Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "sec:Parametricity-theorem-for-relations" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + begins the study of the central theorem from which all applications of + parametricity will follow. + This theorem (the +\begin_inset Quotes eld +\end_inset + +parametricity theorem +\begin_inset Quotes erd +\end_inset + +) says that any fully parametric expression \begin_inset Formula $t:\forall A.\,Q^{A}$ \end_inset - satisfies a relational naturality law + will automatically obey a certain relational naturality law, shown in Eq. \begin_inset space ~ \end_inset @@ -5818,19 +7278,13 @@ noprefix "false" \end_inset ). - In general, the relational naturality law expresses a property of -\emph on -relations -\emph default - rather than functions and is not equivalent to any equation satisfied by -\begin_inset Formula $t$ -\end_inset +\end_layout -. - The chapter explains how relations are defined and introduces certain combinato -rs that manipulate relations: the relational product, co-product, and the - +\begin_layout Standard +We explain how relations are defined and introduce certain combinators that + manipulate relations: the relational product, the relational co-product, + and the \begin_inset Quotes eld \end_inset @@ -5861,7 +7315,7 @@ noprefix "false" \end_inset -), we obtain an inductive proof of the relational naturality law (Section +), Section \begin_inset space ~ \end_inset @@ -5875,13 +7329,22 @@ noprefix "false" \end_inset -). + arrives at an inductive proof of the relational naturality law. \end_layout \begin_layout Standard -Because the relational naturality law is formulated in terms of relations - rather than functions, it is often hard to use directly. +The relational naturality law expresses a property of +\emph on +relations +\emph default + (rather than functions) and is not always equivalent to any equation satisfied + by +\begin_inset Formula $t$ +\end_inset + +. + Because of that, the relational naturality law is often hard to use directly. Programmers are more interested in proving that a fully parametric function satisfies some equation (a \begin_inset Quotes eld @@ -5892,8 +7355,8 @@ law \end_inset ). - Several shortcuts are available that, in most cases, straightforwardly - give such equations. + Several shortcuts are available that, in most cases, quickly produce equational + laws automatically satisfied by fully parametric expressions. \end_layout \begin_layout Standard @@ -6005,26 +7468,12 @@ noprefix "false" . Strong dinaturality gives more information than the ordinary dinaturality - law and is simpler to use than the general relational naturality law -\begin_inset space ~ -\end_inset - -( -\begin_inset CommandInset ref -LatexCommand ref -reference "eq:relational-naturality-law-1" -plural "false" -caps "false" -noprefix "false" - -\end_inset - -). + law. \end_layout \begin_layout Standard The strong dinaturality law is the first of the parametricity techniques - that go beyond Yoneda identities. + that go beyond naturality laws and Yoneda identities. Section \begin_inset space ~ \end_inset @@ -6098,7 +7547,7 @@ noprefix "false" \end_layout \begin_layout Standard -Category theory proves abstract version of the Yoneda identity (the +Category theory proves an abstract version of the Yoneda identity (the \begin_inset Quotes eld \end_inset @@ -6108,7 +7557,8 @@ Yoneda lemma ) for all categories. The two Yoneda identities involving covariant and contravariant functors - are the most important practical application of the Yoneda lemma to programming. + are the most important practical applications of the Yoneda lemma to programmin +g. Other applications used in this book are Yoneda identities for type constructor s (see Section \begin_inset space ~ @@ -6332,19 +7782,19 @@ noprefix "false" \end_inset -can be generalized to the following isomorphism, +can be generalized to the following isomorphism: \begin_inset Formula \[ -\forall A.\,P^{A}\rightarrow F^{A}+G^{A}\cong(\forall A.\,P^{A}\rightarrow F^{A})+(\forall A.\,P^{A}\rightarrow G^{A})\quad, +\forall A.\,P^{A}\rightarrow F^{A}+G^{A}\cong(\forall A.\,P^{A}\rightarrow F^{A})+(\forall A.\,P^{A}\rightarrow G^{A})\quad. \] \end_inset -as long as the type constructor +This holds for type constructors \begin_inset Formula $P$ \end_inset - is, in our terminology, + that are, in our terminology, \begin_inset Quotes eld \end_inset @@ -6368,7 +7818,7 @@ noprefix "false" \end_inset gives a formal definition of that property and goes through structural - analysis, discovering various type constructors that are non-disjunctive. + analysis, discovering various non-disjunctive type constructors. Some recipes for building non-disjunctive type constructors are shown in Example \begin_inset space ~ @@ -6573,8 +8023,8 @@ Trampolines and stack-safe recursion in functor blocks \end_layout \begin_layout Standard -Recursion with applicative and monadic functors (say, a loop with the free - monad) can lead to stack overflows when the nesting of +Recursion with applicative and monadic functors (say, a loop within the + free monad) can lead to stack overflows when the nesting of \begin_inset listings inline true status open @@ -7212,7 +8662,38 @@ Effect systems \begin_layout Standard Algebraic effects are currently an active topic of research and experimentation. - The basic idea of an effect system is to use type signatures that indicate + Programming with +\begin_inset Quotes eld +\end_inset + +effects +\begin_inset Quotes erd +\end_inset + + and +\begin_inset Quotes eld +\end_inset + +handlers +\begin_inset Quotes erd +\end_inset + + is intended to replace the monad-based design patterns and in particular + avoid the need for monad transformers, which have proved to be complicated + and hard to use. + Effect systems can be viewed also as a way of incorporating the +\begin_inset Quotes eld +\end_inset + +free monad +\begin_inset Quotes erd +\end_inset + + design pattern more directly into a programming language. +\end_layout + +\begin_layout Standard +The basic idea of an effect system is to use type signatures that indicate precisely what side effects a function may execute when it is evaluated. For instance, there is one effect type for printing to the console, another effect type for querying a database, yet another for running code via parallel @@ -7395,15 +8876,55 @@ Proving that evaluating an expression will always give the same results \end_layout \begin_layout Itemize -Proving that composition of functions is associative by a rigorous description - of what it means for functions to be equal without involving an evaluation - of those functions. +Proving that composition of functions is associative by using a rigorous + definition of what it means for functions to be equal. +\end_layout + +\begin_layout Itemize +Defining a rigorous mathematical semantics for each construction of a programmin +g language and proving its properties (for example, that it is equivalent, + or not equivalent, to the semantics of some other language). \end_layout \begin_layout Standard This book does not pursue those topics. \end_layout +\begin_layout Subsection +Bibliography +\end_layout + +\begin_layout Standard +This book does not include a list of references at the end. + Instead, throughout the book there are footnote references to books, papers, + video presentations, and blog posts that have some relevance to the material + being discussed. + +\end_layout + +\begin_layout Standard +The lack of bibliography is appropriate because this book is a pedagogical + tutorial, not an academic treatise. + One of the purposes of an academic treatise is to demonstrate ample continuity + with previously published research. + An academic bibliography helps reviewers understand in what new direction + the presented research goes, without having to read the text itself. + It also helps other academic authors whose career depends on increased + citation counts. + For those purposes, it is convenient to see a bibliography showing tens + or hundreds of references to established academic literature. +\end_layout + +\begin_layout Standard +In contrast, the vision of this book is to present a sequence of pedagogically + accessible steps that will help readers to learn the theoretical material + relevant for the practice of functional programming. + All explanations are self-contained; it is not assumed that the reader + will first learn from some other books or papers on FP before embarking + on this book. + So, a bibliography section will not help the readers. +\end_layout + \begin_layout Section Additional exercises and open problems \begin_inset CommandInset label @@ -12067,8 +13588,16 @@ For certain monads \begin_inset Formula $L$ \end_inset -, the monad transformers -\begin_inset Formula $T_{L}$ + (such as the +\begin_inset Quotes eld +\end_inset + +rigid +\begin_inset Quotes erd +\end_inset + + monads), the corresponding monad transformers +\begin_inset Formula $L\varangle$ \end_inset can be defined using a suitable diff --git a/sofp-src/lyx/sofp-transformers.lyx b/sofp-src/lyx/sofp-transformers.lyx index 71c9a04b2..2ce560239 100644 --- a/sofp-src/lyx/sofp-transformers.lyx +++ b/sofp-src/lyx/sofp-transformers.lyx @@ -338,7 +338,7 @@ Combining monadic effects via functor composition \begin_layout Standard Monads describe effects that depend on previously computed values. - It is often necessary to combine effects of several monads in one. + It is often necessary to combine effects of several monads. For example, the effect of \begin_inset listings inline true @@ -612,8 +612,7 @@ Future[Option[A]] \end_inset . - The code is repetitive and deeply nested, which makes it hard to read and - to change. + The code is repetitive and deeply nested, which makes it hard to work with. \end_layout @@ -10622,6 +10621,13 @@ Throughout this chapter, we will build transformers for every monad considered \begin_layout Subsection A typeclass for monad transformers +\begin_inset CommandInset label +LatexCommand label +name "subsec:A-typeclass-for-monad-transformers" + +\end_inset + + \end_layout \begin_layout Standard @@ -11427,7 +11433,7 @@ Having computed a value of type, say, runners, we can run the effects of any chosen monad, e.g., like this: \begin_inset Formula \[ -\text{frun}_{K}^{L\varangle M\varangle N}(\text{frun}_{L}^{M\varangle N}(\text{brun}_{M}^{N}(\theta_{M}))):K\varangle L\varangle M\varangle N\leadsto K\varangle L\varangle N\quad. +\text{frun}_{K}^{L\varangle M\varangle N,L\varangle N}(\text{frun}_{L}^{M\varangle N,N}(\text{brun}_{M}^{N}(\theta_{M}))):K\varangle L\varangle M\varangle N\leadsto K\varangle L\varangle N\quad. \] \end_inset @@ -22634,6 +22640,13 @@ Motivation for the swap \family default function +\begin_inset CommandInset label +LatexCommand label +name "subsec:Motivation-for-the-swap-function" + +\end_inset + + \end_layout \begin_layout Standard @@ -23480,7 +23493,14 @@ swap \end_layout \begin_layout Subsection -Deriving the necessary laws for +Deriving the necessary laws +\begin_inset CommandInset label +LatexCommand label +name "subsec:Deriving-the-necessary-laws-for-swap" + +\end_inset + + for \family typewriter swap \end_layout @@ -29600,18 +29620,6 @@ monads!linear of the form \begin_inset Formula $M^{A}=P+Q\times A$ -\end_inset - - and -\begin_inset Formula $M^{A}=Q\times\left(P+A\right)$ -\end_inset - -, called -\begin_inset Quotes eld -\end_inset - -linear -\begin_inset Quotes erd \end_inset . @@ -29635,6 +29643,17 @@ status open \begin_layout Plain Layout Monads of this kind do not seem to have an already accepted name. + See the discussion here: +\family typewriter + +\begin_inset CommandInset href +LatexCommand href +target "https://stackoverflow.com/questions/39649497/" +literal "false" + +\end_inset + + \end_layout \end_inset @@ -29779,7 +29798,7 @@ literal "false" \end_inset - + for a discussion of the selector monad. \end_layout \end_inset @@ -32451,6 +32470,13 @@ choice \begin_layout Section Transformers for other monad constructions +\begin_inset CommandInset label +LatexCommand label +name "sec:Transformers-for-products-and-free-pointed" + +\end_inset + + \end_layout \begin_layout Subsection @@ -35841,6 +35867,13 @@ This derivation concludes the proof of the laws of the free pointed monad \begin_layout Section Transformers for recursive monads +\begin_inset CommandInset label +LatexCommand label +name "sec:Transformers-for-recursive-monads" + +\end_inset + + \end_layout \begin_layout Subsection @@ -37018,12 +37051,12 @@ To implement the base runner, we use the similarity between the two disjunctive types: \begin_inset Formula \[ -L^{A}\triangleq\text{Free}^{F\circ M,A}=A+F^{M^{\text{Free}^{F\circ M,A}}}=A+(F\circ M\circ L)^{A}\:\text{ and }\:\text{Free}^{F,M^{A}}=M^{A}+F^{\text{Free}^{F,M^{A}}}\quad. +L^{A}\triangleq\text{Free}^{F\circ M,A}=A+F^{M^{\text{Free}^{F\circ M,A}}}=A+(F\circ M\circ L)^{A}\text{ and }\text{Free}^{F,M^{A}}=M^{A}+F^{\text{Free}^{F,M^{A}}}\quad. \] \end_inset -The code for the base runner is: + The code for the base runner is: \begin_inset Formula \begin{align*} & \text{brun}:(\text{Free}^{F}\leadsto\text{Id})\rightarrow M^{L^{A}}\rightarrow M^{A}\quad,\\ @@ -42853,8 +42886,8 @@ Incomplete transformers \end_layout \begin_layout Standard -A monad transformer that obeys the laws of a pointed and co-pointed functor - in the category of monads (see Section +A monad transformer that obeys the laws of a pointed functor in the category + of monads (see Section \begin_inset space ~ \end_inset @@ -47027,6 +47060,10 @@ flift . \end_layout +\begin_layout Section +Further developments +\end_layout + \begin_layout Subsection Examples of monads with several different transformers \begin_inset CommandInset label @@ -47663,10 +47700,6 @@ standard transformer. \end_layout -\begin_layout Section -Further developments -\end_layout - \begin_layout Subsection Some properties of monad morphisms \end_layout @@ -60062,6 +60095,13 @@ simple \begin_layout Subsection Summary of monad transformer constructions +\begin_inset CommandInset label +LatexCommand label +name "subsec:Summary-of-monad-transformer-constructions" + +\end_inset + + \end_layout \begin_layout Standard diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index d851abc44f016fde8430cfee5d5c6285e6a4358d..fd4f5552ec8b490b30cc0c78066013e22bdf6a73 100644 GIT binary patch delta 162 zcmX?Ra?E7IN)cW|T?4}qLo+J_3oB!j$=gKq&_q6pJmED;Gc__Zv@q07O*1vz{796I ziPO-)(9q1l0;uJqxFmwNSy Date: Sat, 1 Nov 2025 20:39:33 +0100 Subject: [PATCH 21/42] minor fixes --- sofp-src/lyx/sofp-summary.lyx | 35 +++++++++++++------ sofp-src/lyx/sofp-transformers.lyx | 46 ++++++++++++++----------- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-summary.tex | 53 +++++++++++++++++++++-------- sofp-src/tex/sofp-transformers.tex | 29 ++++++++-------- sofp-src/tex/sofp.tex | 6 ++-- 6 files changed, 107 insertions(+), 62 deletions(-) diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 8667436ff..00be6593c 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -5626,7 +5626,16 @@ noprefix "false" \end_layout \begin_layout Standard -*** +A +\begin_inset Quotes eld +\end_inset + +free typeclass +\begin_inset Quotes erd +\end_inset + + is an advanced design pattern in functional programming. + *** \end_layout \begin_layout Subsection @@ -6310,8 +6319,8 @@ noprefix "false" \end_layout \begin_layout Standard -The next sections embark on proving the laws for monad transformers of the - individual monads. +The next sections will prove the laws for monad transformers of the individual + monads. We begin with the \begin_inset Quotes eld \end_inset @@ -6945,12 +6954,18 @@ State \end_layout \begin_layout Standard -The next sections prove the laws of the monad transformers for the continuation, - search, and codensity monads. - Those transformers do not support base runners or foreign runners at all; - they are not endofunctors in the category of monads. - Accordingly, programmers can use those monads only in the deepest position - in monad stacks; in that case, all effects can be still lifted to the stack. +The next sections prove the laws of the monad transformers for the continuation + monad, the generalized search monad, and the codensity monad. + Those transformers do not support base lifts, base runners, or foreign + runners; they are +\emph on +not +\emph default + endofunctors in the category of monads. + Because of this, programmers cannot lift effects of different monads into + a transformed monad and cannot run effects in an arbitrary order unless + the problematic monads (continuation, search, codensity, etc.) are in the + deepest position in the monad stack. \end_layout \begin_layout Standard @@ -6959,7 +6974,7 @@ The chapter concludes by considering several directions of developing the \end_layout \begin_layout Itemize -Show examples of monads that have more than one transformer. +Show some examples of monads that have more than one transformer. As a rule, one transformer is complete and all others are incomplete. \end_layout diff --git a/sofp-src/lyx/sofp-transformers.lyx b/sofp-src/lyx/sofp-transformers.lyx index 2ce560239..3b42be142 100644 --- a/sofp-src/lyx/sofp-transformers.lyx +++ b/sofp-src/lyx/sofp-transformers.lyx @@ -61594,12 +61594,16 @@ U^{A}\triangleq L^{(L\varangle M)^{A}}\quad,\quad\quad V^{A}\triangleq M^{(L\var \end_inset -In a shorter notation, -\begin_inset Formula $U\triangleq L\circ(L\varangle M)$ +For brevity, denote +\begin_inset Formula $T\triangleq L\varangle M$ \end_inset - and -\begin_inset Formula $V\triangleq M\circ(L\varangle M)$ +, +\begin_inset Formula $U\triangleq L\circ T$ +\end_inset + +, and +\begin_inset Formula $V\triangleq M\circ T$ \end_inset . @@ -61618,13 +61622,13 @@ swap functions: \begin_inset Formula \begin{align*} -\text{sw}_{L,T} & :(L\varangle M)\circ L\leadsto L\circ(L\varangle M)\quad,\\ -\text{sw}_{M,T} & :(L\varangle M)\circ M\leadsto(M\circ L)\varangle M\quad, +\text{sw}_{L,T} & :T\circ L\leadsto L\circ T\quad,\\ +\text{sw}_{M,T} & :T\circ M\leadsto M\circ T\quad, \end{align*} \end_inset -defined using the already given methods +expressed using the already given methods \begin_inset listings inline true status open @@ -61649,7 +61653,7 @@ blift \end_inset of -\begin_inset Formula $L\varangle M$ +\begin_inset Formula $T$ \end_inset as: @@ -61743,12 +61747,12 @@ swap \begin_inset Formula $\,:M\circ L\leadsto L\circ M$ \end_inset -, assume that the method -\begin_inset Formula $\text{ftn}_{T}$ +, assume that +\begin_inset Formula $T\triangleq L\circ M$ \end_inset - of the monad -\begin_inset Formula $T\triangleq L\circ M$ + is a lawful monad whose method +\begin_inset Formula $\text{ftn}_{T}$ \end_inset is @@ -61987,7 +61991,7 @@ search monad \end_inset by -\begin_inset Formula $\text{Search}^{P,A}\triangleq\left(A\rightarrow\bbnum 1+P\right)\rightarrow\bbnum 1+A$ +\begin_inset Formula $\text{Search}^{P,A}\triangleq(A\rightarrow\bbnum 1+P)\rightarrow\bbnum 1+A$ \end_inset . @@ -62062,7 +62066,7 @@ finder \emph on not \emph default - a monad morphism + a monad morphism of type \begin_inset Formula $\text{Sel}^{\bbnum 1+P,\bullet}\leadsto\text{Search}^{P,\bullet}$ \end_inset @@ -62196,11 +62200,15 @@ noprefix "false" \begin_inset Formula $(K^{A}\times L^{A})\times M^{A}\cong K^{A}\times(L^{A}\times M^{A})$ \end_inset - is also a + has \emph on monad \emph default - isomorphism. + +\emph on +morphisms +\emph default + in both directions. \end_layout \begin_layout Subsubsection @@ -63431,11 +63439,11 @@ Hints: Use the flipped Kleisli formulation of the monad laws. \begin_inset Formula $X$ \end_inset - and for some -\begin_inset Formula $L^{\bullet}$ + and for some functor +\begin_inset Formula $L$ \end_inset -, the type constructor +, the functor \begin_inset Formula $P^{A}\triangleq(A\rightarrow X)\rightarrow L^{X}$ \end_inset diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index fd4f5552ec8b490b30cc0c78066013e22bdf6a73..94fb74c7f7615159e4380550bdc5d5257df060a8 100644 GIT binary patch delta 146 zcmX?Ra?E7IIuQ;d11lqQDTKy^>1t@{=44`SY3XQT>TK?8Wa4OHVPs}xZeeFbNX2Ar GDQN)D#U?ob delta 146 zcmX?Ra?E7IIuQ;-Gb;lND`S(%+eC~JoR1<;c#YCbjm!)!40Th}Obs_b66IuKGc+@> z04n_`E(2w57M8fi=wxW&YGz_=Y3Xe0Y-V9< Option[P]) => A): (A => Option[P]) => Option[A] = { @@ -12156,7 +12156,7 @@ \subsubsection{Exercise \label{subsec:Statement-search-and-selector-monads}\ref{ \end{align*} transforms a \index{monads!Sel (selector) monad@\texttt{Sel} (selector) monad}selector monad $\text{Sel}^{\bbnum 1+P,A}$ to the search monad. Show that -\lstinline!finder! is \emph{not} a monad morphism $\text{Sel}^{\bbnum 1+P,\bullet}\leadsto\text{Search}^{P,\bullet}$. +\lstinline!finder! is \emph{not} a monad morphism of type $\text{Sel}^{\bbnum 1+P,\bullet}\leadsto\text{Search}^{P,\bullet}$. \subsubsection{Exercise \label{subsec:Exercise-selector-and-continuation-monads}\ref{subsec:Exercise-selector-and-continuation-monads}} @@ -12178,7 +12178,7 @@ \subsubsection{Exercise \label{subsec:Exercise-monad-product}\ref{subsec:Exercis is again a monad. \textbf{(b)} Show that the type isomorphism $(K^{A}\times L^{A})\times M^{A}\cong K^{A}\times(L^{A}\times M^{A})$ -is also a \emph{monad} isomorphism. +has \emph{monad} \emph{morphisms} in both directions. \subsubsection{Exercise \label{par:Exercise-mt-3-1}\ref{par:Exercise-mt-3-1}} @@ -12313,9 +12313,8 @@ \subsubsection{Exercise \label{subsec:Exercise-combined-codensity-monad}\ref{sub \textbf{(b)} Show that the quantifier $\forall X$ cannot be removed from the definition of $\text{Cod}_{F}^{L,A}$ even if $F^{A}\triangleq A$: -for a fixed type $X$ and for some $L^{\bullet}$, the type constructor -$P^{A}\triangleq(A\rightarrow X)\rightarrow L^{X}$ is \emph{not} -a monad. +for a fixed type $X$ and for some functor $L$, the functor $P^{A}\triangleq(A\rightarrow X)\rightarrow L^{X}$ +is \emph{not} a monad. \textbf{(c)} Show that in general there is \emph{no} monad morphism $L^{A}\rightarrow\text{Cod}_{F}^{L,A}$. diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index aa51ad00e..55cfe9bd8 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): 0e24f2a1c13340492a90c678d3725593150e5b1d2f045b2dd3f71ab2af7c779a}\\ -{\scriptsize{}Git commit: 6c6d0b1658b3fb05dd9aa80958ffb2ac705f975d}\\ -{\scriptsize{}PDF file built on Sat, 01 Nov 2025 16:08:52 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 6af4509d72f87e855ce25a386cce4eb244289a571f1d0e68d669bf755c50d6b8}\\ +{\scriptsize{}Git commit: 87ea863dca7d7776ef37113e3a3c057657c31411}\\ +{\scriptsize{}PDF file built on Sat, 01 Nov 2025 20:27:44 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From 0172ca486bf15764d1d5b34fe58e56245e544553 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Sun, 2 Nov 2025 00:15:56 +0100 Subject: [PATCH 22/42] wip reformat chapter 13 --- sofp-src/lyx/sofp-free-type.lyx | 158 ++++++++++++++---------------- sofp-src/lyx/sofp-summary.lyx | 20 +++- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-free-type.tex | 155 ++++++++++++++--------------- sofp-src/tex/sofp-summary.tex | 38 ++++--- sofp-src/tex/sofp.tex | 6 +- 6 files changed, 194 insertions(+), 183 deletions(-) diff --git a/sofp-src/lyx/sofp-free-type.lyx b/sofp-src/lyx/sofp-free-type.lyx index 0ed095dd0..da13afee2 100644 --- a/sofp-src/lyx/sofp-free-type.lyx +++ b/sofp-src/lyx/sofp-free-type.lyx @@ -1103,17 +1103,16 @@ Stage 2: implementing type safety in the DSLs \end_layout \begin_layout Standard -The two DSLs defined in the previous section are not fully type-checked +The two DSLs defined in the previous section are not type-safe. \begin_inset Index idx status open \begin_layout Plain Layout -type checking +type safety \end_layout \end_inset - at compile time. This becomes clear by looking at the DSL program \begin_inset listings inline true @@ -1246,7 +1245,7 @@ file \end_inset failed to compile. - To achieve that, it would help to have different Scala types for DSL programs + To achieve that, we need to have different Scala types for DSL programs returning a \begin_inset listings inline true @@ -1259,7 +1258,7 @@ String \end_inset - and a + or a \begin_inset listings inline true status open @@ -1272,7 +1271,7 @@ Path \end_inset . - So, let us replace the type + So, we replace the type \begin_inset listings inline true status open @@ -1296,7 +1295,7 @@ PrgFile[A] \end_inset -, representing a DSL program that will return a value of type +, which means a DSL program that will return a value of type \begin_inset listings inline true status open @@ -1525,7 +1524,19 @@ PrgComplex , and so the Scala compiler is unable to verify that the DSL is being used correctly. - If the programmer uses a plain complex number ( + If the programmer uses +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Rotate +\end_layout + +\end_inset + + with a \begin_inset listings inline true status open @@ -1537,7 +1548,7 @@ Val \end_inset -) instead of a + instead of a \begin_inset listings inline true status open @@ -1549,7 +1560,7 @@ Phase \end_inset - value, the program will return an incorrect result +, the program will return an incorrect result \emph on without \emph default @@ -1560,8 +1571,7 @@ status open \begin_layout Plain Layout -val prgComplex3: PrgComplex = Rotate(prgComplex1, Val(Complex(0, 1))) - // Forgot Phase()! +val prgComplex3: PrgComplex = Rotate(prgComplex1, Val(Complex(0, 1))) \end_layout \begin_layout Plain Layout @@ -1648,8 +1658,7 @@ sealed trait PrgComplex[A] \begin_layout Plain Layout -final case class Val(c: Complex) extends - PrgComplex[Complex] +final case class Val(c: Complex) extends PrgComplex[Complex] \end_layout \begin_layout Plain Layout @@ -1666,14 +1675,12 @@ final case class Mul(p1: PrgComplex[Complex], p2: PrgComplex[Complex]) extends \begin_layout Plain Layout -final case class Conj(p: PrgComplex[Complex]) extends - PrgComplex[Complex] +final case class Conj(p: PrgComplex[Complex]) extends PrgComplex[Complex] \end_layout \begin_layout Plain Layout -final case class Phase(p: PrgComplex[Complex]) extends - PrgComplex[Double] +final case class Phase(p: PrgComplex[Complex]) extends PrgComplex[Double] \end_layout \begin_layout Plain Layout @@ -1755,7 +1762,7 @@ def runComplex[A]: PrgComplex[A] => A = { \end_inset -The example programs, +The example programs ( \begin_inset listings inline true status open @@ -1779,7 +1786,7 @@ prgComplex2 \end_inset -, do not change except for their type: +) remain unchanged except for their types: \begin_inset listings inline false status open @@ -1849,7 +1856,7 @@ status open \begin_layout Plain Layout -PrgComplex[Double] +Phase \end_layout \end_inset @@ -1866,7 +1873,7 @@ Phase \end_inset - will cause a type error: + will be a type error: \begin_inset listings inline false status open @@ -1888,8 +1895,8 @@ scala> val prgComplex3 = Rotate(prgComplex1, Val(Complex(0, 1))) \begin_layout Plain Layout - required: PrgComplex[Double] - + required: Phase + \end_layout \begin_layout Plain Layout @@ -1984,7 +1991,7 @@ PrgFile \end_inset - DSL, we find that we need to set the Scala variable + DSL, we find that we need to set the variable \begin_inset listings inline true status open @@ -1997,7 +2004,7 @@ p \end_inset to the path computed by a previous operation. - Here is a first attempt: + A first attempt is: \begin_inset listings inline false status open @@ -2031,7 +2038,7 @@ No file. \end_inset There are two problems with this code. - The first problem is that + First, \begin_inset listings inline true status open @@ -2043,7 +2050,7 @@ Read(p) \end_inset - does not compile because the argument of + does not compile: the argument of \begin_inset listings inline true status open @@ -2080,7 +2087,7 @@ JPath \end_inset . - To solve this problem, we generalize the + To fix this, we add a type parameter to the \begin_inset listings inline true status open @@ -2092,7 +2099,7 @@ Val \end_inset - class to hold values of arbitrary type: + case class, now supporting values of any type: \begin_inset listings inline false status open @@ -2177,8 +2184,8 @@ bound variable \end_inset -bound variables is by using those variables as arguments of nameless functions. - So, let us consider the nameless function: +bound variables is by using arguments of nameless functions. + So, let us consider the following nameless function: \begin_inset listings inline false status open @@ -2490,7 +2497,7 @@ Bind \end_inset --handling code to the runner, the implementation of the DSL is: +-handling code to the runner, we get: \begin_inset listings inline false status open @@ -2668,7 +2675,7 @@ status open \begin_layout Plain Layout -p:JPath +p: JPath \end_layout \end_inset @@ -2848,7 +2855,7 @@ B => PrgFile[A] \end_inset ), that function may run arbitrary Scala code, not limited to DSL operations, - in order to compute a result of type + as it computes its result value of type \begin_inset listings inline true status open @@ -2910,7 +2917,7 @@ PrgFile[A] \end_inset - describes a computation but does not execute it. + describes a computation but does not run it. \end_layout \begin_layout Subsection @@ -3006,8 +3013,7 @@ sealed trait PrgFile[A] { \begin_layout Plain Layout -final case class Val[A](a: A) extends - PrgFile[A] +final case class Val[A](a: A) extends PrgFile[A] \end_layout \begin_layout Plain Layout @@ -3018,14 +3024,12 @@ final case class Bind[A, B](pa: PrgFile[B])(val f: B => PrgFile[A]) extends \begin_layout Plain Layout -final case class Path(p: PrgFile[String]) extends - PrgFile[JPath] +final case class Path(p: PrgFile[String]) extends PrgFile[JPath] \end_layout \begin_layout Plain Layout -final case class Read(p: PrgFile[JPath]) extends - PrgFile[String] +final case class Read(p: PrgFile[JPath]) extends PrgFile[String] \end_layout \begin_layout Plain Layout @@ -3526,9 +3530,8 @@ B => PrgFile[A] \end_layout \begin_layout Standard -Typically, a monadic DSL program is a nested case class containing some - function that, when called, will return further nested case classes and - functions, etc. +Typically, a monadic DSL program is a case class containing some functions + that, when called, will return further nested case classes or functions. All those functions are waiting to be called; no side effects have been run yet. The actual business logic and side effects will be executed only when the @@ -3545,7 +3548,7 @@ run \end_inset method is applied. - At that time, the entire DSL program will be converted into a result value. + After that, we will get the result value of the entire DSL program. \end_layout \begin_layout Subsection @@ -3607,8 +3610,7 @@ object PrgComplex { \begin_layout Plain Layout -final case class Val[A](a: A) - extends PrgComplex[A] +final case class Val[A](a: A) extends PrgComplex[A] \end_layout \begin_layout Plain Layout @@ -3619,32 +3621,27 @@ final case class Bind[A, B](pa: PrgComplex[B])(val f: B => PrgComplex[A]) \begin_layout Plain Layout -final case class Add(x: Complex, y: Complex) - extends PrgComplex[Complex] +final case class Add(x: Complex, y: Complex) extends PrgComplex[Complex] \end_layout \begin_layout Plain Layout -final case class Mul(x: Complex, y: Complex) - extends PrgComplex[Complex] +final case class Mul(x: Complex, y: Complex) extends PrgComplex[Complex] \end_layout \begin_layout Plain Layout -final case class Conj(x: Complex) - extends PrgComplex[Complex] +final case class Conj(x: Complex) extends PrgComplex[Complex] \end_layout \begin_layout Plain Layout -final case class Phase(p: Complex) - extends PrgComplex[Double] +final case class Phase(p: Complex) extends PrgComplex[Double] \end_layout \begin_layout Plain Layout -final case class Rotate(p: Complex, p: Phase) - extends PrgComplex[Complex] +final case class Rotate(p: Complex, p: Phase) extends PrgComplex[Complex] \end_layout \begin_layout Plain Layout @@ -3952,8 +3949,7 @@ final case class Bind[A, B](pa: PrgFile[B])(val f: B => PrgFile[A]) extends \begin_layout Plain Layout -final case class Op[A](op: PrgFileC[A]) extends PrgFile[A] // Wrap custom - operations. +final case class Op[A](op: PrgFileC[A]) extends PrgFile[A] // Custom operation. \end_layout \begin_layout Plain Layout @@ -3977,8 +3973,7 @@ def runFile[A]: PrgFile[A] => A = { \begin_layout Plain Layout - case Op(op) => runFileC(op) // Run the custom operation and get - the result. + case Op(op) => runFileC(op) // Run a custom operation. \end_layout \begin_layout Plain Layout @@ -4032,8 +4027,8 @@ final case class Bind[A, B](pa: PrgComplex[B])(val f: B => PrgComplex[A]) \begin_layout Plain Layout -final case class Op[A](op: PrgComplexC[A]) extends PrgComplex[A] // - Wrap custom operations. +final case class Op[A](op: PrgComplexC[A]) extends PrgComplex[A] // Custom + operation. \end_layout \begin_layout Plain Layout @@ -4057,8 +4052,7 @@ def runComplex[A]: PrgComplex[A] => A = { \begin_layout Plain Layout - case Op(op) => runComplexC(op) // Run the custom operation - and get the result. + case Op(op) => runComplexC(op) // Run a custom operation. \end_layout \begin_layout Plain Layout @@ -4073,22 +4067,22 @@ sealed trait PrgComplexC[A] \begin_layout Plain Layout -final case class Add(x: Complex, y: Complex) extends PrgComplexC[Complex] +final case class Add(x: Complex, y: Complex) extends PrgComplexC[Complex] \end_layout \begin_layout Plain Layout -final case class Mul(x: Complex, y: Complex) extends PrgComplexC[Complex] +final case class Mul(x: Complex, y: Complex) extends PrgComplexC[Complex] \end_layout \begin_layout Plain Layout -final case class Conj(x: Complex) extends PrgComplexC[Complex] +final case class Conj(x: Complex) extends PrgComplexC[Complex] \end_layout \begin_layout Plain Layout -final case class Phase(p: Complex) extends PrgComplexC[Double] +final case class Phase(p: Complex) extends PrgComplexC[Double] \end_layout \begin_layout Plain Layout @@ -4242,7 +4236,7 @@ PrgFile \end_inset is only concerned with providing the monadic functionality to the DSL. - We can replace those two classes by a single class (called, say, + We can replace those two classes by a single class (called \begin_inset listings inline true status open @@ -5086,7 +5080,7 @@ name "subsec:A-first-recipe-monadic-dsl" \end_layout \begin_layout Standard -The previous section gave motivation for defining the type constructor +The previous section motivated defining the type constructor \begin_inset listings inline true status open @@ -5099,7 +5093,7 @@ MonadDSL[F[_], A] \end_inset . - That type constructor is called the + That type constructor is known as the \begin_inset Quotes eld \end_inset @@ -5656,7 +5650,7 @@ String \end_inset ). - However, in some cases the effect constructor + However, in other cases the effect constructor \begin_inset listings inline true status open @@ -5668,7 +5662,7 @@ F \end_inset - could be itself a lawful functor. + could be a lawful functor. \end_layout \begin_layout Standard @@ -6614,7 +6608,7 @@ The resulting code creates fewer nested case classes in memory. \end_layout \begin_layout Standard -Unlike other laws, the right identity law already holds for any value +The right identity law already holds for any value \begin_inset listings inline true status open @@ -10414,8 +10408,8 @@ FlatMap \end_inset -, we find that the type of their data are not the same: the first part of - +, we find that the types of their data are not the same: the first part + of \begin_inset listings inline true status open @@ -10501,7 +10495,7 @@ Free3[F, A] \end_inset . - So, we write the code of + So, the code of \begin_inset listings inline true status open @@ -10513,7 +10507,7 @@ free2toFree3 \end_inset - like this: + becomes: \begin_inset listings inline false status open @@ -10556,7 +10550,7 @@ free3toFree2 \end_inset -) is more complicated because +) is more complicated because the case classes \begin_inset listings inline true status open @@ -10580,7 +10574,7 @@ FlatMap \end_inset - are not straightforwardly mapped into + are not directly mapped into \begin_inset listings inline true status open diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 00be6593c..68919013f 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -5635,6 +5635,20 @@ free typeclass \end_inset is an advanced design pattern in functional programming. + The chapter begins by developing the +\begin_inset Quotes eld +\end_inset + +free monad +\begin_inset Quotes erd +\end_inset + + organically by implementing embedded domain-specific languages (DSLs). + We consider two example DSLs: one for computations with complex numbers, + and another for reading files. + In the next few sections, we find that the free monad is a natural result + of making a type-safe DSL with the ability to bind variables to results + of previous DSL computations. *** \end_layout @@ -6073,7 +6087,7 @@ We define monad transformer for the monad \begin_inset Formula $\varangle$ \end_inset - associative, meaning that we may write + associative, so that we may write \begin_inset Formula $K\varangle L\varangle M$ \end_inset @@ -6087,8 +6101,8 @@ We define monad transformer for the monad \end_inset . - Later in this chapter we will rigorously prove those properties for all - known monad transformers. + Later in this chapter we will rigorously prove those and other properties + for all known monad transformers. \end_layout \begin_layout Standard diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 94fb74c7f7615159e4380550bdc5d5257df060a8..0ae78f9d332252323888739fc7300dff92bfd1b9 100644 GIT binary patch delta 151 zcmX?Ra?E7I8WAp|5Ca1%LqjWL%gNhB43W7XMV{~`CM6}BnHm}Crlwh%YL4 Jipkni(g2v5CtCmj delta 151 zcmX?Ra?E7I8WAqT5F-OCBXcVw)5+UJ43W7XMV|1QT3DE*T3ROSrly&jZhj=n!NhK8 zWME_tRQ*w08phr%EODLD(b?76(#6u%(9+Gx#N5)-(ZbZ(+}X&)(Za&W%*for&c>L4 Jipkni(g2XlCvpG) diff --git a/sofp-src/tex/sofp-free-type.tex b/sofp-src/tex/sofp-free-type.tex index 9e30417e3..3a61eb00c 100644 --- a/sofp-src/tex/sofp-free-type.tex +++ b/sofp-src/tex/sofp-free-type.tex @@ -154,13 +154,13 @@ \subsection{Stage 1: unevaluated expression trees} \subsection{Stage 2: implementing type safety in the DSLs} -The two DSLs defined in the previous section are not fully type-checked\index{type checking} -at compile time. This becomes clear by looking at the DSL program -\lstinline!prgFile! shown in the previous section. The code of \lstinline!runFile! -assumes that the \lstinline!Read! operation is always applied to -a \lstinline!Path!. However, this assumption is not enforced by the -DSL. When composing a larger DSL program from separately defined parts, -one could by mistake create an invalid DSL program such as \lstinline!Read(Read(Val("file")))! +The two DSLs defined in the previous section are not type-safe.\index{type safety} +This becomes clear by looking at the DSL program \lstinline!prgFile! +shown in the previous section. The code of \lstinline!runFile! assumes +that the \lstinline!Read! operation is always applied to a \lstinline!Path!. +However, this assumption is not enforced by the DSL. When composing +a larger DSL program from separately defined parts, one could by mistake +create an invalid DSL program such as \lstinline!Read(Read(Val("file")))! where the \lstinline!Read! operation is used incorrectly. Running this program causes a run-time error: \begin{lstlisting} @@ -169,12 +169,11 @@ \subsection{Stage 2: implementing type safety in the DSLs} \end{lstlisting} The Scala compiler cannot verify that we are using the DSL correctly. It would be better if the invalid DSL program \lstinline!Read(Read(Val("file")))! -failed to compile. To achieve that, it would help to have different -Scala types for DSL programs returning a \lstinline!String! and a -\lstinline!Path!. So, let us replace the type \lstinline!PrgFile! -by a type constructor \lstinline!PrgFile[A]!, representing a DSL -program that will return a value of type \lstinline!A! when we run -it: +failed to compile. To achieve that, we need to have different Scala +types for DSL programs returning a \lstinline!String! or a \lstinline!Path!. +So, we replace the type \lstinline!PrgFile! by a type constructor +\lstinline!PrgFile[A]!, which means a DSL program that will return +a value of type \lstinline!A! when we run it: \begin{lstlisting} import java.nio.file.{Path => JPath} import java.nio.file.{Files, Paths} @@ -212,11 +211,11 @@ \subsection{Stage 2: implementing type safety in the DSLs} that assumption. Both arguments of the \lstinline!Rotate! operation are values of type \lstinline!PrgComplex!, and so the Scala compiler is unable to verify that the DSL is being used correctly. If the programmer -uses a plain complex number (\lstinline!Val!) instead of a \lstinline!Phase! -value, the program will return an incorrect result \emph{without} -any indication of error: +uses \lstinline!Rotate! with a \lstinline!Val! instead of a \lstinline!Phase!, +the program will return an incorrect result \emph{without} any indication +of error: \begin{lstlisting} -val prgComplex3: PrgComplex = Rotate(prgComplex1, Val(Complex(0, 1))) // Forgot Phase()! +val prgComplex3: PrgComplex = Rotate(prgComplex1, Val(Complex(0, 1))) scala> runComplex(prgComplex3) // The result is incorrect, but there is no error message! res5: Complex = Complex(11.0, -2.0) @@ -230,11 +229,11 @@ \subsection{Stage 2: implementing type safety in the DSLs} of the case classes are: \begin{lstlisting} sealed trait PrgComplex[A] -final case class Val(c: Complex) extends PrgComplex[Complex] +final case class Val(c: Complex) extends PrgComplex[Complex] final case class Add(p1: PrgComplex[Complex], p2: PrgComplex[Complex]) extends PrgComplex[Complex] final case class Mul(p1: PrgComplex[Complex], p2: PrgComplex[Complex]) extends PrgComplex[Complex] -final case class Conj(p: PrgComplex[Complex]) extends PrgComplex[Complex] -final case class Phase(p: PrgComplex[Complex]) extends PrgComplex[Double] +final case class Conj(p: PrgComplex[Complex]) extends PrgComplex[Complex] +final case class Phase(p: PrgComplex[Complex]) extends PrgComplex[Double] final case class Rotate(p: PrgComplex[Complex], a: Phase) extends PrgComplex[Complex] \end{lstlisting} The revised code of \lstinline!runComplex! is clearer because phases @@ -249,8 +248,8 @@ \subsection{Stage 2: implementing type safety in the DSLs} case Rotate(p, alpha) => runComplex(p).rotate(runComplex(alpha)) } \end{lstlisting} -The example programs, \lstinline!prgComplex1! and \lstinline!prgComplex2!, -do not change except for their type: +The example programs (\lstinline!prgComplex1! and \lstinline!prgComplex2!) +remain unchanged except for their types: \begin{lstlisting} val prgComplex1: PrgComplex[Complex] = Conj(Mul(Val(Complex(1, 2)), Val(Complex(3, -4)))) @@ -262,13 +261,13 @@ \subsection{Stage 2: implementing type safety in the DSLs} scala> runComplex(prgComplex2) res7: Complex = Complex(x = 2.000000000000001, y = 11.0) \end{lstlisting} -Since \lstinline!Rotate! now requires a \lstinline!PrgComplex[Double]!, -forgetting to use \lstinline!Phase! will cause a type error: +Since \lstinline!Rotate! now requires a \lstinline!Phase!, forgetting +to use \lstinline!Phase! will be a type error: \begin{lstlisting} scala> val prgComplex3 = Rotate(prgComplex1, Val(Complex(0, 1))) :1: type mismatch; found : Val - required: PrgComplex[Double] + required: Phase case Phase(p) => runComplex(p) ^ Compilation Failed @@ -295,17 +294,17 @@ \subsection{Stage 3: implementing bound variables} val result = if (Files.exists(p)) new String(Files.readAllBytes(p)) else "No file." \end{lstlisting} Trying to translate the above code to the \lstinline!PrgFile! DSL, -we find that we need to set the Scala variable \lstinline!p! to the -path computed by a previous operation. Here is a first attempt: +we find that we need to set the variable \lstinline!p! to the path +computed by a previous operation. A first attempt is: \begin{lstlisting} val p: JPath = runFile(Path(Val("config_location.txt"))) val prg: PrgFile[String] = if (Files.exists(p)) Read(p) else Val("No file.") \end{lstlisting} -There are two problems with this code. The first problem is that \lstinline!Read(p)! -does not compile because the argument of \lstinline!Read! should -be a \lstinline!PrgFile[JPath]! rather than just a \lstinline!JPath!. -To solve this problem, we generalize the \lstinline!Val! class to -hold values of arbitrary type: +There are two problems with this code. First, \lstinline!Read(p)! +does not compile: the argument of \lstinline!Read! should be a \lstinline!PrgFile[JPath]! +rather than just a \lstinline!JPath!. To fix this, we add a type +parameter to the \lstinline!Val! case class, now supporting values +of any type: \begin{lstlisting} final case class Val[A](a: A) extends PrgFile[A] \end{lstlisting} @@ -321,8 +320,8 @@ \subsection{Stage 3: implementing bound variables} To solve this problem, we introduce a new DSL operation that binds Scala variables to values returned by other DSL operations. A standard way of creating \index{bound variable}bound variables is by using -those variables as arguments of nameless functions. So, let us consider -the nameless function: +arguments of nameless functions. So, let us consider the following +nameless function: \begin{lstlisting} { p => if (Files.exists(p)) Read(Val(p)) else Val("No file.") } \end{lstlisting} @@ -353,8 +352,8 @@ \subsection{Stage 3: implementing bound variables} final case class Bind[A, B](pa: PrgFile[B])(f: B => PrgFile[A]) extends PrgFile[A] \end{lstlisting} -After adding the \lstinline!Bind!-handling code to the runner, the -implementation of the DSL is: +After adding the \lstinline!Bind!-handling code to the runner, we +get: \begin{lstlisting} sealed trait PrgFile[A] final case class Val[A](a: A) extends PrgFile[A] @@ -382,7 +381,7 @@ \subsection{Stage 3: implementing bound variables} \end{lstlisting} Because the type parameter \lstinline!B! is already fixed, the argument \lstinline!p! may be written without a type annotation (in this case, -it would have been \lstinline!p:JPath!). This makes the DSL easier +it would have been \lstinline!p: JPath!). This makes the DSL easier to use. However, the underlying implementation becomes more complicated. Scala\textsf{'}s pattern matching syntax is limited to the first curried argument. So, the second curried argument of \lstinline!Bind! needs a \lstinline!val! @@ -397,7 +396,7 @@ \subsection{Stage 3: implementing bound variables} to use values computed by other parts. Since a \lstinline!Bind! value contains a \emph{Scala function} (of type \lstinline!B => PrgFile[A]!), that function may run arbitrary Scala code, not limited to DSL operations, -in order to compute a result of type \lstinline!PrgFile[A]!. All +as it computes its result value of type \lstinline!PrgFile[A]!. All non-DSL code is enclosed inside a \lstinline!Bind! and will be evaluated only when the DSL program is run: \begin{lstlisting} @@ -405,7 +404,7 @@ \subsection{Stage 3: implementing bound variables} res8: String = "version = 1" \end{lstlisting} As before, a value of type \lstinline!PrgFile[A]! describes a computation -but does not execute it. +but does not run it. \subsection{Stage 4: refactoring to a monadic DSL} @@ -418,10 +417,10 @@ \subsection{Stage 4: refactoring to a monadic DSL} def flatMap[B](f: A => PrgFile[B]): PrgFile[B] = Bind(this)(f) def map[B](f: A => B): PrgFile[B] = flatMap(f andThen PrgFile.pure) } -final case class Val[A](a: A) extends PrgFile[A] +final case class Val[A](a: A) extends PrgFile[A] final case class Bind[A, B](pa: PrgFile[B])(val f: B => PrgFile[A]) extends PrgFile[A] -final case class Path(p: PrgFile[String]) extends PrgFile[JPath] -final case class Read(p: PrgFile[JPath]) extends PrgFile[String] +final case class Path(p: PrgFile[String]) extends PrgFile[JPath] +final case class Read(p: PrgFile[JPath]) extends PrgFile[String] object PrgFile { def pure[A](a: A): PrgFile[A] = Val(a) @@ -488,13 +487,12 @@ \subsection{Stage 4: refactoring to a monadic DSL} but that argument is a function that in any case cannot be meaningfully printed. -Typically, a monadic DSL program is a nested case class containing -some function that, when called, will return further nested case classes -and functions, etc. All those functions are waiting to be called; -no side effects have been run yet. The actual business logic and side -effects will be executed only when the \lstinline!run! method is -applied. At that time, the entire DSL program will be converted into -a result value. +Typically, a monadic DSL program is a case class containing some functions +that, when called, will return further nested case classes or functions. +All those functions are waiting to be called; no side effects have +been run yet. The actual business logic and side effects will be executed +only when the \lstinline!run! method is applied. After that, we will +get the result value of the entire DSL program. \subsection{Stage 5: refactoring to reuse common code\label{subsec:Stage-5:-refactoring-monadDSL}} @@ -509,13 +507,13 @@ \subsection{Stage 5: refactoring to reuse common code\label{subsec:Stage-5:-refa def pure[A](a: A): PrgComplex[A] = Val(a) } -final case class Val[A](a: A) extends PrgComplex[A] +final case class Val[A](a: A) extends PrgComplex[A] final case class Bind[A, B](pa: PrgComplex[B])(val f: B => PrgComplex[A]) extends PrgComplex[A] -final case class Add(x: Complex, y: Complex) extends PrgComplex[Complex] -final case class Mul(x: Complex, y: Complex) extends PrgComplex[Complex] -final case class Conj(x: Complex) extends PrgComplex[Complex] -final case class Phase(p: Complex) extends PrgComplex[Double] -final case class Rotate(p: Complex, p: Phase) extends PrgComplex[Complex] +final case class Add(x: Complex, y: Complex) extends PrgComplex[Complex] +final case class Mul(x: Complex, y: Complex) extends PrgComplex[Complex] +final case class Conj(x: Complex) extends PrgComplex[Complex] +final case class Phase(p: Complex) extends PrgComplex[Double] +final case class Rotate(p: Complex, p: Phase) extends PrgComplex[Complex] def runComplex[A]: PrgComplex[A] => A = { case Val(a) => a @@ -562,12 +560,12 @@ \subsection{Stage 5: refactoring to reuse common code\label{subsec:Stage-5:-refa // The case classes are changed to: final case class Val[A](a: A) extends PrgFile[A] final case class Bind[A, B](pa: PrgFile[B])(val f: B => PrgFile[A]) extends PrgFile[A] -final case class Op[A](op: PrgFileC[A]) extends PrgFile[A] // Wrap custom operations. +final case class Op[A](op: PrgFileC[A]) extends PrgFile[A] // Custom operation. def runFile[A]: PrgFile[A] => A = { case Val(a) => a case bind@Bind(pa) => runFile(bind.f(runFile(pa))) - case Op(op) => runFileC(op) // Run the custom operation and get the result. + case Op(op) => runFileC(op) // Run a custom operation. } \end{lstlisting} @@ -577,18 +575,18 @@ \subsection{Stage 5: refactoring to reuse common code\label{subsec:Stage-5:-refa // The case classes are changed to: final case class Val[A](a: A) extends PrgComplex[A] final case class Bind[A, B](pa: PrgComplex[B])(val f: B => PrgComplex[A]) extends PrgComplex[A] -final case class Op[A](op: PrgComplexC[A]) extends PrgComplex[A] // Wrap custom operations. +final case class Op[A](op: PrgComplexC[A]) extends PrgComplex[A] // Custom operation. def runComplex[A]: PrgComplex[A] => A = { case Val(a) => a case bind@Bind(pa) => runComplex(bind.f(runComplex(pa))) - case Op(op) => runComplexC(op) // Run the custom operation and get the result. + case Op(op) => runComplexC(op) // Run a custom operation. } sealed trait PrgComplexC[A] -final case class Add(x: Complex, y: Complex) extends PrgComplexC[Complex] -final case class Mul(x: Complex, y: Complex) extends PrgComplexC[Complex] -final case class Conj(x: Complex) extends PrgComplexC[Complex] -final case class Phase(p: Complex) extends PrgComplexC[Double] +final case class Add(x: Complex, y: Complex) extends PrgComplexC[Complex] +final case class Mul(x: Complex, y: Complex) extends PrgComplexC[Complex] +final case class Conj(x: Complex) extends PrgComplexC[Complex] +final case class Phase(p: Complex) extends PrgComplexC[Double] final case class Rotate(p: Complex, alpha: Phase) extends PrgComplexC[Complex] def runComplexC[A]: PrgComplexC[A] => A = { @@ -607,11 +605,11 @@ \subsection{Stage 5: refactoring to reuse common code\label{subsec:Stage-5:-refa The effect constructor and its runner encapsulate the entire domain-specific logic. The code in the classes \lstinline!PrgComplex! and \lstinline!PrgFile! is only concerned with providing the monadic functionality to the -DSL. We can replace those two classes by a single class (called, say, -\lstinline!MonadDSL!) that takes the effect constructor as a \emph{type -parameter} \lstinline!F!. Since the type parameter \lstinline!F! -is itself a type constructor, we must declare it via the Scala syntax -\lstinline!F[_]!. The code is: +DSL. We can replace those two classes by a single class (called \lstinline!MonadDSL!) +that takes the effect constructor as a \emph{type parameter} \lstinline!F!. +Since the type parameter \lstinline!F! is itself a type constructor, +we must declare it via the Scala syntax \lstinline!F[_]!. The code +is: \begin{lstlisting} sealed trait MonadDSL[F[_], A] { def flatMap[B](f: A => MonadDSL[F, B]): MonadDSL[F, B] = Bind(this)(f) @@ -717,10 +715,9 @@ \subsection{Stage 5: refactoring to reuse common code\label{subsec:Stage-5:-refa \subsection{A first recipe for monadic DSLs\label{subsec:A-first-recipe-monadic-dsl}} -The previous section gave motivation for defining the type constructor -\lstinline!MonadDSL[F[_], A]!. That type constructor is called the -\textsf{``}free monad on \lstinline!F!\textsf{''}, for reasons explained later in -this chapter. The full code is: +The previous section motivated defining the type constructor \lstinline!MonadDSL[F[_], A]!. +That type constructor is known as the \textsf{``}free monad on \lstinline!F!\textsf{''}, +for reasons explained later in this chapter. The full code is: \begin{lstlisting} sealed trait MonadDSL[F[_], A] { def flatMap[B](f: A => MonadDSL[F, B]): MonadDSL[F, B] = Bind(this)(f) @@ -795,8 +792,8 @@ \subsection{A first recipe for monadic DSLs\label{subsec:A-first-recipe-monadic- cannot be a functor because it is impossible to create values of type \lstinline!PrgFileC[A]! with an arbitrary type \lstinline!A! (the type \lstinline!A! must be either \lstinline!JPath! or \lstinline!String!). -However, in some cases the effect constructor \lstinline!F! could -be itself a lawful functor. +However, in other cases the effect constructor \lstinline!F! could +be a lawful functor. Next, we implement an \textsf{``}effect runner\textsf{''} \index{effect runner}for \lstinline!F!. An \textbf{effect runner} for an effect constructor @@ -1284,11 +1281,11 @@ \subsection{Comparing the reduced encodings of the free monad} case classes (\lstinline!Pure3!, \lstinline!Suspend!, and \lstinline!FlatMap!). The \lstinline!Return! case class corresponds to \lstinline!Pure3!. Trying to replace \lstinline!Bind! by \lstinline!FlatMap!, we find -that the type of their data are not the same: the first part of \lstinline!Bind! +that the types of their data are not the same: the first part of \lstinline!Bind! has type \lstinline!F[A]! while the first part of \lstinline!FlatMap! has type \lstinline!Free3[F, A]!. We note that \lstinline!Suspend! -converts \lstinline!F[A]! into \lstinline!Free3[F, A]!. So, we write -the code of \lstinline!free2toFree3! like this: +converts \lstinline!F[A]! into \lstinline!Free3[F, A]!. So, the +code of \lstinline!free2toFree3! becomes: \begin{lstlisting} def free2toFree3[F[_], A]: Free2[F, A] => Free3[F, A] = { case Return(a) => Pure3(a) @@ -1297,8 +1294,8 @@ \subsection{Comparing the reduced encodings of the free monad} \end{lstlisting} The inverse conversion function (\lstinline!free3toFree2!) is more -complicated because \lstinline!Suspend! and \lstinline!FlatMap! -are not straightforwardly mapped into \lstinline!Free2!\textsf{'}s case classes. +complicated because the case classes \lstinline!Suspend! and \lstinline!FlatMap! +are not directly mapped into \lstinline!Free2!\textsf{'}s case classes. \begin{lstlisting} def free3toFree2[F[_], A]: Free3[F, A] => Free2[F, A] = { case Pure3(a) => Return(a) diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index 62e2e015c..0fe836a76 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -750,7 +750,13 @@ \subsection{Chapter~\ref{chap:9-Traversable-functors-and}} \subsection{Chapter~\ref{chap:Free-type-constructions}} A \textsf{``}free typeclass\textsf{''} is an advanced design pattern in functional -programming. {*}{*}{*} +programming. The chapter begins by developing the \textsf{``}free monad\textsf{''} +organically by implementing embedded domain-specific languages (DSLs). +We consider two example DSLs: one for computations with complex numbers, +and another for reading files. In the next few sections, we find that +the free monad is a natural result of making a type-safe DSL with +the ability to bind variables to results of previous DSL computations. +{*}{*}{*} \subsection{Chapter~\ref{chap:monad-transformers}} @@ -817,11 +823,11 @@ \subsection{Chapter~\ref{chap:monad-transformers}} $L$, $M$, ...). We define monad transformer for the monad $K\varangle L$ by $(K\varangle L)\varangle M\triangleq K\varangle(L\varangle M)$. -This makes the operation $\varangle$ associative, meaning that we -may write $K\varangle L\varangle M$ without ambiguity. We also motivate +This makes the operation $\varangle$ associative, so that we may +write $K\varangle L\varangle M$ without ambiguity. We also motivate the properties $\text{Id}\varangle M\cong M$ and $M\varangle\text{Id}\cong M$. -Later in this chapter we will rigorously prove those properties for -all known monad transformers. +Later in this chapter we will rigorously prove those and other properties +for all known monad transformers. Building a monad stack in a different order ($K\varangle L$ or $L\varangle K$) will, as a rule, produce inequivalent monads. Table~\ref{tab:Examples-of-monad-stacks} @@ -875,8 +881,8 @@ \subsection{Chapter~\ref{chap:monad-transformers}} of monads, assuming that all the constituent monad transformers are lawful. -The next sections embark on proving the laws for monad transformers -of the individual monads. We begin with the \textsf{``}compositional\textsf{''} transformers +The next sections will prove the laws for monad transformers of the +individual monads. We begin with the \textsf{``}compositional\textsf{''} transformers that work by composing the foreign monad as a functor either inside or outside the base monad. Both kinds of compositional transformers have common properties that we begin to study in Section~\ref{sec:Monad-transformers-that-use-composition}. @@ -947,19 +953,19 @@ \subsection{Chapter~\ref{chap:monad-transformers}} a program and then compose the results. The next sections prove the laws of the monad transformers for the -continuation, search, and codensity monads. Those transformers do -not support base lifts, base runners, or foreign runners; they are -\emph{not} endofunctors in the category of monads. Because of this, -programmers cannot lift effects of different monads into a transformed -monad and cannot run effects in an arbitrary order unless the problematic -monads (continuation, search, codensity, etc.) are in the deepest -position in the monad stack. +continuation monad, the generalized search monad, and the codensity +monad. Those transformers do not support base lifts, base runners, +or foreign runners; they are \emph{not} endofunctors in the category +of monads. Because of this, programmers cannot lift effects of different +monads into a transformed monad and cannot run effects in an arbitrary +order unless the problematic monads (continuation, search, codensity, +etc.) are in the deepest position in the monad stack. The chapter concludes by considering several directions of developing the theory further: \begin{itemize} -\item Show examples of monads that have more than one transformer. As a -rule, one transformer is complete and all others are incomplete. +\item Show some examples of monads that have more than one transformer. +As a rule, one transformer is complete and all others are incomplete. \item Prove some general properties of monad morphisms that are useful for proofs of laws of monad transformers. \item \textsf{``}Rigid\textsf{''} monad transformers are built via \lstinline!swap! functions. diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 55cfe9bd8..529084eb1 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): 6af4509d72f87e855ce25a386cce4eb244289a571f1d0e68d669bf755c50d6b8}\\ -{\scriptsize{}Git commit: 87ea863dca7d7776ef37113e3a3c057657c31411}\\ -{\scriptsize{}PDF file built on Sat, 01 Nov 2025 20:27:44 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 9beb5049a153e91d58a970816df56232a611534075a8216a70d73e78d13699c5}\\ +{\scriptsize{}Git commit: 392d9f456c5d6e154da127be86580690bcc448c4}\\ +{\scriptsize{}PDF file built on Sun, 02 Nov 2025 00:11:57 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From 77ca64d06ce0ccae63b5345b51c9cf4f96d3c1b6 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Sun, 2 Nov 2025 00:21:05 +0100 Subject: [PATCH 23/42] wip formatting --- sofp-src/lyx/sofp-summary.lyx | 5 +++++ sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-free-type.tex | 4 ++-- sofp-src/tex/sofp-summary.tex | 4 +++- sofp-src/tex/sofp.tex | 6 +++--- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 68919013f..fe136cba6 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -5649,6 +5649,11 @@ free monad In the next few sections, we find that the free monad is a natural result of making a type-safe DSL with the ability to bind variables to results of previous DSL computations. +\end_layout + +\begin_layout Standard +We show code implementing the two DSLs via the free monad, and give examples + of running DSL programs. *** \end_layout diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 0ae78f9d332252323888739fc7300dff92bfd1b9..5a55bb433617887c66635846aac5b0142250d6f5 100644 GIT binary patch delta 132 zcmX?Ra?E7ICJ`2MDtvT${_u(WhGH8i%fA*5omwv;pgAr&KL diff --git a/sofp-src/tex/sofp-free-type.tex b/sofp-src/tex/sofp-free-type.tex index 3a61eb00c..71bb6a584 100644 --- a/sofp-src/tex/sofp-free-type.tex +++ b/sofp-src/tex/sofp-free-type.tex @@ -908,8 +908,8 @@ \subsection{A first recipe for monadic DSLs\label{subsec:A-first-recipe-monadic- \end{lstlisting} The resulting code creates fewer nested case classes in memory. -Unlike other laws, the right identity law already holds for any value -\lstinline!p! of type \lstinline!MonadDSL[F, A]!: +The right identity law already holds for any value \lstinline!p! +of type \lstinline!MonadDSL[F, A]!: \begin{lstlisting} p.flatMap(f andThen MonadDSL.pure) == p.map(f) \end{lstlisting} diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index 0fe836a76..76a4b38e0 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -756,7 +756,9 @@ \subsection{Chapter~\ref{chap:Free-type-constructions}} and another for reading files. In the next few sections, we find that the free monad is a natural result of making a type-safe DSL with the ability to bind variables to results of previous DSL computations. -{*}{*}{*} + +We show code implementing the two DSLs via the free monad, and give +examples of running DSL programs. {*}{*}{*} \subsection{Chapter~\ref{chap:monad-transformers}} diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 529084eb1..d801317f1 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): 9beb5049a153e91d58a970816df56232a611534075a8216a70d73e78d13699c5}\\ -{\scriptsize{}Git commit: 392d9f456c5d6e154da127be86580690bcc448c4}\\ -{\scriptsize{}PDF file built on Sun, 02 Nov 2025 00:11:57 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 5497d2973d52ef084408c5b5083a39a23c81509675cf44769c5735b677d36c83}\\ +{\scriptsize{}Git commit: 0172ca486bf15764d1d5b34fe58e56245e544553}\\ +{\scriptsize{}PDF file built on Sun, 02 Nov 2025 00:17:43 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From d48fe5e227a3daf717e2975487c04fda77732232 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Sun, 2 Nov 2025 22:20:30 +0100 Subject: [PATCH 24/42] wip summary of chapter 13 --- sofp-src/lyx/sofp-free-type.lyx | 17 +++-- sofp-src/lyx/sofp-summary.lyx | 101 +++++++++++++++++++++++++++--- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-free-type.tex | 13 ++-- sofp-src/tex/sofp-summary.tex | 33 ++++++++-- sofp-src/tex/sofp.tex | 6 +- 6 files changed, 138 insertions(+), 32 deletions(-) diff --git a/sofp-src/lyx/sofp-free-type.lyx b/sofp-src/lyx/sofp-free-type.lyx index da13afee2..fa2fdf025 100644 --- a/sofp-src/lyx/sofp-free-type.lyx +++ b/sofp-src/lyx/sofp-free-type.lyx @@ -8001,8 +8001,8 @@ abstract class Free1[F[_]: Functor, T] { \begin_layout Plain Layout - case Flatten(p) => Flatten(p.map(g => g.flatMap(f))) // Use F's Functor - instance. + case Flatten(p) => Flatten(p.map(g => g.flatMap(f))) // Use the Functor + instance for F. \end_layout \begin_layout Plain Layout @@ -8167,7 +8167,7 @@ literal "false" \end_inset - where the code for the free monad looked like this: + showing the following code for the free monad: \begin_inset listings inline false status open @@ -8408,8 +8408,7 @@ free monad!encodings \end_inset of the free monad. - The different codes implement the same idea (turning a type constructor - + The different codes implement the same idea: turn a type constructor \begin_inset listings inline true status open @@ -8421,7 +8420,7 @@ F \end_inset - into a monad) in different ways. + formally into a monad by adding some case classes. \end_layout \begin_layout Standard @@ -8430,7 +8429,7 @@ To figure out how to use those codes in practice, a programmer might ask: \end_layout \begin_layout Itemize -Are these encodings equivalent (given that +Are these encodings equivalent (even though \begin_inset listings inline true status open @@ -8442,7 +8441,7 @@ Free2 \end_inset - has 2 case classes and + has 2 case classes while \begin_inset listings inline true status open @@ -8454,7 +8453,7 @@ Free3 \end_inset - has 3)? + has 3)? What are the differences? \end_layout \begin_layout Itemize diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index fe136cba6..c642b5ba3 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -5646,15 +5646,100 @@ free monad organically by implementing embedded domain-specific languages (DSLs). We consider two example DSLs: one for computations with complex numbers, and another for reading files. - In the next few sections, we find that the free monad is a natural result - of making a type-safe DSL with the ability to bind variables to results - of previous DSL computations. + In the next few sections, we evolve the DSLs to make them type-safe and + to add the ability to bind variables to results of previous DSL computations. \end_layout \begin_layout Standard -We show code implementing the two DSLs via the free monad, and give examples - of running DSL programs. - *** +Refactoring the final code for the two DSLs, we divide the code into one + part that implements the custom DSL operations and another part performing + just the monadic functionality. + That second part is what is known as the +\begin_inset Quotes eld +\end_inset + +free monad +\begin_inset Quotes erd +\end_inset + +, meaning it is free from any domain-specific code. + This allows us to formulate a general recipe for creating DSL of this kind + and to write generic code that creates and runs DSL programs. +\end_layout + +\begin_layout Standard +We notice that the DSL type constructor looks like a monad but fails some + of the monad laws. + However, the monad laws hold after we apply a runner to a DSL program; + runners +\begin_inset Quotes eld +\end_inset + +hide +\begin_inset Quotes erd +\end_inset + + law violations. + Because of that, using a law-violating DSL code is not problematic in practice. + Nevertheless, the code of the free monad can be modified so that the monad + laws hold. + We show that this actually simplifies the code as there are fewer case + classes needed. +\end_layout + +\begin_layout Standard +A monadic DSL can be evaluated ( +\begin_inset Quotes eld +\end_inset + +run +\begin_inset Quotes erd +\end_inset + +) into another monad. + It turns out that the corresponding runner is +\begin_inset Quotes eld +\end_inset + +universal +\begin_inset Quotes erd +\end_inset + + in that it works in the same way for any target monad. + We show how to implement a universal runner for monadic DSLs. + The universal runner translates a free monad's +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +pure +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + + operations into the corresponding operations of another monad. +\end_layout + +\begin_layout Standard +***is that the monad laws are not +\end_layout + +\begin_layout Standard +*** \end_layout \begin_layout Subsection @@ -5681,8 +5766,8 @@ This chapter is an in-depth study of monad transformers. \begin_layout Standard To motivate monad transformers, we begin by trying to use two different - monads in a single functor block and we find that the code becomes hard - to work with. + monads in a single functor block; we find that the code becomes hard to + work with. The code can be simplified if we manage to combine two monads into a single larger monad. One way of combining monads is by functor composition, for example as diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 5a55bb433617887c66635846aac5b0142250d6f5..9bb33512779c6db27fac809e838f7628cebda639 100644 GIT binary patch delta 142 zcmX?Ra?E7IIuUjw11l4AE91#qMNHuA43^zX#v7Q)&rBypY5$;jE<(aq7#)Y9D9)Xmh$(A3$&$jsc_)Wrg%+|||2hLDQM+EUU0 DEJY;_ delta 142 zcmX?Ra?E7IIuUjQ11m#wE2GIq*(awgDipkni F(f~KmB~AbU diff --git a/sofp-src/tex/sofp-free-type.tex b/sofp-src/tex/sofp-free-type.tex index 71bb6a584..c2ec14fe8 100644 --- a/sofp-src/tex/sofp-free-type.tex +++ b/sofp-src/tex/sofp-free-type.tex @@ -1040,7 +1040,7 @@ \subsection{Motivation\label{subsec:Motivation-free-monad-different-encodings}} abstract class Free1[F[_]: Functor, T] { def flatMap[A](f: T => Free1[F, A]): Free1[F, A] = this match { case Pure(t) => f(t) - case Flatten(p) => Flatten(p.map(g => g.flatMap(f))) // Use F\textsf{'}s Functor instance. + case Flatten(p) => Flatten(p.map(g => g.flatMap(f))) // Use the Functor instance for F. } } final case class Pure[F[_]: Functor, T](t: T) extends Free1[F, T] @@ -1062,7 +1062,7 @@ \subsection{Motivation\label{subsec:Motivation-free-monad-different-encodings}} \end{lstlisting} In 2016, K.~Robinson\index{Kelley Robinson} gave a talk\footnote{See \texttt{\href{https://www.slideshare.net/KelleyRobinson1/why-the-free-monad-isnt-free-61836547}{https://www.slideshare.net/KelleyRobinson1/why-the-free-monad-isnt-free-61836547}}} -where the code for the free monad looked like this: +showing the following code for the free monad: \begin{lstlisting} sealed trait Free3[F[_], T] { def flatMap[A](f: T => Free3[F, A]): Free3[F, A] = FlatMap(this, f) @@ -1081,14 +1081,15 @@ \subsection{Motivation\label{subsec:Motivation-free-monad-different-encodings}} However, \lstinline!Free1! and \lstinline!Free2! have different data in their case classes and are not obviously equivalent to each other (or to \lstinline!Free3!). We call these implementations \textbf{encodings}\index{free monad!encodings} -of the free monad. The different codes implement the same idea (turning -a type constructor \lstinline!F! into a monad) in different ways. +of the free monad. The different codes implement the same idea: turn +a type constructor \lstinline!F! formally into a monad by adding +some case classes. To figure out how to use those codes in practice, a programmer might ask: \begin{itemize} -\item Are these encodings equivalent (given that \lstinline!Free2! has -2 case classes and \lstinline!Free3! has 3)? +\item Are these encodings equivalent (even though \lstinline!Free2! has +2 case classes while \lstinline!Free3! has 3)? \item Are there any other encodings of the free monad? \item What laws should an encoding satisfy in order to be considered \textsf{``}correct\textsf{''}? \item These encodings convert an arbitrary type constructor \lstinline!F! diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index 76a4b38e0..ecf36bb25 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -753,12 +753,33 @@ \subsection{Chapter~\ref{chap:Free-type-constructions}} programming. The chapter begins by developing the \textsf{``}free monad\textsf{''} organically by implementing embedded domain-specific languages (DSLs). We consider two example DSLs: one for computations with complex numbers, -and another for reading files. In the next few sections, we find that -the free monad is a natural result of making a type-safe DSL with -the ability to bind variables to results of previous DSL computations. - -We show code implementing the two DSLs via the free monad, and give -examples of running DSL programs. {*}{*}{*} +and another for reading files. In the next few sections, we evolve +the DSLs to make them type-safe and to add the ability to bind variables +to results of previous DSL computations. + +Refactoring the final code for the two DSLs, we divide the code into +one part that implements the custom DSL operations and another part +performing just the monadic functionality. That second part is what +is known as the \textsf{``}free monad\textsf{''}, meaning it is free from any domain-specific +code. This allows us to formulate a general recipe for creating DSL +of this kind and to write generic code that creates and runs DSL programs. + +We notice that the DSL type constructor looks like a monad but fails +some of the monad laws. However, the monad laws hold after we apply +a runner to a DSL program; runners \textsf{``}hide\textsf{''} law violations. Because +of that, using a law-violating DSL code is not problematic in practice. +Nevertheless, the code of the free monad can be modified so that the +monad laws hold. We show that this actually simplifies the code as +there are fewer case classes needed. + +A monadic DSL can be evaluated (\textsf{``}run\textsf{''}) into another monad. It +turns out that the corresponding runner is \textsf{``}universal\textsf{''} and works +in the same way for any target monad. We show how to implement a universal +runner for monadic DSLs. + +{*}{*}{*}is that the monad laws are not + +{*}{*}{*} \subsection{Chapter~\ref{chap:monad-transformers}} diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index d801317f1..e2bdf402b 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): 5497d2973d52ef084408c5b5083a39a23c81509675cf44769c5735b677d36c83}\\ -{\scriptsize{}Git commit: 0172ca486bf15764d1d5b34fe58e56245e544553}\\ -{\scriptsize{}PDF file built on Sun, 02 Nov 2025 00:17:43 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): fe6c9fc2c7698b8bc9e0be078b3ea989740c13261b3748ac3753dd8c2952ad59}\\ +{\scriptsize{}Git commit: 77ca64d06ce0ccae63b5345b51c9cf4f96d3c1b6}\\ +{\scriptsize{}PDF file built on Sun, 02 Nov 2025 20:47:52 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From b258200b16b5e287559f520e0dab0d7c5623dd96 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Mon, 3 Nov 2025 08:52:22 +0100 Subject: [PATCH 25/42] fix formatting --- sofp-src/lyx/sofp-free-type.lyx | 14 ++++++-------- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-free-type.tex | 12 ++++++------ sofp-src/tex/sofp-summary.tex | 16 +++++++++------- sofp-src/tex/sofp.tex | 6 +++--- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/sofp-src/lyx/sofp-free-type.lyx b/sofp-src/lyx/sofp-free-type.lyx index fa2fdf025..a2990a745 100644 --- a/sofp-src/lyx/sofp-free-type.lyx +++ b/sofp-src/lyx/sofp-free-type.lyx @@ -8708,7 +8708,7 @@ MonadDSL \end_inset . - The result is a new encoding that we will call + The result is a new encoding called \begin_inset listings inline true status open @@ -8720,7 +8720,7 @@ Free4 \end_inset - (since it uses + (as it uses \begin_inset Formula $4$ \end_inset @@ -8766,8 +8766,7 @@ object Free4 { \begin_layout Plain Layout -final case class Val[F[_], A](a: A) - extends Free4[F, A] +final case class Val[F[_], A](a: A) extends Free4[F, A] \end_layout \begin_layout Plain Layout @@ -8778,14 +8777,13 @@ final case class Bind4[F[_], A, B](pa: Free4[F, B], f: B => Free4[F, A]) \begin_layout Plain Layout -final case class FMap[F[_], A, B](pa: Free4[F, B], f: B => A) - extends Free4[F, A] +final case class FMap[F[_], A, B](pa: Free4[F, B], f: B => A) extends Free4[F, + A] \end_layout \begin_layout Plain Layout -final case class Op[F[_], A](op: F[A]) extends Free4[F, A] // Wrap domain-specif -ic operations. +final case class Op[F[_], A](op: F[A]) extends Free4[F, A] \end_layout \end_inset diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 9bb33512779c6db27fac809e838f7628cebda639..a3c93e95a67728bbf48c8cf89a5f5040ee73c0cb 100644 GIT binary patch delta 152 zcmX?Ra?E7I8WAqz5CaP<6H6-t%gNhB43W7XMV{~)8JZaxB_>(wrWqufZGI%m!NhKC zU}0hjRQ*w08phr%EOCv|$<)!n+}O;~(#_n$+}za2#N6D{!qnWr*wx6=(b&M*(awgD Jipkni(g2_xCmR3& delta 152 zcmX?Ra?E7I8WAp|5F-OC6LTwLlgZme43W7XMV|1Q8e628rCC_$rWu$RZhj=n!NhK4 zWME Free4[F, B]): Free4[F, B] = Bind4(this, f) @@ -1125,10 +1125,10 @@ \subsection{The raw tree encoding\label{subsec:The-raw-tree-encoding-of-the-free object Free4 { def pure[F[_], A](a: A): Free4[F, A] = Val(a) } -final case class Val[F[_], A](a: A) extends Free4[F, A] +final case class Val[F[_], A](a: A) extends Free4[F, A] final case class Bind4[F[_], A, B](pa: Free4[F, B], f: B => Free4[F, A]) extends Free4[F, A] -final case class FMap[F[_], A, B](pa: Free4[F, B], f: B => A) extends Free4[F, A] -final case class Op[F[_], A](op: F[A]) extends Free4[F, A] // Wrap domain-specific operations. +final case class FMap[F[_], A, B](pa: Free4[F, B], f: B => A) extends Free4[F, A] +final case class Op[F[_], A](op: F[A]) extends Free4[F, A] \end{lstlisting} The code of the runners needs to be revised accordingly: \begin{lstlisting} diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index ecf36bb25..a1c229eb9 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -773,9 +773,11 @@ \subsection{Chapter~\ref{chap:Free-type-constructions}} there are fewer case classes needed. A monadic DSL can be evaluated (\textsf{``}run\textsf{''}) into another monad. It -turns out that the corresponding runner is \textsf{``}universal\textsf{''} and works -in the same way for any target monad. We show how to implement a universal -runner for monadic DSLs. +turns out that the corresponding runner is \textsf{``}universal\textsf{''} in that +it works in the same way for any target monad. We show how to implement +a universal runner for monadic DSLs. The universal runner translates +a free monad\textsf{'}s \lstinline!pure! and \lstinline!flatMap! operations +into the corresponding operations of another monad. {*}{*}{*}is that the monad laws are not @@ -786,10 +788,10 @@ \subsection{Chapter~\ref{chap:monad-transformers}} This chapter is an in-depth study of monad transformers. To motivate monad transformers, we begin by trying to use two different -monads in a single functor block and we find that the code becomes -hard to work with. The code can be simplified if we manage to combine -two monads into a single larger monad. One way of combining monads -is by functor composition, for example as \lstinline!Future[Option[A]]!. +monads in a single functor block; we find that the code becomes hard +to work with. The code can be simplified if we manage to combine two +monads into a single larger monad. One way of combining monads is +by functor composition, for example as \lstinline!Future[Option[A]]!. Table~\ref{tab:Correct-and-incorrect-compositions} shows some examples of working and non-working functor composition of monads. In some cases (such as Future and State), functor composition completely fails. diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index e2bdf402b..1ef8ff6bb 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): fe6c9fc2c7698b8bc9e0be078b3ea989740c13261b3748ac3753dd8c2952ad59}\\ -{\scriptsize{}Git commit: 77ca64d06ce0ccae63b5345b51c9cf4f96d3c1b6}\\ -{\scriptsize{}PDF file built on Sun, 02 Nov 2025 20:47:52 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): ff95586388b700c2729ff959c9005cedee970a800041da484408d9dac3aabb8b}\\ +{\scriptsize{}Git commit: d48fe5e227a3daf717e2975487c04fda77732232}\\ +{\scriptsize{}PDF file built on Mon, 03 Nov 2025 08:49:25 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From 87f08a6a88bc88df72e0e096e16c5e99de0be0ef Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Wed, 5 Nov 2025 10:58:29 +0100 Subject: [PATCH 26/42] reduce size of chapter 8 --- sofp-src/lyx/sofp-free-type.lyx | 51 +++++---- sofp-src/lyx/sofp-typeclasses.lyx | 172 ++++++++++++++++++++++-------- sofp-src/lyx/sofp.lyx | 4 +- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-free-type.tex | 40 +++---- sofp-src/tex/sofp-typeclasses.tex | 128 ++++++++++++---------- sofp-src/tex/sofp.tex | 10 +- 7 files changed, 256 insertions(+), 149 deletions(-) diff --git a/sofp-src/lyx/sofp-free-type.lyx b/sofp-src/lyx/sofp-free-type.lyx index a2990a745..334418cbf 100644 --- a/sofp-src/lyx/sofp-free-type.lyx +++ b/sofp-src/lyx/sofp-free-type.lyx @@ -7586,15 +7586,7 @@ F \end_inset . - The word -\begin_inset Quotes eld -\end_inset - -free -\begin_inset Quotes erd -\end_inset - - indicates that + For intuition, one may say that \begin_inset listings inline true status open @@ -7606,8 +7598,16 @@ MonadDSL \end_inset - is free of any domain-specific code. - We may view + is +\begin_inset Quotes eld +\end_inset + +free of +\begin_inset Quotes erd +\end_inset + + any domain-specific code. + The wrapper type \begin_inset listings inline true status open @@ -7619,8 +7619,7 @@ MonadDSL[F, A] \end_inset - as a wrapper that adds the monad's functionality to any type constructor - + adds the functionality of a monad to any type constructor \begin_inset listings inline true status open @@ -7657,7 +7656,11 @@ F \end_inset - as a type parameter, and so it works equally well with every + as a +\emph on +type parameter +\emph default +, and so it works equally well with every \begin_inset listings inline true status open @@ -8532,7 +8535,7 @@ name "subsec:The-raw-tree-encoding-of-the-free-monad" \end_layout \begin_layout Standard -To understand the relationships between the encodings of the free monad, +To understand the relationship between the encodings of the free monad, let us first examine how the code of \begin_inset listings inline true @@ -8619,7 +8622,11 @@ map \end_inset - method is not similar to the code of the two other monadic methods ( + method is +\emph on + +\emph default +not exactly similar to the code of the two other monadic methods ( \begin_inset listings inline true status open @@ -8643,7 +8650,7 @@ flatMap \end_inset -) that merely create new values of the case classes +) that merely wrap their arguments in new case classes ( \begin_inset listings inline true status open @@ -8667,7 +8674,7 @@ Bind \end_inset - without performing any computations. +) without performing any computations. \end_layout \begin_layout Standard @@ -8772,7 +8779,7 @@ final case class Val[F[_], A](a: A) extends Free4[F, A] \begin_layout Plain Layout final case class Bind4[F[_], A, B](pa: Free4[F, B], f: B => Free4[F, A]) - extends Free4[F, A] + extends Free4[F, A] \end_layout \begin_layout Plain Layout @@ -8909,7 +8916,7 @@ pure \end_inset - merely wraps the arguments of each method into a case class without performing + simply wraps the arguments of each method into a case class without performing any computations with those arguments. We call \begin_inset listings @@ -8946,8 +8953,8 @@ raw tree \begin_inset Quotes erd \end_inset - means that a DSL program is a completely unevaluated expression tree that - uses a new nested case class for each step of a computation. + means that a DSL program is a completely unevaluated expression tree where + each DSL operation is represented by a new nested case class. \end_layout \begin_layout Subsection diff --git a/sofp-src/lyx/sofp-typeclasses.lyx b/sofp-src/lyx/sofp-typeclasses.lyx index 93b492f44..83f760442 100644 --- a/sofp-src/lyx/sofp-typeclasses.lyx +++ b/sofp-src/lyx/sofp-typeclasses.lyx @@ -39107,19 +39107,14 @@ Eq \end_layout \begin_layout Paragraph -Summary -\end_layout - -\begin_layout Standard -Object-oriented interfaces and algebraic data types are particular cases - of typeclasses, if we consider only the type signatures of the required - methods. +Inheritance \end_layout \begin_layout Standard -At that level of abstraction, we can also show that the inheritance of typeclass -es corresponds to the object-oriented inheritance of interfaces. - Let us describe inheritance in the language of method signatures. +We have been reasoning about typeclasses and OOIs purely in terms of type + signatures. + At that level of abstraction, the inheritance of typeclasses corresponds + to the object-oriented inheritance of interfaces, as we will now show. \end_layout @@ -39151,8 +39146,7 @@ A typeclass with signature \end_layout \begin_layout Standard -Object-oriented inheritance of interfaces turns out to be exactly of the - same nature. +Object-oriented inheritance of interfaces turns out to be exactly similar. To see that, consider a first OOI with method signature \begin_inset Formula $T\rightarrow U^{T}$ \end_inset @@ -39162,8 +39156,8 @@ Object-oriented inheritance of interfaces turns out to be exactly of the \end_inset . - The first OOI may not change any type signatures that it inherited; it - may only add new methods. + The first OOI may not change any type signatures that it inherits; it may + only add new methods. Recall that the interface declarations \begin_inset Formula $U^{T}$ \end_inset @@ -39190,12 +39184,11 @@ T\rightarrow U^{T}=T\rightarrow V^{T}\times W^{T}\cong(T\rightarrow V^{T})\times \end_inset -We see that inheritance of OOIs involves products of method signatures, - just as inheritance of typeclasses does. +We see that inheritance of OOIs also involves products of method signatures. \end_layout \begin_layout Standard -A similar situation exists when ADTs are extended by new constructors. +Let us now turn to ADTs. Given an ADT with method signature \begin_inset Formula $P^{T}\rightarrow T$ \end_inset @@ -39205,12 +39198,12 @@ A similar situation exists when ADTs are extended by new constructors. \end_inset . - The result is the ADT with method signature + The result is an ADT with method signature \begin_inset Formula $P^{T}+Q^{T}\rightarrow T$ \end_inset -, because adding new constructors corresponds to adding another part of - a disjunctive type. +, because adding new constructors corresponds to adding more parts to a + disjunctive type. Then we use a standard type equivalence: \begin_inset Formula \[ @@ -39226,10 +39219,19 @@ So, the ADTs expressed as typeclasses with signatures have the same inheritance mechanism, based on products of method signatures. \end_layout +\begin_layout Paragraph +Summary +\end_layout + \begin_layout Standard -Keep in mind that this description is only at the level of method types. - There are other important differences in how the Scala compiler works with - typeclasses, OOIs, and ADTs: +Object-oriented interfaces and algebraic data types are particular cases + of typeclasses, if we consider only the type signatures of the required + methods. +\end_layout + +\begin_layout Standard +If we look beyond just method types, there are important differences in + how the Scala compiler works with typeclasses, OOIs, and ADTs: \end_layout \begin_layout Itemize @@ -39287,9 +39289,8 @@ transitive . The compiler will construct an inheritance tree automatically, extending the tree each time a new interface or class is defined. - However, one cannot add or remove inherited interfaces once a class definition - is given. - For example, if it is declared that + However, one cannot add or remove inherited interfaces later in the code. + For example, \begin_inset Formula $A$ \end_inset @@ -39319,22 +39320,27 @@ transitive . Typeclasses are more flexible in this respect: additional evidence values - for typeclass membership can be defined in any scope, not necessarily together - with the declaration of a type. + for typeclass membership can be defined in any scope, not necessarily at + the declaration site. Typeclasses may be implemented via OOIs, which will enable features of inheritance and subtyping. This will make typeclass inheritance behave like object-oriented interface inheritance, with all its benefits and shortcomings. - As we have seen, typeclasses and their inheritance may be implemented with - or without object-oriented inheritance. + As we have seen, typeclasses and their inheritance may be also implemented + without OOIs. \end_layout \begin_layout Itemize -For typeclasses, the compiler provides rich features for automatic computation - of typeclass evidence values via the mechanism of implicit values and implicit - functions. - These features enable automatic typeclass derivation, which works independently - of and in parallel with typeclass inheritance. +For typeclasses, the Scala compiler provides a rich mechanism known as +\begin_inset Quotes eld +\end_inset + +typeclass derivation +\begin_inset Quotes erd +\end_inset + +: an automatic computation of typeclass evidence values, which works independent +ly of typeclass inheritance. The programmer can tell the compiler how to compute (via custom code) a typeclass evidence value for, say, any pair type \begin_inset listings @@ -39373,8 +39379,21 @@ B \end_inset . + Similarly, a custom derivation rule for +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Either[A, B] +\end_layout + +\end_inset + + may be specified. The compiler will use that custom code to determine automatically whether - any given pair type + \begin_inset listings inline true status open @@ -39386,8 +39405,7 @@ status open \end_inset - belongs to the typeclass. - Similarly, a typeclass derivation rule for + or \begin_inset listings inline true status open @@ -39399,9 +39417,7 @@ Either[A, B] \end_inset - could be specified. - The compiler will compute and use the new typeclass evidence values automatical -ly for + belongs to the typeclass, for \emph on all \emph default @@ -39443,7 +39459,7 @@ status open \end_inset - to all case classes, and from the disjunctive type + to all case classes, and from \begin_inset listings inline true status open @@ -39524,6 +39540,78 @@ noprefix "false" . \end_layout +\begin_layout Standard +How to decide whether to use typeclasses, ADTs, or OOIs in practice? One + approach is to look at the type signatures of functions that one needs + to use in a given problem domain. + If one most often needs to construct new domain values, most type signatures + will be of the form +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Something => T +\end_layout + +\end_inset + +, where +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +T +\end_layout + +\end_inset + + is the type of a domain entity. + This is of the general form +\begin_inset Formula $P^{T}\rightarrow T$ +\end_inset + + and is modeled well by ADTs. + If one most often needs to work with existing domain entities, type signatures + will be of the form +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +T => Something +\end_layout + +\end_inset + +. + This is of the general form +\begin_inset Formula $T\rightarrow P^{T}$ +\end_inset + + and is modeled well by OOIs. + +\end_layout + +\begin_layout Standard +So, the decision of whether to use ADTs or OOIs depends on the prevalence + of method signatures of the form +\begin_inset Formula $P^{T}\rightarrow T$ +\end_inset + + or +\begin_inset Formula $T\rightarrow P^{T}$ +\end_inset + + in the problem domain. + Typeclasses support method signatures of either form and can be used to + implement both ADTs and OOIs, overcoming their limitations. +\end_layout + \begin_layout Standard \begin_inset Note Comment status collapsed diff --git a/sofp-src/lyx/sofp.lyx b/sofp-src/lyx/sofp.lyx index b6370a52a..b41fd1f48 100644 --- a/sofp-src/lyx/sofp.lyx +++ b/sofp-src/lyx/sofp.lyx @@ -370,7 +370,7 @@ literal "false" \series default - in 2024 + in 2025 \end_layout \begin_layout Uppertitleback @@ -391,7 +391,7 @@ copyright \end_inset - 2018-2024 by Sergei Winitzki + 2018-2025 by Sergei Winitzki \begin_inset Newline newline \end_inset diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index a3c93e95a67728bbf48c8cf89a5f5040ee73c0cb..7c346d4fd105a7b14f1f9e0625dace6283266f4f 100644 GIT binary patch delta 152 zcmX?Ra?E7I8WAqj5JLkiQ!^_=i^(wrWqufZGI%m!NhKC zU}0hjRQ*w08phr%EOCv|$<)!n+}O;~(#_n$+}za2#N6D{!qnWr*wx6=(b&M*(awgD Jipkni(g2_xCmR3& diff --git a/sofp-src/tex/sofp-free-type.tex b/sofp-src/tex/sofp-free-type.tex index 0e980d6e0..e51d7cebe 100644 --- a/sofp-src/tex/sofp-free-type.tex +++ b/sofp-src/tex/sofp-free-type.tex @@ -1002,13 +1002,13 @@ \section{Different encodings of the free monad} \subsection{Motivation\label{subsec:Motivation-free-monad-different-encodings}} The type \lstinline!MonadDSL[F, A]! is called a \textbf{free monad} -on\index{free monad} the type constructor \lstinline!F!. The word -\textsf{``}free\textsf{''} indicates that \lstinline!MonadDSL! is free of any domain-specific -code. We may view \lstinline!MonadDSL[F, A]! as a wrapper that adds -the monad\textsf{'}s functionality to any type constructor \lstinline!F! and -creates a new monadic DSL based on \lstinline!F!\textsf{'}s operations. The -construction uses \lstinline!F! as a type parameter, and so it works -equally well with every \lstinline!F!. +on\index{free monad} the type constructor \lstinline!F!. For intuition, +one may say that \lstinline!MonadDSL! is \textsf{``}free of\textsf{''} any domain-specific +code. The wrapper type \lstinline!MonadDSL[F, A]! adds the functionality +of a monad to any type constructor \lstinline!F! and creates a new +monadic DSL based on \lstinline!F!\textsf{'}s operations. The construction +uses \lstinline!F! as a \emph{type parameter}, and so it works equally +well with every \lstinline!F!. A monad must support the methods \lstinline!pure!, \lstinline!flatMap!, and \lstinline!map!. The effect constructor \lstinline!F! will not @@ -1103,15 +1103,15 @@ \subsection{Motivation\label{subsec:Motivation-free-monad-different-encodings}} \subsection{The raw tree encoding\label{subsec:The-raw-tree-encoding-of-the-free-monad}} -To understand the relationships between the encodings of the free -monad, let us first examine how the code of \lstinline!MonadDSL! -(or equivalently \lstinline!Free3!) implements the \lstinline!map! -method. In \lstinline!MonadDSL!, we implemented \lstinline!map! -through \lstinline!flatMap!. As a result, our code for the \lstinline!map! -method is not similar to the code of the two other monadic methods -(\lstinline!pure! and \lstinline!flatMap!) that merely create new -values of the case classes \lstinline!Val! and \lstinline!Bind! -without performing any computations. +To understand the relationship between the encodings of the free monad, +let us first examine how the code of \lstinline!MonadDSL! (or equivalently +\lstinline!Free3!) implements the \lstinline!map! method. In \lstinline!MonadDSL!, +we implemented \lstinline!map! through \lstinline!flatMap!. As a +result, our code for the \lstinline!map! method is\emph{ }not exactly +similar to the code of the two other monadic methods (\lstinline!pure! +and \lstinline!flatMap!) that merely wrap their arguments in new +case classes (\lstinline!Val! and \lstinline!Bind!) without performing +any computations. We could implement \lstinline!map! in a similar way if we added a new case class, say \lstinline!FMap!, to \lstinline!MonadDSL!. The @@ -1126,7 +1126,7 @@ \subsection{The raw tree encoding\label{subsec:The-raw-tree-encoding-of-the-free def pure[F[_], A](a: A): Free4[F, A] = Val(a) } final case class Val[F[_], A](a: A) extends Free4[F, A] -final case class Bind4[F[_], A, B](pa: Free4[F, B], f: B => Free4[F, A]) extends Free4[F, A] +final case class Bind4[F[_], A, B](pa: Free4[F, B], f: B => Free4[F, A]) extends Free4[F, A] final case class FMap[F[_], A, B](pa: Free4[F, B], f: B => A) extends Free4[F, A] final case class Op[F[_], A](op: F[A]) extends Free4[F, A] \end{lstlisting} @@ -1147,12 +1147,12 @@ \subsection{The raw tree encoding\label{subsec:The-raw-tree-encoding-of-the-free \end{lstlisting} The code of \lstinline!Free4!\textsf{'}s methods \lstinline!map!, \lstinline!flatMap!, -and \lstinline!pure! merely wraps the arguments of each method into +and \lstinline!pure! simply wraps the arguments of each method into a case class without performing any computations with those arguments. We call \lstinline!Free4! the \textbf{raw tree encoding}\index{free monad!raw tree encoding} of the free monad. The name \textsf{``}raw tree\textsf{''} means that a DSL program -is a completely unevaluated expression tree that uses a new nested -case class for each step of a computation. +is a completely unevaluated expression tree where each DSL operation +is represented by a new nested case class. \subsection{Comparing the reduced encodings of the free monad} diff --git a/sofp-src/tex/sofp-typeclasses.tex b/sofp-src/tex/sofp-typeclasses.tex index 99ee27d4d..6eb6d5649 100644 --- a/sofp-src/tex/sofp-typeclasses.tex +++ b/sofp-src/tex/sofp-typeclasses.tex @@ -6051,15 +6051,12 @@ \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} which is not equivalent to $P^{T}\rightarrow T$ with any definition of $P$. -\paragraph{Summary} - -Object-oriented interfaces and algebraic data types are particular -cases of typeclasses, if we consider only the type signatures of the -required methods. +\paragraph{Inheritance} -At that level of abstraction, we can also show that the inheritance -of typeclasses corresponds to the object-oriented inheritance of interfaces. -Let us describe inheritance in the language of method signatures. +We have been reasoning about typeclasses and OOIs purely in terms +of type signatures. At that level of abstraction, the inheritance +of typeclasses corresponds to the object-oriented inheritance of interfaces, +as we will now show. A typeclass with signature $\text{Sig}_{1}$ inherits from a typeclass with signature $\text{Sig}_{2}$ if $\text{Sig}_{1}^{T}=\text{Sig}_{2}^{T}\times Q^{T}$ @@ -6068,35 +6065,38 @@ \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} to taking products of method signatures. Object-oriented inheritance of interfaces turns out to be exactly -of the same nature. To see that, consider a first OOI with method -signature $T\rightarrow U^{T}$ that inherits from a second OOI with -method signature $T\rightarrow V^{T}$. The first OOI may not change -any type signatures that it inherited; it may only add new methods. -Recall that the interface declarations $U^{T}$ and $V^{T}$ involve -type signatures without the hidden first argument. If we denote by -$W^{T}$ the type signatures added by the first OOI then it follows -that $U^{T}=V^{T}\times W^{T}$. So, we find: +similar. To see that, consider a first OOI with method signature $T\rightarrow U^{T}$ +that inherits from a second OOI with method signature $T\rightarrow V^{T}$. +The first OOI may not change any type signatures that it inherits; +it may only add new methods. Recall that the interface declarations +$U^{T}$ and $V^{T}$ involve type signatures without the hidden first +argument. If we denote by $W^{T}$ the type signatures added by the +first OOI then it follows that $U^{T}=V^{T}\times W^{T}$. So, we +find: \[ T\rightarrow U^{T}=T\rightarrow V^{T}\times W^{T}\cong(T\rightarrow V^{T})\times(T\rightarrow W^{T})\quad. \] -We see that inheritance of OOIs involves products of method signatures, -just as inheritance of typeclasses does. +We see that inheritance of OOIs also involves products of method signatures. -A similar situation exists when ADTs are extended by new constructors. -Given an ADT with method signature $P^{T}\rightarrow T$, we may add -new constructors with combined type signatures $Q^{T}\rightarrow T$. -The result is the ADT with method signature $P^{T}+Q^{T}\rightarrow T$, -because adding new constructors corresponds to adding another part -of a disjunctive type. Then we use a standard type equivalence: +Let us now turn to ADTs. Given an ADT with method signature $P^{T}\rightarrow T$, +we may add new constructors with combined type signatures $Q^{T}\rightarrow T$. +The result is an ADT with method signature $P^{T}+Q^{T}\rightarrow T$, +because adding new constructors corresponds to adding more parts to +a disjunctive type. Then we use a standard type equivalence: \[ P^{T}+Q^{T}\rightarrow T\cong(P^{T}\rightarrow T)\times(Q^{T}\rightarrow T)\quad. \] So, the ADTs expressed as typeclasses with signatures $P^{T}\rightarrow T$ have the same inheritance mechanism, based on products of method signatures. -Keep in mind that this description is only at the level of method -types. There are other important differences in how the Scala compiler -works with typeclasses, OOIs, and ADTs: +\paragraph{Summary} + +Object-oriented interfaces and algebraic data types are particular +cases of typeclasses, if we consider only the type signatures of the +required methods. + +If we look beyond just method types, there are important differences +in how the Scala compiler works with typeclasses, OOIs, and ADTs: \begin{itemize} \item For OOIs, the compiler provides automatic subtyping for interfaces via the object-oriented inheritance mechanism. If a class (or an interface) @@ -6107,39 +6107,34 @@ \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} $C$ and to be a subtype of $C$. The compiler will construct an inheritance tree automatically, extending the tree each time a new interface or class is defined. However, one cannot add or remove inherited interfaces -once a class definition is given. For example, if it is declared that -$A$ inherits from $B$ (this must be declared together with the definition -of $A$) then the programmer cannot declare in another scope that -$A$ should inherit additionally from some other interface $C$; or -that $A$ should no longer inherit from $B$. Typeclasses are more -flexible in this respect: additional evidence values for typeclass -membership can be defined in any scope, not necessarily together with -the declaration of a type. Typeclasses may be implemented via OOIs, -which will enable features of inheritance and subtyping. This will -make typeclass inheritance behave like object-oriented interface inheritance, -with all its benefits and shortcomings. As we have seen, typeclasses -and their inheritance may be implemented with or without object-oriented -inheritance. -\item For typeclasses, the compiler provides rich features for automatic -computation of typeclass evidence values via the mechanism of implicit -values and implicit functions. These features enable automatic typeclass -derivation, which works independently of and in parallel with typeclass -inheritance. The programmer can tell the compiler how to compute (via -custom code) a typeclass evidence value for, say, any pair type \lstinline!(A, B)! -from evidence values for \lstinline!A! and \lstinline!B!. The compiler -will use that custom code to determine automatically whether any given -pair type \lstinline!(A, B)! belongs to the typeclass. Similarly, -a typeclass derivation rule for \lstinline!Either[A, B]! could be -specified. The compiler will compute and use the new typeclass evidence -values automatically for \emph{all} suitable types \lstinline!A!, +later in the code. For example, $A$ inherits from $B$ (this must +be declared together with the definition of $A$) then the programmer +cannot declare in another scope that $A$ should inherit additionally +from some other interface $C$; or that $A$ should no longer inherit +from $B$. Typeclasses are more flexible in this respect: additional +evidence values for typeclass membership can be defined in any scope, +not necessarily at the declaration site. Typeclasses may be implemented +via OOIs, which will enable features of inheritance and subtyping. +This will make typeclass inheritance behave like object-oriented interface +inheritance, with all its benefits and shortcomings. As we have seen, +typeclasses and their inheritance may be also implemented without +OOIs. +\item For typeclasses, the Scala compiler provides rich features for automatic +computation of typeclass evidence values, which works independently +of typeclass inheritance. The programmer can tell the compiler how +to compute (via custom code) a typeclass evidence value for, say, +any pair type \lstinline!(A, B)! from evidence values for \lstinline!A! +and \lstinline!B!. Similarly, a custom derivation rule for \lstinline!Either[A, B]! +may be specified. The compiler will use that custom code to determine +automatically whether \lstinline!(A, B)! or \lstinline!Either[A, B]! +belongs to the typeclass, for \emph{all} suitable types \lstinline!A!, \lstinline!B!. Certain advanced features of Scala (beyond the scope of this book) allow programmers to extend typeclass derivation from -pairs \lstinline!(A, B)! to all case classes, and from the disjunctive -type \lstinline!Either[A, B]! to all disjunctive types. In this way, -typeclass membership can be provided automatically by the compiler -(with no boilerplate code) for a wide range of user-defined types. -But there are no comparable facilities for object-oriented \textsf{``}interface -derivation\textsf{''}. +pairs \lstinline!(A, B)! to all case classes, and from \lstinline!Either[A, B]! +to all disjunctive types. In this way, typeclass membership can be +provided automatically by the compiler (with no boilerplate code) +for a wide range of user-defined types. But there are no comparable +facilities for object-oriented \textsf{``}interface derivation\textsf{''}. \item The compilers of Scala and other functional languages treat ADTs and typeclasses in rather different ways. An ADT is not just an arbitrary type $T$ that happens to support functions of type $P^{T}\rightarrow T$. @@ -6150,6 +6145,23 @@ \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} $P$. Rigorous definitions and the necessary theory will be developed in Chapter~\ref{chap:Free-type-constructions}. \end{itemize} +How to decide whether to use typeclasses, ADTs, or OOIs in practice? +One approach is to look at the type signatures of functions that one +needs to use in a given problem domain. If one most often needs to +construct new domain values, most type signatures will be of the form +\lstinline!Something => T!, where \lstinline!T! is the type of a +domain entity. This is of the general form $P^{T}\rightarrow T$ and +is modeled well by ADTs. If one most often needs to work with existing +domain entities, type signatures will be of the form \lstinline!T => Something!. +This is of the general form $T\rightarrow P^{T}$ and is modeled well +by OOIs. + +So, the decision of whether to use ADTs or OOIs depends on the prevalence +of method signatures of the form $P^{T}\rightarrow T$ or $T\rightarrow P^{T}$ +in the problem domain. Typeclasses support method signatures of either +form and can be used to implement both ADTs and OOIs, overcoming their +limitations. + \begin{comment} this tutorial is about typeclasses and type level functions to motivate why we want to talk about this let\textsf{'}s consider what happens if we would diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 1ef8ff6bb..12d7b6ab8 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -329,17 +329,17 @@ \subtitle{A tutorial, with examples in Scala} \author{by Sergei Winitzki, Ph.D.} \date{Version of \today} -\publishers{Published by\textbf{ \href{http://lulu.com}{lulu.com}} in 2024} -\uppertitleback{{\footnotesize{}Copyright \copyright\ 2018-2024 by Sergei Winitzki}\\ +\publishers{Published by\textbf{ \href{http://lulu.com}{lulu.com}} in 2025} +\uppertitleback{{\footnotesize{}Copyright \copyright\ 2018-2025 by Sergei Winitzki}\\ {\footnotesize{}~}\\ {\footnotesize{}\href{https://www.lulu.com/en/us/shop/sergei-winitzki/the-science-of-functional-programming-draft-version/paperback/product-1y5zzgje.html}{Print on demand at lulu.com}}\\ {\footnotesize{}~}\\ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): ff95586388b700c2729ff959c9005cedee970a800041da484408d9dac3aabb8b}\\ -{\scriptsize{}Git commit: d48fe5e227a3daf717e2975487c04fda77732232}\\ -{\scriptsize{}PDF file built on Mon, 03 Nov 2025 08:49:25 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 80a0ccc3085808b2bdaa5a4e539632546a6639c269cffb0a8f86c80e039adba3}\\ +{\scriptsize{}Git commit: b258200b16b5e287559f520e0dab0d7c5623dd96}\\ +{\scriptsize{}PDF file built on Wed, 05 Nov 2025 10:56:37 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From e4fa596881b72f64e35039534650cb886475185d Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Wed, 5 Nov 2025 21:38:13 +0100 Subject: [PATCH 27/42] wip --- sofp-src/lyx/sofp-free-type.lyx | 144 +++++++++++++----- sofp-src/lyx/sofp-summary.lyx | 243 +++++++++++++++++++++++++++++- sofp-src/lyx/sofp-typeclasses.lyx | 2 +- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-free-type.tex | 67 ++++---- sofp-src/tex/sofp-summary.tex | 32 +++- sofp-src/tex/sofp-typeclasses.tex | 35 ++--- sofp-src/tex/sofp.tex | 6 +- 8 files changed, 439 insertions(+), 90 deletions(-) diff --git a/sofp-src/lyx/sofp-free-type.lyx b/sofp-src/lyx/sofp-free-type.lyx index 334418cbf..bb75bfc68 100644 --- a/sofp-src/lyx/sofp-free-type.lyx +++ b/sofp-src/lyx/sofp-free-type.lyx @@ -7533,6 +7533,13 @@ The use of universal runners (with an arbitrary monad \begin_layout Section Different encodings of the free monad +\begin_inset CommandInset label +LatexCommand label +name "sec:Different-encodings-of-free-monad" + +\end_inset + + \end_layout \begin_layout Subsection @@ -11136,6 +11143,13 @@ We will find later in this chapter that a similar situation occurs in many \begin_layout Subsection Types with existential quantifiers +\begin_inset CommandInset label +LatexCommand label +name "subsec:Types-with-existential-quantifiers" + +\end_inset + + \end_layout \begin_layout Standard @@ -13065,9 +13079,9 @@ We will use the existential quantifier notation for reasoning about properties are written as: \begin_inset Formula \begin{align*} -\text{free monad on }F\text{ in a reduced encoding}:\quad & \text{Free}_{2}^{F,T}\triangleq T+\exists A.\,F^{A}\times(A\rightarrow\text{Free}_{2}^{F,T})\quad,\\ -\text{free monad on }F\text{ in a reduced encoding}:\quad & \text{Free}_{3}^{F,T}\triangleq T+F^{T}+\exists A.\,\text{Free}_{3}^{F,A}\times(A\rightarrow\text{Free}_{3}^{F,T})\quad,\\ -\text{free monad on }F\text{ in a raw tree encoding}:\quad & \text{Free}_{4}^{F,A}\triangleq A+F^{A}+\exists B.\,\text{Free}_{4}^{F,B}\times(B\rightarrow A)\\ +\text{reduced encoding, 2 case classes}:\quad & \text{Free}_{2}^{F,T}\triangleq T+\exists A.\,F^{A}\times(A\rightarrow\text{Free}_{2}^{F,T})\quad,\\ +\text{reduced encoding, 3 case classes}:\quad & \text{Free}_{3}^{F,T}\triangleq T+F^{T}+\exists A.\,\text{Free}_{3}^{F,A}\times(A\rightarrow\text{Free}_{3}^{F,T})\quad,\\ +\text{raw tree encoding}:\quad & \text{Free}_{4}^{F,A}\triangleq A+F^{A}+\exists B.\,\text{Free}_{4}^{F,B}\times(B\rightarrow A)\\ & \quad\quad+\exists B.\,\text{Free}_{4}^{F,B}\times(B\rightarrow\text{Free}_{4}^{F,A})\quad. \end{align*} @@ -13164,9 +13178,10 @@ toInt is written in the type notation as: \begin_inset Formula -\[ -\text{toInt}:\left(\exists C.\,\text{Int}\times C\times(C\rightarrow\text{Int})\right)\rightarrow\text{Int}\quad,\quad\quad\text{toInt}\triangleq(\exists C.\,a^{:\text{Int}}\times c^{:C}\times p^{:C\rightarrow\text{Int}})\rightarrow a+p(c)\quad. -\] +\begin{align*} + & \text{toInt}:\left(\exists C.\,\text{Int}\times C\times(C\rightarrow\text{Int})\right)\rightarrow\text{Int}\quad,\\ + & \text{toInt}\triangleq(\exists C.\,a^{:\text{Int}}\times c^{:C}\times p^{:C\rightarrow\text{Int}})\rightarrow a+p(c)\quad. +\end{align*} \end_inset @@ -14192,7 +14207,7 @@ covariant co-Yoneda identity \begin_inset Quotes erd \end_inset - (Statement + (which we will prove as Statement \begin_inset space ~ \end_inset @@ -14273,7 +14288,7 @@ Free1 \begin_inset Formula $F$ \end_inset - is a functor) is equivalent to + is a functor) is equivalent at the level of types to \begin_inset listings inline true status open @@ -14285,8 +14300,8 @@ Free2 \end_inset - as type constructors. - (Recall that the equivalence of +. + Recall that the equivalence of \begin_inset listings inline true status open @@ -14363,7 +14378,7 @@ Free4 \emph on not \emph default - equivalent as type constructors.) + equivalent as type constructors. \end_layout \begin_layout Section @@ -15486,7 +15501,7 @@ noprefix "false" , we get the type equivalence: \begin_inset Formula \begin{align*} - & \forall F^{\bullet}.\,\forall A.\,(\forall T.\,F^{T}\rightarrow M^{T})\rightarrow\text{Free}_{4}^{F,A}\rightarrow M^{A}\\ + & \forall F.\,\forall A.\,(\forall T.\,F^{T}\rightarrow M^{T})\rightarrow\text{Free}_{4}^{F,A}\rightarrow M^{A}\\ & \quad\quad\cong\forall A.\,\text{Free}_{4}^{M,A}\rightarrow M^{A}\quad. \end{align*} @@ -15813,7 +15828,7 @@ not \begin_inset Formula $\text{Free}_{4}^{F,A}$ \end_inset - fails to obey the monad laws.) + violates the monad laws.) \end_layout \begin_layout Standard @@ -16128,8 +16143,8 @@ Free4 \end_layout \begin_layout Standard -It turns out that the monad morphism laws of the runner and the free evaluator - have far-reaching consequences for the theory of typeclasses with laws. +It turns out that the laws of the runner and the free evaluator have far-reachin +g consequences for the theory of typeclasses with laws. For now, let us list the properties that are relevant for practical programming with free monads: \end_layout @@ -16977,8 +16992,7 @@ We can now generalize the properties 1–4 to an arbitrary typeclass. \begin_inset Formula $T$ \end_inset - be a type that does not belong to the typeclass, and denote the free typeclass - instance constructed on + be any type and denote a free typeclass instance constructed on \begin_inset Formula $T$ \end_inset @@ -16986,9 +17000,8 @@ We can now generalize the properties 1–4 to an arbitrary typeclass. \begin_inset Formula $\text{Free}^{T}$ \end_inset -. - We will formulate the expected properties in terms of the free evaluator - ( + (in any encoding). + We formulate the expected properties in terms of the free evaluator ( \begin_inset listings inline true status open @@ -17003,6 +17016,48 @@ eval ) as its type signature is simpler than that of the universal runner: \end_layout +\begin_layout Enumerate +The type +\begin_inset Formula $\text{Free}^{T}$ +\end_inset + + is covariant with respect to +\begin_inset Formula $T$ +\end_inset + +. + For any +\begin_inset Formula $T$ +\end_inset + +, the type +\begin_inset Formula $\text{Free}^{T}$ +\end_inset + + supports the typeclass operations (but may violate some typeclass laws). + For any +\begin_inset Formula $T$ +\end_inset + +, +\begin_inset Formula $U$ +\end_inset + + and any +\begin_inset Formula $f:T\rightarrow U$ +\end_inset + +, the function +\begin_inset Formula $f^{\uparrow\text{Free}}$ +\end_inset + + of type +\begin_inset Formula $\text{Free}^{T}\rightarrow\text{Free}^{U}$ +\end_inset + + will preserve the typeclass operations. +\end_layout + \begin_layout Enumerate For a given type \begin_inset Formula $M$ @@ -17052,31 +17107,36 @@ only \end_layout \begin_layout Enumerate -The constructor -\begin_inset Formula $\text{Free}^{T}$ -\end_inset +The universal runner is defined through +\begin_inset listings +inline true +status open - is covariant with respect to -\begin_inset Formula $T$ -\end_inset +\begin_layout Plain Layout + +eval +\end_layout -: For any two types constructors -\begin_inset Formula $T$ \end_inset - and -\begin_inset Formula $U$ + as: +\begin_inset Formula +\begin{align*} + & \text{run}:(T\rightarrow M)\rightarrow\text{Free}^{T}\rightarrow M\quad,\\ + & \text{run}\,(f^{:T\rightarrow M})\triangleq f^{\uparrow\text{Free}}\bef\text{eval}\quad. +\end{align*} + \end_inset - and a map -\begin_inset Formula $f:T\rightarrow U$ +For any +\begin_inset Formula $f$ \end_inset - between them, there is a unique function of type -\begin_inset Formula $\text{Free}^{T}\rightarrow\text{Free}^{U}$ +, the function +\begin_inset Formula $\text{run}\left(f\right)$ \end_inset - that preserves the typeclass operations. + preserves the typeclass operations. \end_layout \begin_layout Enumerate @@ -17122,6 +17182,13 @@ noprefix "false" \begin_layout Subsection Free pointed type +\begin_inset CommandInset label +LatexCommand label +name "subsec:Free-pointed-type" + +\end_inset + + \end_layout \begin_layout Standard @@ -17320,7 +17387,7 @@ Option[T] \end_inset -, so we will define it that way: +, so we may write a simpler definition like this: \begin_inset listings inline false status open @@ -17380,6 +17447,11 @@ free pointed type \end_inset . + +\begin_inset Formula $\square$ +\end_inset + + \end_layout \begin_layout Standard diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index c642b5ba3..1dccc8083 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -5705,7 +5705,7 @@ universal \begin_inset Quotes erd \end_inset - in that it works in the same way for any target monad. + in that it works in the same way for all target monads. We show how to implement a universal runner for monadic DSLs. The universal runner translates a free monad's \begin_inset listings @@ -5735,7 +5735,246 @@ flatMap \end_layout \begin_layout Standard -***is that the monad laws are not +Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "sec:Different-encodings-of-free-monad" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + introduces the notion of an +\begin_inset Quotes eld +\end_inset + +encoding +\begin_inset Quotes erd +\end_inset + + of the free monad. + In Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Motivation-free-monad-different-encodings" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +, we show that there have been different versions of +\begin_inset Quotes eld +\end_inset + +free monad +\begin_inset Quotes erd +\end_inset + + presented in different sources. + Are these versions all correct, are they equivalent, or is one version + of a monadic DSL better than another? To resolve these questions, we look + at four different implementations ( +\begin_inset Quotes eld +\end_inset + +encodings +\begin_inset Quotes erd +\end_inset + +) of a free monad and find out if they could be mapped to each other. + One of the encodings ( +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Free4 +\end_layout + +\end_inset + +) obeys +\emph on +none +\emph default + of the monad laws while other encodings are smaller and do obey some of + the laws. + We show how one can derive a smaller ( +\begin_inset Quotes eld +\end_inset + +reduced +\begin_inset Quotes erd +\end_inset + +) encoding from a larger one by imposing one of the monad laws. + We also show that smaller encodings have injective maps to larger ones. +\end_layout + +\begin_layout Standard +We take a digression to introduce the notion of existential type quantifiers + (Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Types-with-existential-quantifiers" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). + This is necessary in order to describe in a formal way the kinds of types + that free monad encodings require. + We show how existentially quantified types can be expressed through universal + quantifiers in Equations +\begin_inset space ~ +\end_inset + +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:existential-via-universal" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +) and +\begin_inset space ~ +\end_inset + +( +\begin_inset CommandInset ref +LatexCommand ref +reference "eq:existential-via-universal-Yoneda" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). + Finally, we show that the +\begin_inset Quotes eld +\end_inset + +smallest +\begin_inset Quotes erd +\end_inset + + free monad encoding ( +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Free1 +\end_layout + +\end_inset + +) is equivalent to +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Free2 +\end_layout + +\end_inset + + when +\begin_inset Formula $F$ +\end_inset + + is a functor. +\end_layout + +\begin_layout Standard +We now turn to free constructions for other typeclasses. + Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "sec:Expected-properties-of-free-typeclass" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + examines the properties of the free monad construction and generalizes + those properties to other typeclasses. + We introduce an important notion of a function that +\begin_inset Quotes eld +\end_inset + +preserves the typeclass operations +\begin_inset Quotes erd +\end_inset + +. + It is due to this property that a runner function removes monad law violations + in a free monad. + +\end_layout + +\begin_layout Standard +With this motivation, we formulate laws that we expect to hold for other + free typeclass constructions. +\end_layout + +\begin_layout Standard +The first example of a free typeclass is +\begin_inset Quotes eld +\end_inset + +free pointed type +\begin_inset Quotes erd +\end_inset + + (Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Free-pointed-type" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). +\end_layout + +\begin_layout Standard +*** \end_layout \begin_layout Standard diff --git a/sofp-src/lyx/sofp-typeclasses.lyx b/sofp-src/lyx/sofp-typeclasses.lyx index 83f760442..1e01240c4 100644 --- a/sofp-src/lyx/sofp-typeclasses.lyx +++ b/sofp-src/lyx/sofp-typeclasses.lyx @@ -39325,7 +39325,7 @@ transitive Typeclasses may be implemented via OOIs, which will enable features of inheritance and subtyping. This will make typeclass inheritance behave like object-oriented interface - inheritance, with all its benefits and shortcomings. + inheritance with all its benefits and shortcomings. As we have seen, typeclasses and their inheritance may be also implemented without OOIs. \end_layout diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 7c346d4fd105a7b14f1f9e0625dace6283266f4f..bd989331d853ce047a738ab3bc342ae2a098762b 100644 GIT binary patch delta 146 zcmX?Ra?E7IIuQ;dLn{LVD66IuKGcq(V z04n_`E(2w57M8fi=wx7MVdi9RZffRgWMbrGY-;XeU}Wj$YGLGLVs7DN=wfF>NX2Ar GDQN(_WhK-A delta 146 zcmX?Ra?E7IIuQ;-11nQAD?^LP+eC~JoR1<;c#SR1jgrhvOm)+YOcFOg66IuKGc+(Y z11kL}E(2w57M8fi=;Z3+=4fbcVBqX(Y3yiVV&-gMWMN`zYU%1|?&RuZX=!IeNX2Ar GDQN()B_;j< diff --git a/sofp-src/tex/sofp-free-type.tex b/sofp-src/tex/sofp-free-type.tex index e51d7cebe..91d65ac37 100644 --- a/sofp-src/tex/sofp-free-type.tex +++ b/sofp-src/tex/sofp-free-type.tex @@ -997,7 +997,7 @@ \subsection{Running a DSL program into another monad} DSL with a different set of operations and its own effect runner that works more efficiently or supports a different run-time environment. -\section{Different encodings of the free monad} +\section{Different encodings of the free monad\label{sec:Different-encodings-of-free-monad}} \subsection{Motivation\label{subsec:Motivation-free-monad-different-encodings}} @@ -1361,7 +1361,7 @@ \subsection{Comparing the reduced encodings of the free monad} There are injective maps from smaller encodings to larger ones, and surjective maps from larger to smaller encodings. -\subsection{Types with existential quantifiers} +\subsection{Types with existential quantifiers\label{subsec:Types-with-existential-quantifiers}} The previous section showed all derivations in the Scala code syntax rather than in the code notation. The reason is that the constructions @@ -1623,9 +1623,9 @@ \subsection{Types with existential quantifiers} properties of free monads and other constructions. With the new notation for existential types, the free monad constructions are written as: \begin{align*} -{\color{greenunder}\text{free monad on }F\text{ in a reduced encoding}:}\quad & \text{Free}_{2}^{F,T}\triangleq T+\exists A.\,F^{A}\times(A\rightarrow\text{Free}_{2}^{F,T})\quad,\\ -{\color{greenunder}\text{free monad on }F\text{ in a reduced encoding}:}\quad & \text{Free}_{3}^{F,T}\triangleq T+F^{T}+\exists A.\,\text{Free}_{3}^{F,A}\times(A\rightarrow\text{Free}_{3}^{F,T})\quad,\\ -{\color{greenunder}\text{free monad on }F\text{ in a raw tree encoding}:}\quad & \text{Free}_{4}^{F,A}\triangleq A+F^{A}+\exists B.\,\text{Free}_{4}^{F,B}\times(B\rightarrow A)\\ +{\color{greenunder}\text{reduced encoding, 2 case classes}:}\quad & \text{Free}_{2}^{F,T}\triangleq T+\exists A.\,F^{A}\times(A\rightarrow\text{Free}_{2}^{F,T})\quad,\\ +{\color{greenunder}\text{reduced encoding, 3 case classes}:}\quad & \text{Free}_{3}^{F,T}\triangleq T+F^{T}+\exists A.\,\text{Free}_{3}^{F,A}\times(A\rightarrow\text{Free}_{3}^{F,T})\quad,\\ +{\color{greenunder}\text{raw tree encoding}:}\quad & \text{Free}_{4}^{F,A}\triangleq A+F^{A}+\exists B.\,\text{Free}_{4}^{F,B}\times(B\rightarrow A)\\ & \quad\quad+\exists B.\,\text{Free}_{4}^{F,B}\times(B\rightarrow\text{Free}_{4}^{F,A})\quad. \end{align*} @@ -1648,9 +1648,10 @@ \subsection{Expressing existential quantifiers via universal quantifiers} \textsf{``}external code\textsf{''} is the function \lstinline!toInt! shown in the previous section. The type signature and the code of \lstinline!toInt! is written in the type notation as: -\[ -\text{toInt}:\left(\exists C.\,\text{Int}\times C\times(C\rightarrow\text{Int})\right)\rightarrow\text{Int}\quad,\quad\quad\text{toInt}\triangleq(\exists C.\,a^{:\text{Int}}\times c^{:C}\times p^{:C\rightarrow\text{Int}})\rightarrow a+p(c)\quad. -\] +\begin{align*} + & \text{toInt}:\left(\exists C.\,\text{Int}\times C\times(C\rightarrow\text{Int})\right)\rightarrow\text{Int}\quad,\\ + & \text{toInt}\triangleq(\exists C.\,a^{:\text{Int}}\times c^{:C}\times p^{:C\rightarrow\text{Int}})\rightarrow a+p(c)\quad. +\end{align*} Generalizing from this example, we say that \textsf{``}code external to the existential quantifier\textsf{''} means any function having an argument of an existentially quantified type. For instance, this could be a function @@ -1835,11 +1836,11 @@ \subsection{Free monad on a functor (\lstinline!Free1!)} This type expression is the same as the definition of $\text{Free}_{1}^{F,T}$. We have just shown that \lstinline!Free1! (which assumes that $F$ -is a functor) is equivalent to \lstinline!Free2! as type constructors. -(Recall that the equivalence of \lstinline!Free2!, \lstinline!Free3!, +is a functor) is equivalent at the level of types to \lstinline!Free2!. +Recall that the equivalence of \lstinline!Free2!, \lstinline!Free3!, and \lstinline!Free4! holds only after applying a runner to a free monad value; the free monad encodings \lstinline!Free2!, \lstinline!Free3!, -\lstinline!Free4! are \emph{not} equivalent as type constructors.) +\lstinline!Free4! are \emph{not} equivalent as type constructors. \section{Free constructions for other typeclasses} @@ -1991,7 +1992,7 @@ \subsection{Expected properties of a free typeclass construction\label{sec:Expec Substituting in that equation $P\triangleq M$ and $(S^{F})^{A}\triangleq\text{Free}_{4}^{F,A}\rightarrow M^{A}$, we get the type equivalence: \begin{align*} - & \forall F^{\bullet}.\,\forall A.\,(\forall T.\,F^{T}\rightarrow M^{T})\rightarrow\text{Free}_{4}^{F,A}\rightarrow M^{A}\\ + & \forall F.\,\forall A.\,(\forall T.\,F^{T}\rightarrow M^{T})\rightarrow\text{Free}_{4}^{F,A}\rightarrow M^{A}\\ & \quad\quad\cong\forall A.\,\text{Free}_{4}^{M,A}\rightarrow M^{A}\quad. \end{align*} The last line ($\text{Free}_{4}^{M,A}\rightarrow M^{A}$) is the type @@ -2029,8 +2030,8 @@ \subsection{Expected properties of a free typeclass construction\label{sec:Expec the \lstinline!Monad! typeclass. (Strictly speaking, the functions of the form \lstinline!emap4(runner)! are \emph{not} monad morphisms: Those functions do satisfy the monad morphism laws, but they are not -maps between lawful monads, as $\text{Free}_{4}^{F,A}$ fails to obey -the monad laws.) +maps between lawful monads, as $\text{Free}_{4}^{F,A}$ violates the +monad laws.) We have derived the code of \lstinline!emap4! by applying \lstinline!run4M! to a specific runner of type $\forall T.\,F^{T}\rightarrow\text{Free}_{4}^{G,T}$. @@ -2054,10 +2055,10 @@ \subsection{Expected properties of a free typeclass construction\label{sec:Expec value of type $M^{A}$ by translating \lstinline!Free4!\textsf{'}s operations into the corresponding operations of the monad $M$. -It turns out that the monad morphism laws of the runner and the free -evaluator have far-reaching consequences for the theory of typeclasses -with laws. For now, let us list the properties that are relevant for -practical programming with free monads: +It turns out that the laws of the runner and the free evaluator have +far-reaching consequences for the theory of typeclasses with laws. +For now, let us list the properties that are relevant for practical +programming with free monads: \begin{enumerate} \item For a given monad $M$ and a fixed function \lstinline!runnerM!, the function \lstinline!run4M(runnerM)! preserves the monad operations @@ -2182,22 +2183,30 @@ \subsection{Expected properties of a free typeclass construction\label{sec:Expec below. We can now generalize the properties 1\textendash 4 to an arbitrary -typeclass. Let $T$ be a type that does not belong to the typeclass, -and denote the free typeclass instance constructed on $T$ by $\text{Free}^{T}$. -We will formulate the expected properties in terms of the free evaluator -(\lstinline!eval!) as its type signature is simpler than that of -the universal runner: +typeclass. Let $T$ be any type and denote a free typeclass instance +constructed on $T$ by $\text{Free}^{T}$ (in any encoding). We formulate +the expected properties in terms of the free evaluator (\lstinline!eval!) +as its type signature is simpler than that of the universal runner: \begin{enumerate} +\item The type $\text{Free}^{T}$ is covariant with respect to $T$. For +any $T$, the type $\text{Free}^{T}$ supports the typeclass operations +(but may violate some typeclass laws). For any $T$, $U$ and any +$f:T\rightarrow U$, the function $f^{\uparrow\text{Free}}$ of type +$\text{Free}^{T}\rightarrow\text{Free}^{U}$ will preserve the typeclass +operations. \item For a given type $M$ that belongs to a typeclass, the free evaluator function (\lstinline!eval!) of type $\text{Free}^{M}\rightarrow M$ preserves the typeclass operations. \item The free evaluator \lstinline!eval! is the \emph{only} possible function of type $\text{Free}^{M}\rightarrow M$ that preserves the typeclass operations. -\item The constructor $\text{Free}^{T}$ is covariant with respect to $T$: -For any two types constructors $T$ and $U$ and a map $f:T\rightarrow U$ -between them, there is a unique function of type $\text{Free}^{T}\rightarrow\text{Free}^{U}$ -that preserves the typeclass operations. +\item The universal runner is defined through \lstinline!eval! as: +\begin{align*} + & \text{run}:(T\rightarrow M)\rightarrow\text{Free}^{T}\rightarrow M\quad,\\ + & \text{run}\,(f^{:T\rightarrow M})\triangleq f^{\uparrow\text{Free}}\bef\text{eval}\quad. +\end{align*} +For any $f$, the function $\text{run}\left(f\right)$ preserves the +typeclass operations. \item Any violations of the typeclass laws in a $\text{Free}^{T}$ program will disappear once a runner is applied and a final value of type $M$ is computed (as long as $M$ is a lawful typeclass instance). @@ -2236,7 +2245,7 @@ \subsection{Free pointed type} \text{FreeDefault}^{T}\triangleq\bbnum 1+T\quad. \] We find that \lstinline!FreeDefault[T]! is equivalent to \lstinline!Option[T]!, -so we will define it that way: +so we may write a simpler definition like this: \begin{lstlisting} type FreeDefault[T] = Option[T] \end{lstlisting} @@ -2245,7 +2254,7 @@ \subsection{Free pointed type} \subsubsection{Definition \label{subsec:Definition-free-pointed-type}\ref{subsec:Definition-free-pointed-type}} The \textbf{free pointed type} on\index{free pointed type} a given -type $T$ is the type $\bbnum 1+T$. +type $T$ is the type $\bbnum 1+T$. $\square$ The \lstinline!HasDefault! typeclass has no laws, so the raw tree encoding ($\bbnum 1+T$) cannot be reduced by imposing any typeclass diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index a1c229eb9..73bd46557 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -774,12 +774,40 @@ \subsection{Chapter~\ref{chap:Free-type-constructions}} A monadic DSL can be evaluated (\textsf{``}run\textsf{''}) into another monad. It turns out that the corresponding runner is \textsf{``}universal\textsf{''} in that -it works in the same way for any target monad. We show how to implement +it works in the same way for all target monads. We show how to implement a universal runner for monadic DSLs. The universal runner translates a free monad\textsf{'}s \lstinline!pure! and \lstinline!flatMap! operations into the corresponding operations of another monad. -{*}{*}{*}is that the monad laws are not +Section~\ref{sec:Different-encodings-of-free-monad} introduces the +notion of an \textsf{``}encoding\textsf{''} of the free monad. In Section~\ref{subsec:Motivation-free-monad-different-encodings}, +we show that there have been different versions of \textsf{``}free monad\textsf{''} +presented in different sources. Are these versions all correct, are +they equivalent, or is one version of a monadic DSL better than another? +To resolve these questions, we look at four different implementations +(\textsf{``}encodings\textsf{''}) of a free monad and find out if they could be mapped +to each other. One of the encodings (\lstinline!Free4!) obeys \emph{none} +of the monad laws while other encodings are smaller and do obey some +of the laws. We show how one can derive a smaller (\textsf{``}reduced\textsf{''}) +encoding from a larger one by imposing one of the monad laws. We also +show that smaller encodings have injective maps to larger ones. + +We take a digression to introduce the notion of existential type quantifiers +(Section~\ref{subsec:Types-with-existential-quantifiers}). This +is necessary in order to describe in a formal way the kinds of types +that free monad encodings require. We show how existentially quantified +types can be expressed through universal quantifiers in Equations~(\ref{eq:existential-via-universal}) +and~(\ref{eq:existential-via-universal-Yoneda}). Finally, we show +that the \textsf{``}smallest\textsf{''} free monad encoding (\lstinline!Free1!) is +equivalent to \lstinline!Free2! when $F$ is a functor. + +We now turn to free constructions for other typeclasses. The first +step (Section~\ref{sec:Expected-properties-of-free-typeclass}) is +to examine the properties of the free monad construction and to generalize +those properties to other typeclasses. We introduce the notion of +a function that \textsf{``}preserves the typeclass operations\textsf{''}. It is due +to this property that a runner function removes monad law violations +in a free monad. We expect the same to hold for other typeclasses.{*}{*}{*} {*}{*}{*} diff --git a/sofp-src/tex/sofp-typeclasses.tex b/sofp-src/tex/sofp-typeclasses.tex index 6eb6d5649..2fb7fb2b2 100644 --- a/sofp-src/tex/sofp-typeclasses.tex +++ b/sofp-src/tex/sofp-typeclasses.tex @@ -6116,25 +6116,26 @@ \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} not necessarily at the declaration site. Typeclasses may be implemented via OOIs, which will enable features of inheritance and subtyping. This will make typeclass inheritance behave like object-oriented interface -inheritance, with all its benefits and shortcomings. As we have seen, +inheritance with all its benefits and shortcomings. As we have seen, typeclasses and their inheritance may be also implemented without OOIs. -\item For typeclasses, the Scala compiler provides rich features for automatic -computation of typeclass evidence values, which works independently -of typeclass inheritance. The programmer can tell the compiler how -to compute (via custom code) a typeclass evidence value for, say, -any pair type \lstinline!(A, B)! from evidence values for \lstinline!A! -and \lstinline!B!. Similarly, a custom derivation rule for \lstinline!Either[A, B]! -may be specified. The compiler will use that custom code to determine -automatically whether \lstinline!(A, B)! or \lstinline!Either[A, B]! -belongs to the typeclass, for \emph{all} suitable types \lstinline!A!, -\lstinline!B!. Certain advanced features of Scala (beyond the scope -of this book) allow programmers to extend typeclass derivation from -pairs \lstinline!(A, B)! to all case classes, and from \lstinline!Either[A, B]! -to all disjunctive types. In this way, typeclass membership can be -provided automatically by the compiler (with no boilerplate code) -for a wide range of user-defined types. But there are no comparable -facilities for object-oriented \textsf{``}interface derivation\textsf{''}. +\item For typeclasses, the Scala compiler provides a rich mechanism known +as \textsf{``}typeclass derivation\textsf{''}: an automatic computation of typeclass +evidence values, which works independently of typeclass inheritance. +The programmer can tell the compiler how to compute (via custom code) +a typeclass evidence value for, say, any pair type \lstinline!(A, B)! +from evidence values for \lstinline!A! and \lstinline!B!. Similarly, +a custom derivation rule for \lstinline!Either[A, B]! may be specified. +The compiler will use that custom code to determine automatically +whether \lstinline!(A, B)! or \lstinline!Either[A, B]! belongs to +the typeclass, for \emph{all} suitable types \lstinline!A!, \lstinline!B!. +Certain advanced features of Scala (beyond the scope of this book) +allow programmers to extend typeclass derivation from pairs \lstinline!(A, B)! +to all case classes, and from \lstinline!Either[A, B]! to all disjunctive +types. In this way, typeclass membership can be provided automatically +by the compiler (with no boilerplate code) for a wide range of user-defined +types. But there are no comparable facilities for object-oriented +\textsf{``}interface derivation\textsf{''}. \item The compilers of Scala and other functional languages treat ADTs and typeclasses in rather different ways. An ADT is not just an arbitrary type $T$ that happens to support functions of type $P^{T}\rightarrow T$. diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 12d7b6ab8..a591ff2ec 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): 80a0ccc3085808b2bdaa5a4e539632546a6639c269cffb0a8f86c80e039adba3}\\ -{\scriptsize{}Git commit: b258200b16b5e287559f520e0dab0d7c5623dd96}\\ -{\scriptsize{}PDF file built on Wed, 05 Nov 2025 10:56:37 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 4b78d830a2ff3bf580a14de476a97f7f85733e11378600d5592b5a3f03f0fabd}\\ +{\scriptsize{}Git commit: 87f08a6a88bc88df72e0e096e16c5e99de0be0ef}\\ +{\scriptsize{}PDF file built on Wed, 05 Nov 2025 21:00:40 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From 55b5bea70dbd9f2ae83b96f112cb13f2ed3cc152 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Thu, 6 Nov 2025 22:26:26 +0100 Subject: [PATCH 28/42] wip formatting chapter 13 --- sofp-src/lyx/sofp-free-type.lyx | 4 +- sofp-src/lyx/sofp-summary.lyx | 207 +++++++++++++++++++++++++++++- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-free-type.tex | 9 +- sofp-src/tex/sofp-summary.tex | 88 +++++++++++-- sofp-src/tex/sofp.tex | 6 +- 6 files changed, 287 insertions(+), 27 deletions(-) diff --git a/sofp-src/lyx/sofp-free-type.lyx b/sofp-src/lyx/sofp-free-type.lyx index bb75bfc68..1cfead1b4 100644 --- a/sofp-src/lyx/sofp-free-type.lyx +++ b/sofp-src/lyx/sofp-free-type.lyx @@ -19579,7 +19579,7 @@ FMR lines 0 placement l overhang 0in -width "60col%" +width "70col%" status open \begin_layout Plain Layout @@ -19695,7 +19695,7 @@ status open \end_inset - as in the previous section. + as before. \end_layout \begin_layout Standard diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 1dccc8083..d32a77311 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -5792,7 +5792,15 @@ encodings \end_inset ) of a free monad and find out if they could be mapped to each other. - One of the encodings ( + One of the encodings (the +\begin_inset Quotes eld +\end_inset + +raw tree +\begin_inset Quotes erd +\end_inset + + encoding, \begin_inset listings inline true status open @@ -5911,8 +5919,11 @@ Free2 \end_layout \begin_layout Standard -We now turn to free constructions for other typeclasses. - Section +Having studied the free monad at length, we now turn to free constructions + for other typeclasses. + Before we generalize from the monad to other typeclasses, we need to understand + what general properties a free construction must satisfy. + To that end, Section \begin_inset space ~ \end_inset @@ -5928,7 +5939,10 @@ noprefix "false" examines the properties of the free monad construction and generalizes those properties to other typeclasses. - We introduce an important notion of a function that +\end_layout + +\begin_layout Standard +We introduce an important notion of a function that \begin_inset Quotes eld \end_inset @@ -5945,6 +5959,13 @@ preserves the typeclass operations \begin_layout Standard With this motivation, we formulate laws that we expect to hold for other free typeclass constructions. + Those laws are generally applicable for all typeclasses. +\end_layout + +\begin_layout Standard +Armed with this information, we proceed to show the types and the code for + various free typeclass constructions of different complexity. + For each typeclass, we will first construct the raw tree encoding \end_layout \begin_layout Standard @@ -5971,6 +5992,114 @@ noprefix "false" \end_inset ). + We show that the properties of the free pointed type are a reformulation + of the properties of the standard +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Option +\end_layout + +\end_inset + + monad. +\end_layout + +\begin_layout Standard +It is not a coincidence that the free pointed type constructor is a monad; + we will prove later that this is always the case for free +\begin_inset Formula $P$ +\end_inset + +-typeclasses. +\end_layout + +\begin_layout Standard +Since a pointed type has no laws, the raw tree encoding is only one free + typeclass encoding for this typeclass. +\end_layout + +\begin_layout Standard +Next, we consider the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Semigroup +\end_layout + +\end_inset + + typeclass (Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Free-semigroup" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). + We begin by implementing the raw tree encoding and its evaluator. + Then we impose the associativity law and arrive at the reduced encoding. + We prove that the reduced encoding can be mapped (in several ways) to the + raw tree encoding, and all those maps are injective but do not preseve + the semigroup's methods. + The converse map (from the raw tree encoding to the reduced encoding) is + found as an application of the universal runner and preserves the semigroup's + methods. +\end_layout + +\begin_layout Standard +Later we will show that this situation is found in general for all +\begin_inset Formula $P$ +\end_inset + +-typeclasses: a reduced encoding can be injected into the raw tree encoding + by many functions, neither of which preserves the typeclass methods. +\end_layout + +\begin_layout Standard +The next more complicated typeclass is +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Monoid +\end_layout + +\end_inset + + (Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Free-monoids" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +). + We again start with the raw tree encoding and discover several reduced + encodings by imposing different subsets of laws. + To illustrate the In particular, we show four encodings: \end_layout \begin_layout Standard @@ -15187,7 +15316,11 @@ for any covariant functor \end_inset , under assumptions of parametricity. - + (Use this isomorphism with +\begin_inset Formula $F^{A}\triangleq(A\rightarrow P)\rightarrow Q$ +\end_inset + + to obtain the previous formula.) \end_layout \begin_layout Standard @@ -15238,5 +15371,69 @@ P\cong\exists A.\,(A\rightarrow A)\rightarrow P\quad. \end_layout +\begin_layout Subsubsection +Problem +\begin_inset CommandInset label +LatexCommand label +name "par:Problem-Peirce-law-1-1" + +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "par:Problem-Peirce-law-1-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\begin_layout Standard +Consider the following type isomorphisms: +\begin_inset Formula +\begin{align*} + & \forall A.\,\forall B.\,F^{A\times B}\cong\forall C.\,F^{C}\quad,\\ + & \forall A.\,\forall B.\,F^{A+B}\cong\forall C.\,F^{C}\quad,\\ + & \forall A.\,\forall B.\,F^{A\rightarrow B}\cong\forall C.\,F^{C}\quad. +\end{align*} + +\end_inset + +For which +\begin_inset Formula $F$ +\end_inset + + do they hold or fail to hold (assuming parametricity)? +\end_layout + +\begin_layout Standard +The question is easy to decide when +\begin_inset Formula $F$ +\end_inset + + is purely covariant or purely contravariant. + In those cases, all isomorphisms hold except for the one with +\begin_inset Formula $F^{A+B}$ +\end_inset + + when +\begin_inset Formula $F$ +\end_inset + + is contravariant. +\end_layout + +\begin_layout Standard +The question remains open when +\begin_inset Formula $F$ +\end_inset + + is neither covariant nor contravariant. +\end_layout + \end_body \end_document diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index bd989331d853ce047a738ab3bc342ae2a098762b..f1cd986cbaf5497e4a77b2b05edcd6672a3f69f7 100644 GIT binary patch delta 152 zcmX?Ra?E7I8WAqD5F;Zi5VD-SO~eqH`%&ZxuW?$EfrVMJp>CS7x$)*lq8v=@W=0@j zIr*cwG>pAjSmGL^lZkGlvx|j^qpPd4p`(GDtE;1ho0+qrshtfW6_d54 FqyfOsC?5a- delta 152 zcmX?Ra?E7I8WAqj5F Combine(l, r), Empty()) \end{lstlisting} We define a syntax extension for the infix binary operation \lstinline!|+|! -as in the previous section. +as before. As usual with raw tree encodings, this free monoid\textsf{'}s operations do not perform any computations but only create nested case classes in diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index 73bd46557..d996159d7 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -786,11 +786,12 @@ \subsection{Chapter~\ref{chap:Free-type-constructions}} they equivalent, or is one version of a monadic DSL better than another? To resolve these questions, we look at four different implementations (\textsf{``}encodings\textsf{''}) of a free monad and find out if they could be mapped -to each other. One of the encodings (\lstinline!Free4!) obeys \emph{none} -of the monad laws while other encodings are smaller and do obey some -of the laws. We show how one can derive a smaller (\textsf{``}reduced\textsf{''}) -encoding from a larger one by imposing one of the monad laws. We also -show that smaller encodings have injective maps to larger ones. +to each other. One of the encodings (the \textsf{``}raw tree\textsf{''} encoding, +\lstinline!Free4!) obeys \emph{none} of the monad laws while other +encodings are smaller and do obey some of the laws. We show how one +can derive a smaller (\textsf{``}reduced\textsf{''}) encoding from a larger one by +imposing one of the monad laws. We also show that smaller encodings +have injective maps to larger ones. We take a digression to introduce the notion of existential type quantifiers (Section~\ref{subsec:Types-with-existential-quantifiers}). This @@ -801,13 +802,56 @@ \subsection{Chapter~\ref{chap:Free-type-constructions}} that the \textsf{``}smallest\textsf{''} free monad encoding (\lstinline!Free1!) is equivalent to \lstinline!Free2! when $F$ is a functor. -We now turn to free constructions for other typeclasses. The first -step (Section~\ref{sec:Expected-properties-of-free-typeclass}) is -to examine the properties of the free monad construction and to generalize -those properties to other typeclasses. We introduce the notion of -a function that \textsf{``}preserves the typeclass operations\textsf{''}. It is due -to this property that a runner function removes monad law violations -in a free monad. We expect the same to hold for other typeclasses.{*}{*}{*} +Having studied the free monad at length, we now turn to free constructions +for other typeclasses. Before we generalize from the monad to other +typeclasses, we need to understand what general properties a free +construction must satisfy. To that end, Section~\ref{sec:Expected-properties-of-free-typeclass} +examines the properties of the free monad construction and generalizes +those properties to other typeclasses. + +We introduce an important notion of a function that \textsf{``}preserves the +typeclass operations\textsf{''}. It is due to this property that a runner +function removes monad law violations in a free monad. + +With this motivation, we formulate laws that we expect to hold for +other free typeclass constructions. Those laws are generally applicable +for all typeclasses. + +Armed with this information, we proceed to show the types and the +code for various free typeclass constructions of different complexity. +For each typeclass, we will first construct the raw tree encoding + +The first example of a free typeclass is \textsf{``}free pointed type\textsf{''} (Section~\ref{subsec:Free-pointed-type}). +We show that the properties of the free pointed type are a reformulation +of the properties of the standard \lstinline!Option! monad. + +It is not a coincidence that the free pointed type constructor is +a monad; we will prove later that this is always the case for free +$P$-typeclasses. + +Since a pointed type has no laws, the raw tree encoding is only one +free typeclass encoding for this typeclass. + +Next, we consider the \lstinline!Semigroup! typeclass (Section~\ref{subsec:Free-semigroup}). +We begin by implementing the raw tree encoding and its evaluator. +Then we impose the associativity law and arrive at the reduced encoding. +We prove that the reduced encoding can be mapped (in several ways) +to the raw tree encoding, and all those maps are injective but do +not preseve the semigroup\textsf{'}s methods. The converse map (from the raw +tree encoding to the reduced encoding) is found as an application +of the universal runner and preserves the semigroup\textsf{'}s methods. + +Later we will show that this situation is found in general for all +$P$-typeclasses: a reduced encoding can be injected into the raw +tree encoding by many functions, neither of which preserves the typeclass +methods. + +The next more complicated typeclass is \lstinline!Monoid! (Section~\ref{subsec:Free-monoids}). +We again start with the raw tree encoding and discover several reduced +encodings by imposing different subsets of laws. To illustrate the + In particular, we show four encodings: + +{*}{*}{*} {*}{*}{*} @@ -2217,7 +2261,9 @@ \subsubsection{Problem \label{par:Problem-Peirce-law-1}\ref{par:Problem-Peirce-l \[ \forall A.\,F^{A\rightarrow A}\cong F^{\bbnum 1} \] -for any covariant functor $F$, under assumptions of parametricity. +for any covariant functor $F$, under assumptions of parametricity. +(Use this isomorphism with $F^{A}\triangleq(A\rightarrow P)\rightarrow Q$ +to obtain the previous formula.) Note that the last identity already holds for any \emph{strictly} \emph{positive} $F$; see Example~\ref{subsec:Example-simplify-quantifier-A-A}(a). @@ -2229,3 +2275,19 @@ \subsubsection{Problem \label{par:Problem-Peirce-law-1}\ref{par:Problem-Peirce-l P\cong\exists A.\,(A\rightarrow A)\rightarrow P\quad. \] + +\subsubsection{Problem \label{par:Problem-Peirce-law-1-1}\ref{par:Problem-Peirce-law-1-1}} + +Consider the following type isomorphisms: +\begin{align*} + & \forall A.\,\forall B.\,F^{A\times B}\cong\forall C.\,F^{C}\quad,\\ + & \forall A.\,\forall B.\,F^{A+B}\cong\forall C.\,F^{C}\quad,\\ + & \forall A.\,\forall B.\,F^{A\rightarrow B}\cong\forall C.\,F^{C}\quad. +\end{align*} +For which $F$ do they hold or fail to hold (assuming parametricity)? + +The question is easy to decide when $F$ is purely covariant or purely +contravariant. In those cases, all isomorphisms hold except for the +one with $F^{A+B}$ when $F$ is contravariant. + +The question remains open when $F$ is neither covariant nor contravariant. diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index a591ff2ec..7124686cf 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): 4b78d830a2ff3bf580a14de476a97f7f85733e11378600d5592b5a3f03f0fabd}\\ -{\scriptsize{}Git commit: 87f08a6a88bc88df72e0e096e16c5e99de0be0ef}\\ -{\scriptsize{}PDF file built on Wed, 05 Nov 2025 21:00:40 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): a70639319b46319852cc6da010a35b94dbcd7c776244b7be8b69d21767f77b23}\\ +{\scriptsize{}Git commit: e4fa596881b72f64e35039534650cb886475185d}\\ +{\scriptsize{}PDF file built on Thu, 06 Nov 2025 22:22:48 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From 7f11b3eaaf1291535ec6d172ab4e012647412573 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Sat, 8 Nov 2025 22:52:18 +0100 Subject: [PATCH 29/42] wip chapter 13 --- sofp-src/lyx/sofp-free-type.lyx | 831 ++++++++++++++++++++++++- sofp-src/lyx/sofp-summary.lyx | 36 +- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-back-cover-no-bg.tex | 4 +- sofp-src/tex/sofp-free-type.tex | 145 ++++- sofp-src/tex/sofp-summary.tex | 14 +- sofp-src/tex/sofp.tex | 10 +- 7 files changed, 1005 insertions(+), 35 deletions(-) diff --git a/sofp-src/lyx/sofp-free-type.lyx b/sofp-src/lyx/sofp-free-type.lyx index 1cfead1b4..b0e5500f4 100644 --- a/sofp-src/lyx/sofp-free-type.lyx +++ b/sofp-src/lyx/sofp-free-type.lyx @@ -19381,7 +19381,7 @@ noprefix "false" \end_layout \begin_layout Subsection -Free monoid and its partially lawful encodings +Free monoid and its reduced encodings \begin_inset CommandInset label LatexCommand label name "subsec:Free-monoids" @@ -20415,11 +20415,6 @@ type F3[T] = Option[Tree2[T]] \begin_layout Plain Layout -def wrapF3[T](t: T): F3[T] = Some(Leaf(t)) -\end_layout - -\begin_layout Plain Layout - def concatF3[T]: (F3[T], F3[T]) => F3[T] = { \end_layout @@ -20477,7 +20472,7 @@ ght) \begin_layout Plain Layout -def runnerF3[M: Monoid, T](runT: T => M)(fmr: F3[T]): M = fmr match { +def runnerF3[M: Monoid, T](runT: T => M): F3[T] => M = { \end_layout \begin_layout Plain Layout @@ -21205,6 +21200,828 @@ noprefix "false" only a subset of the laws of a given typeclass. \end_layout +\begin_layout Standard +Are there any other encodings of the free monoid? Heuristically, we expect + to find a reduced encoding satisfying any given subset of the monoid laws. + The four encodings shown above correspond to four specific subsets of the + laws; as there are three laws, one has 8 different encodings corresponding + to all different subsets of the 3 laws that could be chosen. + The following examples show how to implement the remaining encodings. +\end_layout + +\begin_layout Subsubsection +Example +\begin_inset CommandInset label +LatexCommand label +name "subsec:Example-reduced-monoid-encoding-one-law" + +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-reduced-monoid-encoding-one-law" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\begin_inset Index idx +status open + +\begin_layout Plain Layout +examples +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +Find a reduced encoding of the free monoid that satisfies the left identity + law and the associativity law, but +\emph on +not +\emph default + the right identity law. +\end_layout + +\begin_layout Subparagraph +Solution +\end_layout + +\begin_layout Standard +We start with the encoding +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +F2 +\end_layout + +\end_inset + +, which satisfies the associativity law. + This encoding represents expressions built up from values of type +\begin_inset Formula $T$ +\end_inset + + and the special empty value +\begin_inset Formula $e$ +\end_inset + + via the operation +\begin_inset Formula $\oplus$ +\end_inset + +. + An example expression is: +\begin_inset Formula +\[ +t_{1}\oplus t_{2}\oplus e\oplus t_{3}\oplus e\oplus e\quad. +\] + +\end_inset + +Here, we do not need parentheses since the operation +\begin_inset Formula $\oplus$ +\end_inset + + is associative and our encoding obeys the associativity law. + This expression is represented by the non-empty list +\begin_inset Formula $\left[t_{1},t_{2},e,t_{3},e,e\right]$ +\end_inset + +. +\end_layout + +\begin_layout Standard +To make the left identity law hold, we replace any expression of the form + +\begin_inset Formula $e\oplus t$ +\end_inset + + by just +\begin_inset Formula $t$ +\end_inset + +. + This will eliminate entries equal to +\begin_inset Formula $e$ +\end_inset + + to the left of any entries of type +\begin_inset Formula $T$ +\end_inset + +. + For the example just shown, the result will be: +\begin_inset Formula +\[ +t_{1}\oplus t_{2}\oplus t_{3}\oplus e\oplus e\quad. +\] + +\end_inset + +This corresponds to a non-empty list of the form +\begin_inset Formula $\left[t_{1},t_{2},t_{3},e,e\right]$ +\end_inset + + where all non-empty values appear before all empty ones. +\end_layout + +\begin_layout Standard +How can we represent this data? A simple solution would be a pair of two + lists, one being a list of values of type +\begin_inset Formula $T$ +\end_inset + + and the other a list of empty values. + However, this type cannot guarantee at the level of types that at least + one of the lists is non-empty. +\end_layout + +\begin_layout Standard +To derive a correct data type, we begin by first defining the required sequence + structure by induction: +\end_layout + +\begin_layout Itemize +Base cases: +\end_layout + +\begin_deeper +\begin_layout Itemize +We may have a single value of type +\begin_inset Formula $T$ +\end_inset + + or a single empty value ( +\begin_inset Formula $e$ +\end_inset + +). + +\end_layout + +\end_deeper +\begin_layout Itemize +Inductive steps: +\end_layout + +\begin_deeper +\begin_layout Itemize +If a sequence begins with a +\begin_inset Formula $t:T$ +\end_inset + + then it may continue to any other sequence of the same type (beginning + either with another +\begin_inset Formula $t':T$ +\end_inset + + or with the empty value). + +\end_layout + +\begin_layout Itemize +If a sequence begins with an +\begin_inset Formula $e$ +\end_inset + +, it may continue to another sequence that begins with +\begin_inset Formula $e$ +\end_inset + +. + +\end_layout + +\end_deeper +\begin_layout Standard +The inductive steps guarantee that once an empty value occurs, all further + values will also be empty. + To describe this logic, we need two case classes for the base cases and + two more case classes to describe the two different types of induction + steps. + The empty values will be represented by the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Unit +\end_layout + +\end_inset + + type: +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +sealed trait F5[T] +\end_layout + +\begin_layout Plain Layout + +final case class OneT[T](single: T) extends F5[T] +\end_layout + +\begin_layout Plain Layout + +final case class OneE[T]() extends F5[T] +\end_layout + +\begin_layout Plain Layout + +final case class NELT[T](head: T, tail: F5[T]) extends F5[T] +\end_layout + +\begin_layout Plain Layout + +final case class NELE[T](head: Unit, tail: NELE[T]) extends F5[T] +\end_layout + +\end_inset + +If the case classes +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +OneE +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +NELE +\end_layout + +\end_inset + + are considered separately, they are equivalent to a recursive definition + of the non-empty list of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Unit +\end_layout + +\end_inset + + values ( +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +NEL[Unit] +\end_layout + +\end_inset + +). + So, we may rewrite the recursive definition of +\begin_inset Formula $F_{5}$ +\end_inset + + as: +\begin_inset Formula +\[ +F_{5}^{T}\triangleq T+T\times F_{5}^{T}+\text{NEL}^{\bbnum 1}\quad. +\] + +\end_inset + +The +\begin_inset Quotes eld +\end_inset + +unrolling trick +\begin_inset Quotes erd +\end_inset + + +\begin_inset Index idx +status open + +\begin_layout Plain Layout +unrolling trick for recursive types +\end_layout + +\end_inset + +(Statement +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "Statement-unrolling-trick" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +) simplifies this recursive definition to: +\begin_inset Formula +\[ +F_{5}^{T}\cong\text{List}^{T}\times(T+\text{NEL}^{\bbnum 1})\quad. +\] + +\end_inset + + +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +final case class F5[T](start: List[T], end: Either[T, NEL[Unit]]) +\end_layout + +\end_inset + +The +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Monoid +\end_layout + +\end_inset + + typeclass instance and the runner code for +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +F5 +\end_layout + +\end_inset + + are written as: +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +def wrapF5[T](t: T): F5[T] = F5(Nil, Left(t)) +\end_layout + +\begin_layout Plain Layout + +def concatF5[T]: (F5[T], F5[T]) => F5[T] = { +\end_layout + +\begin_layout Plain Layout + + case (F5(start1, Left(t)), F5(start2, end)) => F5(start1 ++ List(t) ++ + start2, end) +\end_layout + +\begin_layout Plain Layout + + case (F5(start1, Right(ee1)), F5(Nil, Right(ee2))) => F5(start1, concat(ee1, + ee2)) +\end_layout + +\begin_layout Plain Layout + + case (F5(start1, Right(_)), F5(start2, end)) => F5(start1 ++ start2, end) +\end_layout + +\begin_layout Plain Layout + +} +\end_layout + +\begin_layout Plain Layout + +def emptyF5[T]: F5[T] = F5(Nil, Right(((), Nil))) +\end_layout + +\begin_layout Plain Layout + +implicit def monoidF5[T]: Monoid[F5[T]] = Monoid(concatF5[T], emptyF5[T]) +\end_layout + +\begin_layout Plain Layout + +def runnerF5[M: Monoid, T](runT: T => M)(fm: F5[T]): M = { +\end_layout + +\begin_layout Plain Layout + + val last: M = fm.end match { +\end_layout + +\begin_layout Plain Layout + + case Left(t) => runT(t) +\end_layout + +\begin_layout Plain Layout + + case Right(e) => Monoid[M].empty +\end_layout + +\begin_layout Plain Layout + + } +\end_layout + +\begin_layout Plain Layout + + (fm.start.map(runT) :+ last).reduce(Monoid[M].combine) +\end_layout + +\begin_layout Plain Layout + +}***test this code +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Subsubsection +Example +\begin_inset CommandInset label +LatexCommand label +name "subsec:Example-reduced-monoid-encoding-one-law-1" + +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Example-reduced-monoid-encoding-one-law-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\begin_layout Standard +Find a reduced encoding of the free monoid that satisfies the left identity + law but +\emph on +no +\emph default + other laws of monoids. +\end_layout + +\begin_layout Subparagraph +Solution +\end_layout + +\begin_layout Standard +Start with the raw tree encoding, which is a binary tree with leaves of + type +\begin_inset Formula $\bbnum 1+T$ +\end_inset + +. + The left identity law ( +\begin_inset Formula $e\oplus x=x$ +\end_inset + +) means that in any branching of the tree, the left branch cannot be an + +\begin_inset Quotes eld +\end_inset + +empty +\begin_inset Quotes erd +\end_inset + + leaf (a leaf carrying the value +\begin_inset Formula $e$ +\end_inset + +). + The right branch remains unrestricted. + To implement the restriction on the left branches, we introduce two types + of trees: a tree that cannot be an empty leaf value, and a tree that can. + ( +\emph on +Both +\emph default + trees will disallow empty leaves as left sub-trees.) +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +sealed trait TreeLeftNonEmpty[T] +\end_layout + +\begin_layout Plain Layout + +final case class LeafNE[T](t: T) extends TreeLeftNonEmpty[T] +\end_layout + +\begin_layout Plain Layout + +final case class BranchNE[T](left: TreeLeftNonEmpty[T], right: TreeLeftAny[T]) + extends TreeLeftNonEmpty[T] +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\begin_layout Plain Layout + +sealed trait TreeLeftAny[T] +\end_layout + +\begin_layout Plain Layout + +final case class LeafT[T](t: T) extends TreeLeftAny[T] +\end_layout + +\begin_layout Plain Layout + +final case class LeafE[T]() extends TreeLeftAny[T] +\end_layout + +\begin_layout Plain Layout + +final case class BranchAny[T](left: TreeLeftNonEmpty[T], right: TreeLeftAny[T]) + extends TreeLeftNonEmpty[T] +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\begin_layout Plain Layout + +type F6[T] = TreeLeftAny[T] +\end_layout + +\end_inset + +In the type notation, the encoding +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +F6 +\end_layout + +\end_inset + + is expressed via two +\series bold +mutually recursive types +\series default + +\begin_inset Index idx +status open + +\begin_layout Plain Layout +mutually recursive types +\end_layout + +\end_inset + +: +\begin_inset Formula +\begin{align*} +\text{\texttt{TreeLeftAny} in the code}:\quad & F_{6}^{T}\triangleq\bbnum 1+T+G^{T}\times F_{6}^{T}\quad,\\ +\text{\texttt{TreeLeftNonEmpty} in the code}:\quad & G^{T}\triangleq T+G^{T}\times F_{6}^{T}\quad. +\end{align*} + +\end_inset + + +\begin_inset Quotes erd +\end_inset + +Mutually recursive +\begin_inset Quotes erd +\end_inset + + means that each the definitions of +\begin_inset Formula $F_{6}^{T}$ +\end_inset + + and +\begin_inset Formula $G$ +\end_inset + + uses both these types. +\end_layout + +\begin_layout Standard +Let us implement the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Monoid +\end_layout + +\end_inset + + instance and a universal runner for +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +F6 +\end_layout + +\end_inset + +, which we write via two mutually recursive functions ( +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +runnerF6NE +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +runnerF6 +\end_layout + +\end_inset + +): +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +def wrapF6[T](t: T): F6[T] = LeafNE(t) +\end_layout + +\begin_layout Plain Layout + +def toTreeNE[T]: TreeLeftAny[T] => TreeLeftNonEmpty[T] = { +\end_layout + +\begin_layout Plain Layout + + case LeafE() => ??? // This case will never be used. +\end_layout + +\begin_layout Plain Layout + + case LeafT(t) => LeafNE(t) +\end_layout + +\begin_layout Plain Layout + + case BranchAny(left, right) => BranchNE(left, right) +\end_layout + +\begin_layout Plain Layout + +} +\end_layout + +\begin_layout Plain Layout + +def concatF6[T]: (F6[T], F6[T]) => F6[T] = { +\end_layout + +\begin_layout Plain Layout + + case (LeafE(), x) => x // Left identity law holds automatically. +\end_layout + +\begin_layout Plain Layout + + case (first, second) => BranchAny(toTreeNE(first), second) // `first` + is guaranteed to be non-empty. +\end_layout + +\begin_layout Plain Layout + +} +\end_layout + +\begin_layout Plain Layout + +def emptyF6[T]: F6[T] = LeafE() +\end_layout + +\begin_layout Plain Layout + +implicit def monoidF6[T]: Monoid[F6[T]] = Monoid(concatF6[T], emptyF6[T]) +\end_layout + +\begin_layout Plain Layout + +def runnerF6NE[M: Monoid, T](runT: T => M): TreeLeftNonEmpty[T] => M = { +\end_layout + +\begin_layout Plain Layout + + case LeafNE(t) => runT(t) +\end_layout + +\begin_layout Plain Layout + + case BranchNE(left, LeafE()) => runnerF6NE(runT)(left) +\end_layout + +\begin_layout Plain Layout + + case BranchNE(left, right) => Monoid[M].combine(runnerF6NE(runT)(left), + runnerF6(runT)(right)) +\end_layout + +\begin_layout Plain Layout + +def runnerF6[M: Monoid, T](runT: T => M): F6[T] => M = { +\end_layout + +\begin_layout Plain Layout + + case LeafE() => Monoid[M].empty +\end_layout + +\begin_layout Plain Layout + + case LeafT(t) => runT(t) +\end_layout + +\begin_layout Plain Layout + + case BranchAny(left, right) => Monoid[M].combine(runnerF6NE(runT)(left), + runnerF6(runT)(right)) +\end_layout + +\begin_layout Plain Layout + +}***test this code +\end_layout + +\end_inset + + *** +\end_layout + \begin_layout Subsection Free functors \end_layout diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index d32a77311..1028f3c20 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -6008,15 +6008,6 @@ Option monad. \end_layout -\begin_layout Standard -It is not a coincidence that the free pointed type constructor is a monad; - we will prove later that this is always the case for free -\begin_inset Formula $P$ -\end_inset - --typeclasses. -\end_layout - \begin_layout Standard Since a pointed type has no laws, the raw tree encoding is only one free typeclass encoding for this typeclass. @@ -6097,9 +6088,32 @@ noprefix "false" \end_inset ). - We again start with the raw tree encoding and discover several reduced + We again start with the raw tree encoding and then discover several reduced encodings by imposing different subsets of laws. - To illustrate the In particular, we show four encodings: + To illustrate the relationships between reduced encodings of a free typeclass, + we consider four different encodings of the free monoid (denoted by +\begin_inset Formula $F_{1}$ +\end_inset + +, +\begin_inset Formula $F_{2}$ +\end_inset + +, +\begin_inset Formula $F_{3}$ +\end_inset + +, +\begin_inset Formula $F_{4}$ +\end_inset + +). + We find that a free monoid encoding can be injectively mapped into any + other encoding that obeys +\emph on +fewer +\emph default + laws; but those injective maps do not preserve the monoid operations. \end_layout \begin_layout Standard diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index f1cd986cbaf5497e4a77b2b05edcd6672a3f69f7..2cdc6923ee28005750d9c266ac912190953d8e06 100644 GIT binary patch delta 148 zcmX?Ra?E7I8WB#55JM9yQzI*r$y-H?ka!J>2nH%e-nIxNSek97l#Aab= zVrpbE`GdF&l(|_*;yR;~p_!wJo3n+5iKVNFnWM9Txrw8hiLr&FtC^#biJ_69oed!s IleML!0Wm5jo&W#< delta 148 zcmX?Ra?E7I8WB#j5F;Zi5SqMI#0ZJ^LF6f~aaxjrg;}zpZkn;V@#aUO987FxMj$Zx zgSZToxmif!I-`?`fq{vuk&~l~tEsb#g^8o9tFxh_ft#zVqlKH9v!SV-4IveiwWXv1 DEOI9| diff --git a/sofp-src/tex/sofp-back-cover-no-bg.tex b/sofp-src/tex/sofp-back-cover-no-bg.tex index 7cd865857..6b47f555c 100644 --- a/sofp-src/tex/sofp-back-cover-no-bg.tex +++ b/sofp-src/tex/sofp-back-cover-no-bg.tex @@ -25,9 +25,9 @@ practical applications of parametricity. Long and difficult, yet boring explanations are logically -developed in excruciating detail through 1981 +developed in excruciating detail through 1985 Scala code snippets, 233 statements with step-by-step -derivations, 105 diagrams, 237 examples +derivations, 105 diagrams, 239 examples with tested Scala code, and 315 exercises. Discussions build upon each chapter\textsf{'}s material further. diff --git a/sofp-src/tex/sofp-free-type.tex b/sofp-src/tex/sofp-free-type.tex index 71be6da80..19c631acf 100644 --- a/sofp-src/tex/sofp-free-type.tex +++ b/sofp-src/tex/sofp-free-type.tex @@ -2536,7 +2536,7 @@ \subsection{Free semigroup\label{subsec:Free-semigroup}} still holds. But none of those alternative implementations could preserve the typeclass operations. -\subsection{Free monoid and its partially lawful encodings\label{subsec:Free-monoids}} +\subsection{Free monoid and its reduced encodings\label{subsec:Free-monoids}} A monoid (see Example~\ref{subsec:tc-Example-Monoids}) is a typeclass with a two methods: \lstinline!combine! and \lstinline!empty!. The @@ -2698,7 +2698,6 @@ \subsection{Free monoid and its partially lawful encodings\label{subsec:Free-mon satisfies only the identity laws. The code is: \begin{lstlisting} type F3[T] = Option[Tree2[T]] -def wrapF3[T](t: T): F3[T] = Some(Leaf(t)) def concatF3[T]: (F3[T], F3[T]) => F3[T] = { case (None, x) => x case (x, None) => x @@ -2710,7 +2709,7 @@ \subsection{Free monoid and its partially lawful encodings\label{subsec:Free-mon case Leaf(a) => runT(a) case Branch(left, right) => runnerTree2(runT)(left) |+| runnerTree2(runT)(right) } -def runnerF3[M: Monoid, T](runT: T => M)(fmr: F3[T]): M = fmr match { +def runnerF3[M: Monoid, T](runT: T => M): F3[T] => M = { case Some(t) => runnerTree2(runT)(t) case None => Monoid[M].empty } @@ -2799,6 +2798,146 @@ \subsection{Free monoid and its partially lawful encodings\label{subsec:Free-mon which develops a rigorous theory of free typeclass encodings that satisfy only a subset of the laws of a given typeclass. +Are there any other encodings of the free monoid? Heuristically, we +expect to find a reduced encoding satisfying any given subset of the +monoid laws. The four encodings shown above correspond to four specific +subsets of the laws; as there are three laws, one has 8 different +encodings corresponding to all different subsets of the 3 laws that +could be chosen. The following examples show how to implement the +remaining encodings. + +\subsubsection{Example \label{subsec:Example-reduced-monoid-encoding-one-law}\ref{subsec:Example-reduced-monoid-encoding-one-law}\index{examples}} + +Find a reduced encoding of the free monoid that satisfies the left +identity law and the associativity law, but \emph{not} the right identity +law. + +\subparagraph{Solution} + +We start with the encoding \lstinline!F2!, which satisfies the associativity +law. This encoding represents expressions built up from values of +type $T$ and the special empty value $e$ via the operation $\oplus$. +An example expression is: +\[ +t_{1}\oplus t_{2}\oplus e\oplus t_{3}\oplus e\oplus e\quad. +\] +Here, we do not need parentheses since the operation $\oplus$ is +associative and our encoding obeys the associativity law. This expression +is represented by the non-empty list $\left[t_{1},t_{2},e,t_{3},e,e\right]$. + +To make the left identity law hold, we replace any expression of the +form $e\oplus t$ by just $t$. This will eliminate entries equal +to $e$ to the left of any entries of type $T$. For the example just +shown, the result will be: +\[ +t_{1}\oplus t_{2}\oplus t_{3}\oplus e\oplus e\quad. +\] +This corresponds to a non-empty list of the form $\left[t_{1},t_{2},t_{3},e,e\right]$ +where all non-empty values appear before all empty ones. + +How can we represent this data? A simple solution would be a pair +of two lists, one being a list of values of type $T$ and the other +a list of empty values. However, this type cannot guarantee at the +level of types that at least one of the lists is non-empty. + +To derive a correct data type, we begin by first defining the required +sequence structure by induction: +\begin{itemize} +\item Base cases: +\begin{itemize} +\item We may have a single value of type $T$ or a single empty value ($e$). +\end{itemize} +\item Inductive steps: +\begin{itemize} +\item If a sequence begins with a $t:T$ then it may continue to any other +sequence of the same type (beginning either with another $t':T$ or +with the empty value). +\item If a sequence begins with an $e$, it may continue to another sequence +that begins with $e$. +\end{itemize} +\end{itemize} +The inductive steps guarantee that once an empty value occurs, all +further values will also be empty. To describe this logic, we need +two case classes for the base cases and two more case classes to describe +the two different types of induction steps. The empty values will +be represented by the \lstinline!Unit! type: +\begin{lstlisting} +sealed trait F5[T] +final case class OneT[T](single: T) extends F5[T] +final case class OneE[T]() extends F5[T] +final case class NELT[T](head: T, tail: F5[T]) extends F5[T] +final case class NELE[T](head: Unit, tail: NELE[T]) extends F5[T] +\end{lstlisting} +If the case classes \lstinline!OneE! and \lstinline!NELE! are considered +separately, they are equivalent to a recursive definition of the non-empty +list of \lstinline!Unit! values (\lstinline!NEL[Unit]!). So, we +may rewrite the recursive definition of $F_{5}$ as: +\[ +F_{5}^{T}\triangleq T+T\times F_{5}^{T}+\text{NEL}^{\bbnum 1}\quad. +\] +The \textsf{``}unrolling trick\textsf{''} \index{unrolling trick for recursive types}(Statement~\ref{Statement-unrolling-trick}) +simplifies this recursive definition to: +\[ +F_{5}^{T}\cong\text{List}^{T}\times(T+\text{NEL}^{\bbnum 1})\quad. +\] +\begin{lstlisting} +final case class F5[T](start: List[T], end: Either[T, NEL[Unit]]) +\end{lstlisting} +The \lstinline!Monoid! typeclass instance and the runner code for +\lstinline!F5! are written as: +\begin{lstlisting} +def wrapF5[T](t: T): F3[T] = F5(Nil, Left(t)) +def concatF5[T]: (F5[T], F5[T]) => F5[T] = { + case (F5(start1, Left(t)), F5(start2, end)) => F5(start1 ++ List(t) ++ start2, end) + case (F5(start1, Right(_)), F5(start2, end)) => F5(start1 ++ start2, end) +} +def emptyF5[T]: F5[T] = F5(Nil, Right(((), Nil))) +implicit def monoidF5[T]: Monoid[F5[T]] = Monoid(concatF5[T], emptyF5[T]) +def runnerF5[M: Monoid, T](runT: T => M)(fm: F5[T]): M = { + val last: M = fm.end match { + case Left(t) => runT(t) + case Right(e) => Monoid[M].empty + } + (fm.start.map(runT) :+ last).reduce(Monoid[M].combine) +}***test this code +\end{lstlisting} + + +\subsubsection{Example \label{subsec:Example-reduced-monoid-encoding-one-law-1}\ref{subsec:Example-reduced-monoid-encoding-one-law-1}} + +Find a reduced encoding of the free monoid that satisfies the left +identity law but \emph{no} other laws of monoids. + +\subparagraph{Solution} + +Start with the raw tree encoding, which is a binary tree with leaves +of type $\bbnum 1+T$. The left identity law ($e\oplus x=x$) means +that in any branching of the tree, the left branch cannot be an \textsf{``}empty\textsf{''} +leaf (a leaf carrying the value $e$). The right branch remains unrestricted. +To implement the restriction on the left branches, we introduce two +types of trees: a tree that cannot be an empty leaf value, and a tree +that can. (\emph{Both} trees will disallow empty leaves as left sub-trees.) +\begin{lstlisting} +sealed trait TreeLeftNonEmpty[T] +final case class LeafNE[T](t: T) extends TreeLeftNonEmpty[T] +final case class BranchNE[T](left: TreeLeftNonEmpty[T], right: TreeLeftAny[T]) extends TreeLeftNonEmpty[T] + +sealed trait TreeLeftAny[T] +final case class Leaf1[T](t: T) extends TreeLeftAny[T] +final case class Leaf2[T]() extends TreeLeftAny[T] +final case class BranchAny[T](left: TreeLeftNonEmpty[T], right: TreeLeftAny[T]) extends TreeLeftNonEmpty[T] + +type F6[T] = TreeLeftNonEmpty[T] +\end{lstlisting} +In the type notation, the encoding \lstinline!F6! is expressed via +two \textbf{mutually recursive types}\index{mutually recursive types}: +\begin{align*} + & F_{6}^{T}\triangleq T+F_{6}^{T}\times G^{T}\quad,\\ + & G^{T}\triangleq\bbnum 1+T+F_{6}^{T}\times G^{T}\quad. +\end{align*} +\textsf{''}Mutually recursive\textsf{''} means that each the definitions of $F_{6}^{T}$ +and $G$ uses both these types. {*}{*}{*} + \subsection{Free functors} Consider the \lstinline!Functor! typeclass whose only method is \lstinline!fmap!: diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index d996159d7..052e736b7 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -825,10 +825,6 @@ \subsection{Chapter~\ref{chap:Free-type-constructions}} We show that the properties of the free pointed type are a reformulation of the properties of the standard \lstinline!Option! monad. -It is not a coincidence that the free pointed type constructor is -a monad; we will prove later that this is always the case for free -$P$-typeclasses. - Since a pointed type has no laws, the raw tree encoding is only one free typeclass encoding for this typeclass. @@ -847,9 +843,13 @@ \subsection{Chapter~\ref{chap:Free-type-constructions}} methods. The next more complicated typeclass is \lstinline!Monoid! (Section~\ref{subsec:Free-monoids}). -We again start with the raw tree encoding and discover several reduced -encodings by imposing different subsets of laws. To illustrate the - In particular, we show four encodings: +We again start with the raw tree encoding and then discover several +reduced encodings by imposing different subsets of laws. To illustrate +the relationships between reduced encodings of a free typeclass, we +consider four different encodings of the free monoid (denoted by $F_{1}$, +$F_{2}$, $F_{3}$, $F_{4}$). We find that a free monoid encoding +can be injectively mapped into any other encoding that obeys \emph{fewer} +laws; but those injective maps do not preserve the monoid operations. {*}{*}{*} diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 7124686cf..c5bf07f44 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): a70639319b46319852cc6da010a35b94dbcd7c776244b7be8b69d21767f77b23}\\ -{\scriptsize{}Git commit: e4fa596881b72f64e35039534650cb886475185d}\\ -{\scriptsize{}PDF file built on Thu, 06 Nov 2025 22:22:48 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 6963107417ce1d839c8d5d2d00740e06f1393c82dcf78ae0d54565ff8a1d079b}\\ +{\scriptsize{}Git commit: 55b5bea70dbd9f2ae83b96f112cb13f2ed3cc152}\\ +{\scriptsize{}PDF file built on Sat, 08 Nov 2025 14:53:07 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, @@ -374,9 +374,9 @@ practical applications of parametricity.}\\ {\scriptsize{}}\\ {\scriptsize{}Long and difficult, yet boring explanations are logically -developed in excruciating detail through 1981 Scala +developed in excruciating detail through 1985 Scala code snippets, 233 statements with step-by-step derivations, -105 diagrams, 237 examples with tested Scala +105 diagrams, 239 examples with tested Scala code, and 315 exercises. Discussions build upon each chapter's material further.}\\ {\scriptsize{}}\\ From b7c337b4f7fd43d7a0d27355c6e6bb44bffbf328 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Mon, 10 Nov 2025 10:30:45 +0100 Subject: [PATCH 30/42] validate code for monoids F5 and F6 --- sofp-src/lyx/sofp-free-type.lyx | 697 +++++++++++++++++++++++++------- sofp-src/lyx/sofp-summary.lyx | 23 +- 2 files changed, 577 insertions(+), 143 deletions(-) diff --git a/sofp-src/lyx/sofp-free-type.lyx b/sofp-src/lyx/sofp-free-type.lyx index b0e5500f4..c03723be3 100644 --- a/sofp-src/lyx/sofp-free-type.lyx +++ b/sofp-src/lyx/sofp-free-type.lyx @@ -21303,52 +21303,100 @@ Here, we do not need parentheses since the operation \begin_layout Standard To make the left identity law hold, we replace any expression of the form -\begin_inset Formula $e\oplus t$ +\begin_inset Formula $e\oplus x$ \end_inset by just -\begin_inset Formula $t$ +\begin_inset Formula $x$ \end_inset . - This will eliminate entries equal to -\begin_inset Formula $e$ + This will eliminate +\begin_inset Quotes eld \end_inset - to the left of any entries of type -\begin_inset Formula $T$ +empty +\begin_inset Quotes erd \end_inset -. + list elements ( +\begin_inset Formula $e$ +\end_inset + +) to the left of any other elements (empty or not). For the example just shown, the result will be: \begin_inset Formula \[ -t_{1}\oplus t_{2}\oplus t_{3}\oplus e\oplus e\quad. +t_{1}\oplus t_{2}\oplus t_{3}\oplus e\quad. \] \end_inset This corresponds to a non-empty list of the form -\begin_inset Formula $\left[t_{1},t_{2},t_{3},e,e\right]$ +\begin_inset Formula $\left[t_{1},t_{2},t_{3},e\right]$ \end_inset - where all non-empty values appear before all empty ones. + where all non-empty values appear before the empty one. + The last empty element cannot be removed, since we do not impose the right + identity law. \end_layout \begin_layout Standard -How can we represent this data? A simple solution would be a pair of two - lists, one being a list of values of type -\begin_inset Formula $T$ +What type can represent this data? A simple attempt would be a pair +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +(List[T], Boolean) +\end_layout + \end_inset - and the other a list of empty values. - However, this type cannot guarantee at the level of types that at least - one of the lists is non-empty. +, where the boolean value is +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +true +\end_layout + +\end_inset + + when an empty value is present at the end. + However, this type cannot guarantee that either the list of type +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +List[T] +\end_layout + +\end_inset + + is non-empty or the boolean value is +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +true +\end_layout + +\end_inset + +. \end_layout \begin_layout Standard -To derive a correct data type, we begin by first defining the required sequence - structure by induction: +To derive a correct data type, we begin by first defining the required structure + by induction: \end_layout \begin_layout Itemize @@ -21356,12 +21404,16 @@ Base cases: \end_layout \begin_deeper -\begin_layout Itemize +\begin_layout Enumerate We may have a single value of type \begin_inset Formula $T$ \end_inset - or a single empty value ( +. +\end_layout + +\begin_layout Enumerate +We may have a single empty value ( \begin_inset Formula $e$ \end_inset @@ -21389,27 +21441,21 @@ If a sequence begins with a \end_layout -\begin_layout Itemize +\end_deeper +\begin_layout Standard If a sequence begins with an \begin_inset Formula $e$ \end_inset -, it may continue to another sequence that begins with -\begin_inset Formula $e$ -\end_inset - -. - +, it must end at that point. + So, there is no induction step following the second base case. \end_layout -\end_deeper \begin_layout Standard -The inductive steps guarantee that once an empty value occurs, all further - values will also be empty. - To describe this logic, we need two case classes for the base cases and +To describe this logic, we need two case classes for the base cases and two more case classes to describe the two different types of induction steps. - The empty values will be represented by the + The empty value will be represented by a named \begin_inset listings inline true status open @@ -21421,39 +21467,7 @@ Unit \end_inset - type: -\begin_inset listings -inline false -status open - -\begin_layout Plain Layout - -sealed trait F5[T] -\end_layout - -\begin_layout Plain Layout - -final case class OneT[T](single: T) extends F5[T] -\end_layout - -\begin_layout Plain Layout - -final case class OneE[T]() extends F5[T] -\end_layout - -\begin_layout Plain Layout - -final case class NELT[T](head: T, tail: F5[T]) extends F5[T] -\end_layout - -\begin_layout Plain Layout - -final case class NELE[T](head: Unit, tail: NELE[T]) extends F5[T] -\end_layout - -\end_inset - -If the case classes + type ( \begin_inset listings inline true status open @@ -21465,52 +21479,41 @@ OneE \end_inset - and +): \begin_inset listings -inline true +inline false status open \begin_layout Plain Layout -NELE +sealed trait F5[T] \end_layout -\end_inset - - are considered separately, they are equivalent to a recursive definition - of the non-empty list of -\begin_inset listings -inline true -status open - \begin_layout Plain Layout -Unit +final case class OneT[T](single: T) extends F5[T] // Base case 1. \end_layout -\end_inset +\begin_layout Plain Layout - values ( -\begin_inset listings -inline true -status open +final case class OneE[T]() extends F5[T] // Base case 2. +\end_layout \begin_layout Plain Layout -NEL[Unit] +final case class NELT[T](head: T, tail: F5[T]) extends F5[T] \end_layout \end_inset -). - So, we may rewrite the recursive definition of +In the type notation, we may write the recursive definition of \begin_inset Formula $F_{5}$ \end_inset as: \begin_inset Formula \[ -F_{5}^{T}\triangleq T+T\times F_{5}^{T}+\text{NEL}^{\bbnum 1}\quad. +F_{5}^{T}\triangleq\bbnum 1+T+T\times F_{5}^{T}\quad. \] \end_inset @@ -21550,7 +21553,7 @@ noprefix "false" ) simplifies this recursive definition to: \begin_inset Formula \[ -F_{5}^{T}\cong\text{List}^{T}\times(T+\text{NEL}^{\bbnum 1})\quad. +F_{5}^{T}\cong\text{List}^{T}\times(\bbnum 1+T)\quad. \] \end_inset @@ -21562,7 +21565,7 @@ status open \begin_layout Plain Layout -final case class F5[T](start: List[T], end: Either[T, NEL[Unit]]) +final case class F5[T](start: List[T], end: Option[T]) \end_layout \end_inset @@ -21598,7 +21601,7 @@ status open \begin_layout Plain Layout -def wrapF5[T](t: T): F5[T] = F5(Nil, Left(t)) +def wrapF5[T](t: T): F5[T] = F5(Nil, Some(t)) \end_layout \begin_layout Plain Layout @@ -21608,19 +21611,13 @@ def concatF5[T]: (F5[T], F5[T]) => F5[T] = { \begin_layout Plain Layout - case (F5(start1, Left(t)), F5(start2, end)) => F5(start1 ++ List(t) ++ + case (F5(start1, Some(t)), F5(start2, end)) => F5(start1 ++ List(t) ++ start2, end) \end_layout \begin_layout Plain Layout - case (F5(start1, Right(ee1)), F5(Nil, Right(ee2))) => F5(start1, concat(ee1, - ee2)) -\end_layout - -\begin_layout Plain Layout - - case (F5(start1, Right(_)), F5(start2, end)) => F5(start1 ++ start2, end) + case (F5(start1, None), F5(start2, end)) => F5(start1 ++ start2, end) \end_layout \begin_layout Plain Layout @@ -21630,7 +21627,7 @@ def concatF5[T]: (F5[T], F5[T]) => F5[T] = { \begin_layout Plain Layout -def emptyF5[T]: F5[T] = F5(Nil, Right(((), Nil))) +def emptyF5[T]: F5[T] = F5(Nil, None) \end_layout \begin_layout Plain Layout @@ -21650,12 +21647,12 @@ def runnerF5[M: Monoid, T](runT: T => M)(fm: F5[T]): M = { \begin_layout Plain Layout - case Left(t) => runT(t) + case Some(t) => runT(t) \end_layout \begin_layout Plain Layout - case Right(e) => Monoid[M].empty + case None => Monoid[M].empty \end_layout \begin_layout Plain Layout @@ -21665,17 +21662,206 @@ def runnerF5[M: Monoid, T](runT: T => M)(fm: F5[T]): M = { \begin_layout Plain Layout - (fm.start.map(runT) :+ last).reduce(Monoid[M].combine) + fm.start.map(runT).reduce(Monoid[M].combine) |+| last +\end_layout + +\begin_layout Plain Layout + +} +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +To test this code, let us set +\begin_inset Formula $T=\text{Int}$ +\end_inset + + and create a free monoid value of type +\begin_inset Formula $F_{5}^{\text{Int}}$ +\end_inset + + corresponding to the expression +\begin_inset Formula $e\oplus1\oplus e\oplus2\oplus e$ +\end_inset + +: +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +scala> val testF5 = emptyF5[Int] |+| wrapF5(1) |+| emptyF5 |+| wrapF5(2) + |+| emptyF5 +\end_layout + +\begin_layout Plain Layout + +val testF5: F5[Int] = F5(List(1, 2),None) +\end_layout + +\end_inset + +We see that the free monoid +\begin_inset Formula $F_{5}$ +\end_inset + + simplifies this expression to +\begin_inset Formula $1\oplus2\oplus e$ +\end_inset + +, although the expression should be equivalent to just +\begin_inset Formula $1\oplus2$ +\end_inset + + if we were able to use all the monoid laws. +\end_layout + +\begin_layout Standard +To evaluate the +\begin_inset Quotes eld +\end_inset + +free monoid program +\begin_inset Quotes erd +\end_inset + + +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +testF5 +\end_layout + +\end_inset + +, choose the target monoid +\begin_inset Formula $M=\text{String}$ +\end_inset + + (with the monoidal operation being the concatenation of strings). + For the purposes of this example, define the function +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +runT +\end_layout + +\end_inset + + that prints integers with up to 5 leading zeros. + Then run the program and expect the concatenation of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +\begin_inset Quotes eld +\end_inset + +00001 +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +\begin_inset Quotes eld +\end_inset + +00002 +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\end_inset + +: +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +implicit val monoidString: Monoid[String] = Monoid(_ + _, "") +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\begin_layout Plain Layout + +val runT: Int => String = (x: Int) => f +\begin_inset Quotes erd +\end_inset + +${x}%05d +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\begin_layout Plain Layout + \end_layout \begin_layout Plain Layout -}***test this code +scala> runT(123) +\end_layout + +\begin_layout Plain Layout + +val res0: String = 00123 +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\begin_layout Plain Layout + +scala> runnerF5(runT)(testF5) +\end_layout + +\begin_layout Plain Layout + +val res1: String = 0000100002 \end_layout \end_inset +The result of the evaluation is the same as if the monoid program were just + +\begin_inset Formula $1\oplus2$ +\end_inset +. + The monoid laws appear to hold after applying the runner. \end_layout \begin_layout Subsubsection @@ -21712,6 +21898,22 @@ no Solution \end_layout +\begin_layout Standard +Our goal is to define a recursive type +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +F6 +\end_layout + +\end_inset + + with the required properties. +\end_layout + \begin_layout Standard Start with the raw tree encoding, which is a binary tree with leaves of type @@ -21719,7 +21921,20 @@ Start with the raw tree encoding, which is a binary tree with leaves of \end_inset . - The left identity law ( + The type +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +F6[T] +\end_layout + +\end_inset + + must be similarly a binary tree with leaves of that type. + However, the left identity law ( \begin_inset Formula $e\oplus x=x$ \end_inset @@ -21738,65 +21953,150 @@ empty ). The right branch remains unrestricted. - To implement the restriction on the left branches, we introduce two types - of trees: a tree that cannot be an empty leaf value, and a tree that can. - ( -\emph on -Both -\emph default - trees will disallow empty leaves as left sub-trees.) + To implement the restriction on the left branches, we introduce a special + type ( \begin_inset listings -inline false +inline true status open \begin_layout Plain Layout -sealed trait TreeLeftNonEmpty[T] +TreeNonEmpty \end_layout +\end_inset + +) for a tree that cannot be an empty leaf value. + The left branches of +\begin_inset listings +inline true +status open + \begin_layout Plain Layout -final case class LeafNE[T](t: T) extends TreeLeftNonEmpty[T] +TreeNonEmpty \end_layout +\end_inset + + must also have type +\begin_inset listings +inline true +status open + \begin_layout Plain Layout -final case class BranchNE[T](left: TreeLeftNonEmpty[T], right: TreeLeftAny[T]) - extends TreeLeftNonEmpty[T] +TreeNonEmpty \end_layout +\end_inset + + (cannot be empty leaves), while the right branches are unrestricted (have + type +\begin_inset listings +inline true +status open + \begin_layout Plain Layout +F6 \end_layout +\end_inset + +). + Finally, we define the type +\begin_inset listings +inline true +status open + \begin_layout Plain Layout -sealed trait TreeLeftAny[T] +F6 \end_layout +\end_inset + + as a tree that can itself be an empty leaf, but whose left branches have + type +\begin_inset listings +inline true +status open + \begin_layout Plain Layout -final case class LeafT[T](t: T) extends TreeLeftAny[T] +TreeNonEmpty \end_layout +\end_inset + + (cannot be empty leaves). + The right branches of +\begin_inset listings +inline true +status open + \begin_layout Plain Layout -final case class LeafE[T]() extends TreeLeftAny[T] +F6 \end_layout +\end_inset + + have again type +\begin_inset listings +inline true +status open + \begin_layout Plain Layout -final case class BranchAny[T](left: TreeLeftNonEmpty[T], right: TreeLeftAny[T]) - extends TreeLeftNonEmpty[T] +F6 \end_layout +\end_inset + +. +\begin_inset listings +inline false +status open + \begin_layout Plain Layout +sealed trait TreeNE[T] // Cannot be an empty leaf. \end_layout \begin_layout Plain Layout -type F6[T] = TreeLeftAny[T] +final case class LeafNE[T](t: T) extends TreeNE[T] +\end_layout + +\begin_layout Plain Layout + +final case class BranchNE[T](left: TreeNE[T], right: F6[T]) extends TreeNE[T] +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\begin_layout Plain Layout + +sealed trait F6[T] // This tree can be an empty leaf, but its left branch. +\end_layout + +\begin_layout Plain Layout + +final case class LeafT[T](t: T) extends F6[T] +\end_layout + +\begin_layout Plain Layout + +final case class LeafE[T]() extends F6[T] +\end_layout + +\begin_layout Plain Layout + +final case class BranchF6[T](left: TreeNE[T], right: F6[T]) extends F6[T] \end_layout \end_inset @@ -21830,8 +22130,8 @@ mutually recursive types : \begin_inset Formula \begin{align*} -\text{\texttt{TreeLeftAny} in the code}:\quad & F_{6}^{T}\triangleq\bbnum 1+T+G^{T}\times F_{6}^{T}\quad,\\ -\text{\texttt{TreeLeftNonEmpty} in the code}:\quad & G^{T}\triangleq T+G^{T}\times F_{6}^{T}\quad. +\text{\texttt{F6[T]} in the code}:\quad & F_{6}^{T}\triangleq\bbnum 1+T+G^{T}\times F_{6}^{T}\quad,\\ +\text{\texttt{TreeNE[T]} in the code}:\quad & G^{T}\triangleq T+G^{T}\times F_{6}^{T}\quad. \end{align*} \end_inset @@ -21911,12 +22211,16 @@ status open \begin_layout Plain Layout -def wrapF6[T](t: T): F6[T] = LeafNE(t) +def wrapF6[T](t: T): F6[T] = LeafT(t) \end_layout \begin_layout Plain Layout -def toTreeNE[T]: TreeLeftAny[T] => TreeLeftNonEmpty[T] = { +\end_layout + +\begin_layout Plain Layout + +def toTreeNE[T]: F6[T] => TreeNE[T] = { \end_layout \begin_layout Plain Layout @@ -21931,7 +22235,7 @@ def toTreeNE[T]: TreeLeftAny[T] => TreeLeftNonEmpty[T] = { \begin_layout Plain Layout - case BranchAny(left, right) => BranchNE(left, right) + case BranchF6(left, right) => BranchNE(left, right) \end_layout \begin_layout Plain Layout @@ -21946,18 +22250,18 @@ def concatF6[T]: (F6[T], F6[T]) => F6[T] = { \begin_layout Plain Layout - case (LeafE(), x) => x // Left identity law holds automatically. + case (LeafE(), x) => x // Left identity law holds automatically. \end_layout \begin_layout Plain Layout - case (first, second) => BranchAny(toTreeNE(first), second) // `first` - is guaranteed to be non-empty. + case (first, second) => BranchF6(toTreeNE(first), second) // `first` is + guaranteed to be non-empty. \end_layout \begin_layout Plain Layout -} + } \end_layout \begin_layout Plain Layout @@ -21967,12 +22271,21 @@ def emptyF6[T]: F6[T] = LeafE() \begin_layout Plain Layout +\end_layout + +\begin_layout Plain Layout + implicit def monoidF6[T]: Monoid[F6[T]] = Monoid(concatF6[T], emptyF6[T]) \end_layout \begin_layout Plain Layout -def runnerF6NE[M: Monoid, T](runT: T => M): TreeLeftNonEmpty[T] => M = { +\end_layout + +\begin_layout Plain Layout + +def runnerF6NE[M: Monoid, T](runT: T => M)(tree: TreeNE[T]): M = tree match + { \end_layout \begin_layout Plain Layout @@ -21987,13 +22300,17 @@ def runnerF6NE[M: Monoid, T](runT: T => M): TreeLeftNonEmpty[T] => M = { \begin_layout Plain Layout - case BranchNE(left, right) => Monoid[M].combine(runnerF6NE(runT)(left), - runnerF6(runT)(right)) + case BranchNE(left, right) => runnerF6NE(runT)(left) |+| runnerF6(runT)(right) \end_layout \begin_layout Plain Layout -def runnerF6[M: Monoid, T](runT: T => M): F6[T] => M = { +} +\end_layout + +\begin_layout Plain Layout + +def runnerF6[M: Monoid, T](runT: T => M)(tree: F6[T]): M = tree match { \end_layout \begin_layout Plain Layout @@ -22008,18 +22325,117 @@ def runnerF6[M: Monoid, T](runT: T => M): F6[T] => M = { \begin_layout Plain Layout - case BranchAny(left, right) => Monoid[M].combine(runnerF6NE(runT)(left), - runnerF6(runT)(right)) + case BranchF6(left, right) => runnerF6NE(runT)(left) |+| runnerF6(runT)(right) \end_layout \begin_layout Plain Layout -}***test this code +} \end_layout \end_inset - *** + +\end_layout + +\begin_layout Standard +We test this code with the same data as in the previous example. +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +scala> val testF6 = emptyF6[Int] |+| wrapF6(1) |+| emptyF6 |+| wrapF6(2) + |+| emptyF6 +\end_layout + +\begin_layout Plain Layout + +val testF6: F6[Int] = BranchF6(BranchNE(BranchNE(LeafNE(1),LeafE()),LeafT(2)),Le +afE()) +\end_layout + +\end_inset + +We see that the monoid program +\begin_inset Formula $(((e\oplus1)\oplus e)\oplus2)\oplus e$ +\end_inset + + is simplified to the expression tree +\begin_inset Formula $((1\oplus e)\oplus2)\oplus e$ +\end_inset + + because the free monoid +\begin_inset Formula $F_{6}$ +\end_inset + + only respects the left identity law but not the associativity law. +\end_layout + +\begin_layout Standard +Apply +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +runnerF6 +\end_layout + +\end_inset + + to +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +testF6 +\end_layout + +\end_inset + + using the same function +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +runT +\end_layout + +\end_inset + + as before: +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +scala> runnerF6(runT)(testF6) +\end_layout + +\begin_layout Plain Layout + +val res1: String = 0000100002 +\end_layout + +\end_inset + +This is the same result as in the previous example. +\end_layout + +\begin_layout Standard +***Exercises: free monoids that satisfy the right identity law and the associati +vity law; or just the right identity law. + Use a sorted list to implement commutativity law for semigroups and for + monoids. + Find a free semigroup that is commutative but not associative. \end_layout \begin_layout Subsection @@ -22071,11 +22487,12 @@ fmap \end_inset - method is not available for some type constructors + method is supported by all covariant type constructors, but is not available + when \begin_inset Formula $F$ \end_inset -, such as contrafunctors or GADTs. + is a contrafunctor or a GADT. (See Section \begin_inset space ~ \end_inset diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 1028f3c20..272f27d85 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -6091,7 +6091,8 @@ noprefix "false" We again start with the raw tree encoding and then discover several reduced encodings by imposing different subsets of laws. To illustrate the relationships between reduced encodings of a free typeclass, - we consider four different encodings of the free monoid (denoted by + we write down the code for 4 different encodings of the free monoid (denoted + by \begin_inset Formula $F_{1}$ \end_inset @@ -6108,12 +6109,28 @@ noprefix "false" \end_inset ). - We find that a free monoid encoding can be injectively mapped into any - other encoding that obeys + We find that a given free monoid encoding can be injectively mapped into + any other encoding that obeys \emph on fewer \emph default laws; but those injective maps do not preserve the monoid operations. + A given encoding may be mapped surjectively onto another encoding that + satisfies the same laws (and possibly more laws). +\end_layout + +\begin_layout Standard +As there are 3 monoid laws, we can construct 8 different free monoid encodings + that obey each of the 8 possible subsets of the three laws. + To illustrate the required techniques, we show two more encodings: +\begin_inset Formula $F_{5}$ +\end_inset + + obeying the left identity law and the associativity law, and +\begin_inset Formula $F_{6}$ +\end_inset + + obeying only the left identity law but no other monoid laws. \end_layout \begin_layout Standard From faa890c950ef76b5392bbfd436e4b10f3f889007 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Wed, 12 Nov 2025 10:53:33 +0100 Subject: [PATCH 31/42] wip --- sofp-src/lyx/sofp-free-type.lyx | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/sofp-src/lyx/sofp-free-type.lyx b/sofp-src/lyx/sofp-free-type.lyx index c03723be3..273d1c05a 100644 --- a/sofp-src/lyx/sofp-free-type.lyx +++ b/sofp-src/lyx/sofp-free-type.lyx @@ -19333,7 +19333,11 @@ fromNEL \end_inset - does not!). + does +\emph on +not +\emph default +). It is a general property of free typeclass constructions that there is only one typeclass-preserving function of type \begin_inset listings @@ -19380,6 +19384,17 @@ noprefix "false" operations. \end_layout +\begin_layout Standard +*** There are also alternative implementations of the universal runner that + correspond to those functions. + When the universal runner is applied with a lawful semigroup, the results + are the same. + But when we use SFR instead of a lawful semigroup, the results are not + the same. + We see that it is important to take into account which laws hold when using + the universal runner.*** +\end_layout + \begin_layout Subsection Free monoid and its reduced encodings \begin_inset CommandInset label @@ -22433,9 +22448,13 @@ This is the same result as in the previous example. \begin_layout Standard ***Exercises: free monoids that satisfy the right identity law and the associati vity law; or just the right identity law. + Find a map between free monoids that satisfy the right identity law and + that satisfy the left; show that operations are not preserved and that + maps are not injective. Use a sorted list to implement commutativity law for semigroups and for monoids. Find a free semigroup that is commutative but not associative. + \end_layout \begin_layout Subsection From 9eb07481f0d8a126d77e6499e5a830029f096521 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Mon, 8 Dec 2025 12:12:01 +0100 Subject: [PATCH 32/42] wip --- sofp-src/lyx/sofp-appendices.lyx | 144 ++++++- sofp-src/lyx/sofp-free-type.lyx | 509 +++++++++++++++++++------ sofp-src/lyx/sofp-monads.lyx | 12 +- sofp-src/lyx/sofp-summary.lyx | 85 ++++- sofp-src/lyx/sofp-transformers.lyx | 202 ++++------ sofp-src/lyx/sofp-traversable.lyx | 2 +- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-back-cover-no-bg.tex | 2 +- sofp-src/tex/sofp-free-type.tex | 419 +++++++++++++------- sofp-src/tex/sofp-monads.tex | 10 +- sofp-src/tex/sofp-summary.tex | 28 +- sofp-src/tex/sofp-traversable.tex | 4 +- sofp-src/tex/sofp.tex | 8 +- 13 files changed, 1019 insertions(+), 406 deletions(-) diff --git a/sofp-src/lyx/sofp-appendices.lyx b/sofp-src/lyx/sofp-appendices.lyx index 113012d87..f121c5181 100644 --- a/sofp-src/lyx/sofp-appendices.lyx +++ b/sofp-src/lyx/sofp-appendices.lyx @@ -63321,7 +63321,7 @@ noprefix "false" (a) \series default Denote for brevity -\begin_inset Formula $\text{Cod}_{F}^{M,A}\triangleq C^{A}$ +\begin_inset Formula $C^{A}\triangleq\text{Cod}_{F}^{M,A}$ \end_inset . @@ -63421,7 +63421,7 @@ In the last line, we have used the naturality law of \end_inset -which follows from the associativity law of +which disappears due to the associativity law of \begin_inset Formula $\text{ftn}_{M}$ \end_inset @@ -63445,10 +63445,14 @@ flatMap \end_inset - method must have the type signature: + method of +\begin_inset Formula $P$ +\end_inset + + must have the type signature: \begin_inset Formula \[ -\text{flm}_{L}:\big((A\rightarrow X)\rightarrow M^{X}\big)\rightarrow(A\rightarrow(B\rightarrow X)\rightarrow M^{X})\rightarrow(B\rightarrow X)\rightarrow M^{X}\quad. +\text{flm}_{P}:\big((A\rightarrow X)\rightarrow M^{X}\big)\rightarrow(A\rightarrow(B\rightarrow X)\rightarrow M^{X})\rightarrow(B\rightarrow X)\rightarrow M^{X}\quad. \] \end_inset @@ -63460,8 +63464,8 @@ Choose ; now we need to implement the type signature: \begin_inset Formula \begin{align*} - & \text{flm}_{L}:\big((A\rightarrow X)\rightarrow\bbnum 1+X\big)\rightarrow\left(A\rightarrow(B\rightarrow X)\rightarrow\bbnum 1+X\right)\rightarrow(B\rightarrow X)\rightarrow\bbnum 1+X\quad,\\ - & \text{flm}_{L}\triangleq p^{:(A\rightarrow X)\rightarrow\bbnum 1+X}\rightarrow q^{:\left(A\rightarrow(B\rightarrow X)\rightarrow\bbnum 1+X\right)}\rightarrow r^{:B\rightarrow X}\rightarrow\text{???}^{:\bbnum 1+X}\quad. + & \text{flm}_{P}:\big((A\rightarrow X)\rightarrow\bbnum 1+X\big)\rightarrow\left(A\rightarrow(B\rightarrow X)\rightarrow\bbnum 1+X\right)\rightarrow(B\rightarrow X)\rightarrow\bbnum 1+X\quad,\\ + & \text{flm}_{P}\triangleq p^{:(A\rightarrow X)\rightarrow\bbnum 1+X}\rightarrow q^{:\left(A\rightarrow(B\rightarrow X)\rightarrow\bbnum 1+X\right)}\rightarrow r^{:B\rightarrow X}\rightarrow\text{???}^{:\bbnum 1+X}\quad. \end{align*} \end_inset @@ -63515,23 +63519,135 @@ Can this function ever return a value of type , which is not guaranteed to return nonempty values. So, the only way of implementing -\begin_inset listings -inline true -status open +\begin_inset Formula $\text{flm}_{P}$ +\end_inset -\begin_layout Plain Layout + via fully parametric code is to return the constant value +\begin_inset Formula $1+\bbnum 0^{:X}$ +\end_inset -flatMap +. + This would lose information and violate an identity law of monads. \end_layout +\begin_layout Standard + +\series bold +(c) +\series default + In general, the type +\begin_inset Formula $\forall A.\,M^{A}\rightarrow\forall X.\,(A\rightarrow F^{X})\rightarrow F^{M^{X}}$ \end_inset - via fully parametric code is to return the constant value -\begin_inset Formula $1+\bbnum 0^{:X}$ + is equivalent (via the contravariant Yoneda identity) to +\begin_inset Formula $\forall X.\,M^{F^{X}}\rightarrow F^{M^{X}}$ \end_inset . - This would lose information and violate an identity law of monads. + This cannot be implemented as a natural transformation for arbitrary monads + +\begin_inset Formula $M$ +\end_inset + + and functors +\begin_inset Formula $F$ +\end_inset + +. +\end_layout + +\begin_layout Standard +A simple counterexample is found with +\begin_inset Formula $M^{A}\triangleq R\rightarrow A$ +\end_inset + + and +\begin_inset Formula $F^{A}\triangleq\bbnum 1+A$ +\end_inset + +. + Consider a function +\begin_inset Formula $f$ +\end_inset + + with the type signature of a monad morphism +\begin_inset Formula $\forall A.\,M^{A}\rightarrow\text{Cod}_{F}^{M,A}$ +\end_inset + + with these +\begin_inset Formula $F$ +\end_inset + + and +\begin_inset Formula $M$ +\end_inset + +: +\begin_inset Formula +\[ +f:\forall A.\,(R\rightarrow A)\rightarrow\forall X.\,(A\rightarrow\bbnum 1+X)\rightarrow\bbnum 1+(R\rightarrow X)\quad. +\] + +\end_inset + +Can +\begin_inset Formula $f$ +\end_inset + + be a monad morphism? We can simplify the type of +\begin_inset Formula $f$ +\end_inset + + by using the covariant Yoneda identity: +\begin_inset Formula +\begin{align*} + & \forall A.\,(R\rightarrow A)\rightarrow\forall X.\,(A\rightarrow\bbnum 1+X)\rightarrow\bbnum 1+(R\rightarrow X)\\ + & \cong\forall X.\,(R\rightarrow\bbnum 1+X)\rightarrow\bbnum 1+(R\rightarrow X)\quad. +\end{align*} + +\end_inset + +A function of type +\begin_inset Formula $\forall X.\,(R\rightarrow\bbnum 1+X)\rightarrow\bbnum 1+(R\rightarrow X)$ +\end_inset + + cannot make decisions based on its argument (of type +\begin_inset Formula $R\rightarrow\bbnum 1+X$ +\end_inset + +) as +\begin_inset Formula $R$ +\end_inset + + and +\begin_inset Formula $X$ +\end_inset + + are unknown types. + The function cannot always return +\begin_inset Formula $\bbnum 0+(R\rightarrow X)$ +\end_inset + + as the function of type +\begin_inset Formula $R\rightarrow\bbnum 1+X$ +\end_inset + + could fail to return a value of type +\begin_inset Formula $X$ +\end_inset + + for some argument values +\begin_inset Formula $r^{:R}$ +\end_inset + +. + So, the function must always return +\begin_inset Formula $\bbnum 1+\bbnum 0^{:R\rightarrow X}$ +\end_inset + +. + But that code would lose information and fail the identity law of monad + morphisms. \end_layout \begin_layout Addsec diff --git a/sofp-src/lyx/sofp-free-type.lyx b/sofp-src/lyx/sofp-free-type.lyx index 273d1c05a..c092727cc 100644 --- a/sofp-src/lyx/sofp-free-type.lyx +++ b/sofp-src/lyx/sofp-free-type.lyx @@ -19389,7 +19389,10 @@ noprefix "false" correspond to those functions. When the universal runner is applied with a lawful semigroup, the results are the same. - But when we use SFR instead of a lawful semigroup, the results are not + But when we use SFR instead of a lawful semigroup, the results are +\emph on +not +\emph default the same. We see that it is important to take into account which laws hold when using the universal runner.*** @@ -22627,8 +22630,8 @@ This code corresponds to the following notation for the lifting : \begin_inset Formula \begin{align} - & \text{FFR}^{F^{\bullet},A}\triangleq F^{A}+\exists X.\,(X\rightarrow A)\times\text{FFR}^{F^{\bullet},X}\quad,\label{eq:definition-FFR-existential-type}\\ - & p^{:\text{FFR}^{F^{\bullet},A}}\triangleright(f^{:A\rightarrow B})^{\uparrow\text{FFR}^{F^{\bullet},\bullet}}\triangleq\bbnum 0^{:F^{B}}+\exists^{A}.\,f^{:A\rightarrow B}\times p^{:\text{FFR}^{F^{\bullet},A}}\quad.\nonumber + & \text{FFR}^{F,A}\triangleq F^{A}+\exists X.\,(X\rightarrow A)\times\text{FFR}^{F,X}\quad,\label{eq:definition-FFR-existential-type}\\ + & p^{:\text{FFR}^{F,A}}\triangleright(f^{:A\rightarrow B})^{\uparrow\text{FFR}^{F,\bullet}}\triangleq\bbnum 0^{:F^{B}}+\exists^{A}.\,f^{:A\rightarrow B}\times p^{:\text{FFR}^{F,A}}\quad.\nonumber \end{align} \end_inset @@ -22660,7 +22663,7 @@ noprefix "false" \end_inset ) of -\begin_inset Formula $\text{FFR}^{F^{\bullet},B}$ +\begin_inset Formula $\text{FFR}^{F,B}$ \end_inset . @@ -22783,7 +22786,7 @@ noprefix "false" \end_inset . - Now we can write the code of the runner for + Now we can write the code of the universal runner for \begin_inset Formula $\text{FFR}^{F,A}$ \end_inset @@ -22809,7 +22812,7 @@ def runFFR[F[_], A](runner: Runner[F]): FFR[F, A] => A = { \begin_layout Plain Layout -}*** check if this works +} \end_layout \end_inset @@ -22817,17 +22820,17 @@ def runFFR[F[_], A](runner: Runner[F]): FFR[F, A] => A = { The code notation for this function is: \begin_inset Formula \begin{align*} - & \text{runFFR}^{F^{\bullet},A}:(\forall C.\,F^{C}\rightarrow C)\rightarrow\text{FFR}^{F^{\bullet},A}\rightarrow A\quad,\\ + & \text{runFFR}^{F,A}:(\forall C.\,F^{C}\rightarrow C)\rightarrow\text{FFR}^{F,A}\rightarrow A\quad,\\ & \text{runFFR}(\text{run}:\forall C.\,F^{C}\rightarrow C)\triangleq\forall B.\,\,\begin{array}{|c||c|} & A\\ \hline F^{A} & \text{run}\\ -(B\rightarrow A)\times\text{FFR}^{F^{\bullet},B} & f^{:B\rightarrow A}\times p^{:FFR^{F^{\bullet},B}}\rightarrow p\triangleright\big(\overline{\text{runFFR}}(\text{run})\big)\triangleright f +(B\rightarrow A)\times\text{FFR}^{F,B} & f^{:B\rightarrow A}\times p^{:FFR^{F,B}}\rightarrow p\triangleright\big(\overline{\text{runFFR}}(\text{run})\big)\triangleright f \end{array}\quad. \end{align*} \end_inset -The outside universal quantifier +The outside quantifier \begin_inset Formula $\forall B$ \end_inset @@ -22853,7 +22856,7 @@ noprefix "false" \end_layout \begin_layout Standard -More generally, we may want to run the effects of +More generally, we may need to run the effects of \begin_inset Formula $F$ \end_inset @@ -22867,18 +22870,23 @@ More generally, we may want to run the effects of \end_inset could, for example, describe errors or asynchronous execution.) The correspondin -g runner will have type +g effect runner will have type \begin_inset Formula $\forall C.\,F^{C}\rightarrow G^{C}$ \end_inset -, and the code is: + instead of +\begin_inset Formula $\forall C.\,F^{C}\rightarrow C$ +\end_inset + +. + The code for the universal runner is: \begin_inset Formula \begin{align*} - & \text{runFFR}^{F^{\bullet},G^{\bullet},A}:(\forall C.\,F^{C}\rightarrow G^{C})\rightarrow\text{FFR}^{F^{\bullet},A}\rightarrow G^{A}\quad,\\ + & \text{runFFR}^{F,G,A}:(\forall C.\,F^{C}\rightarrow G^{C})\rightarrow\text{FFR}^{F,A}\rightarrow G^{A}\quad,\\ & \text{runFFR}\,(\text{run})\triangleq\forall B.\,\,\begin{array}{|c||c|} & G^{A}\\ \hline F^{A} & \text{run}\\ -(B\rightarrow A)\times\text{FFR}^{F^{\bullet},B} & f^{:B\rightarrow A}\times p^{:FFR^{F^{\bullet},B}}\rightarrow p\triangleright\big(\overline{\text{runFFR}}\,(\text{run})\big)\triangleright f^{\uparrow G} +(B\rightarrow A)\times\text{FFR}^{F,B} & f^{:B\rightarrow A}\times p^{:FFR^{F,B}}\rightarrow p\triangleright\big(\overline{\text{runFFR}}\,(\text{run})\big)\triangleright f^{\uparrow G} \end{array}\quad. \end{align*} @@ -22887,6 +22895,14 @@ g runner will have type \end_layout +\begin_layout Standard +*** example code: what if +\begin_inset Formula $\forall C.\,F^{C}\rightarrow C$ +\end_inset + + cannot be implemented? What is sufficient +\end_layout + \begin_layout Standard The type constructor \begin_inset listings @@ -22954,7 +22970,7 @@ noprefix "false" \begin_layout Standard Take any free functor ( -\begin_inset Formula $\text{FFR}^{F^{\bullet},A}$ +\begin_inset Formula $\text{FFR}^{F,A}$ \end_inset ) and any runner ( @@ -22967,12 +22983,12 @@ Take any free functor ( is a lawful functor. Denote for brevity -\begin_inset Formula $f^{\uparrow\text{FFR}}\triangleq f^{\uparrow\text{FFR}^{F^{\bullet},\bullet}}$ +\begin_inset Formula $f^{\uparrow\text{FFR}}\triangleq f^{\uparrow\text{FFR}^{F,\bullet}}$ \end_inset . - The functor laws will hold if we apply the runner function, denoted for - brevity by + The functor laws will hold after applying the runner function, denoted + for brevity by \begin_inset Formula $\rho\triangleq\text{runFFR}\,(\text{run})$ \end_inset @@ -23080,8 +23096,7 @@ The right-hand side is then simplified to the same code: \begin_layout Standard To transform the raw tree encoding of the free functor into a reduced encoding, we require that all functor laws should hold even before applying a runner. - We begin by finding out in detail why the functor laws fail to hold for - + We begin by finding out in detail why the functor laws fail for \begin_inset listings inline true status open @@ -23440,19 +23455,7 @@ F \begin_inset Formula $F$ \end_inset --effects by the -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -FMap -\end_layout - -\end_inset - - case class as +-effects by the expression \begin_inset listings inline true status open @@ -23594,7 +23597,7 @@ f \end_inset . - So, we may remove the + It means we may remove the \begin_inset listings inline true status open @@ -23607,11 +23610,94 @@ Op \end_inset case class altogether. + Only one case class ( +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +FMap \end_layout -\begin_layout Standard -The result is a simplified definition of the free functor. - The complete code is: +\end_inset + +) remains. + However, we still need to implement the free functor as a trait +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +FF[F, A] +\end_layout + +\end_inset + + containing a single case class +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +FMap[F, C, A] +\end_layout + +\end_inset + +. + This is because +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +FMap[F, C, A] +\end_layout + +\end_inset + + has an extra type parameter ( +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +C +\end_layout + +\end_inset + +) that does not appear in +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +FF[F, A] +\end_layout + +\end_inset + +. + (In other words, the type parameter +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +X +\end_layout + +\end_inset + + is existentially quantified.) The complete code is: \begin_inset listings inline false status open @@ -23633,12 +23719,12 @@ sealed trait FF[F[_], A] { \begin_layout Plain Layout -final case class FMap[F[_], X, Y](f: X => Y, p: F[X]) extends FF[F, Y] { +final case class FMap[F[_], C, A](f: C => A, p: F[C]) extends FF[F, A] { \end_layout \begin_layout Plain Layout - def map[Z](g: Y => Z): FF[F, Z] = FMap[F, X, Z](f andThen g, p) + def map[B](g: A => B): FF[F, B] = FMap[F, C, B](f andThen g, p) \end_layout \begin_layout Plain Layout @@ -23658,7 +23744,7 @@ def runFF[F[_], A](runner: Runner[F]): FF[F, A] => A = { \begin_layout Plain Layout -}*** check if this works +} \end_layout \end_inset @@ -23667,11 +23753,11 @@ def runFF[F[_], A](runner: Runner[F]): FF[F, A] => A = { \end_layout \begin_layout Standard -The code notation for this code and a general runner is: +The code notation for this code is: \begin_inset Formula \begin{align*} - & \text{FF}^{F^{\bullet},A}\triangleq\exists C.\,\left(C\rightarrow A\right)\times F^{C}\quad,\quad\quad(\exists C.\,f^{:C\rightarrow A}\times p^{:F^{C}})\triangleright(g^{:A\rightarrow B})^{\uparrow\text{FR}}\triangleq\exists^{C}.\,(f\bef g)\times p\quad,\\ - & \text{runFF}:(\forall C.\,F^{C}\rightarrow G^{C})\rightarrow\text{FF}^{F^{\bullet},A}\rightarrow G^{A}\quad,\\ + & \text{FF}^{F,A}\triangleq\exists C.\,\left(C\rightarrow A\right)\times F^{C}\quad,\quad\quad(\exists C.\,f^{:C\rightarrow A}\times p^{:F^{C}})\triangleright(g^{:A\rightarrow B})^{\uparrow\text{FR}}\triangleq\exists^{C}.\,(f\bef g)\times p\quad,\\ + & \text{runFF}:(\forall C.\,F^{C}\rightarrow G^{C})\rightarrow\text{FF}^{F,A}\rightarrow G^{A}\quad,\\ & \text{runFF}\,(\text{run})\triangleq(\exists C.\,f^{:C\rightarrow A}\times p^{:F^{C}})\rightarrow p\triangleright\text{run}\triangleright f^{\uparrow G}\quad. \end{align*} @@ -23709,7 +23795,7 @@ FF[F, A] \end_inset - even before applying a runner. +. \end_layout \begin_layout Standard @@ -23817,7 +23903,7 @@ co-Yoneda identity \end_inset -We will prove this type equivalence in Statement +We will prove this type identity in Statement \begin_inset space ~ \end_inset @@ -23920,54 +24006,55 @@ FMap(f andThen g, p) . The Scala compiler cannot directly handle the composition of a large number - of functions without causing a stack overflow. - This problem can be resolved if we postpone the function composition and - instead create a list of functions that need to be composed. - The runner can evaluate the list of functions without running into a stack - overflow. -\end_layout - -\begin_layout Standard -This gives us an idea for another encoding of the stack-safe free functor, - which we will call + of functions without causing a stack overflow: \begin_inset listings -inline true +inline false status open \begin_layout Plain Layout -FFS +def composed(n: Int): Long => Long = (1 to n).foldLeft[Long => Long](x => + x){ (prev, i) => prev andThen (x => x + i) } \end_layout -\end_inset +\begin_layout Plain Layout -. - First, we implement a data structure called -\begin_inset listings -inline true -status open +\end_layout \begin_layout Plain Layout -FuncSeq +scala> composed(100)(0) // OK to compose 100 functions. \end_layout -\end_inset +\begin_layout Plain Layout - for storing a list of functions with matching types. - A value of type -\begin_inset listings -inline true -status open +res0: Long = 5050 +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\begin_layout Plain Layout + +scala> composed(100000)(0) // Cannot compose 100000 functions. +\end_layout \begin_layout Plain Layout -FuncSeq[A, B] +java.lang.StackOverflowError \end_layout \end_inset - holds a list of functions with types +This code causes a stack overflow because each function composition creates + a new stack frame when functions are applied. +\end_layout + +\begin_layout Standard +Stack overflows can be avoided if we postpone the function compositions. + Instead, we just store all the functions that need to be composed as a + sequence of functions with types \begin_inset Formula $A\rightarrow C_{1}$ \end_inset @@ -23987,113 +24074,272 @@ FuncSeq[A, B] \begin_inset Formula $C_{i}$ \end_inset - are some chosen types. - A list of with those types can be composed to yield a function of type + are some fixed types. + Then we write a +\begin_inset Quotes eld +\end_inset + +runner +\begin_inset Quotes erd +\end_inset + + that applies the functions one by one to a given initial value of type +\begin_inset Formula $A$ +\end_inset + +. + The result is as if we have evaluated a single function of type \begin_inset Formula $A\rightarrow B$ \end_inset . - To simplify code, we will cast all intermediate types to +\end_layout + +\begin_layout Standard +Here is an example implementation of this idea. + Define a helper class \begin_inset listings inline true status open \begin_layout Plain Layout -Any +SafeFunction \end_layout \end_inset - and back. - Our code will take care to construct + as a subclass of \begin_inset listings inline true status open \begin_layout Plain Layout -FuncSeq +A => B \end_layout \end_inset - values with correct types. + that overrides the composition methods ( \begin_inset listings inline true status open \begin_layout Plain Layout -final case class FuncSeq[X, Y](first: X => Any, funcs: Vector[Any => Any]) - { +compose \end_layout +\end_inset + +, +\begin_inset listings +inline true +status open + \begin_layout Plain Layout - def append[Z](g: Y => Z): FuncSeq[X, Z] = FuncSeq(first, funcs :+ g.asInstanceO -f[Any => Any]) +andThen \end_layout +\end_inset + +). + Instead of composing the functions immediately, the new function bodies + are added to a sequence of already stored functions. + The +\begin_inset listings +inline true +status open + \begin_layout Plain Layout -} +apply \end_layout \end_inset + method is the +\begin_inset Quotes eld +\end_inset +runner +\begin_inset Quotes erd +\end_inset + + for computing the final result in constant stack space. \end_layout \begin_layout Standard -To ensure stack safety when working with +To simplify code, we will store functions in a sequence of type \begin_inset listings inline true status open \begin_layout Plain Layout -FuncSeq +Vector[Any => Any] \end_layout \end_inset -, we implement a tail-recursive function +;; type safety will be guaranteed when constructing values of type \begin_inset listings inline true status open \begin_layout Plain Layout -runSeq +SafeFunction \end_layout \end_inset - that composes all functions stored in the sequence and applies them to - a given value. +. + The choice of the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Vector +\end_layout + +\end_inset + + container type allows us efficient appending and prepending to the sequence. + +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +final case class SafeFunction[A, B](funcs: Vector[Any => Any]) extends (A + => B) { +\end_layout + +\begin_layout Plain Layout + + def apply(a: A): B = funcs.foldLeft[Any](a){ (prev, func) => func(prev) + }.asInstanceOf[B] +\end_layout + +\begin_layout Plain Layout + + override def andThen[C](g: B => C): A => C = +\end_layout + +\begin_layout Plain Layout + + SafeFunction(funcs :+ g.asInstanceOf[Any => Any]) +\end_layout + +\begin_layout Plain Layout + + override def compose[C](g: C => A): C => B = +\end_layout + +\begin_layout Plain Layout + + SafeFunction(g.asInstanceOf[Any => Any] +: funcs) +\end_layout + +\begin_layout Plain Layout + +} +\end_layout + +\end_inset + + \end_layout \begin_layout Standard +Converting an ordinary function to a +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +SafeFunction +\end_layout + +\end_inset + + is straightforward: \begin_inset listings inline false status open \begin_layout Plain Layout -@tailrec def runSeq[X, Y](x: X, p: FuncSeq[X, Y]): Y = p.funcs.headOption - match { +def toSafeFunction[A, B](f: A => B): SafeFunction[A, B] = f match { +\end_layout + +\begin_layout Plain Layout + + case SafeFunction(_) => f.asInstanceOf[SafeFunction[A, B]] +\end_layout + +\begin_layout Plain Layout + + case _ => SafeFunction(Vector(f.asInstanceOf[Any => Any])) +\end_layout + +\begin_layout Plain Layout + +} \end_layout +\end_inset + +For convenience, we also define the corresponding extension methods ( +\begin_inset listings +inline true +status open + \begin_layout Plain Layout - case None => p.first(x).asInstanceOf[Y] +safeAndThen \end_layout +\end_inset + +, +\begin_inset listings +inline true +status open + \begin_layout Plain Layout - case Some(second) => runSeq(p.first(x), FuncSeq(second, p.funcs.tail)) +safeCompose +\end_layout + +\end_inset + +) on ordinary functions: +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +implicit class SafeCompose[A, B](f: A => B) { +\end_layout + +\begin_layout Plain Layout + + def safeAndThen[C](g: B => C): A => C = toSafeFunction(f).andThen(g) +\end_layout + +\begin_layout Plain Layout + + def safeCompose[C](g: C => A): C => B = toSafeFunction(f).compose(g) \end_layout \begin_layout Plain Layout @@ -24103,7 +24349,54 @@ status open \end_inset -Now we can write the code of the free functor + +\end_layout + +\begin_layout Standard +Millions of functions can be now composed with no stack overflow: +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +def safeComposed(n: Int): Long => Long = (1 to n).foldLeft[Long => Long](x + => x){ (prev, i) => prev.safeAndThen(x => x + i) } +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\begin_layout Plain Layout + +scala> safeComposed(10000000)(0) // Compose 10 million functions. +\end_layout + +\begin_layout Plain Layout + +res1: Long = 50000005000000 +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Standard +We use +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +safeAndThen +\end_layout + +\end_inset + + to obtain a stack-safe encoding of the free functor ( \begin_inset listings inline true status open @@ -24115,7 +24408,7 @@ FFS \end_inset -: +) with no changes in the runner: \begin_inset listings inline false status open @@ -24137,13 +24430,13 @@ sealed trait FFS[F[_], A] { \begin_layout Plain Layout -final case class FMap[F[_], X, Y](f: FuncSeq[X, Y], p: F[X]) extends FFS[F, - Y] { +final case class FMap[F[_], X, Y](f: X => Y, p: F[X]) extends FFS[F, Y] + { \end_layout \begin_layout Plain Layout - def map[Z](g: Y => Z): FFS[F, Z] = FMap[F, X, Z](f append g, p) + def map[Z](g: Y => Z): FFS[F, Z] = FMap[F, X, Z](f.safeAndThen(g), p) \end_layout \begin_layout Plain Layout @@ -24158,17 +24451,17 @@ def runFF[F[_], A](runner: Runner[F]): FFS[F, A] => A = { \begin_layout Plain Layout - case FMap(f, p) => runSeq(runner.apply(p), f) + case FMap(f, p) => f(runner.apply(p)) \end_layout \begin_layout Plain Layout -}*** check if this works +} \end_layout \end_inset - +Test this code: *** \end_layout \begin_layout Subsection @@ -24185,7 +24478,7 @@ Method \begin_layout Standard Tree encoding: -\begin_inset Formula $\text{FreeCF}^{F^{\bullet},B}\triangleq F^{B}+\exists A.\text{FreeCF}^{F^{\bullet},A}\times\left(B\rightarrow A\right)$ +\begin_inset Formula $\text{FreeCF}^{F,B}\triangleq F^{B}+\exists A.\text{FreeCF}^{F,A}\times\left(B\rightarrow A\right)$ \end_inset @@ -24193,7 +24486,7 @@ Tree encoding: \begin_layout Standard Reduced encoding: -\begin_inset Formula $\text{FreeCF}^{F^{\bullet},B}\triangleq\exists A.F^{A}\times\left(B\rightarrow A\right)$ +\begin_inset Formula $\text{FreeCF}^{F,B}\triangleq\exists A.F^{A}\times\left(B\rightarrow A\right)$ \end_inset @@ -24201,7 +24494,7 @@ Reduced encoding: \begin_layout Standard A value of type -\begin_inset Formula $\text{FreeCF}^{F^{\bullet},B}$ +\begin_inset Formula $\text{FreeCF}^{F,B}$ \end_inset must be of the form @@ -24279,11 +24572,11 @@ def prefixLog[A](p: A): A \begin_layout Standard If -\begin_inset Formula $F^{\bullet}$ +\begin_inset Formula $F$ \end_inset is already a contrafunctor then -\begin_inset Formula $\text{FreeCF}^{F^{\bullet},A}\cong F^{A}$ +\begin_inset Formula $\text{FreeCF}^{F,A}\cong F^{A}$ \end_inset diff --git a/sofp-src/lyx/sofp-monads.lyx b/sofp-src/lyx/sofp-monads.lyx index 5ff337fd4..e4d47ab61 100644 --- a/sofp-src/lyx/sofp-monads.lyx +++ b/sofp-src/lyx/sofp-monads.lyx @@ -13424,11 +13424,11 @@ Eval status open \begin_layout Plain Layout -monads!lazy/eager evaluation monad ( +monads! \family typewriter Eval \family default -) + (lazy/eager evaluation monad) \end_layout \end_inset @@ -37776,11 +37776,13 @@ status open \end_layout \begin_layout Standard -We have shown some examples of +The concepts of \begin_inset Formula $M$ \end_inset --filterable functors in Statement +-filterable functors and contrafunctors are not well known and not widely + used. + To build up intuition, we have shown some examples in Statement \begin_inset space ~ \end_inset @@ -37813,7 +37815,7 @@ In the following constructions, we assume that \end_layout \begin_layout Standard -We omit the proofs of all following statements because they are fully analogous +We omit the proofs of all the following statements because they are analogous to the proofs of filterable functor and contrafunctor constructions in Sections \begin_inset space ~ diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 272f27d85..058131b53 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -4435,7 +4435,90 @@ We formally define the property of commutativity for applicative functors and show how it simplifies the other laws. Most applicative functors used in practice are commutative and are suitable for parallel evaluation. - +\end_layout + +\begin_layout Standard +Many applicative functors are at the same time monads. + However, most monads used in practice are +\emph on +not +\emph default + commutative. + For this reason, it is typically not the case that applicative functors + have their +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + functions derived from +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + +. + For example, the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +List +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Either +\end_layout + +\end_inset + + are monads whose standard +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + methods do not follow from the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +flatMap +\end_layout + +\end_inset + + code for those monads. \end_layout \begin_layout Standard diff --git a/sofp-src/lyx/sofp-transformers.lyx b/sofp-src/lyx/sofp-transformers.lyx index 3b42be142..73e89f180 100644 --- a/sofp-src/lyx/sofp-transformers.lyx +++ b/sofp-src/lyx/sofp-transformers.lyx @@ -45533,16 +45533,7 @@ noprefix "false" \end_layout \begin_layout Standard -Assume a monad -\begin_inset Formula $K^{R,\bullet}$ -\end_inset - - with an extra type parameter -\begin_inset Formula $R$ -\end_inset - -. - In other words, +Assume \begin_inset Formula $K^{R,A}$ \end_inset @@ -45550,7 +45541,7 @@ Assume a monad \begin_inset Formula $A$ \end_inset - and with a fixed + and with a fixed type \begin_inset Formula $R$ \end_inset @@ -45576,7 +45567,11 @@ Assume a monad \begin_inset Formula $L^{\bullet}\leadsto K^{R,\bullet}$ \end_inset -. + (that is, +\begin_inset Formula $\forall A.\,L^{A}\rightarrow K^{R,A}$ +\end_inset + +). \end_layout \begin_layout Subparagraph @@ -62625,86 +62620,12 @@ monads!free pointed \begin_inset Note Note status collapsed -\begin_layout Plain Layout -Exercise -\begin_inset CommandInset ref -LatexCommand ref -reference "par:Exercise-mt-3-2" -plural "false" -caps "false" -noprefix "false" - -\end_inset - - -\end_layout - -\begin_layout Plain Layout - -\series bold -(a) -\series default - Given a monad morphism -\begin_inset Formula $\phi:K\leadsto L$ -\end_inset - -, show that one can implement a monad morphism -\begin_inset Formula $\delta:K\leadsto\text{Opt}$ -\end_inset - -. -\end_layout - -\begin_layout Plain Layout - -\series bold -(b)*??? -\series default - Given a monad morphism -\begin_inset Formula $\delta:K\leadsto\text{Opt}$ -\end_inset - - (from -\begin_inset Formula $K$ -\end_inset - - to the -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -Option -\end_layout - -\end_inset - - monad), show that one can implement a monad morphism -\begin_inset Formula $\phi:K\leadsto L$ -\end_inset - -. -\end_layout - -\begin_layout Plain Layout -– Not clear that we can actually prove part -\series bold -(b) -\series default -! -\end_layout - \begin_layout Plain Layout Solution \end_layout \begin_layout Plain Layout - -\series bold -(a) -\series default - Consider the monad morphism +Consider the monad morphism \begin_inset Formula $\varepsilon:K\leadsto\bbnum 1$ \end_inset @@ -62766,12 +62687,58 @@ Option . \end_layout +\end_inset + + +\begin_inset Note Note +status collapsed + +\begin_layout Plain Layout +Exercise +\end_layout + \begin_layout Plain Layout \series bold -(b) +??? \series default - Given + Given a monad morphism +\begin_inset Formula $\delta:K\leadsto\text{Opt}$ +\end_inset + + (from +\begin_inset Formula $K$ +\end_inset + + to the +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Option +\end_layout + +\end_inset + + monad), show that one can implement a monad morphism +\begin_inset Formula $\phi:K\leadsto L$ +\end_inset + +. +\end_layout + +\begin_layout Plain Layout +– Not clear that we can actually prove this! +\end_layout + +\begin_layout Plain Layout +Solution +\end_layout + +\begin_layout Plain Layout +Given \begin_inset Formula $\delta:K^{A}\rightarrow\bbnum 1+A$ \end_inset @@ -63370,19 +63337,19 @@ composed codensity monad \series default -\begin_inset Formula $\text{Cod}_{F}^{L,A}$ +\begin_inset Formula $\text{Cod}_{F}^{M,A}$ \end_inset is defined by: \begin_inset Formula \[ -\text{Cod}_{F}^{L,A}\triangleq\forall X.\,(A\rightarrow F^{X})\rightarrow F^{L^{X}}\quad, +\text{Cod}_{F}^{M,A}\triangleq\forall X.\,(A\rightarrow F^{X})\rightarrow F^{M^{X}}\quad, \] \end_inset where -\begin_inset Formula $L$ +\begin_inset Formula $M$ \end_inset is any monad and @@ -63391,19 +63358,19 @@ where is any functor. One may define the monad instance for -\begin_inset Formula $\text{Cod}_{F}^{L,A}$ +\begin_inset Formula $\text{Cod}_{F}^{M,A}$ \end_inset via the flipped Kleisli composition: \begin_inset Formula \[ -f^{:\forall X.\,(B\rightarrow F^{X})\rightarrow A\rightarrow F^{L^{X}}}\tilde{\diamond}\,\,g^{:\forall Y.\,(C\rightarrow F^{Y})\rightarrow B\rightarrow F^{L^{Y}}}\triangleq\forall Z.\,k^{:C\rightarrow F^{Z}}\rightarrow\big(k\triangleright g^{Z}\triangleright f^{L^{Z}}\big)\bef\text{ftn}_{L}^{\uparrow F}\quad. +f^{:\forall X.\,(B\rightarrow F^{X})\rightarrow A\rightarrow F^{M^{X}}}\tilde{\diamond}\,\,g^{:\forall Y.\,(C\rightarrow F^{Y})\rightarrow B\rightarrow F^{M^{Y}}}\triangleq\forall Z.\,k^{:C\rightarrow F^{Z}}\rightarrow\big(k\triangleright g^{Z}\triangleright f^{M^{Z}}\big)\bef\text{ftn}_{M}^{\uparrow F}\quad. \] \end_inset Prove that the type constructor -\begin_inset Formula $\text{Cod}_{F}^{L,\bullet}$ +\begin_inset Formula $\text{Cod}_{F}^{M,\bullet}$ \end_inset is a lawful monad. @@ -63412,7 +63379,7 @@ Prove that the type constructor \begin_layout Standard Hints: Use the flipped Kleisli formulation of the monad laws. Assume that values of type -\begin_inset Formula $\text{Cod}_{F}^{L,A}$ +\begin_inset Formula $\text{Cod}_{F}^{M,A}$ \end_inset are natural transformations obeying the appropriate naturality law. @@ -63427,8 +63394,12 @@ Hints: Use the flipped Kleisli formulation of the monad laws. \begin_inset Formula $\forall X$ \end_inset - cannot be removed from the definition of -\begin_inset Formula $\text{Cod}_{F}^{L,A}$ + +\emph on +cannot +\emph default + be removed from the definition of +\begin_inset Formula $\text{Cod}_{F}^{M,A}$ \end_inset even if @@ -63439,19 +63410,15 @@ Hints: Use the flipped Kleisli formulation of the monad laws. \begin_inset Formula $X$ \end_inset - and for some functor -\begin_inset Formula $L$ + and for some monad +\begin_inset Formula $M$ \end_inset , the functor -\begin_inset Formula $P^{A}\triangleq(A\rightarrow X)\rightarrow L^{X}$ +\begin_inset Formula $P^{A}\triangleq(A\rightarrow X)\rightarrow M^{X}$ \end_inset - is -\emph on -not -\emph default - a monad. + is not a monad. \end_layout \begin_layout Standard @@ -63463,32 +63430,13 @@ not \emph on no \emph default - monad morphism -\begin_inset Formula $L^{A}\rightarrow\text{Cod}_{F}^{L,A}$ -\end_inset - -. - -\begin_inset Note Note -status open - -\begin_layout Plain Layout -A simple counterexample is found with -\begin_inset Formula $M^{A}\triangleq R\rightarrow A$ -\end_inset - - and -\begin_inset Formula $L^{A}\triangleq\bbnum 1+A$ + monad morphism of type +\begin_inset Formula $\forall A.\,M^{A}\rightarrow\text{Cod}_{F}^{M,A}$ \end_inset . \end_layout -\end_inset - - -\end_layout - \begin_layout Subsubsection Exercise \begin_inset CommandInset label diff --git a/sofp-src/lyx/sofp-traversable.lyx b/sofp-src/lyx/sofp-traversable.lyx index 19e386c8d..2187c8a71 100644 --- a/sofp-src/lyx/sofp-traversable.lyx +++ b/sofp-src/lyx/sofp-traversable.lyx @@ -25504,7 +25504,7 @@ This definition uses a recursive call to \end_inset of -\begin_inset Formula $S^{A,R}$ +\begin_inset Formula $S^{F^{A},R}$ \end_inset . diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 2cdc6923ee28005750d9c266ac912190953d8e06..0eabd3348122cd098d6c1d3b5f8853f45608f656 100644 GIT binary patch delta 167 zcmX?Ra?E7IN)cWoT?4}qBSR}w3oAqO$=gKq&_q6pJP|T5vPex!F$5|#H#F5XG)zn0 z{9KfgiPOly(8$o#0;un!xFmwNSy-?8l#h;nWKrDvxS9;rK^dVqqBjziKCf`v4x|n TnWK@3p^>4T4IveiwWXv1{KzW6 diff --git a/sofp-src/tex/sofp-back-cover-no-bg.tex b/sofp-src/tex/sofp-back-cover-no-bg.tex index 6b47f555c..5cc2e548b 100644 --- a/sofp-src/tex/sofp-back-cover-no-bg.tex +++ b/sofp-src/tex/sofp-back-cover-no-bg.tex @@ -25,7 +25,7 @@ practical applications of parametricity. Long and difficult, yet boring explanations are logically -developed in excruciating detail through 1985 +developed in excruciating detail through 1994 Scala code snippets, 233 statements with step-by-step derivations, 105 diagrams, 239 examples with tested Scala code, and 315 exercises. Discussions diff --git a/sofp-src/tex/sofp-free-type.tex b/sofp-src/tex/sofp-free-type.tex index 19c631acf..82aba541d 100644 --- a/sofp-src/tex/sofp-free-type.tex +++ b/sofp-src/tex/sofp-free-type.tex @@ -2527,8 +2527,8 @@ \subsection{Free semigroup\label{subsec:Free-semigroup}} surjective). It is important to note that \lstinline!toNEL! preserves the semigroup -operations (but \lstinline!fromNEL! does not!). It is a general property -of free typeclass constructions that there is only one typeclass-preserving +operations (but \lstinline!fromNEL! does \emph{not}). It is a general +property of free typeclass constructions that there is only one typeclass-preserving function of type \lstinline!SFR[T] => NEL[T]! (this is a property of the universal evaluator). However, there are several possible implementations of \lstinline!fromNEL!: we could have created a left-associated tree, @@ -2536,6 +2536,13 @@ \subsection{Free semigroup\label{subsec:Free-semigroup}} still holds. But none of those alternative implementations could preserve the typeclass operations. +{*}{*}{*} There are also alternative implementations of the universal +runner that correspond to those functions. When the universal runner +is applied with a lawful semigroup, the results are the same. But +when we use SFR instead of a lawful semigroup, the results are \emph{not} +the same. We see that it is important to take into account which laws +hold when using the universal runner.{*}{*}{*} + \subsection{Free monoid and its reduced encodings\label{subsec:Free-monoids}} A monoid (see Example~\ref{subsec:tc-Example-Monoids}) is a typeclass @@ -2826,82 +2833,114 @@ \subsubsection{Example \label{subsec:Example-reduced-monoid-encoding-one-law}\re is represented by the non-empty list $\left[t_{1},t_{2},e,t_{3},e,e\right]$. To make the left identity law hold, we replace any expression of the -form $e\oplus t$ by just $t$. This will eliminate entries equal -to $e$ to the left of any entries of type $T$. For the example just -shown, the result will be: +form $e\oplus x$ by just $x$. This will eliminate \textsf{``}empty\textsf{''} list +elements ($e$) to the left of any other elements (empty or not). +For the example just shown, the result will be: \[ -t_{1}\oplus t_{2}\oplus t_{3}\oplus e\oplus e\quad. +t_{1}\oplus t_{2}\oplus t_{3}\oplus e\quad. \] -This corresponds to a non-empty list of the form $\left[t_{1},t_{2},t_{3},e,e\right]$ -where all non-empty values appear before all empty ones. +This corresponds to a non-empty list of the form $\left[t_{1},t_{2},t_{3},e\right]$ +where all non-empty values appear before the empty one. The last empty +element cannot be removed, since we do not impose the right identity +law. -How can we represent this data? A simple solution would be a pair -of two lists, one being a list of values of type $T$ and the other -a list of empty values. However, this type cannot guarantee at the -level of types that at least one of the lists is non-empty. +What type can represent this data? A simple attempt would be a pair +\lstinline!(List[T], Boolean)!, where the boolean value is \lstinline!true! +when an empty value is present at the end. However, this type cannot +guarantee that either the list of type \lstinline!List[T]! is non-empty +or the boolean value is \lstinline!true!. To derive a correct data type, we begin by first defining the required -sequence structure by induction: +structure by induction: \begin{itemize} \item Base cases: -\begin{itemize} -\item We may have a single value of type $T$ or a single empty value ($e$). -\end{itemize} +\begin{enumerate} +\item We may have a single value of type $T$. +\item We may have a single empty value ($e$). +\end{enumerate} \item Inductive steps: \begin{itemize} \item If a sequence begins with a $t:T$ then it may continue to any other sequence of the same type (beginning either with another $t':T$ or with the empty value). -\item If a sequence begins with an $e$, it may continue to another sequence -that begins with $e$. \end{itemize} \end{itemize} -The inductive steps guarantee that once an empty value occurs, all -further values will also be empty. To describe this logic, we need -two case classes for the base cases and two more case classes to describe -the two different types of induction steps. The empty values will -be represented by the \lstinline!Unit! type: +If a sequence begins with an $e$, it must end at that point. So, +there is no induction step following the second base case. + +To describe this logic, we need two case classes for the base cases +and two more case classes to describe the two different types of induction +steps. The empty value will be represented by a named \lstinline!Unit! +type (\lstinline!OneE!): \begin{lstlisting} sealed trait F5[T] -final case class OneT[T](single: T) extends F5[T] -final case class OneE[T]() extends F5[T] +final case class OneT[T](single: T) extends F5[T] // Base case 1. +final case class OneE[T]() extends F5[T] // Base case 2. final case class NELT[T](head: T, tail: F5[T]) extends F5[T] -final case class NELE[T](head: Unit, tail: NELE[T]) extends F5[T] \end{lstlisting} -If the case classes \lstinline!OneE! and \lstinline!NELE! are considered -separately, they are equivalent to a recursive definition of the non-empty -list of \lstinline!Unit! values (\lstinline!NEL[Unit]!). So, we -may rewrite the recursive definition of $F_{5}$ as: +In the type notation, we may write the recursive definition of $F_{5}$ +as: \[ -F_{5}^{T}\triangleq T+T\times F_{5}^{T}+\text{NEL}^{\bbnum 1}\quad. +F_{5}^{T}\triangleq\bbnum 1+T+T\times F_{5}^{T}\quad. \] The \textsf{``}unrolling trick\textsf{''} \index{unrolling trick for recursive types}(Statement~\ref{Statement-unrolling-trick}) simplifies this recursive definition to: \[ -F_{5}^{T}\cong\text{List}^{T}\times(T+\text{NEL}^{\bbnum 1})\quad. +F_{5}^{T}\cong\text{List}^{T}\times(\bbnum 1+T)\quad. \] \begin{lstlisting} -final case class F5[T](start: List[T], end: Either[T, NEL[Unit]]) +final case class F5[T](start: List[T], end: Option[T]) \end{lstlisting} The \lstinline!Monoid! typeclass instance and the runner code for \lstinline!F5! are written as: \begin{lstlisting} -def wrapF5[T](t: T): F3[T] = F5(Nil, Left(t)) +def wrapF5[T](t: T): F5[T] = F5(Nil, Some(t)) def concatF5[T]: (F5[T], F5[T]) => F5[T] = { - case (F5(start1, Left(t)), F5(start2, end)) => F5(start1 ++ List(t) ++ start2, end) - case (F5(start1, Right(_)), F5(start2, end)) => F5(start1 ++ start2, end) + case (F5(start1, Some(t)), F5(start2, end)) => F5(start1 ++ List(t) ++ start2, end) + case (F5(start1, None), F5(start2, end)) => F5(start1 ++ start2, end) } -def emptyF5[T]: F5[T] = F5(Nil, Right(((), Nil))) +def emptyF5[T]: F5[T] = F5(Nil, None) implicit def monoidF5[T]: Monoid[F5[T]] = Monoid(concatF5[T], emptyF5[T]) def runnerF5[M: Monoid, T](runT: T => M)(fm: F5[T]): M = { val last: M = fm.end match { - case Left(t) => runT(t) - case Right(e) => Monoid[M].empty + case Some(t) => runT(t) + case None => Monoid[M].empty } - (fm.start.map(runT) :+ last).reduce(Monoid[M].combine) -}***test this code + fm.start.map(runT).reduce(Monoid[M].combine) |+| last +} +\end{lstlisting} + +To test this code, let us set $T=\text{Int}$ and create a free monoid +value of type $F_{5}^{\text{Int}}$ corresponding to the expression +$e\oplus1\oplus e\oplus2\oplus e$: +\begin{lstlisting} +scala> val testF5 = emptyF5[Int] |+| wrapF5(1) |+| emptyF5 |+| wrapF5(2) |+| emptyF5 +val testF5: F5[Int] = F5(List(1, 2),None) \end{lstlisting} +We see that the free monoid $F_{5}$ simplifies this expression to +$1\oplus2\oplus e$, although the expression should be equivalent +to just $1\oplus2$ if we were able to use all the monoid laws. + +To evaluate the \textsf{``}free monoid program\textsf{''} \lstinline!testF5!, choose +the target monoid $M=\text{String}$ (with the monoidal operation +being the concatenation of strings). For the purposes of this example, +define the function \lstinline!runT! that prints integers with up +to 5 leading zeros. Then run the program and expect the concatenation +of \lstinline!"00001"! and \lstinline!"00002"!: +\begin{lstlisting} +implicit val monoidString: Monoid[String] = Monoid(_ + _, "") + +val runT: Int => String = (x: Int) => f"${x}%05d" + +scala> runT(123) +val res0: String = 00123 +scala> runnerF5(runT)(testF5) +val res1: String = 0000100002 +\end{lstlisting} +The result of the evaluation is the same as if the monoid program +were just $1\oplus2$. The monoid laws appear to hold after applying +the runner. \subsubsection{Example \label{subsec:Example-reduced-monoid-encoding-one-law-1}\ref{subsec:Example-reduced-monoid-encoding-one-law-1}} @@ -2910,33 +2949,98 @@ \subsubsection{Example \label{subsec:Example-reduced-monoid-encoding-one-law-1}\ \subparagraph{Solution} -Start with the raw tree encoding, which is a binary tree with leaves -of type $\bbnum 1+T$. The left identity law ($e\oplus x=x$) means -that in any branching of the tree, the left branch cannot be an \textsf{``}empty\textsf{''} -leaf (a leaf carrying the value $e$). The right branch remains unrestricted. -To implement the restriction on the left branches, we introduce two -types of trees: a tree that cannot be an empty leaf value, and a tree -that can. (\emph{Both} trees will disallow empty leaves as left sub-trees.) -\begin{lstlisting} -sealed trait TreeLeftNonEmpty[T] -final case class LeafNE[T](t: T) extends TreeLeftNonEmpty[T] -final case class BranchNE[T](left: TreeLeftNonEmpty[T], right: TreeLeftAny[T]) extends TreeLeftNonEmpty[T] - -sealed trait TreeLeftAny[T] -final case class Leaf1[T](t: T) extends TreeLeftAny[T] -final case class Leaf2[T]() extends TreeLeftAny[T] -final case class BranchAny[T](left: TreeLeftNonEmpty[T], right: TreeLeftAny[T]) extends TreeLeftNonEmpty[T] +Our goal is to define a recursive type \lstinline!F6! with the required +properties. -type F6[T] = TreeLeftNonEmpty[T] +Start with the raw tree encoding, which is a binary tree with leaves +of type $\bbnum 1+T$. The type \lstinline!F6[T]! must be similarly +a binary tree with leaves of that type. However, the left identity +law ($e\oplus x=x$) means that in any branching of the tree, the +left branch cannot be an \textsf{``}empty\textsf{''} leaf (a leaf carrying the value +$e$). The right branch remains unrestricted. To implement the restriction +on the left branches, we introduce a special type (\lstinline!TreeNonEmpty!) +for a tree that cannot be an empty leaf value. The left branches of +\lstinline!TreeNonEmpty! must also have type \lstinline!TreeNonEmpty! +(cannot be empty leaves), while the right branches are unrestricted +(have type \lstinline!F6!). Finally, we define the type \lstinline!F6! +as a tree that can itself be an empty leaf, but whose left branches +have type \lstinline!TreeNonEmpty! (cannot be empty leaves). The +right branches of \lstinline!F6! have again type \lstinline!F6!. +\begin{lstlisting} +sealed trait TreeNE[T] // Cannot be an empty leaf. +final case class LeafNE[T](t: T) extends TreeNE[T] +final case class BranchNE[T](left: TreeNE[T], right: F6[T]) extends TreeNE[T] + +sealed trait F6[T] // This tree can be an empty leaf, but its left branch. +final case class LeafT[T](t: T) extends F6[T] +final case class LeafE[T]() extends F6[T] +final case class BranchF6[T](left: TreeNE[T], right: F6[T]) extends F6[T] \end{lstlisting} In the type notation, the encoding \lstinline!F6! is expressed via two \textbf{mutually recursive types}\index{mutually recursive types}: \begin{align*} - & F_{6}^{T}\triangleq T+F_{6}^{T}\times G^{T}\quad,\\ - & G^{T}\triangleq\bbnum 1+T+F_{6}^{T}\times G^{T}\quad. +{\color{greenunder}\text{\texttt{F6[T]} in the code}:}\quad & F_{6}^{T}\triangleq\bbnum 1+T+G^{T}\times F_{6}^{T}\quad,\\ +{\color{greenunder}\text{\texttt{TreeNE[T]} in the code}:}\quad & G^{T}\triangleq T+G^{T}\times F_{6}^{T}\quad. \end{align*} \textsf{''}Mutually recursive\textsf{''} means that each the definitions of $F_{6}^{T}$ -and $G$ uses both these types. {*}{*}{*} +and $G$ uses both these types. + +Let us implement the \lstinline!Monoid! instance and a universal +runner for \lstinline!F6!, which we write via two mutually recursive +functions (\lstinline!runnerF6NE! and \lstinline!runnerF6!): +\begin{lstlisting} +def wrapF6[T](t: T): F6[T] = LeafT(t) + +def toTreeNE[T]: F6[T] => TreeNE[T] = { + case LeafE() => ??? // This case will never be used. + case LeafT(t) => LeafNE(t) + case BranchF6(left, right) => BranchNE(left, right) +} +def concatF6[T]: (F6[T], F6[T]) => F6[T] = { + case (LeafE(), x) => x // Left identity law holds automatically. + case (first, second) => BranchF6(toTreeNE(first), second) // `first` is guaranteed to be non-empty. + } +def emptyF6[T]: F6[T] = LeafE() + +implicit def monoidF6[T]: Monoid[F6[T]] = Monoid(concatF6[T], emptyF6[T]) + +def runnerF6NE[M: Monoid, T](runT: T => M)(tree: TreeNE[T]): M = tree match { + case LeafNE(t) => runT(t) + case BranchNE(left, LeafE()) => runnerF6NE(runT)(left) + case BranchNE(left, right) => runnerF6NE(runT)(left) |+| runnerF6(runT)(right) +} +def runnerF6[M: Monoid, T](runT: T => M)(tree: F6[T]): M = tree match { + case LeafE() => Monoid[M].empty + case LeafT(t) => runT(t) + case BranchF6(left, right) => runnerF6NE(runT)(left) |+| runnerF6(runT)(right) +} +\end{lstlisting} + +We test this code with the same data as in the previous example. +\begin{lstlisting} +scala> val testF6 = emptyF6[Int] |+| wrapF6(1) |+| emptyF6 |+| wrapF6(2) |+| emptyF6 +val testF6: F6[Int] = BranchF6(BranchNE(BranchNE(LeafNE(1),LeafE()),LeafT(2)),LeafE()) +\end{lstlisting} +We see that the monoid program $(((e\oplus1)\oplus e)\oplus2)\oplus e$ +is simplified to the expression tree $((1\oplus e)\oplus2)\oplus e$ +because the free monoid $F_{6}$ only respects the left identity law +but not the associativity law. + +Apply \lstinline!runnerF6! to \lstinline!testF6! using the same +function \lstinline!runT! as before: +\begin{lstlisting} +scala> runnerF6(runT)(testF6) +val res1: String = 0000100002 +\end{lstlisting} +This is the same result as in the previous example. + +{*}{*}{*}Exercises: free monoids that satisfy the right identity law +and the associativity law; or just the right identity law. Find a +map between free monoids that satisfy the right identity law and that +satisfy the left; show that operations are not preserved and that +maps are not injective. Use a sorted list to implement commutativity +law for semigroups and for monoids. Find a free semigroup that is +commutative but not associative. \subsection{Free functors} @@ -2944,11 +3048,12 @@ \subsection{Free functors} \[ \text{fmap}:\left(A\rightarrow B\right)\rightarrow F^{A}\rightarrow F^{B}\quad. \] -The \lstinline!fmap! method is not available for some type constructors -$F$, such as contrafunctors or GADTs. (See Section~\ref{subsec:Examples-of-non-functors} -for more examples.) Let us now apply the raw tree encoding recipe -to the \lstinline!Functor! typeclass. The result will be a new type -constructor that we call a \textbf{free functor on} $F$.\index{free functor} +The \lstinline!fmap! method is supported by all covariant type constructors, +but is not available when $F$ is a contrafunctor or a GADT. (See +Section~\ref{subsec:Examples-of-non-functors} for more examples.) +Let us now apply the raw tree encoding recipe to the \lstinline!Functor! +typeclass. The result will be a new type constructor that we call +a \textbf{free functor on} $F$.\index{free functor} The recipe tells us to define a case class for the \lstinline!fmap! method and another case class to wrap the given type constructor $F$. @@ -2963,14 +3068,14 @@ \subsection{Free functors} This code corresponds to the following notation for the lifting $f^{\uparrow\text{FFR}}$: \begin{align} - & \text{FFR}^{F^{\bullet},A}\triangleq F^{A}+\exists X.\,(X\rightarrow A)\times\text{FFR}^{F^{\bullet},X}\quad,\label{eq:definition-FFR-existential-type}\\ - & p^{:\text{FFR}^{F^{\bullet},A}}\triangleright(f^{:A\rightarrow B})^{\uparrow\text{FFR}^{F^{\bullet},\bullet}}\triangleq\bbnum 0^{:F^{B}}+\exists^{A}.\,f^{:A\rightarrow B}\times p^{:\text{FFR}^{F^{\bullet},A}}\quad.\nonumber + & \text{FFR}^{F,A}\triangleq F^{A}+\exists X.\,(X\rightarrow A)\times\text{FFR}^{F,X}\quad,\label{eq:definition-FFR-existential-type}\\ + & p^{:\text{FFR}^{F,A}}\triangleright(f^{:A\rightarrow B})^{\uparrow\text{FFR}^{F,\bullet}}\triangleq\bbnum 0^{:F^{B}}+\exists^{A}.\,f^{:A\rightarrow B}\times p^{:\text{FFR}^{F,A}}\quad.\nonumber \end{align} The notation $\exists^{A}$ means that we bind the type $A$ to the existentially quantified type $X$ in the definition~(\ref{eq:definition-FFR-existential-type}) -of $\text{FFR}^{F^{\bullet},B}$. This notation expresses the requirement -that the existentially quantified type must be assigned to a specific -type every time we create a specific value. +of $\text{FFR}^{F,B}$. This notation expresses the requirement that +the existentially quantified type must be assigned to a specific type +every time we create a specific value. A \textsf{``}free functor program\textsf{''} is a value of type \lstinline!FFR[F, A]!. To construct such values, we must begin with a wrapped \lstinline!F!-operation @@ -2984,38 +3089,42 @@ \subsection{Free functors} $\forall C.\,F^{C}\rightarrow C$ (an \index{effect runner}effect runner for $F$). To implement such functions, we use the trait \lstinline!Runner! defined in Section~\ref{subsec:A-first-recipe-monadic-dsl}. Now -we can write the code of the runner for $\text{FFR}^{F,A}$: +we can write the code of the universal runner for $\text{FFR}^{F,A}$: \begin{lstlisting} def runFFR[F[_], A](runner: Runner[F]): FFR[F, A] => A = { case FMap(f, p) => f(runFFR(runner)(p)) case Op(op) => runner.apply(op) -}*** check if this works +} \end{lstlisting} The code notation for this function is: \begin{align*} - & \text{runFFR}^{F^{\bullet},A}:(\forall C.\,F^{C}\rightarrow C)\rightarrow\text{FFR}^{F^{\bullet},A}\rightarrow A\quad,\\ + & \text{runFFR}^{F,A}:(\forall C.\,F^{C}\rightarrow C)\rightarrow\text{FFR}^{F,A}\rightarrow A\quad,\\ & \text{runFFR}(\text{run}:\forall C.\,F^{C}\rightarrow C)\triangleq\forall B.\,\,\begin{array}{|c||c|} & A\\ \hline F^{A} & \text{run}\\ -(B\rightarrow A)\times\text{FFR}^{F^{\bullet},B} & f^{:B\rightarrow A}\times p^{:FFR^{F^{\bullet},B}}\rightarrow p\triangleright\big(\overline{\text{runFFR}}(\text{run})\big)\triangleright f +(B\rightarrow A)\times\text{FFR}^{F,B} & f^{:B\rightarrow A}\times p^{:FFR^{F,B}}\rightarrow p\triangleright\big(\overline{\text{runFFR}}(\text{run})\big)\triangleright f \end{array}\quad. \end{align*} -The outside universal quantifier $\forall B$ replaces $\exists B$ -in the function argument, according to Eq.~(\ref{eq:existential-via-universal}). +The outside quantifier $\forall B$ replaces $\exists B$ in the function +argument, according to Eq.~(\ref{eq:existential-via-universal}). -More generally, we may want to run the effects of $F$ into the effects +More generally, we may need to run the effects of $F$ into the effects of a given functor $G$. (The functor $G$ could, for example, describe -errors or asynchronous execution.) The corresponding runner will have -type $\forall C.\,F^{C}\rightarrow G^{C}$, and the code is: +errors or asynchronous execution.) The corresponding effect runner +will have type $\forall C.\,F^{C}\rightarrow G^{C}$ instead of $\forall C.\,F^{C}\rightarrow C$. +The code for the universal runner is: \begin{align*} - & \text{runFFR}^{F^{\bullet},G^{\bullet},A}:(\forall C.\,F^{C}\rightarrow G^{C})\rightarrow\text{FFR}^{F^{\bullet},A}\rightarrow G^{A}\quad,\\ + & \text{runFFR}^{F,G,A}:(\forall C.\,F^{C}\rightarrow G^{C})\rightarrow\text{FFR}^{F,A}\rightarrow G^{A}\quad,\\ & \text{runFFR}\,(\text{run})\triangleq\forall B.\,\,\begin{array}{|c||c|} & G^{A}\\ \hline F^{A} & \text{run}\\ -(B\rightarrow A)\times\text{FFR}^{F^{\bullet},B} & f^{:B\rightarrow A}\times p^{:FFR^{F^{\bullet},B}}\rightarrow p\triangleright\big(\overline{\text{runFFR}}\,(\text{run})\big)\triangleright f^{\uparrow G} +(B\rightarrow A)\times\text{FFR}^{F,B} & f^{:B\rightarrow A}\times p^{:FFR^{F,B}}\rightarrow p\triangleright\big(\overline{\text{runFFR}}\,(\text{run})\big)\triangleright f^{\uparrow G} \end{array}\quad. \end{align*} +{*}{*}{*} example code: what if $\forall C.\,F^{C}\rightarrow C$ +cannot be implemented? What is sufficient + The type constructor \lstinline!FFR! is a \index{free functor!raw tree encoding}raw tree encoding of the free functor and does not satisfy the functor laws. This is not a problem in practice, because the functor laws @@ -3024,10 +3133,9 @@ \subsection{Free functors} \subsubsection{Statement \label{subsec:Statement-free-functor-raw-tree-encoding-satisfies-laws}\ref{subsec:Statement-free-functor-raw-tree-encoding-satisfies-laws}} -Take any free functor ($\text{FFR}^{F^{\bullet},A}$) and any runner -($\text{run}:\forall C.\,F^{C}\rightarrow G^{C}$), where $G$ is -a lawful functor. Denote for brevity $f^{\uparrow\text{FFR}}\triangleq f^{\uparrow\text{FFR}^{F^{\bullet},\bullet}}$. -The functor laws will hold if we apply the runner function, denoted +Take any free functor ($\text{FFR}^{F,A}$) and any runner ($\text{run}:\forall C.\,F^{C}\rightarrow G^{C}$), +where $G$ is a lawful functor. Denote for brevity $f^{\uparrow\text{FFR}}\triangleq f^{\uparrow\text{FFR}^{F,\bullet}}$. +The functor laws will hold after applying the runner function, denoted for brevity by $\rho\triangleq\text{runFFR}\,(\text{run})$,{*}{*}{*}replace $\rho$ with some other letter{*}{*}{*} to both sides of the laws: \begin{align*} @@ -3075,7 +3183,7 @@ \subsubsection{Statement \label{subsec:Statement-free-functor-raw-tree-encoding- To transform the raw tree encoding of the free functor into a reduced encoding, we require that all functor laws should hold even before applying a runner. We begin by finding out in detail why the functor -laws fail to hold for \lstinline!FFR[F, A]!. +laws fail for \lstinline!FFR[F, A]!. The type \lstinline!FFR[F, A]! is a disjunction of two case classes, \lstinline!FMap! and \lstinline!Op!. The functor\textsf{'}s composition law @@ -3105,40 +3213,42 @@ \subsubsection{Statement \label{subsec:Statement-free-functor-raw-tree-encoding- not return \lstinline!Op(op)! but instead gives \lstinline!FMap(identity, Op(op))!. Values of the form \lstinline!Op(op)! represent \lstinline!F!-effects. The functor identity law would hold if we instead represented $F$-effects -by the \lstinline!FMap! case class as \lstinline!FMap(identity, Op(op))!. +by the expression \lstinline!FMap(identity, Op(op))!. Any \lstinline!FFR!-program must have the form \lstinline!Op(x).map(y).map(z)...!, having zero or more \lstinline!map! methods. If we represent \lstinline!F!-effects by \lstinline!FMap(identity, Op(op))! and implement the \lstinline!map! methods for \lstinline!FMap! as shown above, it will follow that \emph{all} \lstinline!FFR!-programs always have the form \lstinline!FMap(f, Op(op))! -for some function \lstinline!f!. So, we may remove the \lstinline!Op! -case class altogether. - -The result is a simplified definition of the free functor. The complete +for some function \lstinline!f!. It means we may remove the \lstinline!Op! +case class altogether. Only one case class (\lstinline!FMap!) remains. +However, we still need to implement the free functor as a trait \lstinline!FF[F, A]! +containing a single case class \lstinline!FMap[F, C, A]!. This is +because \lstinline!FMap[F, C, A]! has an extra type parameter (\lstinline!C!) +that does not appear in \lstinline!FF[F, A]!. (In other words, the +type parameter \lstinline!X! is existentially quantified.) The complete code is: \begin{lstlisting} sealed trait FF[F[_], A] { def map[B](f: A => B): FF[F, B] } -final case class FMap[F[_], X, Y](f: X => Y, p: F[X]) extends FF[F, Y] { - def map[Z](g: Y => Z): FF[F, Z] = FMap[F, X, Z](f andThen g, p) +final case class FMap[F[_], C, A](f: C => A, p: F[C]) extends FF[F, A] { + def map[B](g: A => B): FF[F, B] = FMap[F, C, B](f andThen g, p) } def runFF[F[_], A](runner: Runner[F]): FF[F, A] => A = { case FMap(f, p) => f(runner.apply(p)) -}*** check if this works +} \end{lstlisting} -The code notation for this code and a general runner is: +The code notation for this code is: \begin{align*} - & \text{FF}^{F^{\bullet},A}\triangleq\exists C.\,\left(C\rightarrow A\right)\times F^{C}\quad,\quad\quad(\exists C.\,f^{:C\rightarrow A}\times p^{:F^{C}})\triangleright(g^{:A\rightarrow B})^{\uparrow\text{FR}}\triangleq\exists^{C}.\,(f\bef g)\times p\quad,\\ - & \text{runFF}:(\forall C.\,F^{C}\rightarrow G^{C})\rightarrow\text{FF}^{F^{\bullet},A}\rightarrow G^{A}\quad,\\ + & \text{FF}^{F,A}\triangleq\exists C.\,\left(C\rightarrow A\right)\times F^{C}\quad,\quad\quad(\exists C.\,f^{:C\rightarrow A}\times p^{:F^{C}})\triangleright(g^{:A\rightarrow B})^{\uparrow\text{FR}}\triangleq\exists^{C}.\,(f\bef g)\times p\quad,\\ + & \text{runFF}:(\forall C.\,F^{C}\rightarrow G^{C})\rightarrow\text{FF}^{F,A}\rightarrow G^{A}\quad,\\ & \text{runFF}\,(\text{run})\triangleq(\exists C.\,f^{:C\rightarrow A}\times p^{:F^{C}})\rightarrow p\triangleright\text{run}\triangleright f^{\uparrow G}\quad. \end{align*} This is the \textbf{reduced encoding}\index{free functor!reduced encoding} of the free functor on $F$. This encoding was derived by imposing -the functor laws, so those laws will hold for values of type \lstinline!FF[F, A]! -even before applying a runner. +the functor laws, so those laws will hold for values of type \lstinline!FF[F, A]!. The free functor construction \lstinline!FF[F, A]! converts \emph{any} type constructor \lstinline!F[_]! into a lawful functor. What if @@ -3150,7 +3260,7 @@ \subsubsection{Statement \label{subsec:Statement-free-functor-raw-tree-encoding- \begin{align*} {\color{greenunder}\text{covariant co-Yoneda identity}:}\quad & \exists C.\,\left(C\rightarrow A\right)\times F^{C}\cong F^{A}\quad\text{for any functor }F\quad. \end{align*} -We will prove this type equivalence in Statement~\ref{subsec:Statement-co-Yoneda-two-identities} +We will prove this type identity in Statement~\ref{subsec:Statement-co-Yoneda-two-identities} (Appendix~\ref{app:Proofs-of-naturality-parametricity}). We conclude that the reduced encoding of the free functor (\lstinline!FF[F, A]!) @@ -3163,57 +3273,98 @@ \subsubsection{Statement \label{subsec:Statement-free-functor-raw-tree-encoding- A disadvantage of the reduced encoding is that the function composition is done in the code \lstinline!FMap(f andThen g, p)!. The Scala compiler cannot directly handle the composition of a large number of functions -without causing a stack overflow. This problem can be resolved if -we postpone the function composition and instead create a list of -functions that need to be composed. The runner can evaluate the list -of functions without running into a stack overflow. - -This gives us an idea for another encoding of the stack-safe free -functor, which we will call \lstinline!FFS!. First, we implement -a data structure called \lstinline!FuncSeq! for storing a list of -functions with matching types. A value of type \lstinline!FuncSeq[A, B]! -holds a list of functions with types $A\rightarrow C_{1}$, $C_{1}\rightarrow C_{2}$, -..., $C_{n-1}\rightarrow C_{n}$, $C_{n}\rightarrow B$, where $C_{i}$ -are some chosen types. A list of with those types can be composed -to yield a function of type $A\rightarrow B$. To simplify code, we -will cast all intermediate types to \lstinline!Any! and back. Our -code will take care to construct \lstinline!FuncSeq! values with -correct types.\lstinline!final case class FuncSeq[X, Y](first: X => Any, funcs: Vector[Any => Any]) { def append[Z](g: Y => Z): FuncSeq[X, Z] = FuncSeq(first, funcs :+ g.asInstanceOf[Any => Any])}! +without causing a stack overflow: +\begin{lstlisting} +def composed(n: Int): Long => Long = (1 to n).foldLeft[Long => Long](x => x){ (prev, i) => prev andThen (x => x + i) } + +scala> composed(100)(0) // OK to compose 100 functions. +res0: Long = 5050 -To ensure stack safety when working with \lstinline!FuncSeq!, we -implement a tail-recursive function \lstinline!runSeq! that composes -all functions stored in the sequence and applies them to a given value. +scala> composed(100000)(0) // Cannot compose 100000 functions. +java.lang.StackOverflowError +\end{lstlisting} +This code causes a stack overflow because each function composition +creates a new stack frame when functions are applied. +Stack overflows can be avoided if we postpone the function compositions. +Instead, we just store all the functions that need to be composed +as a sequence of functions with types $A\rightarrow C_{1}$, $C_{1}\rightarrow C_{2}$, +..., $C_{n-1}\rightarrow C_{n}$, $C_{n}\rightarrow B$, where $C_{i}$ +are some fixed types. Then we write a \textsf{``}runner\textsf{''} that applies the +functions one by one to a given initial value of type $A$. The result +is as if we have evaluated a single function of type $A\rightarrow B$. + +Here is an example implementation of this idea. Define a helper class +\lstinline!SafeFunction! as a subclass of \lstinline!A => B! that +overrides the composition methods (\lstinline!compose!, \lstinline!andThen!). +Instead of composing the functions immediately, the new function bodies +are added to a sequence of already stored functions. The \lstinline!apply! +method is the \textsf{``}runner\textsf{''} for computing the final result in constant +stack space. + +To simplify code, we will store functions in a sequence of type \lstinline!Vector[Any => Any]!;; +type safety will be guaranteed when constructing values of type \lstinline!SafeFunction!. +The choice of the \lstinline!Vector! container type allows us efficient +appending and prepending to the sequence. +\begin{lstlisting} +final case class SafeFunction[A, B](funcs: Vector[Any => Any]) extends (A => B) { + def apply(a: A): B = funcs.foldLeft[Any](a){ (prev, func) => func(prev) }.asInstanceOf[B] + override def andThen[C](g: B => C): A => C = + SafeFunction(funcs :+ g.asInstanceOf[Any => Any]) + override def compose[C](g: C => A): C => B = + SafeFunction(g.asInstanceOf[Any => Any] +: funcs) +} +\end{lstlisting} + +Converting an ordinary function to a \lstinline!SafeFunction! is +straightforward: \begin{lstlisting} -@tailrec def runSeq[X, Y](x: X, p: FuncSeq[X, Y]): Y = p.funcs.headOption match { - case None => p.first(x).asInstanceOf[Y] - case Some(second) => runSeq(p.first(x), FuncSeq(second, p.funcs.tail)) +def toSafeFunction[A, B](f: A => B): SafeFunction[A, B] = f match { + case SafeFunction(_) => f.asInstanceOf[SafeFunction[A, B]] + case _ => SafeFunction(Vector(f.asInstanceOf[Any => Any])) } \end{lstlisting} -Now we can write the code of the free functor \lstinline!FFS!: +For convenience, we also define the corresponding extension methods +(\lstinline!safeAndThen!, \lstinline!safeCompose!) on ordinary functions: +\begin{lstlisting} +implicit class SafeCompose[A, B](f: A => B) { + def safeAndThen[C](g: B => C): A => C = toSafeFunction(f).andThen(g) + def safeCompose[C](g: C => A): C => B = toSafeFunction(f).compose(g) +} +\end{lstlisting} + +Millions of functions can be now composed with no stack overflow: +\begin{lstlisting} +def safeComposed(n: Int): Long => Long = (1 to n).foldLeft[Long => Long](x => x){ (prev, i) => prev.safeAndThen(x => x + i) } + +scala> safeComposed(10000000)(0) // Compose 10 million functions. +res1: Long = 50000005000000 +\end{lstlisting} + +We use \lstinline!safeAndThen! to obtain a stack-safe encoding of +the free functor (\lstinline!FFS!) with no changes in the runner: \begin{lstlisting} sealed trait FFS[F[_], A] { def map[B](f: A => B): FFS[F, B] } -final case class FMap[F[_], X, Y](f: FuncSeq[X, Y], p: F[X]) extends FFS[F, Y] { - def map[Z](g: Y => Z): FFS[F, Z] = FMap[F, X, Z](f append g, p) +final case class FMap[F[_], X, Y](f: X => Y, p: F[X]) extends FFS[F, Y] { + def map[Z](g: Y => Z): FFS[F, Z] = FMap[F, X, Z](f.safeAndThen(g), p) } def runFF[F[_], A](runner: Runner[F]): FFS[F, A] => A = { - case FMap(f, p) => runSeq(runner.apply(p), f) -}*** check if this works + case FMap(f, p) => f(runner.apply(p)) +} \end{lstlisting} - +Test this code: {*}{*}{*} \subsection{Free contrafunctors} Method $\text{contramap}:C^{A}\times\left(B\rightarrow A\right)\rightarrow C^{B}$ -Tree encoding: $\text{FreeCF}^{F^{\bullet},B}\triangleq F^{B}+\exists A.\text{FreeCF}^{F^{\bullet},A}\times\left(B\rightarrow A\right)$ +Tree encoding: $\text{FreeCF}^{F,B}\triangleq F^{B}+\exists A.\text{FreeCF}^{F,A}\times\left(B\rightarrow A\right)$ -Reduced encoding: $\text{FreeCF}^{F^{\bullet},B}\triangleq\exists A.F^{A}\times\left(B\rightarrow A\right)$ +Reduced encoding: $\text{FreeCF}^{F,B}\triangleq\exists A.F^{A}\times\left(B\rightarrow A\right)$ -A value of type $\text{FreeCF}^{F^{\bullet},B}$ must be of the form -{\footnotesize{} +A value of type $\text{FreeCF}^{F,B}$ must be of the form {\footnotesize{} \[ \exists Z_{1}.\exists Z_{2}...\exists Z_{n}.F^{Z_{1}}\times\left(B\rightarrow Z_{n}\right)\times\left(Z_{n}\rightarrow Z_{n-1}\right)\times...\times\left(Z_{2}\rightarrow Z_{1}\right) \] @@ -3232,7 +3383,7 @@ \subsection{Free contrafunctors} \texttt{\textcolor{blue}{\footnotesize{}def prefixLog{[}A{]}(p: A): A $\rightarrow$ String = a $\rightarrow$ p.toString + a.toString}}{\footnotesize\par} -If $F^{\bullet}$ is already a contrafunctor then $\text{FreeCF}^{F^{\bullet},A}\cong F^{A}$ +If $F$ is already a contrafunctor then $\text{FreeCF}^{F,A}\cong F^{A}$ \subsection{Free constructions that assume other typeclasses} diff --git a/sofp-src/tex/sofp-monads.tex b/sofp-src/tex/sofp-monads.tex index 8addf18c3..ad37dfaff 100644 --- a/sofp-src/tex/sofp-monads.tex +++ b/sofp-src/tex/sofp-monads.tex @@ -1927,7 +1927,7 @@ \subsection{The eager/lazy evaluation monad\label{subsec:The-eager-lazy-evaluati To derive the type constructor we denoted \lstinline!Eval!, note that lazy values of type $A$ are equivalent to functions of type $\bbnum 1\rightarrow A$. So, the disjunctive type $\text{Eval}^{A}\triangleq A+\left(\bbnum 1\rightarrow A\right)$ -represents a value that is either lazy or eager:\index{monads!lazy/eager evaluation monad (Eval)@lazy/eager evaluation monad (\texttt{Eval})} +represents a value that is either lazy or eager:\index{monads!Eval (lazy/eager evaluation monad)@\texttt{Eval} (lazy/eager evaluation monad)} \begin{lstlisting} sealed trait Eval[A] final case class Eager[A](x: A) extends Eval[A] @@ -7851,7 +7851,9 @@ \subsection{Constructions of $M$-filterable functors and contrafunctors\label{su \end{align*} This gave us the definitions of $M$-filterable functors and contrafunctors.\index{$M$-filterable contrafunctor}\index{$M$-filterable functor} -We have shown some examples of $M$-filterable functors in Statement~\ref{subsec:Statement-examples-of-filterable-contrafunctors}. +The concepts of $M$-filterable functors and contrafunctors are not +well known and not widely used. To build up intuition, we have shown +some examples in Statement~\ref{subsec:Statement-examples-of-filterable-contrafunctors}. Structural analysis can discover other examples of such functors systematically. As in the case of ordinary filterable functors, it turns out that we must at the same time analyze $M$-filterable contrafunctors. @@ -7859,8 +7861,8 @@ \subsection{Constructions of $M$-filterable functors and contrafunctors\label{su In the following constructions, we assume that $M$ is a fixed, lawful monad. -We omit the proofs of all following statements because they are fully -analogous to the proofs of filterable functor and contrafunctor constructions +We omit the proofs of all the following statements because they are + analogous to the proofs of filterable functor and contrafunctor constructions in Sections~\ref{subsec:Constructions-of-filterable-functors} and~\ref{subsec:Constructions-of-filterable-contrafunctors}. In those proofs, we only used the properties of the functions $\text{liftOpt}_{F}$, which are fully analogous to the properties of the function $\text{lift}_{M,F}$ diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index 052e736b7..c395405d1 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -585,7 +585,15 @@ \subsection{Chapter~\ref{chap:8-Applicative-functors,-contrafunctors}} We formally define the property of commutativity for applicative functors and show how it simplifies the other laws. Most applicative functors -used in practice are commutative and are suitable for parallel evaluation. +used in practice are commutative and are suitable for parallel evaluation. + +Many applicative functors are at the same time monads. However, most +monads used in practice are \emph{not} commutative. For this reason, +it is typically not the case that applicative functors have their +\lstinline!zip! functions derived from \lstinline!flatMap!. For +example, the \lstinline!List! and \lstinline!Either! are monads +whose standard \lstinline!zip! methods do not follow from the \lstinline!flatMap! +code for those monads. Having derived the laws of \lstinline!zip!, the next step is to perform structural analysis and to discover type constructions that create @@ -846,10 +854,20 @@ \subsection{Chapter~\ref{chap:Free-type-constructions}} We again start with the raw tree encoding and then discover several reduced encodings by imposing different subsets of laws. To illustrate the relationships between reduced encodings of a free typeclass, we -consider four different encodings of the free monoid (denoted by $F_{1}$, -$F_{2}$, $F_{3}$, $F_{4}$). We find that a free monoid encoding -can be injectively mapped into any other encoding that obeys \emph{fewer} -laws; but those injective maps do not preserve the monoid operations. +write down the code for 4 different encodings of the free monoid (denoted +by $F_{1}$, $F_{2}$, $F_{3}$, $F_{4}$). We find that a given free +monoid encoding can be injectively mapped into any other encoding +that obeys \emph{fewer} laws; but those injective maps do not preserve +the monoid operations. A given encoding may be mapped surjectively +onto another encoding that satisfies the same laws (and possibly more +laws). + +As there are 3 monoid laws, we can construct 8 different free monoid +encodings that obey each of the 8 possible subsets of the three laws. +To illustrate the required techniques, we show two more encodings: +$F_{5}$ obeying the left identity law and the associativity law, +and $F_{6}$ obeying only the left identity law but no other monoid +laws. {*}{*}{*} diff --git a/sofp-src/tex/sofp-traversable.tex b/sofp-src/tex/sofp-traversable.tex index b60f4c85a..7cf8cbf05 100644 --- a/sofp-src/tex/sofp-traversable.tex +++ b/sofp-src/tex/sofp-traversable.tex @@ -3636,8 +3636,8 @@ \subsection{All polynomial functors are traversable\label{subsec:All-polynomial- \text{seq}_{L}^{F,A}:S^{F^{A},L^{F^{A}}}\rightarrow F^{S^{A,L^{A}}}\quad,\quad\quad\text{seq}_{L}^{F,A}\triangleq\big(\overline{\text{seq}}_{L}^{F,A}\big)^{\uparrow S^{F^{A},\bullet}}\bef\text{seq2}_{S}^{F,A,L^{A}}\quad. \] This definition uses a recursive call to $\overline{\text{seq}}_{L}^{F,A}$ -lifted with respect to the type parameter $R$ of $S^{A,R}$. The -inductive assumption is that the recursively called $\overline{\text{seq}}_{L}^{F,A}$ +lifted with respect to the type parameter $R$ of $S^{F^{A},R}$. +The inductive assumption is that the recursively called $\overline{\text{seq}}_{L}^{F,A}$ already obeys the laws we are proving. To verify the identity law~(\ref{eq:identity-law-of-sequence}), diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index c5bf07f44..f012f1203 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): 6963107417ce1d839c8d5d2d00740e06f1393c82dcf78ae0d54565ff8a1d079b}\\ -{\scriptsize{}Git commit: 55b5bea70dbd9f2ae83b96f112cb13f2ed3cc152}\\ -{\scriptsize{}PDF file built on Sat, 08 Nov 2025 14:53:07 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 6b204bb35b698eec23ae80e1ef9c17663f988bf15df634f7d3e0ee05d1b2bd70}\\ +{\scriptsize{}Git commit: faa890c950ef76b5392bbfd436e4b10f3f889007}\\ +{\scriptsize{}PDF file built on Mon, 01 Dec 2025 21:58:36 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, @@ -374,7 +374,7 @@ practical applications of parametricity.}\\ {\scriptsize{}}\\ {\scriptsize{}Long and difficult, yet boring explanations are logically -developed in excruciating detail through 1985 Scala +developed in excruciating detail through 1994 Scala code snippets, 233 statements with step-by-step derivations, 105 diagrams, 239 examples with tested Scala code, and 315 exercises. Discussions build upon each From 684ec605e3adfcc403df0d5953135b2719d16f70 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Thu, 11 Dec 2025 23:54:45 +0100 Subject: [PATCH 33/42] more detail about transformers --- sofp-src/lyx/sofp-free-type.lyx | 2 +- sofp-src/lyx/sofp-transformers.lyx | 262 ++++++++++++++++++++++------- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-appendices.tex | 42 ++++- sofp-src/tex/sofp-free-type.tex | 2 +- sofp-src/tex/sofp-transformers.tex | 107 ++++++------ sofp-src/tex/sofp.tex | 6 +- 7 files changed, 300 insertions(+), 121 deletions(-) diff --git a/sofp-src/lyx/sofp-free-type.lyx b/sofp-src/lyx/sofp-free-type.lyx index c092727cc..80997806b 100644 --- a/sofp-src/lyx/sofp-free-type.lyx +++ b/sofp-src/lyx/sofp-free-type.lyx @@ -22900,7 +22900,7 @@ g effect runner will have type \begin_inset Formula $\forall C.\,F^{C}\rightarrow C$ \end_inset - cannot be implemented? What is sufficient + cannot be implemented? What weaker property is sufficient? \end_layout \begin_layout Standard diff --git a/sofp-src/lyx/sofp-transformers.lyx b/sofp-src/lyx/sofp-transformers.lyx index 73e89f180..79825f321 100644 --- a/sofp-src/lyx/sofp-transformers.lyx +++ b/sofp-src/lyx/sofp-transformers.lyx @@ -10730,8 +10730,13 @@ texttt{'}$s typeclass instance must be defined elsewhere. \begin_layout Plain Layout -trait MTrans[T[_[_]]] { // The type parameter T is a type constructor - with 2 parameters. +trait MTrans[T[_[_]]] { // The type parameter T has kind $(* +\backslash +rightarrow*) +\backslash +rightarrow * +\backslash +rightarrow*$. \end_layout \begin_layout Plain Layout @@ -10767,12 +10772,31 @@ The transformer's code is parametric in the foreign monad \begin_inset Formula $M$ \end_inset - (but not in the base monad + but not in the base monad \begin_inset Formula $L$ \end_inset -). - Although +; in fact, the code of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +MTrans +\end_layout + +\end_inset + + does not refer to +\begin_inset Formula $L$ +\end_inset + + at all. +\end_layout + +\begin_layout Standard +Although \begin_inset listings inline true status open @@ -44113,6 +44137,13 @@ brun \begin_layout Subsection Transformer for the continuation monad. Proofs +\begin_inset CommandInset label +LatexCommand label +name "subsec:Transformer-for-the-continuation-monad" + +\end_inset + + \end_layout \begin_layout Standard @@ -60100,7 +60131,7 @@ name "subsec:Summary-of-monad-transformer-constructions" \end_layout \begin_layout Standard -Monad transformers seen in this chapter fall into one of the 6 cases: +All known monad transformers fall into one of the 7 cases: \end_layout \begin_layout Standard @@ -60156,7 +60187,7 @@ rigid \begin_layout Standard 2. - The special monads + The special \begin_inset listings inline true status open @@ -60168,47 +60199,103 @@ State \end_inset -, + monad has a special, fully featured transformer. + The only deficiency is that the transformer \begin_inset listings inline true status open \begin_layout Plain Layout -Cont +StateT \end_layout \end_inset -, -\begin_inset listings -inline true -status open + has no lawful base runner. +\end_layout -\begin_layout Plain Layout +\begin_layout Standard +3. + The +\begin_inset Quotes eld +\end_inset -Cod -\end_layout +continuation-like +\begin_inset Quotes erd +\end_inset + monads have transformers that are incomplete, having no foreign runners + or base lifts. + These are the transformers for the continuation monad (Section +\begin_inset space ~ \end_inset -, -\begin_inset listings -inline true -status open -\begin_layout Plain Layout +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Transformer-for-the-continuation-monad" +plural "false" +caps "false" +noprefix "false" -Search -\end_layout +\end_inset + +), the search monad (Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Transformer-for-the-generalized-search-monad" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +), the codensity monad (Section +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:The-codensity-monad" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +), and the +\begin_inset Quotes eld +\end_inset + +composed codensity +\begin_inset Quotes erd +\end_inset + + monad (Exercise +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Exercise-combined-codensity-monad" +plural "false" +caps "false" +noprefix "false" \end_inset -, whose transformers are not fully-featured. +). \end_layout \begin_layout Standard -3. +4. The \begin_inset listings inline true @@ -60225,18 +60312,17 @@ List \end_layout \begin_layout Standard -4. - The transformer for a Cartesian product of monads is the Cartesian product - of transformers. +5. + The transformer for a product of monads is the product of transformers. \end_layout \begin_layout Standard -5. +6. The free pointed monad has its special transformer. \end_layout \begin_layout Standard -6. +7. Monad stacks (monads of the form \begin_inset Formula $K\varangle L\varangle...\varangle P$ \end_inset @@ -60253,12 +60339,76 @@ List \begin_inset Formula $P$ \end_inset - are given monads). + are given monads) have transformers defined via larger monad stacks, making + the operation +\begin_inset Formula $\varangle$ +\end_inset + + associative. + \end_layout \begin_layout Standard -No one knows any explicit examples of monads that do not fit into one of - these cases. +Known monad transformers are complete (that is, they are pointed endofunctors + in the category of monads) for all monads except the +\begin_inset Quotes eld +\end_inset + +continuation-like +\begin_inset Quotes erd +\end_inset + + monads whose type signatures have the form +\begin_inset Formula $(A\rightarrow P^{...})\rightarrow Q^{...}$ +\end_inset + +. + These are +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Cont +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Cod +\end_layout + +\end_inset + +, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +Search +\end_layout + +\end_inset + +, and the composed codensity monads. + The transformers for those monads have type signatures of the form +\begin_inset Formula $(A\rightarrow M^{P^{...}})\rightarrow M^{Q^{...}}$ +\end_inset + +, which is not covariant with respect to +\begin_inset Formula $M$ +\end_inset + +. \end_layout \begin_layout Subsection @@ -61058,10 +61208,9 @@ def dbl[M[_]: Monad, A](m: M[A]): M[A] = for { \begin_inset Formula -\begin{align*} -m^{:M^{A}}\triangleright\text{dbl} & \triangleq m\triangleright\text{flm}_{M}(\_^{:A}\rightarrow m)\\ - & =m\triangleright(\_\rightarrow m)^{\uparrow M}\bef\text{ftn}_{M}\quad. -\end{align*} +\[ +m^{:M^{A}}\triangleright\text{dbl}\triangleq m\triangleright\text{flm}_{M}(\_^{:A}\rightarrow m)\quad. +\] \end_inset @@ -61301,7 +61450,7 @@ Consider the monads \begin_inset Formula $\text{State}^{R,A}$ \end_inset - (where + ( \begin_inset Formula $R$ \end_inset @@ -61602,7 +61751,7 @@ For brevity, denote \end_inset . - We have the + The \begin_inset listings inline true status open @@ -61614,16 +61763,7 @@ swap \end_inset - functions: -\begin_inset Formula -\begin{align*} -\text{sw}_{L,T} & :T\circ L\leadsto L\circ T\quad,\\ -\text{sw}_{M,T} & :T\circ M\leadsto M\circ T\quad, -\end{align*} - -\end_inset - -expressed using the already given methods + functions are expressed using the already given methods \begin_inset listings inline true status open @@ -61654,8 +61794,8 @@ blift as: \begin_inset Formula \begin{align*} -\text{sw}_{L,T} & =\text{blift}^{\uparrow T}\bef\text{ftn}_{T}\bef\text{pu}_{L}\quad,\\ -\text{sw}_{M,T} & =\text{flift}^{\uparrow T}\bef\text{ftn}_{T}\bef\text{pu}_{M}\quad. +\text{sw}_{L,T}:T\circ L\leadsto L\circ T\quad,\quad\quad\text{sw}_{L,T} & =\text{blift}^{\uparrow T}\bef\text{ftn}_{T}\bef\text{pu}_{L}\quad,\\ +\text{sw}_{M,T}:T\circ M\leadsto M\circ T\quad,\quad\quad\text{sw}_{M,T} & =\text{flift}^{\uparrow T}\bef\text{ftn}_{T}\bef\text{pu}_{M}\quad. \end{align*} \end_inset @@ -62131,7 +62271,7 @@ def scc[P, A](s: (A => P) => A): (A => P) => P = { f: (A => P) => f(s(f)) \end_layout \begin_layout Standard -Hint: Use the flipped Kleisli technique to simplify the proof of the composition +Hint: Use the flipped Kleisli technique for the proof of the composition law. \begin_inset Index idx status open @@ -63337,7 +63477,7 @@ composed codensity monad \series default -\begin_inset Formula $\text{Cod}_{F}^{M,A}$ +\begin_inset Formula $\text{Cod}_{F}^{M,\bullet}$ \end_inset is defined by: @@ -63352,16 +63492,16 @@ where \begin_inset Formula $M$ \end_inset - is any monad and + is any given monad and \begin_inset Formula $F$ \end_inset - is any functor. - One may define the monad instance for -\begin_inset Formula $\text{Cod}_{F}^{M,A}$ + is any given functor. + The monad methods for +\begin_inset Formula $\text{Cod}_{F}^{M,\bullet}$ \end_inset - via the flipped Kleisli composition: + are defined via the flipped Kleisli composition: \begin_inset Formula \[ f^{:\forall X.\,(B\rightarrow F^{X})\rightarrow A\rightarrow F^{M^{X}}}\tilde{\diamond}\,\,g^{:\forall Y.\,(C\rightarrow F^{Y})\rightarrow B\rightarrow F^{M^{Y}}}\triangleq\forall Z.\,k^{:C\rightarrow F^{Z}}\rightarrow\big(k\triangleright g^{Z}\triangleright f^{M^{Z}}\big)\bef\text{ftn}_{M}^{\uparrow F}\quad. @@ -63382,7 +63522,7 @@ Hints: Use the flipped Kleisli formulation of the monad laws. \begin_inset Formula $\text{Cod}_{F}^{M,A}$ \end_inset - are natural transformations obeying the appropriate naturality law. + are natural transformations obeying their naturality laws. \end_layout \begin_layout Standard @@ -63399,11 +63539,11 @@ Hints: Use the flipped Kleisli formulation of the monad laws. cannot \emph default be removed from the definition of -\begin_inset Formula $\text{Cod}_{F}^{M,A}$ +\begin_inset Formula $\text{Cod}_{F}^{M,\bullet}$ \end_inset even if -\begin_inset Formula $F^{A}\triangleq A$ +\begin_inset Formula $F^{X}\triangleq X$ \end_inset : for a fixed type diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 0eabd3348122cd098d6c1d3b5f8853f45608f656..037236e6561703965507910b92d9f73dd5f5b550 100644 GIT binary patch delta 156 zcmX?Ra?E7IY7uTj!w@55D^o)&V}r@tL<~^)A4Q(2*~!Jg&BfTr%*oQk*~r4s(a6BS(#_Dx$=KA<(Z#~f LhLDQM+EUU05HlzH delta 156 zcmX?Ra?E7IY7uS&!w@4wD^m+AL-WboL<~^)A4Q(<8W>rmrllAf=^B_Dnr?n1%Fe`L zU}$7$Y5`RLQCten*(@w^jnT={%-O=+#n{Qn#Mr{z&C*o LhLDQM+EUU05d$a0 diff --git a/sofp-src/tex/sofp-appendices.tex b/sofp-src/tex/sofp-appendices.tex index 4c81fb2a8..76839a734 100644 --- a/sofp-src/tex/sofp-appendices.tex +++ b/sofp-src/tex/sofp-appendices.tex @@ -11099,7 +11099,7 @@ \subsubsection*{Exercise \ref{subsec:Exercise-effectful-list-not-monad}} \subsubsection*{Exercise \ref{subsec:Exercise-combined-codensity-monad}} -\textbf{(a)} Denote for brevity $\text{Cod}_{F}^{M,A}\triangleq C^{A}$. +\textbf{(a)} Denote for brevity $C^{A}\triangleq\text{Cod}_{F}^{M,A}$. The naturality law for functions $c^{:C^{A}}$ says that for any $k^{:A\rightarrow F^{X}}$ and $q^{:X\rightarrow Y}$, we have: \[ @@ -11141,17 +11141,18 @@ \subsubsection*{Exercise \ref{subsec:Exercise-combined-codensity-monad}} \[ \text{ftn}_{M}^{\uparrow F}\bef\text{ftn}_{M}^{\uparrow F}\overset{?}{=}\text{ftn}_{M}^{\uparrow M\uparrow F}\bef\text{ftn}_{M}^{\uparrow F}\quad, \] -which follows from the associativity law of $\text{ftn}_{M}$. +which disappears due to the associativity law of $\text{ftn}_{M}$. -\textbf{(b)} The \lstinline!flatMap! method must have the type signature: +\textbf{(b)} The \lstinline!flatMap! method of $P$ must have the +type signature: \[ -\text{flm}_{L}:\big((A\rightarrow X)\rightarrow M^{X}\big)\rightarrow(A\rightarrow(B\rightarrow X)\rightarrow M^{X})\rightarrow(B\rightarrow X)\rightarrow M^{X}\quad. +\text{flm}_{P}:\big((A\rightarrow X)\rightarrow M^{X}\big)\rightarrow(A\rightarrow(B\rightarrow X)\rightarrow M^{X})\rightarrow(B\rightarrow X)\rightarrow M^{X}\quad. \] Choose $M^{A}\triangleq\bbnum 1+A$; now we need to implement the type signature: \begin{align*} - & \text{flm}_{L}:\big((A\rightarrow X)\rightarrow\bbnum 1+X\big)\rightarrow\left(A\rightarrow(B\rightarrow X)\rightarrow\bbnum 1+X\right)\rightarrow(B\rightarrow X)\rightarrow\bbnum 1+X\quad,\\ - & \text{flm}_{L}\triangleq p^{:(A\rightarrow X)\rightarrow\bbnum 1+X}\rightarrow q^{:\left(A\rightarrow(B\rightarrow X)\rightarrow\bbnum 1+X\right)}\rightarrow r^{:B\rightarrow X}\rightarrow\text{???}^{:\bbnum 1+X}\quad. + & \text{flm}_{P}:\big((A\rightarrow X)\rightarrow\bbnum 1+X\big)\rightarrow\left(A\rightarrow(B\rightarrow X)\rightarrow\bbnum 1+X\right)\rightarrow(B\rightarrow X)\rightarrow\bbnum 1+X\quad,\\ + & \text{flm}_{P}\triangleq p^{:(A\rightarrow X)\rightarrow\bbnum 1+X}\rightarrow q^{:\left(A\rightarrow(B\rightarrow X)\rightarrow\bbnum 1+X\right)}\rightarrow r^{:B\rightarrow X}\rightarrow\text{???}^{:\bbnum 1+X}\quad. \end{align*} Can this function ever return a value of type $\bbnum 0+X$? When we try filling out the typed hole $\text{???}^{:\bbnum 1+X}$, we @@ -11161,10 +11162,37 @@ \subsubsection*{Exercise \ref{subsec:Exercise-combined-codensity-monad}} we have no available values of type $A$. We also cannot apply the function $p$ since its argument is of type $A\rightarrow X$, but we only have $A\rightarrow\bbnum 1+X$, which is not guaranteed to -return nonempty values. So, the only way of implementing \lstinline!flatMap! +return nonempty values. So, the only way of implementing $\text{flm}_{P}$ via fully parametric code is to return the constant value $1+\bbnum 0^{:X}$. This would lose information and violate an identity law of monads. +\textbf{(c)} In general, the type $\forall A.\,M^{A}\rightarrow\forall X.\,(A\rightarrow F^{X})\rightarrow F^{M^{X}}$ +is equivalent (via the contravariant Yoneda identity) to $\forall X.\,M^{F^{X}}\rightarrow F^{M^{X}}$. +This cannot be implemented as a natural transformation for arbitrary +monads $M$ and functors $F$. + +A simple counterexample is found with $M^{A}\triangleq R\rightarrow A$ +and $F^{A}\triangleq\bbnum 1+A$. Consider a function $f$ with the +type signature of a monad morphism $\forall A.\,M^{A}\rightarrow\text{Cod}_{F}^{M,A}$ +with these $F$ and $M$: +\[ +f:\forall A.\,(R\rightarrow A)\rightarrow\forall X.\,(A\rightarrow\bbnum 1+X)\rightarrow\bbnum 1+(R\rightarrow X)\quad. +\] +Can $f$ be a monad morphism? We can simplify the type of $f$ by +using the covariant Yoneda identity: +\begin{align*} + & \forall A.\,(R\rightarrow A)\rightarrow\forall X.\,(A\rightarrow\bbnum 1+X)\rightarrow\bbnum 1+(R\rightarrow X)\\ + & \cong\forall X.\,(R\rightarrow\bbnum 1+X)\rightarrow\bbnum 1+(R\rightarrow X)\quad. +\end{align*} +A function of type $\forall X.\,(R\rightarrow\bbnum 1+X)\rightarrow\bbnum 1+(R\rightarrow X)$ +cannot make decisions based on its argument (of type $R\rightarrow\bbnum 1+X$) +as $R$ and $X$ are unknown types. The function cannot always return +$\bbnum 0+(R\rightarrow X)$ as the function of type $R\rightarrow\bbnum 1+X$ +could fail to return a value of type $X$ for some argument values +$r^{:R}$. So, the function must always return $\bbnum 1+\bbnum 0^{:R\rightarrow X}$. +But that code would lose information and fail the identity law of +monad morphisms. + \addsec{Chapter \ref{chap:Summary-of-the}} \subsubsection*{Exercise \ref{par:Exercise-additional-1-9}} diff --git a/sofp-src/tex/sofp-free-type.tex b/sofp-src/tex/sofp-free-type.tex index 82aba541d..99225d1b1 100644 --- a/sofp-src/tex/sofp-free-type.tex +++ b/sofp-src/tex/sofp-free-type.tex @@ -3123,7 +3123,7 @@ \subsection{Free functors} \end{align*} {*}{*}{*} example code: what if $\forall C.\,F^{C}\rightarrow C$ -cannot be implemented? What is sufficient +cannot be implemented? What weaker property is sufficient? The type constructor \lstinline!FFR! is a \index{free functor!raw tree encoding}raw tree encoding of the free functor and does not satisfy the functor diff --git a/sofp-src/tex/sofp-transformers.tex b/sofp-src/tex/sofp-transformers.tex index 0b9eb12c1..c5b60b6cb 100644 --- a/sofp-src/tex/sofp-transformers.tex +++ b/sofp-src/tex/sofp-transformers.tex @@ -1350,16 +1350,19 @@ \subsection{A typeclass for monad transformers\label{subsec:A-typeclass-for-mona typeclass can look like this: \begin{lstlisting}[mathescape=true] type Id[A] = A // The identity monad$\color{dkgreen}\texttt{'}$s typeclass instance must be defined elsewhere. -trait MTrans[T[_[_]]] { // The type parameter T is a type constructor with 2 parameters. +trait MTrans[T[_[_]]] { // The type parameter T has kind $(*\rightarrow*)\rightarrow *\rightarrow*$. def monadT[M[_]: Monad]: Monad[T[M, *]] // A monad instance must exist for T[M, *]. def flift[M[_]: Monad, A]: M[A] => T[M, A] def blift[M[_]: Monad, A]: T[Id, A] => T[M, A] = frun[Id, M, A](Monad[M].pure) def frun[M[_]: Monad, N[_]: Monad, A](phi: M[A] => N[A]): T[M, A] => T[N, A] } \end{lstlisting} -The transformer\textsf{'}s code is parametric in the foreign monad $M$ (but -not in the base monad $L$). Although \lstinline!blift! can be implemented -via \lstinline!frun! as $\text{blift}_{L}^{M}\triangleq\text{frun}_{L}^{\text{Id},M}(\text{pu}_{M})$, +The transformer\textsf{'}s code is parametric in the foreign monad $M$ but +not in the base monad $L$; in fact, the code of \lstinline!MTrans! +does not refer to $L$ at all. + +Although \lstinline!blift! can be implemented via \lstinline!frun! +as $\text{blift}_{L}^{M}\triangleq\text{frun}_{L}^{\text{Id},M}(\text{pu}_{M})$, it is convenient to keep all three methods defined separately in the typeclass. @@ -9039,7 +9042,7 @@ \subsubsection{Statement \label{subsec:Statement-state-monad-transformer}\ref{su \end{align*} -\subsection{Transformer for the continuation monad. Proofs} +\subsection{Transformer for the continuation monad. Proofs\label{subsec:Transformer-for-the-continuation-monad}} The continuation monad transformer\textsf{'}s type constructor \lstinline!ContT[R, M[_], *]! is defined by: @@ -9358,11 +9361,11 @@ \subsection{The codensity monad and its transformer. Proofs\label{subsec:The-cod \subsubsection{Statement \label{subsec:Statement-monad-with-quantifier}\ref{subsec:Statement-monad-with-quantifier}} -Assume a monad $K^{R,\bullet}$ with an extra type parameter $R$. -In other words, $K^{R,A}$ is a lawful monad with respect to the type -parameter $A$ and with a fixed $R$. Then: \textbf{(a)} $L^{A}\triangleq\forall R.\,K^{R,A}$ +Assume $K^{R,A}$ is a lawful monad with respect to the type parameter +$A$ and with a fixed type $R$. Then: \textbf{(a)} $L^{A}\triangleq\forall R.\,K^{R,A}$ is also a lawful monad. \textbf{(b)} For any fixed $R$, there is -a monad morphism of type $L^{\bullet}\leadsto K^{R,\bullet}$. +a monad morphism of type $L^{\bullet}\leadsto K^{R,\bullet}$ (that +is, $\forall A.\,L^{A}\rightarrow K^{R,A}$). \subparagraph{Proof} @@ -11904,28 +11907,41 @@ \subsubsection{Example \label{subsec:Example-monatron-free-monad-operation}\ref{ \subsection{Summary of monad transformer constructions\label{subsec:Summary-of-monad-transformer-constructions}} -Monad transformers seen in this chapter fall into one of the 6 cases: +All known monad transformers fall into one of the 7 cases: 1. Compositional transformers that work by functor composition in one or another order. This applies to \lstinline!Either!, \lstinline!Writer!, \lstinline!Reader!, and the \textsf{``}rigid\textsf{''} monads. -2. The special monads \lstinline!State!, \lstinline!Cont!, \lstinline!Cod!, -\lstinline!Search!, whose transformers are not fully-featured. +2. The special \lstinline!State! monad has a special, fully featured +transformer. The only deficiency is that the transformer \lstinline!StateT! +has no lawful base runner. + +3. The \textsf{``}continuation-like\textsf{''} monads have transformers that are incomplete, +having no foreign runners or base lifts. These are the transformers +for the continuation monad (Section~\ref{subsec:Transformer-for-the-continuation-monad}), +the search monad (Section~\ref{subsec:Transformer-for-the-generalized-search-monad}), +the codensity monad (Section~\ref{subsec:The-codensity-monad}), +and the \textsf{``}composed codensity\textsf{''} monad (Exercise~\ref{subsec:Exercise-combined-codensity-monad}). -3. The \lstinline!List! monad and the free monad have recursively +4. The \lstinline!List! monad and the free monad have recursively defined transformers. -4. The transformer for a Cartesian product of monads is the Cartesian -product of transformers. +5. The transformer for a product of monads is the product of transformers. -5. The free pointed monad has its special transformer. +6. The free pointed monad has its special transformer. -6. Monad stacks (monads of the form $K\varangle L\varangle...\varangle P$ -where $K$, $L$, ..., $P$ are given monads). +7. Monad stacks (monads of the form $K\varangle L\varangle...\varangle P$ +where $K$, $L$, ..., $P$ are given monads) have transformers defined +via larger monad stacks, making the operation $\varangle$ associative. -No one knows any explicit examples of monads that do not fit into -one of these cases. +Known monad transformers are complete (that is, they are pointed endofunctors +in the category of monads) for all monads except the \textsf{``}continuation-like\textsf{''} +monads whose type signatures have the form $(A\rightarrow P^{...})\rightarrow Q^{...}$. +These are \lstinline!Cont!, \lstinline!Cod!, \lstinline!Search!, +and the composed codensity monads. The transformers for those monads +have type signatures of the form $(A\rightarrow M^{P^{...}})\rightarrow M^{Q^{...}}$, +which is not covariant with respect to $M$. \subsection{Exercises\index{exercises}} @@ -12012,10 +12028,9 @@ \subsubsection{Exercise \label{subsec:Exercise-monad-transformer-extra-layer-3}\ x <- m } yield x \end{lstlisting} -\begin{align*} -m^{:M^{A}}\triangleright\text{dbl} & \triangleq m\triangleright\text{flm}_{M}(\_^{:A}\rightarrow m)\\ - & =m\triangleright(\_\rightarrow m)^{\uparrow M}\bef\text{ftn}_{M}\quad. -\end{align*} +\[ +m^{:M^{A}}\triangleright\text{dbl}\triangleq m\triangleright\text{flm}_{M}(\_^{:A}\rightarrow m)\quad. +\] This function \textsf{``}doubles\textsf{''} the $M$-effect in a given monadic value $m$ while keeping the value $x^{:A}$ from the second copy of $m$. @@ -12048,7 +12063,7 @@ \subsubsection{Exercise \label{subsec:Exercise-monad-morphism-reader-writer-morp \subsubsection{Exercise \label{subsec:Exercise-monad-morphism-reader-state}\ref{subsec:Exercise-monad-morphism-reader-state}} Consider the monads $\text{Reader}^{R,A}$ and $\text{State}^{R,A}$ -(where $R$ is a fixed type).\index{monads!State monad@\texttt{State} monad}\index{monads!Reader monad@\texttt{Reader} monad} +($R$ is a fixed type).\index{monads!State monad@\texttt{State} monad}\index{monads!Reader monad@\texttt{Reader} monad} \textbf{(a)} Implement a monad morphism $\text{inS}:\text{Reader}^{R,A}\rightarrow\text{State}^{R,A}$ and prove that the laws hold. @@ -12091,16 +12106,12 @@ \subsubsection{Exercise \label{subsec:Exercise-monad-transformer-extra-layer-2}\ U^{A}\triangleq L^{(L\varangle M)^{A}}\quad,\quad\quad V^{A}\triangleq M^{(L\varangle M)^{A}}\quad. \] For brevity, denote $T\triangleq L\varangle M$, $U\triangleq L\circ T$, -and $V\triangleq M\circ T$. We have the \lstinline!swap! functions: -\begin{align*} -\text{sw}_{L,T} & :T\circ L\leadsto L\circ T\quad,\\ -\text{sw}_{M,T} & :T\circ M\leadsto M\circ T\quad, -\end{align*} -expressed using the already given methods \lstinline!flift! and \lstinline!blift! +and $V\triangleq M\circ T$. The \lstinline!swap! functions are expressed +using the already given methods \lstinline!flift! and \lstinline!blift! of $T$ as: \begin{align*} -\text{sw}_{L,T} & =\text{blift}^{\uparrow T}\bef\text{ftn}_{T}\bef\text{pu}_{L}\quad,\\ -\text{sw}_{M,T} & =\text{flift}^{\uparrow T}\bef\text{ftn}_{T}\bef\text{pu}_{M}\quad. +\text{sw}_{L,T}:T\circ L\leadsto L\circ T\quad,\quad\quad\text{sw}_{L,T} & =\text{blift}^{\uparrow T}\bef\text{ftn}_{T}\bef\text{pu}_{L}\quad,\\ +\text{sw}_{M,T}:T\circ M\leadsto M\circ T\quad,\quad\quad\text{sw}_{M,T} & =\text{flift}^{\uparrow T}\bef\text{ftn}_{T}\bef\text{pu}_{M}\quad. \end{align*} We can define the monad methods $\text{ftn}_{U}$ and $\text{ftn}_{V}$ using these \lstinline!swap! functions. Will $U$ and/or $V$ be @@ -12169,8 +12180,8 @@ \subsubsection{Exercise \label{subsec:Exercise-selector-and-continuation-monads} \text{scc}:\text{Sel}^{P,A}\rightarrow\text{Cont}^{P,A}\quad,\quad\quad\text{scc}\,(s^{:(A\rightarrow P)\rightarrow A})\triangleq f^{:A\rightarrow P}\rightarrow f(s(f))\quad. \] -Hint: Use the flipped Kleisli technique to simplify the proof of the -composition law.\index{flipped@\textsf{``}flipped Kleisli\textsf{''} technique} +Hint: Use the flipped Kleisli technique for the proof of the composition +law.\index{flipped@\textsf{``}flipped Kleisli\textsf{''} technique} \subsubsection{Exercise \label{subsec:Exercise-monad-product}\ref{subsec:Exercise-monad-product}} @@ -12294,30 +12305,30 @@ \subsubsection{Exercise \label{subsec:Exercise-effectful-list-not-monad}\ref{sub \subsubsection{Exercise \label{subsec:Exercise-combined-codensity-monad}\ref{subsec:Exercise-combined-codensity-monad}} \textbf{(a)} The\index{monads!composed codensity monad} \textbf{composed} -\textbf{codensity monad} $\text{Cod}_{F}^{L,A}$ is defined by: +\textbf{codensity monad} $\text{Cod}_{F}^{M,A}$ is defined by: \[ -\text{Cod}_{F}^{L,A}\triangleq\forall X.\,(A\rightarrow F^{X})\rightarrow F^{L^{X}}\quad, +\text{Cod}_{F}^{M,A}\triangleq\forall X.\,(A\rightarrow F^{X})\rightarrow F^{M^{X}}\quad, \] -where $L$ is any monad and $F$ is any functor. One may define the -monad instance for $\text{Cod}_{F}^{L,A}$ via the flipped Kleisli +where $M$ is any given monad and $F$ is any given functor. The monad +methods for $\text{Cod}_{F}^{M,A}$ are defined via the flipped Kleisli composition: \[ -f^{:\forall X.\,(B\rightarrow F^{X})\rightarrow A\rightarrow F^{L^{X}}}\tilde{\diamond}\,\,g^{:\forall Y.\,(C\rightarrow F^{Y})\rightarrow B\rightarrow F^{L^{Y}}}\triangleq\forall Z.\,k^{:C\rightarrow F^{Z}}\rightarrow\big(k\triangleright g^{Z}\triangleright f^{L^{Z}}\big)\bef\text{ftn}_{L}^{\uparrow F}\quad. +f^{:\forall X.\,(B\rightarrow F^{X})\rightarrow A\rightarrow F^{M^{X}}}\tilde{\diamond}\,\,g^{:\forall Y.\,(C\rightarrow F^{Y})\rightarrow B\rightarrow F^{M^{Y}}}\triangleq\forall Z.\,k^{:C\rightarrow F^{Z}}\rightarrow\big(k\triangleright g^{Z}\triangleright f^{M^{Z}}\big)\bef\text{ftn}_{M}^{\uparrow F}\quad. \] -Prove that the type constructor $\text{Cod}_{F}^{L,\bullet}$ is a +Prove that the type constructor $\text{Cod}_{F}^{M,\bullet}$ is a lawful monad. Hints: Use the flipped Kleisli formulation of the monad laws. Assume -that values of type $\text{Cod}_{F}^{L,A}$ are natural transformations -obeying the appropriate naturality law. +that values of type $\text{Cod}_{F}^{M,A}$ are natural transformations +obeying their naturality laws. -\textbf{(b)} Show that the quantifier $\forall X$ cannot be removed -from the definition of $\text{Cod}_{F}^{L,A}$ even if $F^{A}\triangleq A$: -for a fixed type $X$ and for some functor $L$, the functor $P^{A}\triangleq(A\rightarrow X)\rightarrow L^{X}$ -is \emph{not} a monad. +\textbf{(b)} Show that the quantifier $\forall X$ \emph{cannot} be +removed from the definition of $\text{Cod}_{F}^{M,A}$ even if $F^{A}\triangleq A$: +for a fixed type $X$ and for some monad $M$, the functor $P^{A}\triangleq(A\rightarrow X)\rightarrow M^{X}$ +is not a monad. \textbf{(c)} Show that in general there is \emph{no} monad morphism -$L^{A}\rightarrow\text{Cod}_{F}^{L,A}$. +of type $\forall A.\,M^{A}\rightarrow\text{Cod}_{F}^{M,A}$. \subsubsection{Exercise \label{subsec:Exercise-pair-functor-is-rigid}\ref{subsec:Exercise-pair-functor-is-rigid}} diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index f012f1203..965ee6c2d 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): 6b204bb35b698eec23ae80e1ef9c17663f988bf15df634f7d3e0ee05d1b2bd70}\\ -{\scriptsize{}Git commit: faa890c950ef76b5392bbfd436e4b10f3f889007}\\ -{\scriptsize{}PDF file built on Mon, 01 Dec 2025 21:58:36 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 3353088c11f75ab310151d29d96234b54e5df2dd360d27529468251cc80b60cc}\\ +{\scriptsize{}Git commit: 9eb07481f0d8a126d77e6499e5a830029f096521}\\ +{\scriptsize{}PDF file built on Thu, 11 Dec 2025 23:51:47 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From 70b9d6bb08f713ead583afe0aadb1124b5a5bbc3 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Fri, 12 Dec 2025 23:10:28 +0100 Subject: [PATCH 34/42] one more exercise for transformers --- sofp-src/lyx/sofp-transformers.lyx | 59 ++++++++++++++++++++++--- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-back-cover-no-bg.tex | 2 +- sofp-src/tex/sofp-transformers.tex | 23 +++++++--- sofp-src/tex/sofp.tex | 8 ++-- 5 files changed, 74 insertions(+), 18 deletions(-) diff --git a/sofp-src/lyx/sofp-transformers.lyx b/sofp-src/lyx/sofp-transformers.lyx index 79825f321..9b1105e2e 100644 --- a/sofp-src/lyx/sofp-transformers.lyx +++ b/sofp-src/lyx/sofp-transformers.lyx @@ -62470,6 +62470,53 @@ monads!free pointed \end_layout +\begin_layout Subsubsection +Exercise +\begin_inset CommandInset label +LatexCommand label +name "par:Exercise-mt-3-4" + +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "par:Exercise-mt-3-4" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\begin_layout Standard +For any monad +\begin_inset Formula $M$ +\end_inset + +, implement a natural transformation of type +\begin_inset Formula $\forall(A,B).\,M^{A+M^{B}}\rightarrow M^{A+B}$ +\end_inset + +. + Show that this transformation is monadically natural with respect to a + suitable law involving arbitrary monads +\begin_inset Formula $M$ +\end_inset + +, +\begin_inset Formula $N$ +\end_inset + + and an arbitrary monad morphism +\begin_inset Formula $\phi:M\leadsto N$ +\end_inset + +. +\end_layout + \begin_layout Subsubsection Exercise \begin_inset CommandInset label @@ -62615,7 +62662,11 @@ cannot \begin_inset Formula $(L\varangle M)^{A}\triangleq A+(K\varangle M)^{A}$ \end_inset - because then (at least for some monads + because then there will be no monad morphism of type +\begin_inset Formula $M^{A}\rightarrow A+(K\varangle M)^{A}$ +\end_inset + +, at least for some monads \begin_inset Formula $K$ \end_inset @@ -62623,10 +62674,6 @@ cannot \begin_inset Formula $M$ \end_inset -) there is no monad morphism -\begin_inset Formula $\text{flift}:M\leadsto(L\varangle M)^{A}$ -\end_inset - . \end_layout @@ -62689,7 +62736,7 @@ not \begin_layout Standard \series bold -(d)* +(d) \series default Given a monad morphism \begin_inset Formula $\theta_{L}:L^{A}\rightarrow A$ diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 037236e6561703965507910b92d9f73dd5f5b550..b6a224ac0ba44462783174dd4d1f0dda4ca64135 100644 GIT binary patch delta 148 zcmX?Ra?E7I8WB#T5F;ZiQ&TI`$y-H?ka! Date: Sat, 27 Dec 2025 23:06:33 +0100 Subject: [PATCH 35/42] remark about List applicative property and paddingZip --- sofp-src/lyx/sofp-applicative.lyx | 40 ++++++++++++++++++++++- sofp-src/lyx/sofp-disjunctions.lyx | 49 ++++++++++++++++++++++++++--- sofp-src/lyx/sofp-free-type.lyx | 9 ++++-- sofp-src/lyx/sofp-transformers.lyx | 16 +++++----- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-applicative.tex | 4 ++- sofp-src/tex/sofp-disjunctions.tex | 14 ++++++--- sofp-src/tex/sofp-free-type.tex | 10 +++--- sofp-src/tex/sofp-transformers.tex | 21 ++++++------- sofp-src/tex/sofp.tex | 6 ++-- 10 files changed, 128 insertions(+), 41 deletions(-) diff --git a/sofp-src/lyx/sofp-applicative.lyx b/sofp-src/lyx/sofp-applicative.lyx index 584dc3481..dd9249046 100644 --- a/sofp-src/lyx/sofp-applicative.lyx +++ b/sofp-src/lyx/sofp-applicative.lyx @@ -22841,7 +22841,45 @@ wu \end_inset does not lead to practical disadvantages when working with finite lists. - + (A definition of +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + for eager +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +List +\end_layout + +\end_inset + + that obeys the laws is given in Exercise +\begin_inset space ~ +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Exercise-applicative-I-1-1-1" +plural "false" +caps "false" +noprefix "false" + +\end_inset + +.) \end_layout \begin_layout Standard diff --git a/sofp-src/lyx/sofp-disjunctions.lyx b/sofp-src/lyx/sofp-disjunctions.lyx index 6bfb8170b..b8fa6497a 100644 --- a/sofp-src/lyx/sofp-disjunctions.lyx +++ b/sofp-src/lyx/sofp-disjunctions.lyx @@ -1321,7 +1321,7 @@ Int \end_inset -, the type parameter +, the compiler has automatically set the type parameter \begin_inset listings inline true status open @@ -1345,7 +1345,7 @@ MySockX[A] \end_inset - was automatically set to the type + to the type \begin_inset listings inline true status open @@ -1372,7 +1372,6 @@ MySockX[Int] \end_inset . - The programmer does not need to specify that type explicitly. \end_layout \begin_layout Standard @@ -1519,7 +1518,47 @@ A \end_inset is. - Scala will set the type parameter + (In this simple example, +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +fits +\end_layout + +\end_inset + + does not actually use the value of type +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +A +\end_layout + +\end_inset + + stored inside +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +MySockX +\end_layout + +\end_inset + +; but another function might.) +\end_layout + +\begin_layout Standard +The type parameter \begin_inset listings inline true status open @@ -1531,7 +1570,7 @@ A \end_inset - automatically when we apply + is set automatically when we apply \begin_inset listings inline true status open diff --git a/sofp-src/lyx/sofp-free-type.lyx b/sofp-src/lyx/sofp-free-type.lyx index 80997806b..c8017060d 100644 --- a/sofp-src/lyx/sofp-free-type.lyx +++ b/sofp-src/lyx/sofp-free-type.lyx @@ -17035,6 +17035,11 @@ The type \end_inset supports the typeclass operations (but may violate some typeclass laws). + There exists a natural transformation +\begin_inset Formula $T\rightarrow\text{Free}^{T}$ +\end_inset + +. For any \begin_inset Formula $T$ \end_inset @@ -17055,7 +17060,7 @@ The type \begin_inset Formula $\text{Free}^{T}\rightarrow\text{Free}^{U}$ \end_inset - will preserve the typeclass operations. + preserves the typeclass operations. \end_layout \begin_layout Enumerate @@ -17177,7 +17182,7 @@ noprefix "false" \begin_inset Formula $P$ \end_inset --typeclasses and to all possible laws. +-typeclasses and to all possible choices of typeclass laws. \end_layout \begin_layout Subsection diff --git a/sofp-src/lyx/sofp-transformers.lyx b/sofp-src/lyx/sofp-transformers.lyx index 9b1105e2e..9eedf4612 100644 --- a/sofp-src/lyx/sofp-transformers.lyx +++ b/sofp-src/lyx/sofp-transformers.lyx @@ -36017,7 +36017,7 @@ Monad laws \end_layout \begin_layout Standard -Heuristically we may say that the recursively defined type +Heuristically we may that the recursively defined type \begin_inset Formula $(\text{Free}\varangle M)^{A}$ \end_inset @@ -44593,7 +44593,7 @@ The generalized status open \begin_layout Plain Layout -monads!generalized +monads! \family typewriter Search \family default @@ -44643,7 +44643,7 @@ Search \end_inset monad is obtained with -\begin_inset Formula $L\triangleq\text{Opt}$ +\begin_inset Formula $L^{A}\triangleq\bbnum 1+A$ \end_inset and @@ -44732,7 +44732,7 @@ We assume that \begin_inset Formula $L\varangle$ \end_inset - already satisfies all the necessary transformer laws. + already satisfies all the laws of transformers. \end_layout \begin_layout Paragraph @@ -44763,7 +44763,7 @@ noprefix "false" \end_inset -filterable contrafunctor -\begin_inset Formula $H^{A}\triangleq A\rightarrow L^{Q}$ +\begin_inset Formula $K^{A}\triangleq A\rightarrow L^{Q}$ \end_inset (see Statement @@ -44811,11 +44811,11 @@ Search is a lawful monad. We will use this definition of -\begin_inset Formula $H^{A}$ +\begin_inset Formula $H$ \end_inset in the proof below. - For brevity, we will denote the transformed monad + We denote the transformed monad \begin_inset listings inline true status open @@ -44835,7 +44835,7 @@ Search \begin_inset Formula $T$ \end_inset - (the foreign monad + for brevity (the foreign monad \begin_inset Formula $M$ \end_inset diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index b6a224ac0ba44462783174dd4d1f0dda4ca64135..c582ca073603b9253206047cef8385c86057ff1e 100644 GIT binary patch delta 156 zcmX?Ra?E7IY7uTD^AIB=D^qhT1JlXdL<~^)A4Q(Kdda8*Y9i%Fe`L zXk=t$Y6?{UQCten*(@w^jnT=)z|hRq(ahY$z{SkP+0@m-%+1W)(Zt2X#mU&s&A`&m LhLDQM+EUU0U85-8 diff --git a/sofp-src/tex/sofp-applicative.tex b/sofp-src/tex/sofp-applicative.tex index fb3fba275..e70d6246b 100644 --- a/sofp-src/tex/sofp-applicative.tex +++ b/sofp-src/tex/sofp-applicative.tex @@ -3338,7 +3338,9 @@ \subsubsection{Statement \label{subsec:Statement-applicative-recursive-type-1}\r functor if the standard definition of \lstinline!zip! is used. Nevertheless, the associativity and the commutativity laws hold for \lstinline!zip!. The absence of a well-defined value \lstinline!wu! does not lead -to practical disadvantages when working with finite lists. +to practical disadvantages when working with finite lists. (A definition +of \lstinline!zip! for eager \lstinline!List! that obeys the laws +is given in Exercise~\ref{subsec:Exercise-applicative-I-1-1-1}.) For certain choices of $F$, $G$, and $H$, the functor $L$ will be a monad. It is important that the implementation of applicative diff --git a/sofp-src/tex/sofp-disjunctions.tex b/sofp-src/tex/sofp-disjunctions.tex index feebc9b43..3651bcc41 100644 --- a/sofp-src/tex/sofp-disjunctions.tex +++ b/sofp-src/tex/sofp-disjunctions.tex @@ -188,9 +188,9 @@ \subsection{Case classes with type parameters} s: MySockX[Int] = MySockX(10.5,white,123) \end{lstlisting} Because the value \lstinline!123! has type \lstinline!Int!, the -type parameter \lstinline!A! in \lstinline!MySockX[A]! was automatically -set to the type \lstinline!Int!. The result has type \lstinline!MySockX[Int]!. -The programmer does not need to specify that type explicitly. +compiler has automatically set the type parameter \lstinline!A! in +\lstinline!MySockX[A]! to the type \lstinline!Int!. The result has +type \lstinline!MySockX[Int]!. Each time we create a value of type \lstinline!MySockX!, a specific type will have to be used instead of the type parameter \lstinline!A!. @@ -210,8 +210,12 @@ \subsection{Case classes with type parameters} \end{lstlisting} This function is defined for all types \lstinline!A! at once, because its code works in the same way regardless of what \lstinline!A! is. -Scala will set the type parameter \lstinline!A! automatically when -we apply \lstinline!fits! to an argument: +(In this simple example, \lstinline!fits! does not actually use the +value of type \lstinline!A! stored inside \lstinline!MySockX!; but +another function might.) + +The type parameter \lstinline!A! is set automatically when we apply +\lstinline!fits! to an argument: \begin{lstlisting} scala> fits(MySockX(10.5, "blue", List(1, 2, 3))) // Using MySockX[List[Int]]. res0: Boolean = true diff --git a/sofp-src/tex/sofp-free-type.tex b/sofp-src/tex/sofp-free-type.tex index 99225d1b1..1867dd661 100644 --- a/sofp-src/tex/sofp-free-type.tex +++ b/sofp-src/tex/sofp-free-type.tex @@ -2191,10 +2191,10 @@ \subsection{Expected properties of a free typeclass construction\label{sec:Expec \begin{enumerate} \item The type $\text{Free}^{T}$ is covariant with respect to $T$. For any $T$, the type $\text{Free}^{T}$ supports the typeclass operations -(but may violate some typeclass laws). For any $T$, $U$ and any -$f:T\rightarrow U$, the function $f^{\uparrow\text{Free}}$ of type -$\text{Free}^{T}\rightarrow\text{Free}^{U}$ will preserve the typeclass -operations. +(but may violate some typeclass laws). There exists a natural transformation +$T\rightarrow\text{Free}^{T}$. For any $T$, $U$ and any $f:T\rightarrow U$, +the function $f^{\uparrow\text{Free}}$ of type $\text{Free}^{T}\rightarrow\text{Free}^{U}$ +preserves the typeclass operations. \item For a given type $M$ that belongs to a typeclass, the free evaluator function (\lstinline!eval!) of type $\text{Free}^{M}\rightarrow M$ preserves the typeclass operations. @@ -2216,7 +2216,7 @@ \subsection{Expected properties of a free typeclass construction\label{sec:Expec We will not prove that those properties hold for those constructions. Instead, Section~\ref{sec:Laws-of-free-constructions} will show general proofs that apply to all $P$-typeclasses and to all possible -laws. +choices of typeclass laws. \subsection{Free pointed type\label{subsec:Free-pointed-type}} diff --git a/sofp-src/tex/sofp-transformers.tex b/sofp-src/tex/sofp-transformers.tex index ef2f5501d..2ae37f242 100644 --- a/sofp-src/tex/sofp-transformers.tex +++ b/sofp-src/tex/sofp-transformers.tex @@ -6491,7 +6491,7 @@ \subsubsection{Statement \label{subsec:Statement-free-monad-transformer}\ref{sub \paragraph{Monad laws} -Heuristically we may say that the recursively defined type $(\text{Free}\varangle M)^{A}$ +Heuristically we may that the recursively defined type $(\text{Free}\varangle M)^{A}$ contains \textsf{``}infinitely many\textsf{''} nested layers of the monad $M$ composed with the functor $F$. Denote by $L$ the type constructor defined recursively by: @@ -9135,13 +9135,13 @@ \subsection{Transformer for the continuation monad. Proofs\label{subsec:Transfor \subsection{Transformer for the generalized \texttt{Search} monad. Proofs\label{subsec:Transformer-for-the-generalized-search-monad}} -The generalized\index{monads!generalized Search monad@generalized \texttt{Search} monad} +The generalized\index{monads!Search monad@\texttt{Search} monad} \lstinline!Search! monad is defined, for a fixed monad $L$ and a fixed type $Q$, by: \[ \text{Search}^{L,Q,A}\triangleq(A\rightarrow L^{Q})\rightarrow L^{A}\quad. \] -The ordinary \lstinline!Search! monad is obtained with $L\triangleq\text{Opt}$ +The ordinary \lstinline!Search! monad is obtained with $L^{A}\triangleq\bbnum 1+A$ and $Q\triangleq\bbnum 1$. \subsubsection{Statement \label{subsec:Statement-generalized-search-monad}\ref{subsec:Statement-generalized-search-monad}} @@ -9158,20 +9158,19 @@ \subsubsection{Statement \label{subsec:Statement-generalized-search-monad}\ref{s \subparagraph{Proof} -We assume that $L\varangle$ already satisfies all the necessary transformer -laws. +We assume that $L\varangle$ already satisfies all the laws of transformers. \paragraph{Monad laws} The monad laws hold for $\text{Search}^{L,Q,A}$ due to Statement~\ref{subsec:Statement-monad-construction-3}, -where we use the $L$-filterable contrafunctor $H^{A}\triangleq A\rightarrow L^{Q}$ +where we use the $L$-filterable contrafunctor $K^{A}\triangleq A\rightarrow L^{Q}$ (see Statement~\ref{subsec:Statement-examples-of-filterable-contrafunctors}). Similarly, we find that the monad laws hold for \lstinline!Search!$\,\varangle M$ if we use the $L\varangle M$-filterable contrafunctor $H^{A}\triangleq A\rightarrow(L\varangle M)^{Q}$, where we assume that $L\varangle M$ is a lawful monad. We will use -this definition of $H^{A}$ in the proof below. For brevity, we will -denote the transformed monad \lstinline!Search!$\,\varangle M$ by -just $T$ (the foreign monad $M$ is fixed throughout the derivations). +this definition of $H$ in the proof below. We denote the transformed +monad \lstinline!Search!$\,\varangle M$ by just $T$ for brevity +(the foreign monad $M$ is fixed throughout the derivations). The monad methods of $T$ are defined according to Statement~\ref{subsec:Statement-monad-construction-3}: \begin{align*} @@ -12248,8 +12247,8 @@ \subsubsection{Exercise \label{par:Exercise-mt-3-2-1}\ref{par:Exercise-mt-3-2-1} \textbf{(a)} Show that the monad transformer for $L$ \emph{cannot} be defined as the monad $(L\varangle M)^{A}\triangleq A+(K\varangle M)^{A}$ -because then (at least for some monads $K$ and $M$) there is no -monad morphism of type $M^{A}\rightarrow A+(K\varangle M)^{A}$. +because then there will be no monad morphism of type $M^{A}\rightarrow A+(K\varangle M)^{A}$, +at least for some monads $K$ and $M$. \textbf{(b)} Given a runner $\theta_{K}:K\leadsto M$, where $M$ is an arbitrary (but fixed) target monad, implement a runner $\theta_{L}:L\leadsto M$ diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 33e79017b..47a2a7e5e 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): a4d8dd3cb26ca9a56005e51c600f9ae7d4e416165c68bb61325285d43c92554b}\\ -{\scriptsize{}Git commit: 684ec605e3adfcc403df0d5953135b2719d16f70}\\ -{\scriptsize{}PDF file built on Fri, 12 Dec 2025 22:56:08 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): d08b7e0731982c59791ebd00c5655400417c8e0528eb03ce5abbc9ccebea666b}\\ +{\scriptsize{}Git commit: 70b9d6bb08f713ead583afe0aadb1124b5a5bbc3}\\ +{\scriptsize{}PDF file built on Sat, 27 Dec 2025 22:57:25 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From b9344d8278e7a114d11bf5c806c7f7500517e323 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Tue, 27 Jan 2026 10:23:29 +0100 Subject: [PATCH 36/42] first wip replacement of FM-typeclasses --- sofp-src/lyx/sofp-appendices.lyx | 66 +++---- sofp-src/lyx/sofp-applicative.lyx | 62 +++++- sofp-src/lyx/sofp-filterable.lyx | 4 +- sofp-src/lyx/sofp-free-type.lyx | 268 +++++++++++++------------- sofp-src/lyx/sofp-summary.lyx | 6 +- sofp-src/lyx/sofp-transformers.lyx | 16 +- sofp-src/lyx/sofp-typeclasses.lyx | 83 ++++++--- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-appendices.tex | 58 +++--- sofp-src/tex/sofp-applicative.tex | 15 +- sofp-src/tex/sofp-filterable.tex | 2 +- sofp-src/tex/sofp-free-type.tex | 290 +++++++++++++++-------------- sofp-src/tex/sofp-summary.tex | 6 +- sofp-src/tex/sofp-transformers.tex | 16 +- sofp-src/tex/sofp-typeclasses.tex | 61 +++--- sofp-src/tex/sofp.tex | 6 +- 16 files changed, 520 insertions(+), 439 deletions(-) diff --git a/sofp-src/lyx/sofp-appendices.lyx b/sofp-src/lyx/sofp-appendices.lyx index f121c5181..f57a30c5e 100644 --- a/sofp-src/lyx/sofp-appendices.lyx +++ b/sofp-src/lyx/sofp-appendices.lyx @@ -5312,7 +5312,7 @@ Another use of \end_inset -algebras is in formulating properties of -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses. @@ -5320,7 +5320,7 @@ Another use of status open \begin_layout Plain Layout -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass @@ -5328,8 +5328,8 @@ status open \end_inset - A -\begin_inset Formula $P$ + An +\begin_inset Formula $FM$ \end_inset -typeclass is a @@ -5342,7 +5342,7 @@ status open \end_inset -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass @@ -5393,7 +5393,7 @@ tagless final \end_inset pattern), or more generally to Church encodings of free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses that involve functions of type @@ -5751,7 +5751,7 @@ laws \end_inset , and -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses. @@ -5759,7 +5759,7 @@ laws status open \begin_layout Plain Layout -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass @@ -52049,14 +52049,14 @@ literal "false" is a type equivalence between certain type constructors quantified over a typeclass. This section proves a version of that theorem that holds for simple types - belonging to a -\begin_inset Formula $P$ + belonging to an +\begin_inset Formula $FM$ \end_inset -typeclass. Then the theorem gives a general type formula for the free construction of any -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. @@ -52085,7 +52085,7 @@ noprefix "false" \begin_layout Standard The free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass instance @@ -52109,7 +52109,7 @@ Here the quantifier goes only over the types \end_inset that belong to the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. @@ -52149,7 +52149,7 @@ One of the defining properties of the free typeclass constructor \end_inset and -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass morphisms of type @@ -52178,7 +52178,7 @@ All types \end_inset belonging to the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass are @@ -52199,7 +52199,7 @@ where \end_inset is any fixed type that also belongs to the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. @@ -52238,7 +52238,7 @@ name "subsec:The-Jaskelioff-OConnor-theorem" The full formulation of the theorem involves functor typeclasses instead of typeclasses for simple types. The theorem applies to all -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses for functors. @@ -52272,7 +52272,7 @@ The full formulation of the theorem involves functor typeclasses instead . Examples of well-known -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses of that form are pointed functors, filterable functors, applicative @@ -52302,7 +52302,7 @@ noprefix "false" \begin_layout Standard Given any fixed -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass for functors, denote by @@ -52318,7 +52318,7 @@ Given any fixed \end_inset is an instance of the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass satisfying the properties of free typeclass constructors. @@ -52349,7 +52349,7 @@ Here, it is assumed that the type \end_inset is restricted to functions satisfying the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass naturality law with respect to @@ -52369,7 +52369,7 @@ Denote by \end_inset the type of -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass morphisms between functors @@ -52381,8 +52381,8 @@ Denote by \end_inset that belong to the typeclass. - (The full type signature of a -\begin_inset Formula $P$ + (The full type signature of an +\begin_inset Formula $FM$ \end_inset -typeclass morphism is @@ -52447,7 +52447,7 @@ In the first line of this derivation, we have used the assumption that (2) \series default By the universal property of the free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass runner, for any functor @@ -52455,7 +52455,7 @@ In the first line of this derivation, we have used the assumption that \end_inset that belongs to the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass and for any functor @@ -52463,11 +52463,11 @@ In the first line of this derivation, we have used the assumption that \end_inset (not necessarily a member of the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass) there is a one-to-one correspondence between -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass morphisms @@ -52532,7 +52532,7 @@ noprefix "false" \series default We use the covariant Yoneda identity in the category of functors that belong to the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. @@ -52556,7 +52556,7 @@ noprefix "false" -monad algebras, which form a category. The -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass morphisms are in one-to-one correspondence with the @@ -52578,7 +52578,7 @@ where \end_inset is any fixed functor from the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass, @@ -52999,8 +52999,8 @@ Monad \end_inset - typeclass has methods in the form of a -\begin_inset Formula $P$ + typeclass has methods in the form of an +\begin_inset Formula $FM$ \end_inset -typeclass for functors diff --git a/sofp-src/lyx/sofp-applicative.lyx b/sofp-src/lyx/sofp-applicative.lyx index dd9249046..928441cac 100644 --- a/sofp-src/lyx/sofp-applicative.lyx +++ b/sofp-src/lyx/sofp-applicative.lyx @@ -22841,7 +22841,27 @@ wu \end_inset does not lead to practical disadvantages when working with finite lists. - (A definition of + (To make the eager +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +List +\end_layout + +\end_inset + + a lawful applicative functor, one can define a +\begin_inset Quotes eld +\end_inset + +padding +\begin_inset Quotes erd +\end_inset + + version of \begin_inset listings inline true status open @@ -22853,19 +22873,29 @@ zip \end_inset - for eager + +\begin_inset Index idx +status open + +\begin_layout Plain Layout +padding \begin_inset listings inline true status open \begin_layout Plain Layout -List +zip \end_layout \end_inset - that obeys the laws is given in Exercise + +\end_layout + +\end_inset + + as shown in Exercise \begin_inset space ~ \end_inset @@ -33768,7 +33798,29 @@ zip \end_inset - method for lists such that the shorter list is padded with the + method +\begin_inset Index idx +status open + +\begin_layout Plain Layout +padding +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + +\end_layout + +\end_inset + + for lists such that the shorter list is padded with the \emph on last \emph default diff --git a/sofp-src/lyx/sofp-filterable.lyx b/sofp-src/lyx/sofp-filterable.lyx index 982741725..c9bde4ed1 100644 --- a/sofp-src/lyx/sofp-filterable.lyx +++ b/sofp-src/lyx/sofp-filterable.lyx @@ -23689,8 +23689,8 @@ Filterable \end_inset - typeclass is a -\begin_inset Formula $P$ + typeclass is an +\begin_inset Formula $FM$ \end_inset -typeclass (see Section diff --git a/sofp-src/lyx/sofp-free-type.lyx b/sofp-src/lyx/sofp-free-type.lyx index c8017060d..822910b44 100644 --- a/sofp-src/lyx/sofp-free-type.lyx +++ b/sofp-src/lyx/sofp-free-type.lyx @@ -17179,7 +17179,7 @@ noprefix "false" \end_inset will show general proofs that apply to all -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses and to all possible choices of typeclass laws. @@ -25437,8 +25437,8 @@ noprefix "false" \end_inset -), consider a -\begin_inset Formula $P$ +), consider an +\begin_inset Formula $FM$ \end_inset -typeclass called @@ -25687,7 +25687,7 @@ TC parametrically. We expect that similar code will work for any other -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass to define a free instance. @@ -25758,7 +25758,7 @@ TC \end_inset to an arbitrary -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass, replacing the type @@ -25770,12 +25770,12 @@ TC \end_inset that describes all the methods of the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. Then the free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass instance constructor is given by: @@ -25809,7 +25809,7 @@ This type can be rewritten as . Indeed, we know from the theory of -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses that the free monad on @@ -25817,12 +25817,12 @@ This type can be rewritten as \end_inset gives the raw tree encoding of the free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. If the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass has no laws then this is the only available encoding. @@ -26229,8 +26229,8 @@ What happens if we apply the same technique to a typeclass that is \emph on not \emph default - of the form of a -\begin_inset Formula $P$ + of the form of an +\begin_inset Formula $FM$ \end_inset -typeclass? As it turns out, the construction no longer works as expected. @@ -26495,7 +26495,7 @@ This chapter started by developing the free monad via the implementation those constructions? Are all the different encodings equally safe to use? We will now develop the necessary theory for answering these questions in the case of -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses for ordinary types. @@ -26504,7 +26504,7 @@ This chapter started by developing the free monad via the implementation \end_inset -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass @@ -26526,7 +26526,7 @@ noprefix "false" \end_inset .) We expect that -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses for type constructors (such as @@ -26559,7 +26559,7 @@ Monad \begin_layout Subsection Free constructions for -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses @@ -26580,23 +26580,23 @@ Some features are common to all the free typeclass constructions we have free monoids, etc.) to an arbitrary typeclass. We will use the encodings of the free monoid as the starting point and generalize to encodings of an arbitrary free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. \end_layout \begin_layout Standard -The free monoid is a type constructor (denoted by -\begin_inset Quotes eld -\end_inset - +The free monoid is a type constructor (which turns out to be +\begin_inset listings +inline true +status open -\begin_inset Formula $\text{FM}$ -\end_inset +\begin_layout Plain Layout +List +\end_layout -\begin_inset Quotes erd \end_inset ) that transforms an arbitrary type @@ -26604,7 +26604,7 @@ The free monoid is a type constructor (denoted by \end_inset into a new type ( -\begin_inset Formula $\text{FM}^{T}$ +\begin_inset Formula $\text{List}^{T}$ \end_inset ) having a @@ -26625,7 +26625,7 @@ Monoid \end_inset can be wrapped into values of type -\begin_inset Formula $\text{FM}^{T}$ +\begin_inset Formula $\text{List}^{T}$ \end_inset . @@ -26646,7 +26646,7 @@ free monoid program \end_inset (i.e., a value of type -\begin_inset Formula $\text{FM}^{T}$ +\begin_inset Formula $\text{List}^{T}$ \end_inset ) can be @@ -26663,11 +26663,11 @@ run into . The resulting runner (of type -\begin_inset Formula $\text{FM}^{T}\rightarrow M$ +\begin_inset Formula $\text{List}^{T}\rightarrow M$ \end_inset ) will preserve the monoid operations between -\begin_inset Formula $\text{FM}^{T}$ +\begin_inset Formula $\text{List}^{T}$ \end_inset and @@ -26684,7 +26684,7 @@ free monoid program \end_inset , even when the chosen encoding -\begin_inset Formula $\text{FM}^{T}$ +\begin_inset Formula $\text{List}^{T}$ \end_inset violates some of the monoid laws. @@ -26692,8 +26692,8 @@ free monoid program \begin_layout Standard To generalize from monoids to other typeclasses, recall the definition of - a -\begin_inset Formula $P$ + an +\begin_inset Formula $FM$ \end_inset -typeclass (Section @@ -26714,8 +26714,8 @@ noprefix "false" \begin_inset Formula $P$ \end_inset -, a -\begin_inset Formula $P$ +, an +\begin_inset Formula $FM$ \end_inset @@ -26727,7 +26727,7 @@ noprefix "false" status open \begin_layout Plain Layout -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass @@ -26783,7 +26783,7 @@ arguments ). So, we imagine that the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass combines all methods of a typeclass into a single value (of type @@ -26804,7 +26804,7 @@ preserving the monoid's operations \end_inset to an arbitrary -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. @@ -27051,7 +27051,7 @@ preserving the typeclass operations \end_inset for an arbitrary -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass: we just need to impose Eq. @@ -27501,7 +27501,7 @@ F\text{-algebra morphism law for }h^{:L\rightarrow M}:\quad & =\gunderline{g^{\u \begin_layout Standard We can now formulate our findings about -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses in the language of @@ -27517,8 +27517,8 @@ We can now formulate our findings about \end_inset ). - We say that a -\begin_inset Formula $P$ + We say that an +\begin_inset Formula $FM$ \end_inset @@ -27530,7 +27530,7 @@ We can now formulate our findings about status open \begin_layout Plain Layout -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass!with laws @@ -27557,7 +27557,7 @@ evidence value \end_inset belongs to the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. @@ -27590,7 +27590,7 @@ evidence value \end_inset preserves the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass operations @@ -27607,7 +27607,7 @@ The next step is to generalize the free monoid construction to a \end_inset free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass @@ -27635,7 +27635,7 @@ encoding \end_inset of a free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass: @@ -27650,13 +27650,13 @@ We expect to have a type constructor \begin_inset Formula $T$ \end_inset - and produces a -\begin_inset Formula $P$ + and produces an +\begin_inset Formula $FM$ \end_inset -typeclass instance automatically. (However, that -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass instance may not obey all of the typeclass laws.) @@ -27689,7 +27689,7 @@ Values of type \end_inset -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass programs @@ -27723,7 +27723,7 @@ runner \end_inset must be an instance of the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. @@ -27828,7 +27828,7 @@ So, we require that a function of type \begin_layout Standard We now define a free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encoding by making these expectations precise: @@ -27856,7 +27856,7 @@ noprefix "false" \end_layout \begin_layout Standard -Given a functor +Given a structure functor \begin_inset Formula $P$ \end_inset @@ -27865,7 +27865,7 @@ Given a functor free \series default -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset @@ -27959,13 +27959,13 @@ noprefix "false" \end_inset may obey some (or none) of the laws of the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. There is only a finite number of typeclass laws; so we may consider the largest subset of the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass laws obeyed by @@ -28096,7 +28096,7 @@ evaluator \end_inset obeys all the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass laws assured by @@ -28161,8 +28161,8 @@ all \begin_inset Formula $E$ \end_inset - means that if a -\begin_inset Formula $P$ + means that if an +\begin_inset Formula $FM$ \end_inset -typeclass law (such as an identity law, an associativity law, etc.) is satisfied @@ -28207,7 +28207,7 @@ noprefix "false" \end_inset will describe -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass laws in more detail, but we do not yet need the techniques developed @@ -28250,12 +28250,12 @@ noprefix "false" \begin_layout Standard The uniqueness property of the evaluator reflects a programmer's expectation that there is only one correct way of running (i.e., evaluating) a free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass program while preserving the typeclass's operations. However, in practice we need to evaluate not only -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass programs of type @@ -28272,11 +28272,11 @@ The uniqueness property of the evaluator reflects a programmer's expectation -algebra and already belongs to the typeclass. The usefulness of a free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass construction is in supporting -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass programs of type @@ -28363,7 +28363,7 @@ universal runner \end_inset will evaluate a free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass program of type @@ -28416,7 +28416,7 @@ Suppose \end_inset is a free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encoding, @@ -28685,7 +28685,7 @@ noprefix "false" \begin_layout Standard It is important that the definition of a free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encoding @@ -28701,7 +28701,7 @@ It is important that the definition of a free all \emph default of the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass laws. @@ -28716,7 +28716,7 @@ not \end_inset free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encodings @@ -28741,7 +28741,7 @@ Monoid \end_inset to an arbitrary -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass and to show that it satisfies the definition of a @@ -28749,7 +28749,7 @@ Monoid \end_inset free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encoding @@ -28760,7 +28760,7 @@ free Although the raw tree encoding does not satisfy any typeclass laws, it gives us a valid and usable encoding that we can use as a starting point to develop other, more concise encodings for a free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. @@ -28815,11 +28815,11 @@ The parts of the disjunctive type . We can now generalize to arbitrary -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses and define the raw tree encoding of a free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass (denoted by @@ -28920,7 +28920,7 @@ The free monad on \end_inset , is a free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encoding. @@ -29380,7 +29380,7 @@ The two code matrices are now equal due to the assumed law \end_inset with -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass instance @@ -29528,12 +29528,12 @@ flatten \end_inset -algebra morphism; in other words, it preserves the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass operations. So, it is not useful to apply the free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass construction twice, as the result can be reduced to a single @@ -29685,7 +29685,7 @@ It is not accidental that the raw tree encoding ( all \emph default free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encodings are monads (although not necessarily free monads): @@ -29714,7 +29714,7 @@ noprefix "false" \begin_layout Standard Any free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encoding @@ -30140,7 +30140,7 @@ noprefix "false" \begin_layout Subsection Describing laws of -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses as values @@ -30164,7 +30164,7 @@ first-class \end_inset description of -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass laws: each law will be represented by a value of a certain type. @@ -30306,7 +30306,7 @@ Monoid will be different. To generalize to arbitrary -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses, let us express the laws as much as possible through @@ -30446,12 +30446,12 @@ Monoid \end_inset laws to other -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses. - A -\begin_inset Formula $P$ + An +\begin_inset Formula $FM$ \end_inset -typeclass may impose zero or more laws. @@ -30532,7 +30532,7 @@ Laws as expression trees Another approach to describing typeclass laws is by viewing the two sides of a law as expression trees. Recall that the raw tree encoding of a free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass (which we denoted by @@ -30921,7 +30921,7 @@ Monoid \end_inset to an arbitrary -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. @@ -31000,7 +31000,7 @@ et: LawET \end_inset with -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass evidence value @@ -31457,7 +31457,7 @@ FMR[Int] \begin_layout Standard Generalizing this to arbitrary -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses, we obtain the type @@ -31793,8 +31793,8 @@ LawET \end_layout \begin_layout Standard -It turns out that laws of a -\begin_inset Formula $P$ +It turns out that laws of an +\begin_inset Formula $FM$ \end_inset -typeclass are closely connected with @@ -31903,7 +31903,7 @@ preserve \end_inset the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass laws. @@ -31968,7 +31968,7 @@ hides \end_inset violations of the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass laws. @@ -32229,7 +32229,7 @@ noprefix "false" . Now we see that this is a general property that applies to all -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses. @@ -32249,7 +32249,7 @@ partially lawful \begin_layout Subsection Free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses that satisfy a subset of the laws @@ -32342,11 +32342,11 @@ noprefix "false" , although they obey different subsets of the laws of monoids. We will now generalize that situation to -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses and study the properties of free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass constructions that satisfy only a subset of the typeclass's laws. @@ -32356,7 +32356,7 @@ r \end_inset is indeed a valid free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encoding as specified by Definition @@ -32665,7 +32665,7 @@ Let \end_inset be any free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encoding. @@ -32693,7 +32693,7 @@ Let \end_inset obeys all the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass laws that @@ -32742,7 +32742,7 @@ smaller \end_inset obeys some law of the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass then @@ -32770,7 +32770,7 @@ smaller \end_inset obeys some law of the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass then @@ -32902,7 +32902,7 @@ noprefix "false" \end_inset obeys all the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass laws that @@ -33264,7 +33264,7 @@ The restriction to polynomial functors is not a limitation in practice. All known -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses have only a finite set of operations, and each operation has @@ -33287,7 +33287,7 @@ The next statement shows that a functor \end_inset is a free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encoding if it has an injective map into the raw tree encoding @@ -33305,7 +33305,7 @@ FPR ) and has certain additional properties. This statement helps us validate free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encodings with less work than by using Definition @@ -33512,7 +33512,7 @@ smaller \end_inset satisfies some (or all) of the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass laws but @@ -33539,7 +33539,7 @@ no other \end_inset for describing -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass laws (see Section @@ -33566,7 +33566,7 @@ noprefix "false" \end_inset no other laws than those of the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass @@ -33582,7 +33582,7 @@ no other laws than those of the \end_inset that obeys all the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass laws and for any @@ -33656,7 +33656,7 @@ If assumptions 1-5 hold then: \end_inset is a free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encoding. @@ -33703,7 +33703,7 @@ not -algebra morphism. Then we are able to describe free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encodings @@ -33916,7 +33916,7 @@ We find that we must have isomorphism \emph default (a type equivalence that preserves the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass operations) between @@ -33952,8 +33952,8 @@ To show that \begin_inset Formula $E$ \end_inset - is a -\begin_inset Formula $P$ + is an +\begin_inset Formula $FM$ \end_inset -typeclass encoding, we look at the conditions in Definition @@ -34001,7 +34001,7 @@ To verify condition (c), we assume that \end_inset -algebra that obeys all the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass laws that @@ -34600,7 +34600,7 @@ noprefix "false" \begin_layout Subsection Imposing laws of -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses via monad algebras @@ -34629,7 +34629,7 @@ noprefix "false" \end_inset that any free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encoding @@ -34642,7 +34642,7 @@ noprefix "false" \end_inset 's monad methods to impose -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass laws on a given @@ -34911,7 +34911,7 @@ Suppose \end_inset is a free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encoding according to Definition @@ -35630,7 +35630,7 @@ Let \end_inset be any free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encoding by Definition @@ -35830,7 +35830,7 @@ In the next section, we will use monad algebras to prove that certain typeclass \begin_layout Subsection Laws for the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass derivation constructions @@ -35860,13 +35860,13 @@ noprefix "false" we have shown certain type constructions that derive new typeclass instances from previous ones. - For example, the product of two types that belong to a -\begin_inset Formula $P$ + For example, the product of two types that belong to an +\begin_inset Formula $FM$ \end_inset -typeclass will again belong to that typeclass. - However, in that chapter we only showed that one can compute a -\begin_inset Formula $P$ + However, in that chapter we only showed that one can compute an +\begin_inset Formula $FM$ \end_inset -typeclass evidence values for those constructions. @@ -35889,8 +35889,8 @@ Instead of dealing with laws explicitly as values, it is more convenient \begin_inset Formula $T$ \end_inset - is a lawful member of a -\begin_inset Formula $P$ + is a lawful member of an +\begin_inset Formula $FM$ \end_inset -typeclass if @@ -35906,7 +35906,7 @@ Instead of dealing with laws explicitly as values, it is more convenient \end_inset is the free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass encoding that assures the laws of the typeclass. @@ -36573,7 +36573,7 @@ Unlike the proof in part \begin_layout Subsection Church encodings of free -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses @@ -38457,7 +38457,7 @@ call structure functor \series default of the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass @@ -40545,8 +40545,8 @@ acts \begin_inset Formula $\text{Mod}_{L}$ \end_inset - is a -\begin_inset Formula $P$ + is an +\begin_inset Formula $FM$ \end_inset -typeclass. diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 058131b53..08b48a844 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -2372,7 +2372,7 @@ Why many typeclasses have similar properties as regards typeclass derivation; \end_inset -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses @@ -6136,7 +6136,7 @@ noprefix "false" \begin_layout Standard Later we will show that this situation is found in general for all -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses: a reduced encoding can be injected into the raw tree encoding @@ -8176,7 +8176,7 @@ noprefix "false" \end_inset ) and for lawful -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses (used in Section diff --git a/sofp-src/lyx/sofp-transformers.lyx b/sofp-src/lyx/sofp-transformers.lyx index 9eedf4612..3045be3c8 100644 --- a/sofp-src/lyx/sofp-transformers.lyx +++ b/sofp-src/lyx/sofp-transformers.lyx @@ -47565,7 +47565,7 @@ noprefix "false" \end_inset and, for -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses, by Statement @@ -63162,7 +63162,7 @@ noprefix "false" that adding a type quantifier to a monad gives again a monad. Show that adding a type quantifier to any -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass (Section @@ -63179,13 +63179,13 @@ noprefix "false" \end_inset -) gives again a -\begin_inset Formula $P$ +) gives again an +\begin_inset Formula $FM$ \end_inset -typeclass. - In detail: assume a -\begin_inset Formula $P$ + In detail: assume an +\begin_inset Formula $FM$ \end_inset -typeclass defined via a structure functor @@ -63210,8 +63210,8 @@ noprefix "false" \begin_inset Formula $\forall R.\,S^{R,A}\rightarrow A$ \end_inset - is again a -\begin_inset Formula $P$ + is again an +\begin_inset Formula $FM$ \end_inset -typeclass (with a different choice of the structure functor). diff --git a/sofp-src/lyx/sofp-typeclasses.lyx b/sofp-src/lyx/sofp-typeclasses.lyx index 1e01240c4..6422a1199 100644 --- a/sofp-src/lyx/sofp-typeclasses.lyx +++ b/sofp-src/lyx/sofp-typeclasses.lyx @@ -36261,7 +36261,7 @@ John de Goes. \end_layout \begin_layout Subsection -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses, their laws and structure @@ -36662,7 +36662,7 @@ pointed contrafunctor \begin_layout Plain Layout Structure of typeclass instance values for various -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses. @@ -36803,7 +36803,7 @@ This motivates the definition of status open \begin_layout Plain Layout -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass|textit @@ -36811,8 +36811,8 @@ status open \end_inset - a -\begin_inset Formula $P$ + an +\begin_inset Formula $FM$ \end_inset - @@ -36853,6 +36853,31 @@ typeclass!structure functor structure functor \series default of the typeclass. + (The name +\begin_inset Quotes eld +\end_inset + +FM +\begin_inset Quotes erd +\end_inset + + refers to +\begin_inset Quotes eld +\end_inset + +functors +\begin_inset Quotes erd +\end_inset + + and +\begin_inset Quotes eld +\end_inset + +monads +\begin_inset Quotes erd +\end_inset + + and will be justified later.) \end_layout \begin_layout Standard @@ -36863,13 +36888,13 @@ status open \begin_layout Plain Layout -final case class PTypeclass[P[_]: Functor, A](methods: P[A] => A) +final case class FMTypeclass[P[_]: Functor, A](methods: P[A] => A) \end_layout \end_inset The code allows us to declare any -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. @@ -36921,7 +36946,7 @@ val functorMonoidSF: Functor[MonoidSF] = ... \begin_layout Plain Layout -type PMonoid[A] = PTypeclass[MonoidSF, A] +type FMMonoid[A] = FMTypeclass[MonoidSF, A] \end_layout \end_inset @@ -37017,7 +37042,7 @@ noprefix "false" The laws of type constructor typeclasses are also more complicated because they often involve multiple type parameters and arbitrary functions. To simplify the presentation in this section, we will only consider -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses for simple types, such as @@ -37076,7 +37101,7 @@ Monoid is useful for reasoning about general properties of typeclasses. To illustrate that kind of reasoning, we will now show that the product-type, the function-type, and the recursive-type constructions work for all -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses. @@ -37089,7 +37114,7 @@ Products \begin_layout Standard Consider an arbitrary -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass @@ -37212,7 +37237,7 @@ noprefix "false" \end_inset after developing some advanced techniques for formal reasoning about -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass laws. @@ -37224,7 +37249,7 @@ We note that the co-product construction does not \emph default work for arbitrary -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses: given evidence values of types @@ -37241,7 +37266,7 @@ not . Later we will see that some -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses, such as monads or applicative functors, do not support the @@ -37255,8 +37280,8 @@ Functions \end_layout \begin_layout Standard -The function-type construction creates a -\begin_inset Formula $P$ +The function-type construction creates an +\begin_inset Formula $FM$ \end_inset -typeclass instance for the type @@ -37268,7 +37293,7 @@ The function-type construction creates a \end_inset belongs to the -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. @@ -37340,7 +37365,7 @@ preserves \end_inset -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass instances: if @@ -37506,7 +37531,7 @@ def tcT: P[T] => T = p => T(tcS(tcT)(p.map(_.s))) // The recursive instance. \end_inset In this way, the recursive-type construction works for any -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclass. @@ -37533,7 +37558,7 @@ Similar arguments can be made for type constructor typeclasses, although This book shows that the product-type, the function-type, and the recursive-typ e constructions work for functors, contrafunctors, pointed functors, and pointed contrafunctors, as well as for other important -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses such as filterable functors (Chapter @@ -37594,7 +37619,7 @@ noprefix "false" \end_inset that another general construction also works for all -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses, — the @@ -37614,7 +37639,7 @@ Some typeclasses cannot \emph default be viewed as -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses. @@ -37739,7 +37764,7 @@ noprefix "false" co- \series default -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset @@ -37752,7 +37777,7 @@ status open \begin_layout Plain Layout co- -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses @@ -37786,8 +37811,8 @@ co-product \begin_inset Formula $A+B\rightarrow P^{A+B}$ \end_inset -, i.e., a -\begin_inset Formula $P$ +, i.e., an +\begin_inset Formula $FM$ \end_inset -typeclass evidence for the co-product @@ -37796,7 +37821,7 @@ co-product . Similarly to -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses, the typeclass laws will hold automatically for the type @@ -37805,7 +37830,7 @@ co-product . A detailed description of co- -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses is beyond the scope of this book. @@ -39067,7 +39092,7 @@ es whose method signature has the form \end_inset -\begin_inset Formula $P$ +\begin_inset Formula $FM$ \end_inset -typeclasses diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index c582ca073603b9253206047cef8385c86057ff1e..050710054994bd23012ca00aff0c558d1999849e 100644 GIT binary patch delta 172 zcmX?Ra?E7IG7$kYT?0d1Bl8eL11m#wD-)B++eEZ61wV>B;k7g~PfkoRN!2wrHc#37 zNR)+%+swew$lTDt&>X1mqqsOSf3vW}HAW|MCsz|kQ%3_M7egZ_Lvv#nGgm`bLklM- UOGhUcLpO6f8$v23YfDK30EjXx#{d8T delta 172 zcmX?Ra?E7IG7$k&T|*;XBl8d=BP&yLD+ANX+eEZ61wV>B;kB?ZGE22cGt)IpvPjze zNR)+%+tkp=$lS=t)EubqqqsOSf3vW}HAW{RBUd*QS64H0V>1g=H%C(=7XuR~3o|2E UQ%fULHzzkc8$v23YfDK30D3MflK=n! diff --git a/sofp-src/tex/sofp-appendices.tex b/sofp-src/tex/sofp-appendices.tex index 76839a734..55a82cd11 100644 --- a/sofp-src/tex/sofp-appendices.tex +++ b/sofp-src/tex/sofp-appendices.tex @@ -705,14 +705,14 @@ \section{How the term \textquotedblleft algebra\textquotedblright{} is used theory, least fixpoints of a type equation $F^{T}\cong T$ is the \textsf{``}initial $F$-algebra\textsf{''}.\footnote{See \texttt{\href{https://homepages.inf.ed.ac.uk/wadler/papers/free-rectypes/free-rectypes.txt}{https://homepages.inf.ed.ac.uk/wadler/papers/free-rectypes/free-rectypes.txt}} } -Another use of $F$-algebras is in formulating properties of $P$-typeclasses.\index{$P$-typeclass} -A $P$-typeclass is a $P$-algebra with (usually) additional laws -imposed. This book prefers the term \textsf{``}$P$-typeclass\textsf{''} for brevity, +Another use of $F$-algebras is in formulating properties of $FM$-typeclasses.\index{$FM$-typeclass} +An $FM$-typeclass is a $P$-algebra with (usually) additional laws +imposed. This book prefers the term \textsf{``}$FM$-typeclass\textsf{''} for brevity, although those typeclasses could also be called \textsf{``}$P$-algebraic\textsf{''}. The \textsf{``}algebra\textsf{''} defined in this sense is also relevant to the Church encoding of a free monad (also known as the \textsf{``}tagless final\index{tagless final}\textsf{''} -pattern), or more generally to Church encodings of free $P$-typeclasses +pattern), or more generally to Church encodings of free $FM$-typeclasses that involve functions of type $\forall E^{\bullet}.\,(S^{E}\leadsto E)\leadsto E$. That type uses a higher-order type $S^{E}$ parameterized by a \emph{type constructor} parameter $E^{\bullet}$. In this context, a value of @@ -763,7 +763,7 @@ \section{How the term \textquotedblleft algebra\textquotedblright{} is used book, the word \textsf{``}algebra\textsf{''} always means a branch of mathematics, as in \textsf{``}high-school algebra\textsf{''}. Instead of \textsf{``}algebras\textsf{''} as in Definitions~1 to~3, this book talks about \textsf{``}polynomial types\textsf{''} or \textsf{``}recursive -polynomial types\textsf{''}, \textsf{``}equations\textsf{''} or \textsf{``}laws\textsf{''}, and $P$-typeclasses.\index{$P$-typeclass} +polynomial types\textsf{''}, \textsf{``}equations\textsf{''} or \textsf{``}laws\textsf{''}, and $FM$-typeclasses.\index{$FM$-typeclass} \chapter{Parametricity theorem and naturality laws\label{app:Proofs-of-naturality-parametricity}} @@ -8353,18 +8353,18 @@ \subsection{The Jaskelioff-O\textsf{'}Connor theorem for simple types} The Jaskelioff-O\textsf{'}Connor theorem\footnote{See \texttt{\href{https://arxiv.org/abs/1402.1699}{https://arxiv.org/abs/1402.1699}}} is a type equivalence between certain type constructors quantified over a typeclass. This section proves a version of that theorem that -holds for simple types belonging to a $P$-typeclass. Then the theorem -gives a general type formula for the free construction of any $P$-typeclass. +holds for simple types belonging to an $FM$-typeclass. Then the theorem +gives a general type formula for the free construction of any $FM$-typeclass. \subsubsection{Statement \label{subsec:Statement-JOC-theorem-simple-types}\ref{subsec:Statement-JOC-theorem-simple-types}} -The free $P$-typeclass instance $E^{T}$ generated by a type $T$ +The free $FM$-typeclass instance $E^{T}$ generated by a type $T$ is equivalent to the type defined by: \begin{equation} E^{T}\cong\forall(A\in P\text{-typeclass}).\,(T\rightarrow A)\rightarrow A\quad.\label{eq:free-typeclass-via-church-encoding} \end{equation} Here the quantifier goes only over the types $A$ that belong to the -$P$-typeclass. It is also assumed that the type in the right-hand +$FM$-typeclass. It is also assumed that the type in the right-hand side of Eq.~(\ref{eq:free-typeclass-via-church-encoding}) admits only functions that satisfy the naturality law with respect to $A$. @@ -8372,20 +8372,20 @@ \subsubsection{Statement \label{subsec:Statement-JOC-theorem-simple-types}\ref{s One of the defining properties of the free typeclass constructor $E$ is the one-to-one correspondence between functions of type $T\rightarrow A$ -and $P$-typeclass morphisms of type $E^{T}\rightarrow A$. Denoting +and $FM$-typeclass morphisms of type $E^{T}\rightarrow A$. Denoting by $E^{T}\overset{P}{\rightarrow}A$ the type of those morphisms, we have: \[ \forall(A\in P\text{-typeclass}).\,(T\rightarrow A)\rightarrow A\cong\forall(A\in P\text{-typeclass}).\,(E^{T}\overset{P}{\rightarrow}A)\rightarrow A\quad. \] -All types $A$ belonging to the $P$-typeclass are $E$-monad algebras, +All types $A$ belonging to the $FM$-typeclass are $E$-monad algebras, and those algebras form a category. Now we use the Yoneda identity in that category: \[ \forall(A\in P\text{-typeclass}).\,(X\overset{P}{\rightarrow}A)\rightarrow A\cong X\quad, \] -where $X$ is any fixed type that also belongs to the $P$-typeclass. +where $X$ is any fixed type that also belongs to the $FM$-typeclass. We use this identity with $X=E^{T}$ and obtain: \[ \forall(A\in P\text{-typeclass}).\,(E^{T}\overset{P}{\rightarrow}A)\rightarrow A\cong E^{T}\quad, @@ -8395,36 +8395,36 @@ \subsubsection{Statement \label{subsec:Statement-JOC-theorem-simple-types}\ref{s \subsection{The Jaskelioff-O\textsf{'}Connor theorem for type constructors\label{subsec:The-Jaskelioff-OConnor-theorem}} The full formulation of the theorem involves functor typeclasses instead -of typeclasses for simple types. The theorem applies to all $P$-typeclasses +of typeclasses for simple types. The theorem applies to all $FM$-typeclasses for functors. Those typeclasses have method signatures of the form $\forall A.\,(P^{F})^{A}\rightarrow F^{A}$, where $P$ is a functor on functors (the kind of $P$ is $(*\rightarrow*)\rightarrow*\rightarrow*$) and functions of type $(P^{F})^{A}\rightarrow F^{A}$ are restricted to natural transformations between functors $P^{F}$ and $F$. Examples -of well-known $P$-typeclasses of that form are pointed functors, +of well-known $FM$-typeclasses of that form are pointed functors, filterable functors, applicative functors, and monads. \subsubsection{Statement \label{subsec:Statement-Jaskelioff-OConnor}\ref{subsec:Statement-Jaskelioff-OConnor} (Jaskelioff-O\textsf{'}Connor)} -Given any fixed $P$-typeclass for functors, denote by $E$ the constructor +Given any fixed $FM$-typeclass for functors, denote by $E$ the constructor of free instances of that typeclass: if $T$ is any functor then the -functor $E^{T}$ is an instance of the $P$-typeclass satisfying the -properties of free typeclass constructors. Suppose $A$, $B$, $C$ -are some fixed types. Then the following type equivalence holds: +functor $E^{T}$ is an instance of the $FM$-typeclass satisfying +the properties of free typeclass constructors. Suppose $A$, $B$, +$C$ are some fixed types. Then the following type equivalence holds: \begin{align} & \forall(F\in P\text{-typeclass}).\,(A\rightarrow F^{B})\rightarrow F^{C}\cong(E^{R})^{C}\quad,\label{eq:jaskelioff-o-connor-theorem}\\ {\color{greenunder}\text{where }R\text{ is defined by}:}\quad & R^{T}\triangleq A\times(B\rightarrow T)\quad.\nonumber \end{align} Here, it is assumed that the type $(A\rightarrow F^{B})\rightarrow F^{C}$ -is restricted to functions satisfying the $P$-typeclass naturality +is restricted to functions satisfying the $FM$-typeclass naturality law with respect to $F$. \subparagraph{Proof} -Denote by $K\overset{P}{\rightarrow}L$ the type of $P$-typeclass +Denote by $K\overset{P}{\rightarrow}L$ the type of $FM$-typeclass morphisms between functors $K$ and $L$ that belong to the typeclass. -(The full type signature of a $P$-typeclass morphism is $\forall A.\,K^{A}\overset{P}{\rightarrow}L^{A}$.) +(The full type signature of an $FM$-typeclass morphism is $\forall A.\,K^{A}\overset{P}{\rightarrow}L^{A}$.) We will prove the type equivalence~(\ref{eq:jaskelioff-o-connor-theorem}) in three steps. @@ -8443,10 +8443,10 @@ \subsubsection{Statement \label{subsec:Statement-Jaskelioff-OConnor}\ref{subsec: In the first line of this derivation, we have used the assumption that $F$ is a (covariant) functor. -\textbf{(2)} By the universal property of the free $P$-typeclass -runner, for any functor $F$ that belongs to the $P$-typeclass and -for any functor $R$ (not necessarily a member of the $P$-typeclass) -there is a one-to-one correspondence between $P$-typeclass morphisms +\textbf{(2)} By the universal property of the free $FM$-typeclass +runner, for any functor $F$ that belongs to the $FM$-typeclass and +for any functor $R$ (not necessarily a member of the $FM$-typeclass) +there is a one-to-one correspondence between $FM$-typeclass morphisms $E^{R}\overset{P}{\rightarrow}F$ and natural transformations $R\leadsto F$. In other words, there is a type equivalence between the following types (where we wrote out the full type signatures): @@ -8464,16 +8464,16 @@ \subsubsection{Statement \label{subsec:Statement-Jaskelioff-OConnor}\ref{subsec: \] \textbf{(3)} We use the covariant Yoneda identity in the category -of functors that belong to the $P$-typeclass. As we have found in +of functors that belong to the $FM$-typeclass. As we have found in Section~\ref{subsec:Imposing-laws-of-P-typeclasses-via-monad-algebras}, all those functors are $E$-monad algebras, which form a category. -The $P$-typeclass morphisms are in one-to-one correspondence with +The $FM$-typeclass morphisms are in one-to-one correspondence with the $E$-monad algebra morphisms. Therefore, we may write the covariant Yoneda identity for that category as: \[ \forall(F\in P\text{-typeclass}).\,(\forall X.\,Q^{X}\overset{P}{\rightarrow}F^{X})\rightarrow S^{F}\cong S^{Q}\quad, \] -where $Q$ is any fixed functor from the $P$-typeclass, $S^{F}$ +where $Q$ is any fixed functor from the $FM$-typeclass, $S^{F}$ is any type expression that is covariant in $F$, and the naturality law with respect to $F$ is assumed to hold. We will use this Yoneda identity with $Q=E^{R}$, and set $S^{F}$ to just $F^{C}$ (the application @@ -8555,7 +8555,7 @@ \subsubsection{Statement \label{subsec:Statement-identity-monad-morphism}\ref{su \subparagraph{Proof} -The \lstinline!Monad! typeclass has methods in the form of a $P$-typeclass +The \lstinline!Monad! typeclass has methods in the form of an $FM$-typeclass for functors $K$ if we define $P$ by $(P^{K})^{A}\triangleq A+K^{K^{A}}$. Then the methods of the \lstinline!Monad! typeclass are represented by a single value of type: diff --git a/sofp-src/tex/sofp-applicative.tex b/sofp-src/tex/sofp-applicative.tex index e70d6246b..b6aa436f6 100644 --- a/sofp-src/tex/sofp-applicative.tex +++ b/sofp-src/tex/sofp-applicative.tex @@ -3338,9 +3338,10 @@ \subsubsection{Statement \label{subsec:Statement-applicative-recursive-type-1}\r functor if the standard definition of \lstinline!zip! is used. Nevertheless, the associativity and the commutativity laws hold for \lstinline!zip!. The absence of a well-defined value \lstinline!wu! does not lead -to practical disadvantages when working with finite lists. (A definition -of \lstinline!zip! for eager \lstinline!List! that obeys the laws -is given in Exercise~\ref{subsec:Exercise-applicative-I-1-1-1}.) +to practical disadvantages when working with finite lists. (To make +the eager \lstinline!List! a lawful applicative functor, one can +define a \textsf{``}padding\textsf{''} version of \lstinline!zip!\index{padding zip@padding \lstinline!zip!} +as shown in Exercise~\ref{subsec:Exercise-applicative-I-1-1-1}.) For certain choices of $F$, $G$, and $H$, the functor $L$ will be a monad. It is important that the implementation of applicative @@ -5367,10 +5368,10 @@ \subsubsection{Exercise \label{subsec:Exercise-applicative-II-4-2}\ref{subsec:Ex \subsubsection{Exercise \label{subsec:Exercise-applicative-I-1-1-1}\ref{subsec:Exercise-applicative-I-1-1-1}} -Implement a \textsf{``}padding\textsf{''} \lstinline!zip! method for lists such that -the shorter list is padded with the \emph{last} value until its length -is equal to that of the longer list. Zipping with an empty list returns -again an empty list. A sample test: +Implement a \textsf{``}padding\textsf{''} \lstinline!zip! method\index{padding zip@padding \lstinline!zip!} +for lists such that the shorter list is padded with the \emph{last} +value until its length is equal to that of the longer list. Zipping +with an empty list returns again an empty list. A sample test: \begin{lstlisting} def paddingZip[A, B](left: List[A], right: List[B]): List[(A, B)] = ??? diff --git a/sofp-src/tex/sofp-filterable.tex b/sofp-src/tex/sofp-filterable.tex index cbb6ecdbd..a177f4e12 100644 --- a/sofp-src/tex/sofp-filterable.tex +++ b/sofp-src/tex/sofp-filterable.tex @@ -3686,7 +3686,7 @@ \subsection{Constructions of filterable contrafunctors\label{subsec:Construction \caption{Constructions of filterable contrafunctors.\label{tab:Constructions-of-filterable-contrafunctors}} \end{table} -The \lstinline!Filterable! typeclass is a $P$-typeclass (see Section~\ref{subsec:P-typeclasses}) +The \lstinline!Filterable! typeclass is an $FM$-typeclass (see Section~\ref{subsec:P-typeclasses}) if formulated via \lstinline!filter! or via \lstinline!liftOpt!, because those methods return the type $C^{A}$ itself. So, we expect that the product, the exponential, and the recursive constructions diff --git a/sofp-src/tex/sofp-free-type.tex b/sofp-src/tex/sofp-free-type.tex index 1867dd661..b4d9653e9 100644 --- a/sofp-src/tex/sofp-free-type.tex +++ b/sofp-src/tex/sofp-free-type.tex @@ -2215,7 +2215,7 @@ \subsection{Expected properties of a free typeclass construction\label{sec:Expec The following sections will show various free typeclass constructions. We will not prove that those properties hold for those constructions. Instead, Section~\ref{sec:Laws-of-free-constructions} will show -general proofs that apply to all $P$-typeclasses and to all possible +general proofs that apply to all $FM$-typeclasses and to all possible choices of typeclass laws. \subsection{Free pointed type\label{subsec:Free-pointed-type}} @@ -3487,7 +3487,7 @@ \subsection{Church encodings of free typeclasses} theorem.{*}{*}{*} As a first example of using Eq.~(\ref{eq:free-typeclass-via-church-encoding}), -consider a $P$-typeclass called \lstinline!TC! whose methods do +consider an $FM$-typeclass called \lstinline!TC! whose methods do not have to obey any laws. The Scala code for the typeclass \lstinline!TC! contains two methods: \begin{lstlisting} @@ -3527,7 +3527,7 @@ \subsection{Church encodings of free typeclasses} The code of \lstinline!FreeTC[T]! and of \lstinline!instanceFreeTC! uses the trait \lstinline!TC! parametrically. We expect that similar -code will work for any other $P$-typeclass to define a free instance. +code will work for any other $FM$-typeclass to define a free instance. To see that more clearly, rewrite the type signature of the function \lstinline!run! showing the implicit parameter at the end: \begin{lstlisting} @@ -3539,19 +3539,19 @@ \subsection{Church encodings of free typeclasses} \[ \forall A.\,(T\rightarrow A)\rightarrow\text{TC}^{A}\rightarrow A\quad. \] -Let us generalize from \lstinline!TC! to an arbitrary $P$-typeclass, +Let us generalize from \lstinline!TC! to an arbitrary $FM$-typeclass, replacing the type $\text{TC}^{A}$ by the type $P^{A}\rightarrow A$ -that describes all the methods of the $P$-typeclass. Then the free -$P$-typeclass instance constructor is given by: +that describes all the methods of the $FM$-typeclass. Then the free +$FM$-typeclass instance constructor is given by: \[ \forall A.\,(T\rightarrow A)\rightarrow(P^{A}\rightarrow A)\rightarrow A\quad. \] This type can be rewritten as $\forall A.\,(T+P^{A}\rightarrow A)\rightarrow A$, which is the Church encoding of the recursive type $F\cong T+P^{F}$. We recognize that $F$ is the free monad on the functor $P$, applied -to the type $T$. Indeed, we know from the theory of $P$-typeclasses +to the type $T$. Indeed, we know from the theory of $FM$-typeclasses that the free monad on $P$ gives the raw tree encoding of the free -$P$-typeclass. If the $P$-typeclass has no laws then this is the +$FM$-typeclass. If the $FM$-typeclass has no laws then this is the only available encoding. Most typeclasses do require some laws to hold. This technique will @@ -3616,11 +3616,11 @@ \subsection{Church encodings of free typeclasses} monoid laws will also hold for \lstinline!FreeMonoid[T]!. What happens if we apply the same technique to a typeclass that is -\emph{not} of the form of a $P$-typeclass? As it turns out, the construction -no longer works as expected. An example is the \lstinline!Eq! typeclass -(Section~\ref{subsec:The-Eq-typeclass}) whose evidence values have -type $T\times T\rightarrow\bbnum 2$, giving a comparison operation -for values of type $T$. The \lstinline!Eq! typeclass \emph{cannot} +\emph{not} of the form of an $FM$-typeclass? As it turns out, the +construction no longer works as expected. An example is the \lstinline!Eq! +typeclass (Section~\ref{subsec:The-Eq-typeclass}) whose evidence +values have type $T\times T\rightarrow\bbnum 2$, giving a comparison +operation for values of type $T$. The \lstinline!Eq! typeclass \emph{cannot} have a free instance; in other words, no free typeclass encoding $E$ exists. If we apply the type formula~(\ref{eq:free-typeclass-via-church-encoding}) to that typeclass, we get the following type constructor $E$: @@ -3662,48 +3662,48 @@ \section{Laws of free constructions\label{sec:Laws-of-free-constructions}} its various encodings. Can we formulate any properties or laws that validate the correctness of those constructions? Are all the different encodings equally safe to use? We will now develop the necessary theory -for answering these questions in the case of $P$-typeclasses for -ordinary types. (The notion of a \textsf{``}$P$-typeclass\textsf{''} was introduced -in Section~\ref{subsec:P-typeclasses}.) We expect that $P$-typeclasses +for answering these questions in the case of $FM$-typeclasses for +ordinary types. (The notion of a \textsf{``}$FM$-typeclass\textsf{''} was introduced +in Section~\ref{subsec:P-typeclasses}.) We expect that $FM$-typeclasses for type constructors (such as \lstinline!Functor! and \lstinline!Monad!) will have similar properties, although the technical details of the proofs will be more difficult to work out. -\subsection{Free constructions for $P$-typeclasses\label{subsec:Free-constructions-for-inductive-typeclasses}} +\subsection{Free constructions for $FM$-typeclasses\label{subsec:Free-constructions-for-inductive-typeclasses}} Some features are common to all the free typeclass constructions we have seen. To find a mathematical description of those common features, we need to generalize what we have learned about specific typeclasses (free monads, free monoids, etc.) to an arbitrary typeclass. We will use the encodings of the free monoid as the starting point and generalize -to encodings of an arbitrary free $P$-typeclass. +to encodings of an arbitrary free $FM$-typeclass. -The free monoid is a type constructor (denoted by \textsf{``}$\text{FM}$\textsf{''}) -that transforms an arbitrary type $T$ into a new type ($\text{FM}^{T}$) +The free monoid is a type constructor (which turns out to be \lstinline!List!) +that transforms an arbitrary type $T$ into a new type ($\text{List}^{T}$) having a \lstinline!Monoid! typeclass instance. Values of type $T$ -can be wrapped into values of type $\text{FM}^{T}$. For any given +can be wrapped into values of type $\text{List}^{T}$. For any given monoid $M$ and a given function of type $T\rightarrow M$, a \textsf{``}free -monoid program\textsf{''} (i.e., a value of type $\text{FM}^{T}$) can be -\textsf{``}run into $M$\textsf{''}. The resulting runner (of type $\text{FM}^{T}\rightarrow M$) -will preserve the monoid operations between $\text{FM}^{T}$ and $M$. -So, the monoid laws will hold after running a \textsf{``}free monoid program\textsf{''}, -even when the chosen encoding $\text{FM}^{T}$ violates some of the -monoid laws. +monoid program\textsf{''} (i.e., a value of type $\text{List}^{T}$) can be +\textsf{``}run into $M$\textsf{''}. The resulting runner (of type $\text{List}^{T}\rightarrow M$) +will preserve the monoid operations between $\text{List}^{T}$ and +$M$. So, the monoid laws will hold after running a \textsf{``}free monoid +program\textsf{''}, even when the chosen encoding $\text{List}^{T}$ violates +some of the monoid laws. To generalize from monoids to other typeclasses, recall the definition -of a $P$-typeclass (Section~\ref{subsec:P-typeclasses}): For a -given (covariant) functor $P$, a $P$\textbf{-typeclass} \index{$P$-typeclass} +of an $FM$-typeclass (Section~\ref{subsec:P-typeclasses}): For +a given (covariant) functor $P$, a $P$\textbf{-typeclass} \index{$FM$-typeclass} has the evidence data equivalent to a value of type $P^{A}\rightarrow A$. The evidence data for the \lstinline!Monoid! typeclass has type $A\times\left(A\times A\rightarrow A\right)$, which is equivalent to $P^{A}\rightarrow A$ if we define $P^{A}\triangleq\bbnum 1+A\times A$. The two parts of the disjunctive type $\bbnum 1+A\times A$ correspond to the \emph{arguments} of the monoid\textsf{'}s two operations: the empty value ($e_{A}$) and the binary operation ($\oplus_{A}$). So, we -imagine that the $P$-typeclass combines all methods of a typeclass +imagine that the $FM$-typeclass combines all methods of a typeclass into a single value (of type $P^{A}\rightarrow A$). The next step is to generalize the property of \textsf{``}preserving the monoid\textsf{'}s -operations\textsf{''} to an arbitrary $P$-typeclass. Given two monoids $M$ +operations\textsf{''} to an arbitrary $FM$-typeclass. Given two monoids $M$ and $N$, a function $f:M\rightarrow N$ that preserves the monoid\textsf{'}s operations is a monoid morphism\index{monoid morphism} according to Definition~\ref{subsec:Definition-monoid-morphism}. Can we describe @@ -3779,7 +3779,7 @@ \subsection{Free constructions for $P$-typeclasses\label{subsec:Free-constructio This equation is the same as the identity and composition laws in Definition~\ref{subsec:Definition-monoid-morphism}. It is now clear how to define the property of \textsf{``}preserving the typeclass operations\textsf{''} -for an arbitrary $P$-typeclass: we just need to impose Eq.~(\ref{eq:p-algebra-morphism-law}). +for an arbitrary $FM$-typeclass: we just need to impose Eq.~(\ref{eq:p-algebra-morphism-law}). In this way, we have reformulated the typeclass preservation property in terms of the functor $P$. @@ -3839,35 +3839,36 @@ \subsubsection{Statement \label{subsec:Statement-category-of-P-algebras}\ref{sub \end{align*} $\square$ -We can now formulate our findings about $P$-typeclasses in the language +We can now formulate our findings about $FM$-typeclasses in the language of $P$-functor algebras (using the functor $P$ instead of $F$). -We say that a $P$\textbf{-typeclass with laws} is\index{$P$-typeclass!with laws} +We say that an $FM$\textbf{-typeclass with laws} is\index{$FM$-typeclass!with laws} a $P$-algebra whose structure map needs to satisfy the given laws. The structure map ($p_{M}:P^{M}\rightarrow M$) describes at once all the typeclass methods and so plays the role of an \emph{evidence -value} showing that a type $M$ belongs to the $P$-typeclass. If +value} showing that a type $M$ belongs to the $FM$-typeclass. If $M$ and $N$ are two $P$-algebras and a function $f^{:M\rightarrow N}$ is a $P$-algebra morphism then we say that $f$ \textsf{``}preserves the -$P$-typeclass operations\textsf{''}. +$FM$-typeclass operations\textsf{''}. The next step is to generalize the free monoid construction to a \textsf{``}free -$P$-typeclass\textsf{''} construction. We have seen that there are several +$FM$-typeclass\textsf{''} construction. We have seen that there are several versions, or \textsf{``}encodings\textsf{''} as we called them, of the free monoid. Different encodings satisfy different subsets of the monoid laws. By analogy with the free monoid, we list the expected properties of -an \textsf{``}encoding\textsf{''} of a free $P$-typeclass: +an \textsf{``}encoding\textsf{''} of a free $FM$-typeclass: \begin{itemize} \item We expect to have a type constructor $E^{T}$ that wraps an arbitrary -type $T$ and produces a $P$-typeclass instance automatically. (However, -that $P$-typeclass instance may not obey all of the typeclass laws.) +type $T$ and produces an $FM$-typeclass instance automatically. +(However, that $FM$-typeclass instance may not obey all of the typeclass +laws.) \item We should be able to convert values of type $T$ into the type $E^{T}$; in other words, there should be a function of type $T\rightarrow E^{T}$. -\item Values of type $E^{T}$ represent \textsf{``}$P$-typeclass programs\textsf{''}, that -is, unevaluated expression trees with primitive values of type $T$. -So, we need a \textsf{``}runner\textsf{''} for evaluating those expression trees into -values of a specific type $C$, as long as a function of type $T\rightarrow C$ -is given. Here, $C$ must be an instance of the $P$-typeclass. The -\textsf{``}runner\textsf{''} should have the type signature: +\item Values of type $E^{T}$ represent \textsf{``}$FM$-typeclass programs\textsf{''}, +that is, unevaluated expression trees with primitive values of type +$T$. So, we need a \textsf{``}runner\textsf{''} for evaluating those expression trees +into values of a specific type $C$, as long as a function of type +$T\rightarrow C$ is given. Here, $C$ must be an instance of the +$FM$-typeclass. The \textsf{``}runner\textsf{''} should have the type signature: \[ \text{run}_{E}^{T,C}:(T\rightarrow C)\rightarrow E^{T}\rightarrow C\quad. \] @@ -3891,13 +3892,13 @@ \subsubsection{Statement \label{subsec:Statement-category-of-P-algebras}\ref{sub be the unique $P$-algebra morphism of that type, at least for all $C$ that belong to the typeclass. -We now define a free $P$-typeclass encoding by making these expectations +We now define a free $FM$-typeclass encoding by making these expectations precise: \subsubsection{Definition \label{subsec:Definition-free-P-typeclass-encoding}\ref{subsec:Definition-free-P-typeclass-encoding}} -Given a functor $P$, a \textbf{free} $P$\textbf{-typeclass} \textbf{encoding} -is a functor $E$ such that: +Given a structure functor $P$, a \textbf{free} $FM$\textbf{-typeclass} +\textbf{encoding} is a functor $E$ such that: \textbf{(a)} For any type $T$, the type $E^{T}$ is a $P$-algebra with the structure map $p_{E}^{T}:P^{E^{T}}\rightarrow E^{T}$ natural @@ -3910,9 +3911,9 @@ \subsubsection{Definition \label{subsec:Definition-free-P-typeclass-encoding}\re is a $P$-algebra morphism. \textbf{(b)} The function $p_{E}^{T}$ for specific types $T$ may -obey some (or none) of the laws of the $P$-typeclass. There is only +obey some (or none) of the laws of the $FM$-typeclass. There is only a finite number of typeclass laws; so we may consider the largest -subset of the $P$-typeclass laws obeyed by $p_{E}^{T}$ for \emph{all} +subset of the $FM$-typeclass laws obeyed by $p_{E}^{T}$ for \emph{all} $T$. We call that subset \textsf{``}the laws \textbf{assured by} $E$\textsf{''} or \textsf{``}the laws obeyed by $E^{T}$ for all $T$\textsf{''}. (Typically, $E^{T}$ will obey the same set of laws for almost all types $T$. We will @@ -3924,7 +3925,7 @@ \subsubsection{Definition \label{subsec:Definition-free-P-typeclass-encoding}\re \textbf{(d)} There exists an \textsf{``}evaluator\textsf{''} function ($\text{eval}_{E}^{C}:E^{C}\rightarrow C$), where $C$ is required to be a $P$-algebra whose structure map $p_{C}:P^{C}\rightarrow C$ -obeys all the $P$-typeclass laws assured by $E$. To be precise, +obeys all the $FM$-typeclass laws assured by $E$. To be precise, the evaluator function depends on $p_{C}$ and has the full type signature $(P^{C}\rightarrow C)\rightarrow E^{C}\rightarrow C$. For brevity, we will write $\text{eval}_{E}^{C}$ instead of $\text{eval}_{E}^{C}(p_{C})$, @@ -3940,11 +3941,11 @@ \subsubsection{Definition \label{subsec:Definition-free-P-typeclass-encoding}\re \end{align} The requirement that $C$ should obey \textsf{``}all\textsf{''} the laws assured by -$E$ means that if a $P$-typeclass law (such as an identity law, +$E$ means that if an $FM$-typeclass law (such as an identity law, an associativity law, etc.) is satisfied by $E^{T}$ for all $T$ then that law must also hold for $C$. (It is acceptable if the type $C$ obeys \emph{more} laws than assured by $E$. Section~\ref{subsec:Describing-laws-of-P-typeclasses-as-values} -will describe $P$-typeclass laws in more detail, but we do not yet +will describe $FM$-typeclass laws in more detail, but we do not yet need the techniques developed there.) \textbf{(e)} The evaluator function $\text{eval}_{E}^{C}$ has a uniqueness @@ -3954,14 +3955,15 @@ \subsubsection{Definition \label{subsec:Definition-free-P-typeclass-encoding}\re The uniqueness property of the evaluator reflects a programmer\textsf{'}s expectation that there is only one correct way of running (i.e., evaluating) a -free $P$-typeclass program while preserving the typeclass\textsf{'}s operations. -However, in practice we need to evaluate not only $P$-typeclass programs -of type $E^{C}$ where $C$ is a $P$-algebra and already belongs -to the typeclass. The usefulness of a free $P$-typeclass construction -is in supporting $P$-typeclass programs of type $E^{T}$, where $T$ -is an arbitrary type. To \textsf{``}run\textsf{''} such a program means to evaluate -the typeclass operations into a value of type $C$ (where $C$ already -belongs to the typeclass). For that, we need a function of type $E^{T}\rightarrow C$. +free $FM$-typeclass program while preserving the typeclass\textsf{'}s operations. +However, in practice we need to evaluate not only $FM$-typeclass +programs of type $E^{C}$ where $C$ is a $P$-algebra and already +belongs to the typeclass. The usefulness of a free $FM$-typeclass +construction is in supporting $FM$-typeclass programs of type $E^{T}$, +where $T$ is an arbitrary type. To \textsf{``}run\textsf{''} such a program means +to evaluate the typeclass operations into a value of type $C$ (where +$C$ already belongs to the typeclass). For that, we need a function +of type $E^{T}\rightarrow C$. That functionality is provided by the \textsf{``}universal runner\textsf{''} ($\text{run}_{E}^{T,C}$), which can be defined via $\text{eval}_{E}^{C}$ as: @@ -3970,14 +3972,14 @@ \subsubsection{Definition \label{subsec:Definition-free-P-typeclass-encoding}\re \] As long as we are able to map values of $T$ into $C$ (using any given function $r$ of type $T\rightarrow C$), the \textsf{``}universal runner\textsf{''} -will evaluate a free $P$-typeclass program of type $E^{T}$ and compute -a result value of type $C$. +will evaluate a free $FM$-typeclass program of type $E^{T}$ and +compute a result value of type $C$. The \textsf{``}universal runner\textsf{''} also has a uniqueness property: \subsubsection{Statement \label{subsec:Statement-some-properties-of-free-P-typeclass-encoding}\ref{subsec:Statement-some-properties-of-free-P-typeclass-encoding}} -Suppose $E$ is a free $P$-typeclass encoding, $C$ is a $P$-algebra +Suppose $E$ is a free $FM$-typeclass encoding, $C$ is a $P$-algebra that obeys all the laws assured by $E$, and $T$ is any type (not necessarily a $P$-algebra). @@ -4028,21 +4030,21 @@ \subsubsection{Statement \label{subsec:Statement-some-properties-of-free-P-typec \end{align*} $\square$ -It is important that the definition of a free $P$-typeclass encoding +It is important that the definition of a free $FM$-typeclass encoding $E$ does not require that the free instances $E^{T}$ should obey -\emph{all} of the $P$-typeclass laws. For instance, we have seen +\emph{all} of the $FM$-typeclass laws. For instance, we have seen that the raw tree encoding of free monads, free monoids, and other typeclasses does not obey any of the relevant laws. Because this does \emph{not} lead to problems in practical programming, our definition -of \textsf{``}free $P$-typeclass encodings\textsf{''} admits encodings that obey +of \textsf{``}free $FM$-typeclass encodings\textsf{''} admits encodings that obey only a subset of typeclass laws (or even none of the laws). The next step is to generalize the raw tree encoding from \lstinline!Monoid! -to an arbitrary $P$-typeclass and to show that it satisfies the definition -of a \textsf{``}free $P$-typeclass encoding\textsf{''}. Although the raw tree encoding -does not satisfy any typeclass laws, it gives us a valid and usable -encoding that we can use as a starting point to develop other, more -concise encodings for a free $P$-typeclass. +to an arbitrary $FM$-typeclass and to show that it satisfies the +definition of a \textsf{``}free $FM$-typeclass encoding\textsf{''}. Although the +raw tree encoding does not satisfy any typeclass laws, it gives us +a valid and usable encoding that we can use as a starting point to +develop other, more concise encodings for a free $FM$-typeclass. The raw tree encoding of a free monoid (see Section~\ref{subsec:Free-monoids}) has the type: @@ -4055,8 +4057,8 @@ \subsubsection{Statement \label{subsec:Statement-some-properties-of-free-P-typec values of the free monoid type. The structure functor $P$ describes two of these three ways. This suggests to rewrite the definition of $\text{FMR}^{T}$ as $\text{FMR}^{T}\triangleq T+P^{\text{FMR}^{T}}$. -We can now generalize to arbitrary $P$-typeclasses and define the -raw tree encoding of a free $P$-typeclass (denoted by $\text{FPR}^{T}$) +We can now generalize to arbitrary $FM$-typeclasses and define the +raw tree encoding of a free $FM$-typeclass (denoted by $\text{FPR}^{T}$) as: \[ \text{FPR}^{T}\triangleq T+P^{\text{FPR}^{T}}\quad. @@ -4071,7 +4073,7 @@ \subsubsection{Statement \label{subsec:Statement-some-properties-of-free-P-typec \subsubsection{Statement \label{subsec:Statement-free-P-typeclass-raw-tree-encoding}\ref{subsec:Statement-free-P-typeclass-raw-tree-encoding}} The free monad on $P$, denoted by $\text{FPR}^{T}\triangleq T+P^{\text{FPR}^{T}}$, -is a free $P$-typeclass encoding. The monad\textsf{'}s \lstinline!flatten! +is a free $FM$-typeclass encoding. The monad\textsf{'}s \lstinline!flatten! method is the same as \lstinline!eval! applied to an argument of type \lstinline!FPR[FPR[T]]!. @@ -4204,7 +4206,7 @@ \subsubsection{Statement \label{subsec:Statement-free-P-typeclass-raw-tree-encod \end{align*} The two code matrices are now equal due to the assumed law $p_{C}\bef g=g^{\uparrow P}\bef p_{D}$. -\textbf{(d)} For a given type $C$ with $P$-typeclass instance $p_{C}:P^{C}\rightarrow C$, +\textbf{(d)} For a given type $C$ with $FM$-typeclass instance $p_{C}:P^{C}\rightarrow C$, suppose a function $f:\text{FPR}^{C}\rightarrow C$ satisfies the left identity law and is a $P$-algebra morphism: \[ @@ -4244,8 +4246,8 @@ \subsubsection{Statement \label{subsec:Statement-free-P-typeclass-raw-tree-encod are equal. $\square$ As we will now show, \lstinline!FPR!\textsf{'}s \lstinline!flatten! function -is a $P$-algebra morphism; in other words, it preserves the $P$-typeclass -operations. So, it is not useful to apply the free $P$-typeclass +is a $P$-algebra morphism; in other words, it preserves the $FM$-typeclass +operations. So, it is not useful to apply the free $FM$-typeclass construction twice, as the result can be reduced to a single layer of \lstinline!FPR[T]! while preserving the operations. @@ -4265,12 +4267,12 @@ \subsubsection{Statement \label{subsec:Statement-free-P-typeclass-monad}\ref{sub $\square$ It is not accidental that the raw tree encoding ($\text{FPR}^{T}$) -is a monad. It turns out that \emph{all} free $P$-typeclass encodings +is a monad. It turns out that \emph{all} free $FM$-typeclass encodings are monads (although not necessarily free monads): \subsubsection{Statement \label{subsec:Statement-free-typeclass-encoding-is-a-monad}\ref{subsec:Statement-free-typeclass-encoding-is-a-monad}} -Any free $P$-typeclass encoding $E$ satisfying Definition~\ref{subsec:Definition-free-P-typeclass-encoding} +Any free $FM$-typeclass encoding $E$ satisfying Definition~\ref{subsec:Definition-free-P-typeclass-encoding} is a monad. The monad $E$\textsf{'}s \lstinline!flatten! function ($\text{ftn}_{E}$) is equal to the unique $P$-algebra morphism $\text{eval}_{E}^{E^{A}}$ between $P$-algebras $E^{E^{A}}$ and $E^{A}$. The $P$-algebra @@ -4340,12 +4342,12 @@ \subsubsection{Statement \label{subsec:Statement-free-typeclass-encoding-is-a-mo \end{align*} $\square$ -\subsection{Describing laws of $P$-typeclasses as values\label{subsec:Describing-laws-of-P-typeclasses-as-values}} +\subsection{Describing laws of $FM$-typeclasses as values\label{subsec:Describing-laws-of-P-typeclasses-as-values}} Usually, typeclasses impose laws on their methods. We will now develop -a \textsf{``}first-class\textsf{''} description of $P$-typeclass laws: each law will -be represented by a value of a certain type. To make sure we have -really found a representation that adequately captures our understanding +a \textsf{``}first-class\textsf{''} description of $FM$-typeclass laws: each law +will be represented by a value of a certain type. To make sure we +have really found a representation that adequately captures our understanding of what typeclass laws are, we will show three type formulas for the laws, arriving at them via different motivations. We will then prove that those three types are isomorphic to each other. @@ -4385,7 +4387,7 @@ \subsection{Describing laws of $P$-typeclasses as values\label{subsec:Describing The data in the pair $(\oplus,e)$ is equivalent to a single value of type $P^{A}\rightarrow A$, where $P^{A}\triangleq\bbnum 1+A\times A$ for the \lstinline!Monoid! typeclass. For other typeclasses, $P$ -will be different. To generalize to arbitrary $P$-typeclasses, let +will be different. To generalize to arbitrary $FM$-typeclasses, let us express the laws as much as possible through $P$ alone. For instance, the type of the functions $f_{1}$ and $f_{2}$ can be written as $(P^{A}\rightarrow A)\times A\times A\times A\rightarrow A$. The @@ -4411,8 +4413,8 @@ \subsection{Describing laws of $P$-typeclasses as values\label{subsec:Describing needed to formulate a law. Now we are ready to generalize the definition of the \lstinline!Monoid! -laws to other $P$-typeclasses. A $P$-typeclass may impose zero or -more laws. Each law is represented by a function of type $\text{LawF}_{P}$: +laws to other $FM$-typeclasses. An $FM$-typeclass may impose zero +or more laws. Each law is represented by a function of type $\text{LawF}_{P}$: \begin{equation} \text{LawF}_{P}\triangleq\forall A.\,(P^{A}\rightarrow A)\times(\text{Int}\rightarrow A)\rightarrow A\times A\quad.\label{eq:P-typeclass-law-type} \end{equation} @@ -4431,9 +4433,9 @@ \subsection{Describing laws of $P$-typeclasses as values\label{subsec:Describing Another approach to describing typeclass laws is by viewing the two sides of a law as expression trees. Recall that the raw tree encoding -of a free $P$-typeclass (which we denoted by $\text{FPR}^{T}$) is -a type of unevaluated expression trees with leaf values of type $T$ -and operations from the functor $P$. We can use a pair of values +of a free $FM$-typeclass (which we denoted by $\text{FPR}^{T}$) +is a type of unevaluated expression trees with leaf values of type +$T$ and operations from the functor $P$. We can use a pair of values of type $\text{FPR}^{T}$ to represent two sides of the law. Given a specific type $T$ for which the typeclass evidence $p_{T}:P^{T}\rightarrow T$ is known, we can evaluate the two sides of the law by translating @@ -4497,7 +4499,7 @@ \subsection{Describing laws of $P$-typeclasses as values\label{subsec:Describing \end{lstlisting} We can now generalize the type of expression trees from \lstinline!Monoid! -to an arbitrary $P$-typeclass. The two sides of the law are functions +to an arbitrary $FM$-typeclass. The two sides of the law are functions that take as arguments one or more arbitrary values of type $T$ and will return a value of type $\text{FPR}^{T}$. In order to be able to describe any number of arbitrary values of type $T$, we use an @@ -4510,7 +4512,7 @@ \subsection{Describing laws of $P$-typeclasses as values\label{subsec:Describing \end{equation} A given value \lstinline!et: LawET! specifies a law through the following -computation: Choose a type $T$ with $P$-typeclass evidence value +computation: Choose a type $T$ with $FM$-typeclass evidence value $p_{T}:P^{T}\rightarrow T$. First, we apply \lstinline!et! to an arbitrary function \lstinline!v: Int => T! and obtain a pair \lstinline!(lhs, rhs)! of expression trees of type \lstinline!FPR[T]!: @@ -4562,7 +4564,7 @@ \subsection{Describing laws of $P$-typeclasses as values\label{subsec:Describing In this way, a pair of values of type \lstinline!FMR[Int]! encodes the monoid associativity law. -Generalizing this to arbitrary $P$-typeclasses, we obtain the type +Generalizing this to arbitrary $FM$-typeclasses, we obtain the type $\text{FPR}^{\text{Int}}\times\text{FPR}^{\text{Int}}$. Each value of that type represents a possible typeclass law. The integer-valued indices correspond to different arbitrary variables used in the two @@ -4620,10 +4622,10 @@ \subsubsection{Statement \label{subsec:Statement-equivalence-law-function-law-ex within a particular derivation or proof. It is usually easier to work with the type $\text{FPR}^{\text{Int}}\times\text{FPR}^{\text{Int}}$. -It turns out that laws of a $P$-typeclass are closely connected with -$P$-algebra morphisms. In particular, $P$-algebra morphisms preserve -the typeclass laws and hide the law violations, in the precise sense -explained in the following statement. +It turns out that laws of an $FM$-typeclass are closely connected +with $P$-algebra morphisms. In particular, $P$-algebra morphisms +preserve the typeclass laws and hide the law violations, in the precise +sense explained in the following statement. \subsubsection{Statement \label{subsec:Statement-P-algebra-morphisms-and-laws}\ref{subsec:Statement-P-algebra-morphisms-and-laws}} @@ -4634,7 +4636,7 @@ \subsubsection{Statement \label{subsec:Statement-P-algebra-morphisms-and-laws}\r \textbf{(a)} Suppose that the law holds for $M$ and $\phi$ is \emph{surjective}. Then the same law also holds for $N$. In this sense, surjective $P$-algebra -morphisms \textsf{``}preserve\textsf{''} the $P$-typeclass laws. +morphisms \textsf{``}preserve\textsf{''} the $FM$-typeclass laws. \textbf{(b)} Suppose the law holds for $N$ but \emph{not} for $M$. Suppose a violation of the law for $M$ is found using a specific @@ -4648,7 +4650,7 @@ \subsubsection{Statement \label{subsec:Statement-P-algebra-morphisms-and-laws}\r l_{1}\triangleright v^{\uparrow\text{FPR}}\bef\text{eval}_{\text{FPR}}^{M}\bef\phi=l_{2}\triangleright v^{\uparrow\text{FPR}}\bef\text{eval}_{\text{FPR}}^{M}\bef\phi\quad.\label{eq:p-typeclass-law-violation-hidden} \end{equation} In this sense, a $P$-algebra morphism \textsf{``}hides\textsf{''} violations of the -$P$-typeclass laws. +$FM$-typeclass laws. \subparagraph{Proof} @@ -4709,24 +4711,24 @@ \subsubsection{Statement \label{subsec:Statement-P-algebra-morphisms-and-laws}\r typeclass operations (i.e., it is a $P$-algebra morphism). Then Statement~\ref{subsec:Statement-P-algebra-morphisms-and-laws}(b) shows that law violations no longer exist after the runner is applied. We have proved this explicitly for our free monad DSL in Section~\ref{subsec:A-first-recipe-monadic-dsl}. -Now we see that this is a general property that applies to all $P$-typeclasses. +Now we see that this is a general property that applies to all $FM$-typeclasses. It is safe to use a free typeclass encoding (even if it violates some laws) as long as its runner preserves the typeclass operations and the target type is a lawful typeclass member. In the next section we will study such \textsf{``}partially lawful\textsf{''} free typeclass encodings in more detail. -\subsection{Free $P$-typeclasses that satisfy a subset of the laws\label{subsec:Free--typeclasses-that-satisfy-laws}} +\subsection{Free $FM$-typeclasses that satisfy a subset of the laws\label{subsec:Free--typeclasses-that-satisfy-laws}} In Section~\ref{subsec:Free-monoids}, we have seen four different encodings of the free monoid (denoted by \lstinline!F1!, \lstinline!F2!, \lstinline!F3!, and \lstinline!F4!). It turns out that all those encodings satisfy the requirements of Definition~\ref{subsec:Definition-free-P-typeclass-encoding}, although they obey different subsets of the laws of monoids. We will -now generalize that situation to $P$-typeclasses and study the properties -of free $P$-typeclass constructions that satisfy only a subset of +now generalize that situation to $FM$-typeclasses and study the properties +of free $FM$-typeclass constructions that satisfy only a subset of the typeclass\textsf{'}s laws. The resulting theory will make it simpler to -prove that a given type constructor $E$ is indeed a valid free $P$-typeclass +prove that a given type constructor $E$ is indeed a valid free $FM$-typeclass encoding as specified by Definition~\ref{subsec:Definition-free-P-typeclass-encoding}. One important question is whether a free typeclass encoding $E^{T}$ @@ -4766,19 +4768,19 @@ \subsection{Free $P$-typeclasses that satisfy a subset of the laws\label{subsec: \subsubsection{Statement \label{subsec:Statement-free-typeclass-more-laws}\ref{subsec:Statement-free-typeclass-more-laws}} -Let $E$ be any free $P$-typeclass encoding. +Let $E$ be any free $FM$-typeclass encoding. \textbf{(a)} If types $T$, $U$ are such that a surjective function -$f:T\rightarrow U$ exists then $E^{U}$ obeys all the $P$-typeclass +$f:T\rightarrow U$ exists then $E^{U}$ obeys all the $FM$-typeclass laws that $E^{T}$ obeys. (A \textsf{``}larger\textsf{''} type $E^{T}$ satisfies at least as many laws as a \textsf{``}smaller\textsf{''} type $E^{U}$.) \textbf{(b)} If $E$ is a polynomial functor and $E^{\text{Int}\times\text{Int}}$ -obeys some law of the $P$-typeclass then $E^{T}$ obeys that law +obeys some law of the $FM$-typeclass then $E^{T}$ obeys that law for all types $T$. \textbf{(c)} If $E$ is a polynomial functor and $E^{\text{Int}}$ -obeys some law of the $P$-typeclass then $E^{T}$ obeys that law +obeys some law of the $FM$-typeclass then $E^{T}$ obeys that law for all types $T$. It follows that the set of laws \textsf{``}ensured by\textsf{''} $E$ are just the @@ -4792,7 +4794,7 @@ \subsubsection{Statement \label{subsec:Statement-free-typeclass-more-laws}\ref{s due to Statement~\ref{subsec:f-Statement-functor-preserves-injective}. The function $\phi$ is a $P$-algebra morphism due to Definition~\ref{subsec:Definition-free-P-typeclass-encoding}(a). So, Statement~\ref{subsec:Statement-P-algebra-morphisms-and-laws}(a) -is applicable and gives the result that $E^{U}$ obeys all the $P$-typeclass +is applicable and gives the result that $E^{U}$ obeys all the $FM$-typeclass laws that $E^{T}$ obeys. \textbf{(b)} Given a type $T$, a law $l_{1}\times l_{2}:\text{FPR}^{\text{Int}}\times\text{FPR}^{\text{Int}}$, @@ -4864,15 +4866,15 @@ \subsubsection{Statement \label{subsec:Statement-free-typeclass-more-laws}\ref{s for natural numbers). $\square$ The restriction to polynomial functors $E$ is not a limitation in -practice. All known $P$-typeclasses have only a finite set of operations, +practice. All known $FM$-typeclasses have only a finite set of operations, and each operation has a fixed and finite number of arguments. The functor $P$ describing those operations will be always polynomial, and so will be the corresponding functor $E$. -The next statement shows that a functor $E$ is a free $P$-typeclass +The next statement shows that a functor $E$ is a free $FM$-typeclass encoding if it has an injective map into the raw tree encoding (\lstinline!FPR!) and has certain additional properties. This statement helps us validate -free $P$-typeclass encodings with less work than by using Definition~\ref{subsec:Definition-free-P-typeclass-encoding} +free $FM$-typeclass encodings with less work than by using Definition~\ref{subsec:Definition-free-P-typeclass-encoding} directly. \subsubsection{Statement \label{subsec:Statement-compatible-retract-of-free-monad}\ref{subsec:Statement-compatible-retract-of-free-monad}} @@ -4900,14 +4902,14 @@ \subsubsection{Statement \label{subsec:Statement-compatible-retract-of-free-mona by $\text{ftn}_{E}\triangleq\text{in}_{E}^{E^{T}}\bef\text{eval}_{\text{FPR}}^{E^{T}}$ is a $P$-algebra morphism (even though $\text{in}_{E}$ is not!). -5. The $P$-algebra $E^{T}$ satisfies some (or all) of the $P$-typeclass +5. The $P$-algebra $E^{T}$ satisfies some (or all) of the $FM$-typeclass laws but \emph{no other} laws. {*}{*}{*}This is misleading, as in fact $E^{T}$ does satisfy more laws for some $T$; say for $T=\bbnum 0$. How do we actually use item 5 as an assumption?{*}{*}{*}To formulate this requirement precisely, we use law expressions $e:\text{FPR}^{\text{Int}}\times\text{FPR}^{\text{Int}}$ -for describing $P$-typeclass laws (see Section~\ref{subsec:Describing-laws-of-P-typeclasses-as-values}). -We say that $E^{T}$ obeys \textsf{``}no other laws than those of the $P$-typeclass\textsf{''} -if for any $P$-algebra $C$ that obeys all the $P$-typeclass laws +for describing $FM$-typeclass laws (see Section~\ref{subsec:Describing-laws-of-P-typeclasses-as-values}). +We say that $E^{T}$ obeys \textsf{``}no other laws than those of the $FM$-typeclass\textsf{''} +if for any $P$-algebra $C$ that obeys all the $FM$-typeclass laws and for any $e:\text{FPR}^{\text{Int}}\times\text{FPR}^{\text{Int}}$ whose corresponding $e$-law holds for $E^{T}$, the same $e$-law will also hold for $C$. (A counterexample is an $E^{T}$ that satisfies @@ -4919,12 +4921,12 @@ \subsubsection{Statement \label{subsec:Statement-compatible-retract-of-free-mona If assumptions 1-5 hold then: -\textbf{(a)} The functor $E$ is a free $P$-typeclass encoding. When -the function $\text{in}_{E}$ is itself a $P$-algebra morphism then -the encoding $E$ will be \emph{equivalent} to \lstinline!FPR!. (This -is why we do \emph{not} require $\text{in}_{E}^{T}$ to be a $P$-algebra -morphism. Then we are able to describe free $P$-typeclass encodings -$E$ that are different from $\text{FPR}$.) +\textbf{(a)} The functor $E$ is a free $FM$-typeclass encoding. +When the function $\text{in}_{E}$ is itself a $P$-algebra morphism +then the encoding $E$ will be \emph{equivalent} to \lstinline!FPR!. +(This is why we do \emph{not} require $\text{in}_{E}^{T}$ to be a +$P$-algebra morphism. Then we are able to describe free $FM$-typeclass +encodings $E$ that are different from $\text{FPR}$.) \textbf{(b)} The universal evaluator $\text{eval}_{E}^{C}$ does not depend on the choice of the function $\text{in}_{E}$. @@ -4958,18 +4960,18 @@ \subsubsection{Statement \label{subsec:Statement-compatible-retract-of-free-mona We find that we must have $g_{E}^{T}=\text{id}$. It means that the $P$-algebra morphisms $\text{in}_{E}^{T}$ and $g$ are inverses of each other and give a $P$-algebra \emph{isomorphism} (a type equivalence -that preserves the $P$-typeclass operations) between $E^{T}$ and +that preserves the $FM$-typeclass operations) between $E^{T}$ and $\text{FPR}^{T}$. So, $E^{T}$ is equivalent to the raw tree encoding ($\text{FPR}^{T}$) when $\text{in}_{E}$ is a $P$-algebra morphism. -To show that $E$ is a $P$-typeclass encoding, we look at the conditions +To show that $E$ is an $FM$-typeclass encoding, we look at the conditions in Definition~\ref{subsec:Definition-free-P-typeclass-encoding}. Conditions (a) and (b) of Definition~\ref{subsec:Definition-free-P-typeclass-encoding} are satisfied by our assumptions 1 and 2. To verify condition (c), we assume that $C$ is any $P$-algebra that -obeys all the $P$-typeclass laws that $E$ obeys. We then define +obeys all the $FM$-typeclass laws that $E$ obeys. We then define $\text{eval}_{E}^{C}$ via $\text{eval}_{\text{FPR}}^{C}$: \[ \text{eval}_{E}^{C}:E^{C}\rightarrow C\quad,\quad\quad\text{eval}_{E}^{C}\triangleq\text{in}_{E}^{C}\bef\text{eval}_{\text{FPR}}^{C}\quad. @@ -5094,11 +5096,11 @@ \subsubsection{Statement \label{subsec:Statement-compatible-retract-of-free-mona obeying the left identity law, namely $\text{eval}_{E}^{C}$. So, $\text{eval}_{E}^{\prime C}=\text{eval}_{E}^{C}$. $\square$ -\subsection{Imposing laws of $P$-typeclasses via monad algebras\label{subsec:Imposing-laws-of-P-typeclasses-via-monad-algebras}} +\subsection{Imposing laws of $FM$-typeclasses via monad algebras\label{subsec:Imposing-laws-of-P-typeclasses-via-monad-algebras}} We have shown in Statement~\ref{subsec:Statement-free-typeclass-encoding-is-a-monad} -that any free $P$-typeclass encoding $E$ is always a monad. It turns -out that we may may use $E$\textsf{'}s monad methods to impose $P$-typeclass +that any free $FM$-typeclass encoding $E$ is always a monad. It +turns out that we may may use $E$\textsf{'}s monad methods to impose $FM$-typeclass laws on a given $P$-algebra. The required technique is based on the notion of a \textsf{``}\index{monad algebra}monad algebra\textsf{''} that comes from category theory: @@ -5143,7 +5145,7 @@ \subsubsection{Definition \label{subsec:Definition-monad-algebra}\ref{subsec:Def \subsubsection{Statement \label{subsec:Statement-Monad-algebra-is-P-typeclass}\ref{subsec:Statement-Monad-algebra-is-P-typeclass}} -Suppose $E$ is a free $P$-typeclass encoding according to Definition~\ref{subsec:Definition-free-P-typeclass-encoding}. +Suppose $E$ is a free $FM$-typeclass encoding according to Definition~\ref{subsec:Definition-free-P-typeclass-encoding}. A monad structure for $E$ is given by Statement~\ref{subsec:Statement-free-typeclass-encoding-is-a-monad}. Then the type of $E$-monad algebras is equivalent to the type of $P$-algebras that obey all the laws of $E$. In more detail: @@ -5246,7 +5248,7 @@ \subsubsection{Statement \label{subsec:Statement-Monad-algebra-is-P-typeclass}\r \subsubsection{Exercise \label{subsec:Exercise-P-algebras-monad-algebras}\ref{subsec:Exercise-P-algebras-monad-algebras}\index{exercises}} -Let $E$ be any free $P$-typeclass encoding by Definition~\ref{subsec:Definition-free-P-typeclass-encoding}. +Let $E$ be any free $FM$-typeclass encoding by Definition~\ref{subsec:Definition-free-P-typeclass-encoding}. \textbf{(a)} If $C$ and $D$ are any given $E$-monad algebras, the proof of Statement~\ref{subsec:Statement-Monad-algebra-is-P-typeclass}(a) @@ -5265,15 +5267,15 @@ \subsubsection{Exercise \label{subsec:Exercise-P-algebras-monad-algebras}\ref{su In the next section, we will use monad algebras to prove that certain typeclass constructions automatically produce lawful typeclass instances. -\subsection{Laws for the $P$-typeclass derivation constructions\label{subsec:Laws-for-the-P-typeclass-constructions}} +\subsection{Laws for the $FM$-typeclass derivation constructions\label{subsec:Laws-for-the-P-typeclass-constructions}} In Section~\ref{subsec:P-typeclasses} we have shown certain type constructions that derive new typeclass instances from previous ones. -For example, the product of two types that belong to a $P$-typeclass +For example, the product of two types that belong to an $FM$-typeclass will again belong to that typeclass. However, in that chapter we only -showed that one can compute a $P$-typeclass evidence values for those -constructions. Now we have developed a theory that can also prove -that the laws hold automatically for each of those constructions. +showed that one can compute an $FM$-typeclass evidence values for +those constructions. Now we have developed a theory that can also +prove that the laws hold automatically for each of those constructions. This theory justifies automatic typeclass derivation for those cases. The next statements prove that the typeclass laws hold automatically @@ -5283,11 +5285,11 @@ \subsection{Laws for the $P$-typeclass derivation constructions\label{subsec:Law Instead of dealing with laws explicitly as values, it is more convenient in these proofs if we impose typeclass laws via monad algebras. As we have seen in the previous section, a type $T$ is a lawful member -of a $P$-typeclass if $T$ is an $E$-monad algebra, where the monad -$E$ is the free $P$-typeclass encoding that assures the laws of -the typeclass. Using this formulation of laws, it is sufficient to -prove that a new derived type is again an $E$-monad algebra if so -are the previously given types. +of an $FM$-typeclass if $T$ is an $E$-monad algebra, where the +monad $E$ is the free $FM$-typeclass encoding that assures the laws +of the typeclass. Using this formulation of laws, it is sufficient +to prove that a new derived type is again an $E$-monad algebra if +so are the previously given types. In each of the following statements, $E$ is a fixed monad. @@ -5452,7 +5454,7 @@ \subsubsection{Statement \label{subsec:Statement-Monad-algebra-exp-1}\ref{subsec Other than that, we can repeat the proof for part \textbf{(a)} except for replacing $s(\overline{t})$ by $s$. $\square$ -\subsection{Church encodings of free $P$-typeclasses\label{subsec:Church-encodings-for-free-P-typeclasses}} +\subsection{Church encodings of free $FM$-typeclasses\label{subsec:Church-encodings-for-free-P-typeclasses}} \subsection{Free constructions on more than one generator} @@ -5879,7 +5881,7 @@ \section{Slides } Type class $C$ is defined by its operations{\footnotesize{} $C^{X}\rightarrow X$} (with a suitable $C^{\bullet}$) -call $C^{\bullet}$ the \textbf{structure functor} of the $P$-typeclass +call $C^{\bullet}$ the \textbf{structure functor} of the $FM$-typeclass $C$ Tree encoding of \textsf{``}free $C$ over $Z$\textsf{''} is recursive, $\text{FreeC}^{Z}\triangleq Z+C^{\text{FreeC}^{Z}}$ @@ -6317,7 +6319,7 @@ \subsubsection{Exercise \label{subsec:Exercise-free-type-2}\ref{subsec:Exercise- \textsf{``}acts\textsf{''} on $P$ via a function act$:L\rightarrow P\rightarrow P$, with laws $\text{act}\,x\bef\text{act}\,y=\text{act}\left(x\bef y\right)$ and $\text{act}\left(e_{L}\right)=\text{id}$. - Monoid morphism between -$L$ and $\text{MF}^{P}$. Show that $\text{Mod}_{L}$ is a $P$-typeclass. +$L$ and $\text{MF}^{P}$. Show that $\text{Mod}_{L}$ is an $FM$-typeclass. Implement a free $L$-module on a type $Z$. \subsubsection{Exercise \label{subsec:Exercise-free-type-3}\ref{subsec:Exercise-free-type-3}} diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index c395405d1..dea1062b5 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -322,7 +322,7 @@ \subsection{Chapter~\ref{chap:Typeclasses-and-functions}} relations\textsf{''}) \item Inheritance and automatic conversion of typeclasses \item Why many typeclasses have similar properties as regards typeclass -derivation; the concept of \textsf{``}$P$-typeclasses\textsf{''} +derivation; the concept of \textsf{``}$FM$-typeclasses\textsf{''} \item How typeclasses unify and generalize both algebraic data types and object-oriented interfaces \end{itemize} @@ -846,7 +846,7 @@ \subsection{Chapter~\ref{chap:Free-type-constructions}} of the universal runner and preserves the semigroup\textsf{'}s methods. Later we will show that this situation is found in general for all -$P$-typeclasses: a reduced encoding can be injected into the raw +$FM$-typeclasses: a reduced encoding can be injected into the raw tree encoding by many functions, neither of which preserves the typeclass methods. @@ -1179,7 +1179,7 @@ \subsection{Appendix~\ref{app:Proofs-of-naturality-parametricity}} practical applications of the Yoneda lemma to programming. Other applications used in this book are Yoneda identities for type constructors (see Section~\ref{subsec:The-Yoneda-identities-for-type-constructors}) -and for lawful $P$-typeclasses (used in Section~\ref{subsec:The-Jaskelioff-OConnor-theorem} +and for lawful $FM$-typeclasses (used in Section~\ref{subsec:The-Jaskelioff-OConnor-theorem} in the proof of the Jaskelioff-O\textsf{'}Connor theorem). We turn to further applications of parametricity that go beyond what diff --git a/sofp-src/tex/sofp-transformers.tex b/sofp-src/tex/sofp-transformers.tex index 2ae37f242..59774bfad 100644 --- a/sofp-src/tex/sofp-transformers.tex +++ b/sofp-src/tex/sofp-transformers.tex @@ -9718,7 +9718,7 @@ \subsection{Examples of monads with several different transformers\label{subsec: (\text{FTC}\varangle M)^{A}\triangleq\forall X^{:\text{TC}}.\,(A\rightarrow M^{X})\rightarrow M^{X}\quad. \] Note that $\text{FTC}^{A}$ is always a monad (by Statement~\ref{subsec:Statement-monad-with-quantifier} -and, for $P$-typeclasses, by Statement~\ref{subsec:Statement-free-typeclass-encoding-is-a-monad}). +and, for $FM$-typeclasses, by Statement~\ref{subsec:Statement-free-typeclass-encoding-is-a-monad}). For some typeclasses, $\text{FTC}^{A}$ is equivalent to a simpler known monad $G^{A}$. Specific examples are found with \lstinline!TC!$\,=\,$\lstinline!Monoid! and $G$$\,=\,$\lstinline!List! (see Exercise~\ref{par:Exercise-additional-16-1}(e)), @@ -12272,13 +12272,13 @@ \subsubsection{Exercise \label{par:Exercise-mt-3-2-2}\ref{par:Exercise-mt-3-2-2} It follows from Statement~\ref{subsec:Statement-monad-with-quantifier} that adding a type quantifier to a monad gives again a monad. Show -that adding a type quantifier to any $P$-typeclass (Section~\ref{subsec:P-typeclasses}) -gives again a $P$-typeclass. In detail: assume a $P$-typeclass defined -via a structure functor $S^{R,\bullet}$ that has an extra type parameter -$R$. All methods of the typeclass are then contained in a value of -type $S^{R,A}\rightarrow A$, where the type $R$ is fixed. Show that -$\forall R.\,S^{R,A}\rightarrow A$ is again a $P$-typeclass (with -a different choice of the structure functor). +that adding a type quantifier to any $FM$-typeclass (Section~\ref{subsec:P-typeclasses}) +gives again an $FM$-typeclass. In detail: assume an $FM$-typeclass +defined via a structure functor $S^{R,\bullet}$ that has an extra +type parameter $R$. All methods of the typeclass are then contained +in a value of type $S^{R,A}\rightarrow A$, where the type $R$ is +fixed. Show that $\forall R.\,S^{R,A}\rightarrow A$ is again an $FM$-typeclass +(with a different choice of the structure functor). \subsubsection{Exercise \label{subsec:Exercise-effectful-list-not-monad}\ref{subsec:Exercise-effectful-list-not-monad}} diff --git a/sofp-src/tex/sofp-typeclasses.tex b/sofp-src/tex/sofp-typeclasses.tex index 2fb7fb2b2..845c10cc9 100644 --- a/sofp-src/tex/sofp-typeclasses.tex +++ b/sofp-src/tex/sofp-typeclasses.tex @@ -5628,7 +5628,7 @@ \subsection{Inheritance and automatic conversions of typeclasses\label{subsec:In Goes.} So far, it is not known whether any encoding can solve all issues that come from multiple inheritance of typeclasses. -\subsection{$P$-typeclasses, their laws and structure\label{subsec:P-typeclasses}} +\subsection{$FM$-typeclasses, their laws and structure\label{subsec:P-typeclasses}} We have seen that many typeclasses have similar structural properties. For instance, a product of semigroups is again a semigroup, a product @@ -5663,7 +5663,7 @@ \subsection{$P$-typeclasses, their laws and structure\label{subsec:P-typeclasses \hline \end{tabular} \par\end{centering} -\caption{Structure of typeclass instance values for various $P$-typeclasses.\label{tab:Types-of-typeclass-instance-values}} +\caption{Structure of typeclass instance values for various $FM$-typeclasses.\label{tab:Types-of-typeclass-instance-values}} \end{table} The \lstinline!Semigroup! typeclass has a single method ($\oplus_{_{A}}$) @@ -5682,16 +5682,17 @@ \subsection{$P$-typeclasses, their laws and structure\label{subsec:P-typeclasses the empty value ($e_{_{A}}$) and the binary operation ($\oplus_{_{A}}$) of the monoid $A$. -This motivates the definition of \index{$P$-typeclass|textit} a $P$-\textbf{typeclass}: -it is a typeclass whose instance values have type $P^{T}\rightarrow T$. -The functor $P$ is called the \index{structure functor of a typeclass}\index{typeclass!structure functor}\textbf{structure -functor} of the typeclass. +This motivates the definition of \index{$FM$-typeclass|textit} an +$FM$-\textbf{typeclass}: it is a typeclass whose instance values +have type $P^{T}\rightarrow T$. The functor $P$ is called the \index{structure functor of a typeclass}\index{typeclass!structure functor}\textbf{structure +functor} of the typeclass. (The name \textsf{``}FM\textsf{''} refers to \textsf{``}functors\textsf{''} +and \textsf{``}monads\textsf{''} and will be justified later.) We can implement this definition by the Scala code: \begin{lstlisting} -final case class PTypeclass[P[_]: Functor, A](methods: P[A] => A) +final case class FMTypeclass[P[_]: Functor, A](methods: P[A] => A) \end{lstlisting} -The code allows us to declare any $P$-typeclass. For example, the +The code allows us to declare any $FM$-typeclass. For example, the \lstinline!Monoid! typeclass can be declared by first defining a type constructor corresponding to the monoid\textsf{'}s structure functor ($P^{A}\triangleq\bbnum 1+A\times A$) and then using that functor to define a type constructor for evidence @@ -5699,7 +5700,7 @@ \subsection{$P$-typeclasses, their laws and structure\label{subsec:P-typeclasses \begin{lstlisting} final case class MonoidSF[A](s: Option[(A, A)]) val functorMonoidSF: Functor[MonoidSF] = ... /* implementation */ -type PMonoid[A] = PTypeclass[MonoidSF, A] +type FMMonoid[A] = FMTypeclass[MonoidSF, A] \end{lstlisting} Typeclasses for type constructors (\lstinline!Functor!, \lstinline!Pointed!, @@ -5714,7 +5715,7 @@ \subsection{$P$-typeclasses, their laws and structure\label{subsec:P-typeclasses the additional type parameters. The laws of type constructor typeclasses are also more complicated because they often involve multiple type parameters and arbitrary functions. To simplify the presentation in -this section, we will only consider $P$-typeclasses for simple types, +this section, we will only consider $FM$-typeclasses for simple types, such as \lstinline!Semigroup! or \lstinline!Monoid!. Implementing the \lstinline!Monoid! typeclass via a structure functor @@ -5722,12 +5723,12 @@ \subsection{$P$-typeclasses, their laws and structure\label{subsec:P-typeclasses programming. But the form $P^{A}\rightarrow A$ is useful for reasoning about general properties of typeclasses. To illustrate that kind of reasoning, we will now show that the product-type, the function-type, -and the recursive-type constructions work for all $P$-typeclasses. +and the recursive-type constructions work for all $FM$-typeclasses. \paragraph{Products} -Consider an arbitrary $P$-typeclass \lstinline!TC! defined via a -structure functor \lstinline!P!. If two types $A$, $B$ have an +Consider an arbitrary $FM$-typeclass \lstinline!TC! defined via +a structure functor \lstinline!P!. If two types $A$, $B$ have an instance of the typeclass \lstinline!TC!, an instance for the product type $A\times B$ can be derived automatically using the function \lstinline!productTC!: @@ -5744,12 +5745,12 @@ \subsection{$P$-typeclasses, their laws and structure\label{subsec:P-typeclasses This argument does \emph{not} prove that the typeclass laws will also hold for $A\times B$. We will prove that in Section~\ref{subsec:Laws-for-the-P-typeclass-constructions} after developing some advanced techniques for formal reasoning about -$P$-typeclass laws. +$FM$-typeclass laws. We note that the co-product construction does \emph{not} work for -arbitrary $P$-typeclasses: given evidence values of types $P^{A}\rightarrow A$ +arbitrary $FM$-typeclasses: given evidence values of types $P^{A}\rightarrow A$ and $P^{B}\rightarrow B$, we cannot always find a suitable value -of type $P^{A+B}\rightarrow A+B$. Later we will see that some $P$-typeclasses, +of type $P^{A+B}\rightarrow A+B$. Later we will see that some $FM$-typeclasses, such as monads or applicative functors, do not support the co-product construction. The co-product of two monads is not always a lawful monad; the co-product of two applicative functors is not always an @@ -5757,8 +5758,8 @@ \subsection{$P$-typeclasses, their laws and structure\label{subsec:P-typeclasses \paragraph{Functions} -The function-type construction creates a $P$-typeclass instance for -the type $E\rightarrow A$ if the type $A$ belongs to the $P$-typeclass. +The function-type construction creates an $FM$-typeclass instance +for the type $E\rightarrow A$ if the type $A$ belongs to the $FM$-typeclass. Using the fact that $P$ is a functor, an evidence value of type $P^{E\rightarrow A}\rightarrow E\rightarrow A$ can be computed from an evidence value of type $P^{A}\rightarrow A$ like this: @@ -5773,9 +5774,9 @@ \subsection{$P$-typeclasses, their laws and structure\label{subsec:P-typeclasses \paragraph{Recursive types} Consider a recursive type $T$ defined by a type equation $T\triangleq S^{T}$, -where the functor $S$ \textsf{``}preserves\textsf{''} $P$-typeclass instances: if -$A$ has an instance then $S^{A}$ also does, as we saw in all our -examples in this chapter. In other words, we have a function $\text{tcS}:(P^{A}\rightarrow A)\rightarrow P^{S^{A}}\rightarrow S^{A}$ +where the functor $S$ \textsf{``}preserves\textsf{''} $FM$-typeclass instances: +if $A$ has an instance then $S^{A}$ also does, as we saw in all +our examples in this chapter. In other words, we have a function $\text{tcS}:(P^{A}\rightarrow A)\rightarrow P^{S^{A}}\rightarrow S^{A}$ that creates evidence values of type $P^{S^{A}}\rightarrow S^{A}$ out of evidence values of type $P^{A}\rightarrow A$. Then we define an evidence value \lstinline!tcT! for $T$ as: @@ -5801,7 +5802,7 @@ \subsection{$P$-typeclasses, their laws and structure\label{subsec:P-typeclasses def tcS: TC[A] => TC[S[A]] = ... // Compute instances for S[A] given instances for A. def tcT: P[T] => T = p => T(tcS(tcT)(p.map(_.s))) // The recursive instance. \end{lstlisting} -In this way, the recursive-type construction works for any $P$-typeclass. +In this way, the recursive-type construction works for any $FM$-typeclass. (We will prove in Section~\ref{subsec:Laws-for-the-P-typeclass-constructions} that the laws will hold automatically for the new typeclass instances.) @@ -5809,14 +5810,14 @@ \subsection{$P$-typeclasses, their laws and structure\label{subsec:P-typeclasses their properties are more difficult to prove. This book shows that the product-type, the function-type, and the recursive-type constructions work for functors, contrafunctors, pointed functors, and pointed contrafunctors, -as well as for other important $P$-typeclasses such as filterable +as well as for other important $FM$-typeclasses such as filterable functors (Chapter~\ref{chap:Filterable-functors}), monads (Chapter~\ref{chap:Semimonads-and-monads}), and applicative functors (Chapter~\ref{chap:8-Applicative-functors,-contrafunctors}). We will see in Chapter~\ref{chap:Free-type-constructions} that another -general construction also works for all $P$-typeclasses, \textemdash{} +general construction also works for all $FM$-typeclasses, \textemdash{} the \textsf{``}free\textsf{''} type construction. -Some typeclasses \emph{cannot} be viewed as $P$-typeclasses. The +Some typeclasses \emph{cannot} be viewed as $FM$-typeclasses. The \lstinline!Extractor! typeclass (see Section~\ref{subsec:Extractors-typeclasses}) has instances of type $A\rightarrow Z$, which is not of the form $P^{A}\rightarrow A$ for any functor $P$. Another example is the @@ -5826,16 +5827,16 @@ \subsection{$P$-typeclasses, their laws and structure\label{subsec:P-typeclasses of type $F\rightarrow P^{F}$ with a suitable functor $P$. This type signature can be obtained for \textsf{``}extractor\textsf{''} typeclasses, for \lstinline!Copointed! functors, and also for \lstinline!Traversable! functors (Chapter~\ref{chap:9-Traversable-functors-and}). -We may call those typeclasses \textbf{co-}$P$\textbf{-typeclasses}.\index{co-$P$-typeclasses} +We may call those typeclasses \textbf{co-}$P$\textbf{-typeclasses}.\index{co-$FM$-typeclasses} For all typeclasses whose evidence values have type $A\rightarrow P^{A}$, some general properties will also hold. For example, the \emph{co-product} construction (rather than the product construction) works for them. Given evidence values of types $A\rightarrow P^{A}$ and $B\rightarrow P^{B}$, -we can produce a value of type $A+B\rightarrow P^{A+B}$, i.e., a -$P$-typeclass evidence for the co-product $A+B$. Similarly to $P$-typeclasses, +we can produce a value of type $A+B\rightarrow P^{A+B}$, i.e., an +$FM$-typeclass evidence for the co-product $A+B$. Similarly to $FM$-typeclasses, the typeclass laws will hold automatically for the type $A+B$. A -detailed description of co-$P$-typeclasses is beyond the scope of +detailed description of co-$FM$-typeclasses is beyond the scope of this book. An example of a typeclass to which neither description applies is @@ -6044,7 +6045,7 @@ \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} We have achieved a description that presents ADTs as a special case of typeclasses whose method signature has the form $\text{Sig}^{T}=P^{T}\rightarrow T$. -(This book calls them \textsf{``}$P$-typeclasses\textsf{''}.) +(This book calls them \textsf{``}$FM$-typeclasses\textsf{''}.) Not all typeclasses have signatures of this form. For example, the equality typeclass (\lstinline!Eq!) has the method signature $\text{Sig}_{\text{Eq}}^{T}=T\times T\rightarrow\bbnum 2$, diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 47a2a7e5e..5deea1f7c 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): d08b7e0731982c59791ebd00c5655400417c8e0528eb03ce5abbc9ccebea666b}\\ -{\scriptsize{}Git commit: 70b9d6bb08f713ead583afe0aadb1124b5a5bbc3}\\ -{\scriptsize{}PDF file built on Sat, 27 Dec 2025 22:57:25 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 06f84cbe54050f946a065946dc8aeb9666c209cfa7387802ac0bec527a14cf64}\\ +{\scriptsize{}Git commit: f3a0fed9306fd4144774468ecf52a5b27ab1c6ca}\\ +{\scriptsize{}PDF file built on Tue, 27 Jan 2026 10:18:03 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From eac209785629d7ef5b79a28c734114192d0a996e Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Tue, 27 Jan 2026 10:32:05 +0100 Subject: [PATCH 37/42] rename to FM-typeclasses --- sofp-src/lyx/sofp-free-type.lyx | 667 ++++++------------------------ sofp-src/lyx/sofp-summary.lyx | 21 +- sofp-src/lyx/sofp-typeclasses.lyx | 170 +++----- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-free-type.tex | 319 +++++++------- sofp-src/tex/sofp-summary.tex | 8 +- sofp-src/tex/sofp-typeclasses.tex | 84 ++-- sofp-src/tex/sofp.tex | 6 +- 8 files changed, 394 insertions(+), 881 deletions(-) diff --git a/sofp-src/lyx/sofp-free-type.lyx b/sofp-src/lyx/sofp-free-type.lyx index 822910b44..07fc81190 100644 --- a/sofp-src/lyx/sofp-free-type.lyx +++ b/sofp-src/lyx/sofp-free-type.lyx @@ -17178,11 +17178,8 @@ noprefix "false" \end_inset - will show general proofs that apply to all -\begin_inset Formula $FM$ -\end_inset - --typeclasses and to all possible choices of typeclass laws. + will show general proofs that apply to all FM-typeclasses and to all possible + choices of typeclass laws. \end_layout \begin_layout Subsection @@ -25437,11 +25434,7 @@ noprefix "false" \end_inset -), consider an -\begin_inset Formula $FM$ -\end_inset - --typeclass called +), consider an FM-typeclass called \begin_inset listings inline true status open @@ -25686,11 +25679,8 @@ TC \end_inset parametrically. - We expect that similar code will work for any other -\begin_inset Formula $FM$ -\end_inset - --typeclass to define a free instance. + We expect that similar code will work for any other FM-typeclass to define + a free instance. To see that more clearly, rewrite the type signature of the function \begin_inset listings inline true @@ -25757,11 +25747,7 @@ TC \end_inset - to an arbitrary -\begin_inset Formula $FM$ -\end_inset - --typeclass, replacing the type + to an arbitrary FM-typeclass, replacing the type \begin_inset Formula $\text{TC}^{A}$ \end_inset @@ -25769,16 +25755,8 @@ TC \begin_inset Formula $P^{A}\rightarrow A$ \end_inset - that describes all the methods of the -\begin_inset Formula $FM$ -\end_inset - --typeclass. - Then the free -\begin_inset Formula $FM$ -\end_inset - --typeclass instance constructor is given by: + that describes all the methods of the FM-typeclass. + Then the free FM-typeclass instance constructor is given by: \begin_inset Formula \[ \forall A.\,(T\rightarrow A)\rightarrow(P^{A}\rightarrow A)\rightarrow A\quad. @@ -25808,24 +25786,13 @@ This type can be rewritten as \end_inset . - Indeed, we know from the theory of -\begin_inset Formula $FM$ -\end_inset - --typeclasses that the free monad on + Indeed, we know from the theory of FM-typeclasses that the free monad on + \begin_inset Formula $P$ \end_inset - gives the raw tree encoding of the free -\begin_inset Formula $FM$ -\end_inset - --typeclass. - If the -\begin_inset Formula $FM$ -\end_inset - --typeclass has no laws then this is the only available encoding. + gives the raw tree encoding of the free FM-typeclass. + If the FM-typeclass has no laws then this is the only available encoding. \end_layout \begin_layout Standard @@ -26229,11 +26196,8 @@ What happens if we apply the same technique to a typeclass that is \emph on not \emph default - of the form of an -\begin_inset Formula $FM$ -\end_inset - --typeclass? As it turns out, the construction no longer works as expected. + of the form of an FM-typeclass? As it turns out, the construction no longer + works as expected. An example is the \begin_inset listings inline true @@ -26494,20 +26458,12 @@ This chapter started by developing the free monad via the implementation Can we formulate any properties or laws that validate the correctness of those constructions? Are all the different encodings equally safe to use? We will now develop the necessary theory for answering these questions - in the case of -\begin_inset Formula $FM$ -\end_inset - --typeclasses for ordinary types. + in the case of FM-typeclasses for ordinary types. (The notion of a \begin_inset Quotes eld \end_inset - -\begin_inset Formula $FM$ -\end_inset - --typeclass +FM-typeclass \begin_inset Quotes erd \end_inset @@ -26525,11 +26481,7 @@ noprefix "false" \end_inset -.) We expect that -\begin_inset Formula $FM$ -\end_inset - --typeclasses for type constructors (such as +.) We expect that FM-typeclasses for type constructors (such as \begin_inset listings inline true status open @@ -26558,11 +26510,7 @@ Monad \end_layout \begin_layout Subsection -Free constructions for -\begin_inset Formula $FM$ -\end_inset - --typeclasses +Free constructions for FM-typeclasses \begin_inset CommandInset label LatexCommand label name "subsec:Free-constructions-for-inductive-typeclasses" @@ -26579,11 +26527,7 @@ Some features are common to all the free typeclass constructions we have generalize what we have learned about specific typeclasses (free monads, free monoids, etc.) to an arbitrary typeclass. We will use the encodings of the free monoid as the starting point and - generalize to encodings of an arbitrary free -\begin_inset Formula $FM$ -\end_inset - --typeclass. + generalize to encodings of an arbitrary free FM-typeclass. \end_layout \begin_layout Standard @@ -26692,11 +26636,7 @@ free monoid program \begin_layout Standard To generalize from monoids to other typeclasses, recall the definition of - an -\begin_inset Formula $FM$ -\end_inset - --typeclass (Section + an FM-typeclass (Section \begin_inset space ~ \end_inset @@ -26714,23 +26654,16 @@ noprefix "false" \begin_inset Formula $P$ \end_inset -, an -\begin_inset Formula $FM$ -\end_inset - - +, an FM- \series bold --typeclass +typeclass \series default \begin_inset Index idx status open \begin_layout Plain Layout -\begin_inset Formula $FM$ -\end_inset - --typeclass +FM-typeclass \end_layout \end_inset @@ -26782,12 +26715,8 @@ arguments \end_inset ). - So, we imagine that the -\begin_inset Formula $FM$ -\end_inset - --typeclass combines all methods of a typeclass into a single value (of type - + So, we imagine that the FM-typeclass combines all methods of a typeclass + into a single value (of type \begin_inset Formula $P^{A}\rightarrow A$ \end_inset @@ -26803,11 +26732,7 @@ preserving the monoid's operations \begin_inset Quotes erd \end_inset - to an arbitrary -\begin_inset Formula $FM$ -\end_inset - --typeclass. + to an arbitrary FM-typeclass. Given two monoids \begin_inset Formula $M$ \end_inset @@ -27050,11 +26975,7 @@ preserving the typeclass operations \begin_inset Quotes erd \end_inset - for an arbitrary -\begin_inset Formula $FM$ -\end_inset - --typeclass: we just need to impose Eq. + for an arbitrary FM-typeclass: we just need to impose Eq. \begin_inset space ~ \end_inset @@ -27500,11 +27421,8 @@ F\text{-algebra morphism law for }h^{:L\rightarrow M}:\quad & =\gunderline{g^{\u \end_layout \begin_layout Standard -We can now formulate our findings about -\begin_inset Formula $FM$ -\end_inset - --typeclasses in the language of +We can now formulate our findings about FM-typeclasses in the language of + \begin_inset Formula $P$ \end_inset @@ -27517,23 +27435,16 @@ We can now formulate our findings about \end_inset ). - We say that an -\begin_inset Formula $FM$ -\end_inset - - + We say that an FM- \series bold --typeclass with laws +typeclass with laws \series default is \begin_inset Index idx status open \begin_layout Plain Layout -\begin_inset Formula $FM$ -\end_inset - --typeclass!with laws +FM-typeclass!with laws \end_layout \end_inset @@ -27556,11 +27467,7 @@ evidence value \begin_inset Formula $M$ \end_inset - belongs to the -\begin_inset Formula $FM$ -\end_inset - --typeclass. + belongs to the FM-typeclass. If \begin_inset Formula $M$ \end_inset @@ -27589,11 +27496,7 @@ evidence value \begin_inset Quotes eld \end_inset -preserves the -\begin_inset Formula $FM$ -\end_inset - --typeclass operations +preserves the FM-typeclass operations \begin_inset Quotes erd \end_inset @@ -27606,11 +27509,7 @@ The next step is to generalize the free monoid construction to a \begin_inset Quotes eld \end_inset -free -\begin_inset Formula $FM$ -\end_inset - --typeclass +free FM-typeclass \begin_inset Quotes erd \end_inset @@ -27634,11 +27533,7 @@ encoding \begin_inset Quotes erd \end_inset - of a free -\begin_inset Formula $FM$ -\end_inset - --typeclass: + of a free FM-typeclass: \end_layout \begin_layout Itemize @@ -27650,16 +27545,9 @@ We expect to have a type constructor \begin_inset Formula $T$ \end_inset - and produces an -\begin_inset Formula $FM$ -\end_inset - --typeclass instance automatically. - (However, that -\begin_inset Formula $FM$ -\end_inset - --typeclass instance may not obey all of the typeclass laws.) + and produces an FM-typeclass instance automatically. + (However, that FM-typeclass instance may not obey all of the typeclass + laws.) \end_layout \begin_layout Itemize @@ -27688,11 +27576,7 @@ Values of type \begin_inset Quotes eld \end_inset - -\begin_inset Formula $FM$ -\end_inset - --typeclass programs +FM-typeclass programs \begin_inset Quotes erd \end_inset @@ -27722,11 +27606,7 @@ runner \begin_inset Formula $C$ \end_inset - must be an instance of the -\begin_inset Formula $FM$ -\end_inset - --typeclass. + must be an instance of the FM-typeclass. The \begin_inset Quotes eld \end_inset @@ -27827,11 +27707,8 @@ So, we require that a function of type \end_layout \begin_layout Standard -We now define a free -\begin_inset Formula $FM$ -\end_inset - --typeclass encoding by making these expectations precise: +We now define a free FM-typeclass encoding by making these expectations + precise: \end_layout \begin_layout Subsubsection @@ -27864,13 +27741,9 @@ Given a structure functor \series bold free \series default - -\begin_inset Formula $FM$ -\end_inset - - + FM- \series bold --typeclass +typeclass \series default \series bold @@ -27958,17 +27831,9 @@ noprefix "false" \begin_inset Formula $T$ \end_inset - may obey some (or none) of the laws of the -\begin_inset Formula $FM$ -\end_inset - --typeclass. + may obey some (or none) of the laws of the FM-typeclass. There is only a finite number of typeclass laws; so we may consider the - largest subset of the -\begin_inset Formula $FM$ -\end_inset - --typeclass laws obeyed by + largest subset of the FM-typeclass laws obeyed by \begin_inset Formula $p_{E}^{T}$ \end_inset @@ -28095,11 +27960,7 @@ evaluator \begin_inset Formula $p_{C}:P^{C}\rightarrow C$ \end_inset - obeys all the -\begin_inset Formula $FM$ -\end_inset - --typeclass laws assured by + obeys all the FM-typeclass laws assured by \begin_inset Formula $E$ \end_inset @@ -28161,12 +28022,8 @@ all \begin_inset Formula $E$ \end_inset - means that if an -\begin_inset Formula $FM$ -\end_inset - --typeclass law (such as an identity law, an associativity law, etc.) is satisfied - by + means that if an FM-typeclass law (such as an identity law, an associativity + law, etc.) is satisfied by \begin_inset Formula $E^{T}$ \end_inset @@ -28206,12 +28063,8 @@ noprefix "false" \end_inset - will describe -\begin_inset Formula $FM$ -\end_inset - --typeclass laws in more detail, but we do not yet need the techniques developed - there.) + will describe FM-typeclass laws in more detail, but we do not yet need + the techniques developed there.) \end_layout \begin_layout Standard @@ -28249,16 +28102,10 @@ noprefix "false" \begin_layout Standard The uniqueness property of the evaluator reflects a programmer's expectation - that there is only one correct way of running (i.e., evaluating) a free -\begin_inset Formula $FM$ -\end_inset - --typeclass program while preserving the typeclass's operations. - However, in practice we need to evaluate not only -\begin_inset Formula $FM$ -\end_inset - --typeclass programs of type + that there is only one correct way of running (i.e., evaluating) a free FM-typecl +ass program while preserving the typeclass's operations. + However, in practice we need to evaluate not only FM-typeclass programs + of type \begin_inset Formula $E^{C}$ \end_inset @@ -28271,15 +28118,8 @@ The uniqueness property of the evaluator reflects a programmer's expectation \end_inset -algebra and already belongs to the typeclass. - The usefulness of a free -\begin_inset Formula $FM$ -\end_inset - --typeclass construction is in supporting -\begin_inset Formula $FM$ -\end_inset - --typeclass programs of type + The usefulness of a free FM-typeclass construction is in supporting FM-typeclas +s programs of type \begin_inset Formula $E^{T}$ \end_inset @@ -28362,11 +28202,7 @@ universal runner \begin_inset Quotes erd \end_inset - will evaluate a free -\begin_inset Formula $FM$ -\end_inset - --typeclass program of type + will evaluate a free FM-typeclass program of type \begin_inset Formula $E^{T}$ \end_inset @@ -28415,11 +28251,7 @@ Suppose \begin_inset Formula $E$ \end_inset - is a free -\begin_inset Formula $FM$ -\end_inset - --typeclass encoding, + is a free FM-typeclass encoding, \begin_inset Formula $C$ \end_inset @@ -28684,11 +28516,7 @@ noprefix "false" \end_layout \begin_layout Standard -It is important that the definition of a free -\begin_inset Formula $FM$ -\end_inset - --typeclass encoding +It is important that the definition of a free FM-typeclass encoding \begin_inset Formula $E$ \end_inset @@ -28700,11 +28528,7 @@ It is important that the definition of a free \emph on all \emph default - of the -\begin_inset Formula $FM$ -\end_inset - --typeclass laws. + of the FM-typeclass laws. For instance, we have seen that the raw tree encoding of free monads, free monoids, and other typeclasses does not obey any of the relevant laws. Because this does @@ -28715,11 +28539,7 @@ not \begin_inset Quotes eld \end_inset -free -\begin_inset Formula $FM$ -\end_inset - --typeclass encodings +free FM-typeclass encodings \begin_inset Quotes erd \end_inset @@ -28740,30 +28560,19 @@ Monoid \end_inset - to an arbitrary -\begin_inset Formula $FM$ -\end_inset - --typeclass and to show that it satisfies the definition of a + to an arbitrary FM-typeclass and to show that it satisfies the definition + of a \begin_inset Quotes eld \end_inset -free -\begin_inset Formula $FM$ -\end_inset - --typeclass encoding +free FM-typeclass encoding \begin_inset Quotes erd \end_inset . Although the raw tree encoding does not satisfy any typeclass laws, it gives us a valid and usable encoding that we can use as a starting point - to develop other, more concise encodings for a free -\begin_inset Formula $FM$ -\end_inset - --typeclass. + to develop other, more concise encodings for a free FM-typeclass. \end_layout @@ -28814,15 +28623,8 @@ The parts of the disjunctive type \end_inset . - We can now generalize to arbitrary -\begin_inset Formula $FM$ -\end_inset - --typeclasses and define the raw tree encoding of a free -\begin_inset Formula $FM$ -\end_inset - --typeclass (denoted by + We can now generalize to arbitrary FM-typeclasses and define the raw tree + encoding of a free FM-typeclass (denoted by \begin_inset Formula $\text{FPR}^{T}$ \end_inset @@ -28919,11 +28721,7 @@ The free monad on \begin_inset Formula $\text{FPR}^{T}\triangleq T+P^{\text{FPR}^{T}}$ \end_inset -, is a free -\begin_inset Formula $FM$ -\end_inset - --typeclass encoding. +, is a free FM-typeclass encoding. The monad's \begin_inset listings inline true @@ -29379,11 +29177,7 @@ The two code matrices are now equal due to the assumed law \begin_inset Formula $C$ \end_inset - with -\begin_inset Formula $FM$ -\end_inset - --typeclass instance + with FM-typeclass instance \begin_inset Formula $p_{C}:P^{C}\rightarrow C$ \end_inset @@ -29527,17 +29321,9 @@ flatten \begin_inset Formula $P$ \end_inset --algebra morphism; in other words, it preserves the -\begin_inset Formula $FM$ -\end_inset - --typeclass operations. - So, it is not useful to apply the free -\begin_inset Formula $FM$ -\end_inset - --typeclass construction twice, as the result can be reduced to a single - layer of +-algebra morphism; in other words, it preserves the FM-typeclass operations. + So, it is not useful to apply the free FM-typeclass construction twice, + as the result can be reduced to a single layer of \begin_inset listings inline true status open @@ -29684,11 +29470,7 @@ It is not accidental that the raw tree encoding ( \emph on all \emph default - free -\begin_inset Formula $FM$ -\end_inset - --typeclass encodings are monads (although not necessarily free monads): + free FM-typeclass encodings are monads (although not necessarily free monads): \end_layout \begin_layout Subsubsection @@ -29713,11 +29495,7 @@ noprefix "false" \end_layout \begin_layout Standard -Any free -\begin_inset Formula $FM$ -\end_inset - --typeclass encoding +Any free FM-typeclass encoding \begin_inset Formula $E$ \end_inset @@ -30139,11 +29917,7 @@ noprefix "false" \end_layout \begin_layout Subsection -Describing laws of -\begin_inset Formula $FM$ -\end_inset - --typeclasses as values +Describing laws of FM-typeclasses as values \begin_inset CommandInset label LatexCommand label name "subsec:Describing-laws-of-P-typeclasses-as-values" @@ -30163,11 +29937,8 @@ first-class \begin_inset Quotes erd \end_inset - description of -\begin_inset Formula $FM$ -\end_inset - --typeclass laws: each law will be represented by a value of a certain type. + description of FM-typeclass laws: each law will be represented by a value + of a certain type. To make sure we have really found a representation that adequately captures our understanding of what typeclass laws are, we will show three type formulas for the laws, arriving at them via different motivations. @@ -30305,11 +30076,8 @@ Monoid \end_inset will be different. - To generalize to arbitrary -\begin_inset Formula $FM$ -\end_inset - --typeclasses, let us express the laws as much as possible through + To generalize to arbitrary FM-typeclasses, let us express the laws as much + as possible through \begin_inset Formula $P$ \end_inset @@ -30445,16 +30213,8 @@ Monoid \end_inset - laws to other -\begin_inset Formula $FM$ -\end_inset - --typeclasses. - An -\begin_inset Formula $FM$ -\end_inset - --typeclass may impose zero or more laws. + laws to other FM-typeclasses. + An FM-typeclass may impose zero or more laws. Each law is represented by a function of type \begin_inset Formula $\text{LawF}_{P}$ \end_inset @@ -30531,11 +30291,8 @@ Laws as expression trees \begin_layout Standard Another approach to describing typeclass laws is by viewing the two sides of a law as expression trees. - Recall that the raw tree encoding of a free -\begin_inset Formula $FM$ -\end_inset - --typeclass (which we denoted by + Recall that the raw tree encoding of a free FM-typeclass (which we denoted + by \begin_inset Formula $\text{FPR}^{T}$ \end_inset @@ -30920,11 +30677,7 @@ Monoid \end_inset - to an arbitrary -\begin_inset Formula $FM$ -\end_inset - --typeclass. + to an arbitrary FM-typeclass. The two sides of the law are functions that take as arguments one or more arbitrary values of type \begin_inset Formula $T$ @@ -30999,11 +30752,7 @@ et: LawET \begin_inset Formula $T$ \end_inset - with -\begin_inset Formula $FM$ -\end_inset - --typeclass evidence value + with FM-typeclass evidence value \begin_inset Formula $p_{T}:P^{T}\rightarrow T$ \end_inset @@ -31456,11 +31205,7 @@ FMR[Int] \end_layout \begin_layout Standard -Generalizing this to arbitrary -\begin_inset Formula $FM$ -\end_inset - --typeclasses, we obtain the type +Generalizing this to arbitrary FM-typeclasses, we obtain the type \begin_inset Formula $\text{FPR}^{\text{Int}}\times\text{FPR}^{\text{Int}}$ \end_inset @@ -31793,11 +31538,7 @@ LawET \end_layout \begin_layout Standard -It turns out that laws of an -\begin_inset Formula $FM$ -\end_inset - --typeclass are closely connected with +It turns out that laws of an FM-typeclass are closely connected with \begin_inset Formula $P$ \end_inset @@ -31902,11 +31643,7 @@ preserve \begin_inset Quotes erd \end_inset - the -\begin_inset Formula $FM$ -\end_inset - --typeclass laws. + the FM-typeclass laws. \end_layout \begin_layout Standard @@ -31967,11 +31704,7 @@ hides \begin_inset Quotes erd \end_inset - violations of the -\begin_inset Formula $FM$ -\end_inset - --typeclass laws. + violations of the FM-typeclass laws. \end_layout \begin_layout Subparagraph @@ -32228,11 +31961,7 @@ noprefix "false" \end_inset . - Now we see that this is a general property that applies to all -\begin_inset Formula $FM$ -\end_inset - --typeclasses. + Now we see that this is a general property that applies to all FM-typeclasses. It is safe to use a free typeclass encoding (even if it violates some laws) as long as its runner preserves the typeclass operations and the target type is a lawful typeclass member. @@ -32248,11 +31977,7 @@ partially lawful \end_layout \begin_layout Subsection -Free -\begin_inset Formula $FM$ -\end_inset - --typeclasses that satisfy a subset of the laws +Free FM-typeclasses that satisfy a subset of the laws \begin_inset CommandInset label LatexCommand label name "subsec:Free--typeclasses-that-satisfy-laws" @@ -32341,25 +32066,15 @@ noprefix "false" \end_inset , although they obey different subsets of the laws of monoids. - We will now generalize that situation to -\begin_inset Formula $FM$ -\end_inset - --typeclasses and study the properties of free -\begin_inset Formula $FM$ -\end_inset - --typeclass constructions that satisfy only a subset of the typeclass's laws. + We will now generalize that situation to FM-typeclasses and study the propertie +s of free FM-typeclass constructions that satisfy only a subset of the typeclass +'s laws. The resulting theory will make it simpler to prove that a given type constructo r \begin_inset Formula $E$ \end_inset - is indeed a valid free -\begin_inset Formula $FM$ -\end_inset - --typeclass encoding as specified by Definition + is indeed a valid free FM-typeclass encoding as specified by Definition \begin_inset space ~ \end_inset @@ -32664,11 +32379,7 @@ Let \begin_inset Formula $E$ \end_inset - be any free -\begin_inset Formula $FM$ -\end_inset - --typeclass encoding. + be any free FM-typeclass encoding. \end_layout \begin_layout Standard @@ -32692,11 +32403,7 @@ Let \begin_inset Formula $E^{U}$ \end_inset - obeys all the -\begin_inset Formula $FM$ -\end_inset - --typeclass laws that + obeys all the FM-typeclass laws that \begin_inset Formula $E^{T}$ \end_inset @@ -32741,11 +32448,7 @@ smaller \begin_inset Formula $E^{\text{Int}\times\text{Int}}$ \end_inset - obeys some law of the -\begin_inset Formula $FM$ -\end_inset - --typeclass then + obeys some law of the FM-typeclass then \begin_inset Formula $E^{T}$ \end_inset @@ -32769,11 +32472,7 @@ smaller \begin_inset Formula $E^{\text{Int}}$ \end_inset - obeys some law of the -\begin_inset Formula $FM$ -\end_inset - --typeclass then + obeys some law of the FM-typeclass then \begin_inset Formula $E^{T}$ \end_inset @@ -32901,11 +32600,7 @@ noprefix "false" \begin_inset Formula $E^{U}$ \end_inset - obeys all the -\begin_inset Formula $FM$ -\end_inset - --typeclass laws that + obeys all the FM-typeclass laws that \begin_inset Formula $E^{T}$ \end_inset @@ -33263,12 +32958,8 @@ The restriction to polynomial functors \end_inset is not a limitation in practice. - All known -\begin_inset Formula $FM$ -\end_inset - --typeclasses have only a finite set of operations, and each operation has - a fixed and finite number of arguments. + All known FM-typeclasses have only a finite set of operations, and each + operation has a fixed and finite number of arguments. The functor \begin_inset Formula $P$ \end_inset @@ -33286,12 +32977,8 @@ The next statement shows that a functor \begin_inset Formula $E$ \end_inset - is a free -\begin_inset Formula $FM$ -\end_inset - --typeclass encoding if it has an injective map into the raw tree encoding - ( + is a free FM-typeclass encoding if it has an injective map into the raw + tree encoding ( \begin_inset listings inline true status open @@ -33304,11 +32991,8 @@ FPR \end_inset ) and has certain additional properties. - This statement helps us validate free -\begin_inset Formula $FM$ -\end_inset - --typeclass encodings with less work than by using Definition + This statement helps us validate free FM-typeclass encodings with less + work than by using Definition \begin_inset space ~ \end_inset @@ -33511,11 +33195,7 @@ smaller \begin_inset Formula $E^{T}$ \end_inset - satisfies some (or all) of the -\begin_inset Formula $FM$ -\end_inset - --typeclass laws but + satisfies some (or all) of the FM-typeclass laws but \emph on no other \emph default @@ -33538,11 +33218,7 @@ no other \begin_inset Formula $e:\text{FPR}^{\text{Int}}\times\text{FPR}^{\text{Int}}$ \end_inset - for describing -\begin_inset Formula $FM$ -\end_inset - --typeclass laws (see Section + for describing FM-typeclass laws (see Section \begin_inset space ~ \end_inset @@ -33565,11 +33241,7 @@ noprefix "false" \begin_inset Quotes eld \end_inset -no other laws than those of the -\begin_inset Formula $FM$ -\end_inset - --typeclass +no other laws than those of the FM-typeclass \begin_inset Quotes erd \end_inset @@ -33581,11 +33253,7 @@ no other laws than those of the \begin_inset Formula $C$ \end_inset - that obeys all the -\begin_inset Formula $FM$ -\end_inset - --typeclass laws and for any + that obeys all the FM-typeclass laws and for any \begin_inset Formula $e:\text{FPR}^{\text{Int}}\times\text{FPR}^{\text{Int}}$ \end_inset @@ -33655,11 +33323,7 @@ If assumptions 1-5 hold then: \begin_inset Formula $E$ \end_inset - is a free -\begin_inset Formula $FM$ -\end_inset - --typeclass encoding. + is a free FM-typeclass encoding. When the function \begin_inset Formula $\text{in}_{E}$ \end_inset @@ -33702,11 +33366,7 @@ not \end_inset -algebra morphism. - Then we are able to describe free -\begin_inset Formula $FM$ -\end_inset - --typeclass encodings + Then we are able to describe free FM-typeclass encodings \begin_inset Formula $E$ \end_inset @@ -33915,11 +33575,8 @@ We find that we must have \emph on isomorphism \emph default - (a type equivalence that preserves the -\begin_inset Formula $FM$ -\end_inset - --typeclass operations) between + (a type equivalence that preserves the FM-typeclass operations) between + \begin_inset Formula $E^{T}$ \end_inset @@ -33952,11 +33609,7 @@ To show that \begin_inset Formula $E$ \end_inset - is an -\begin_inset Formula $FM$ -\end_inset - --typeclass encoding, we look at the conditions in Definition + is an FM-typeclass encoding, we look at the conditions in Definition \begin_inset space ~ \end_inset @@ -34000,11 +33653,7 @@ To verify condition (c), we assume that \begin_inset Formula $P$ \end_inset --algebra that obeys all the -\begin_inset Formula $FM$ -\end_inset - --typeclass laws that +-algebra that obeys all the FM-typeclass laws that \begin_inset Formula $E$ \end_inset @@ -34599,11 +34248,7 @@ noprefix "false" \end_layout \begin_layout Subsection -Imposing laws of -\begin_inset Formula $FM$ -\end_inset - --typeclasses via monad algebras +Imposing laws of FM-typeclasses via monad algebras \begin_inset CommandInset label LatexCommand label name "subsec:Imposing-laws-of-P-typeclasses-via-monad-algebras" @@ -34628,11 +34273,7 @@ noprefix "false" \end_inset - that any free -\begin_inset Formula $FM$ -\end_inset - --typeclass encoding + that any free FM-typeclass encoding \begin_inset Formula $E$ \end_inset @@ -34641,11 +34282,7 @@ noprefix "false" \begin_inset Formula $E$ \end_inset -'s monad methods to impose -\begin_inset Formula $FM$ -\end_inset - --typeclass laws on a given +'s monad methods to impose FM-typeclass laws on a given \begin_inset Formula $P$ \end_inset @@ -34910,11 +34547,7 @@ Suppose \begin_inset Formula $E$ \end_inset - is a free -\begin_inset Formula $FM$ -\end_inset - --typeclass encoding according to Definition + is a free FM-typeclass encoding according to Definition \begin_inset space ~ \end_inset @@ -35629,11 +35262,7 @@ Let \begin_inset Formula $E$ \end_inset - be any free -\begin_inset Formula $FM$ -\end_inset - --typeclass encoding by Definition + be any free FM-typeclass encoding by Definition \begin_inset space ~ \end_inset @@ -35829,11 +35458,7 @@ In the next section, we will use monad algebras to prove that certain typeclass \end_layout \begin_layout Subsection -Laws for the -\begin_inset Formula $FM$ -\end_inset - --typeclass derivation constructions +Laws for the FM-typeclass derivation constructions \begin_inset CommandInset label LatexCommand label name "subsec:Laws-for-the-P-typeclass-constructions" @@ -35860,16 +35485,10 @@ noprefix "false" we have shown certain type constructions that derive new typeclass instances from previous ones. - For example, the product of two types that belong to an -\begin_inset Formula $FM$ -\end_inset - --typeclass will again belong to that typeclass. - However, in that chapter we only showed that one can compute an -\begin_inset Formula $FM$ -\end_inset - --typeclass evidence values for those constructions. + For example, the product of two types that belong to an FM-typeclass will + again belong to that typeclass. + However, in that chapter we only showed that one can compute an FM-typeclass + evidence values for those constructions. Now we have developed a theory that can also prove that the laws hold automatic ally for each of those constructions. This theory justifies automatic typeclass derivation for those cases. @@ -35889,11 +35508,7 @@ Instead of dealing with laws explicitly as values, it is more convenient \begin_inset Formula $T$ \end_inset - is a lawful member of an -\begin_inset Formula $FM$ -\end_inset - --typeclass if + is a lawful member of an FM-typeclass if \begin_inset Formula $T$ \end_inset @@ -35905,11 +35520,7 @@ Instead of dealing with laws explicitly as values, it is more convenient \begin_inset Formula $E$ \end_inset - is the free -\begin_inset Formula $FM$ -\end_inset - --typeclass encoding that assures the laws of the typeclass. + is the free FM-typeclass encoding that assures the laws of the typeclass. Using this formulation of laws, it is sufficient to prove that a new derived type is again an \begin_inset Formula $E$ @@ -36572,11 +36183,7 @@ Unlike the proof in part \end_layout \begin_layout Subsection -Church encodings of free -\begin_inset Formula $FM$ -\end_inset - --typeclasses +Church encodings of free FM-typeclasses \begin_inset CommandInset label LatexCommand label name "subsec:Church-encodings-for-free-P-typeclasses" @@ -38456,11 +38063,7 @@ call \series bold structure functor \series default - of the -\begin_inset Formula $FM$ -\end_inset - --typeclass + of the FM-typeclass \begin_inset Formula $C$ \end_inset @@ -40545,11 +40148,7 @@ acts \begin_inset Formula $\text{Mod}_{L}$ \end_inset - is an -\begin_inset Formula $FM$ -\end_inset - --typeclass. + is an FM-typeclass. Implement a free \begin_inset Formula $L$ \end_inset diff --git a/sofp-src/lyx/sofp-summary.lyx b/sofp-src/lyx/sofp-summary.lyx index 08b48a844..dcb2194fc 100644 --- a/sofp-src/lyx/sofp-summary.lyx +++ b/sofp-src/lyx/sofp-summary.lyx @@ -2371,11 +2371,7 @@ Why many typeclasses have similar properties as regards typeclass derivation; \begin_inset Quotes eld \end_inset - -\begin_inset Formula $FM$ -\end_inset - --typeclasses +FM-typeclasses \begin_inset Quotes erd \end_inset @@ -6135,12 +6131,9 @@ noprefix "false" \end_layout \begin_layout Standard -Later we will show that this situation is found in general for all -\begin_inset Formula $FM$ -\end_inset - --typeclasses: a reduced encoding can be injected into the raw tree encoding - by many functions, neither of which preserves the typeclass methods. +Later we will show that this situation is found in general for all FM-typeclasse +s: a reduced encoding can be injected into the raw tree encoding by many + functions, neither of which preserves the typeclass methods. \end_layout \begin_layout Standard @@ -8175,11 +8168,7 @@ noprefix "false" \end_inset -) and for lawful -\begin_inset Formula $FM$ -\end_inset - --typeclasses (used in Section +) and for lawful FM-typeclasses (used in Section \begin_inset space ~ \end_inset diff --git a/sofp-src/lyx/sofp-typeclasses.lyx b/sofp-src/lyx/sofp-typeclasses.lyx index 6422a1199..7c65c3595 100644 --- a/sofp-src/lyx/sofp-typeclasses.lyx +++ b/sofp-src/lyx/sofp-typeclasses.lyx @@ -36261,10 +36261,7 @@ John de Goes. \end_layout \begin_layout Subsection -\begin_inset Formula $FM$ -\end_inset - --typeclasses, their laws and structure +FM-typeclasses, their laws and structure \begin_inset CommandInset label LatexCommand label name "subsec:P-typeclasses" @@ -36661,11 +36658,7 @@ pointed contrafunctor \begin_inset Caption Standard \begin_layout Plain Layout -Structure of typeclass instance values for various -\begin_inset Formula $FM$ -\end_inset - --typeclasses. +Structure of typeclass instance values for various FM-typeclasses. \begin_inset CommandInset label LatexCommand label name "tab:Types-of-typeclass-instance-values" @@ -36803,19 +36796,12 @@ This motivates the definition of status open \begin_layout Plain Layout -\begin_inset Formula $FM$ -\end_inset - --typeclass|textit +FM-typeclass|textit \end_layout \end_inset - an -\begin_inset Formula $FM$ -\end_inset - -- + an FM- \series bold typeclass \series default @@ -36893,11 +36879,7 @@ final case class FMTypeclass[P[_]: Functor, A](methods: P[A] => A) \end_inset -The code allows us to declare any -\begin_inset Formula $FM$ -\end_inset - --typeclass. +The code allows us to declare any FM-typeclass. For example, the \begin_inset listings inline true @@ -37041,11 +37023,8 @@ noprefix "false" except for the additional type parameters. The laws of type constructor typeclasses are also more complicated because they often involve multiple type parameters and arbitrary functions. - To simplify the presentation in this section, we will only consider -\begin_inset Formula $FM$ -\end_inset - --typeclasses for simple types, such as + To simplify the presentation in this section, we will only consider FM-typeclas +ses for simple types, such as \begin_inset listings inline true status open @@ -37100,11 +37079,8 @@ Monoid is useful for reasoning about general properties of typeclasses. To illustrate that kind of reasoning, we will now show that the product-type, - the function-type, and the recursive-type constructions work for all -\begin_inset Formula $FM$ -\end_inset - --typeclasses. + the function-type, and the recursive-type constructions work for all FM-typecla +sses. \end_layout @@ -37113,11 +37089,7 @@ Products \end_layout \begin_layout Standard -Consider an arbitrary -\begin_inset Formula $FM$ -\end_inset - --typeclass +Consider an arbitrary FM-typeclass \begin_inset listings inline true status open @@ -37236,23 +37208,16 @@ noprefix "false" \end_inset - after developing some advanced techniques for formal reasoning about -\begin_inset Formula $FM$ -\end_inset - --typeclass laws. + after developing some advanced techniques for formal reasoning about FM-typecla +ss laws. \end_layout \begin_layout Standard -We note that the co-product construction does +The co-product construction does \emph on not \emph default - work for arbitrary -\begin_inset Formula $FM$ -\end_inset - --typeclasses: given evidence values of types + work for arbitrary FM-typeclasses: given evidence values of types \begin_inset Formula $P^{A}\rightarrow A$ \end_inset @@ -37265,14 +37230,10 @@ not \end_inset . - Later we will see that some -\begin_inset Formula $FM$ -\end_inset - --typeclasses, such as monads or applicative functors, do not support the - co-product construction. - The co-product of two monads is not always a lawful monad; the co-product - of two applicative functors is not always an applicative functor. + Later we will see that some FM-typeclasses, such as monads or applicative + functors, do not support the co-product construction. + The co-product of two monads is not always a monad; the co-product of + two applicative functors is not always an applicative functor. \end_layout \begin_layout Paragraph @@ -37280,11 +37241,8 @@ Functions \end_layout \begin_layout Standard -The function-type construction creates an -\begin_inset Formula $FM$ -\end_inset - --typeclass instance for the type +The function-type construction creates an FM-typeclass instance for the + type \begin_inset Formula $E\rightarrow A$ \end_inset @@ -37292,11 +37250,7 @@ The function-type construction creates an \begin_inset Formula $A$ \end_inset - belongs to the -\begin_inset Formula $FM$ -\end_inset - --typeclass. + belongs to the FM-typeclass. Using the fact that \begin_inset Formula $P$ \end_inset @@ -37364,11 +37318,7 @@ preserves \begin_inset Quotes erd \end_inset - -\begin_inset Formula $FM$ -\end_inset - --typeclass instances: if + FM-typeclass instances: if \begin_inset Formula $A$ \end_inset @@ -37530,11 +37480,7 @@ def tcT: P[T] => T = p => T(tcS(tcT)(p.map(_.s))) // The recursive instance. \end_inset -In this way, the recursive-type construction works for any -\begin_inset Formula $FM$ -\end_inset - --typeclass. +In this way, the recursive-type construction works for any FM-typeclass. (We will prove in Section \begin_inset space ~ \end_inset @@ -37557,11 +37503,8 @@ Similar arguments can be made for type constructor typeclasses, although their properties are more difficult to prove. This book shows that the product-type, the function-type, and the recursive-typ e constructions work for functors, contrafunctors, pointed functors, and - pointed contrafunctors, as well as for other important -\begin_inset Formula $FM$ -\end_inset - --typeclasses such as filterable functors (Chapter + pointed contrafunctors, as well as for other important FM-typeclasses such + as filterable functors (Chapter \begin_inset space ~ \end_inset @@ -37618,11 +37561,8 @@ noprefix "false" \end_inset - that another general construction also works for all -\begin_inset Formula $FM$ -\end_inset - --typeclasses, — the + that another general construction also works for all FM-typeclasses, — + the \begin_inset Quotes eld \end_inset @@ -37638,11 +37578,7 @@ Some typeclasses \emph on cannot \emph default - be viewed as -\begin_inset Formula $FM$ -\end_inset - --typeclasses. + be viewed as FM-typeclasses. The \begin_inset listings inline true @@ -37763,24 +37699,16 @@ noprefix "false" \series bold co- \series default - -\begin_inset Formula $FM$ -\end_inset - - +FM- \series bold --typeclasses +typeclasses \series default . \begin_inset Index idx status open \begin_layout Plain Layout -co- -\begin_inset Formula $FM$ -\end_inset - --typeclasses +co-FM-typeclasses \end_layout \end_inset @@ -37811,29 +37739,19 @@ co-product \begin_inset Formula $A+B\rightarrow P^{A+B}$ \end_inset -, i.e., an -\begin_inset Formula $FM$ -\end_inset - --typeclass evidence for the co-product +, i.e., an FM-typeclass evidence for the co-product \begin_inset Formula $A+B$ \end_inset . - Similarly to -\begin_inset Formula $FM$ -\end_inset - --typeclasses, the typeclass laws will hold automatically for the type + Similarly to FM-typeclasses, the typeclass laws will hold automatically + for the type \begin_inset Formula $A+B$ \end_inset . - A detailed description of co- -\begin_inset Formula $FM$ -\end_inset - --typeclasses is beyond the scope of this book. + A detailed description of co-FM-typeclasses is beyond the scope of this + book. \end_layout \begin_layout Standard @@ -39091,12 +39009,22 @@ es whose method signature has the form \begin_inset Quotes eld \end_inset +FM-typeclasses +\begin_inset Quotes erd +\end_inset -\begin_inset Formula $FM$ + for reasons explained in Chapter +\begin_inset space ~ \end_inset --typeclasses -\begin_inset Quotes erd + +\begin_inset CommandInset ref +LatexCommand ref +reference "chap:Free-type-constructions" +plural "false" +caps "false" +noprefix "false" + \end_inset .) diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 050710054994bd23012ca00aff0c558d1999849e..98baabc3ea78afb42d52b1f0f6a039dd08605e76 100644 GIT binary patch delta 136 zcmX?Ra?E7IMiEvcb1M^r$=gKCpsbG~Pk7TTladV5Oigr+jm=XxKN96;VlgrYs`@A{ z2WD&*mbk{~Waj2%ZtUh_;ACXrU}|*9>=xS); T! and obtain a pair \lstinline!(lhs, rhs)! -of expression trees of type \lstinline!FPR[T]!: +computation: Choose a type $T$ with FM-typeclass evidence value $p_{T}:P^{T}\rightarrow T$. +First, we apply \lstinline!et! to an arbitrary function \lstinline!v: Int => T! +and obtain a pair \lstinline!(lhs, rhs)! of expression trees of type +\lstinline!FPR[T]!: \begin{lstlisting} val v: Int => T = ... val (lhs: FPR[T], rhs: FPR[T]) = et(v) @@ -4564,7 +4561,7 @@ \subsection{Describing laws of $FM$-typeclasses as values\label{subsec:Describin In this way, a pair of values of type \lstinline!FMR[Int]! encodes the monoid associativity law. -Generalizing this to arbitrary $FM$-typeclasses, we obtain the type +Generalizing this to arbitrary FM-typeclasses, we obtain the type $\text{FPR}^{\text{Int}}\times\text{FPR}^{\text{Int}}$. Each value of that type represents a possible typeclass law. The integer-valued indices correspond to different arbitrary variables used in the two @@ -4622,10 +4619,10 @@ \subsubsection{Statement \label{subsec:Statement-equivalence-law-function-law-ex within a particular derivation or proof. It is usually easier to work with the type $\text{FPR}^{\text{Int}}\times\text{FPR}^{\text{Int}}$. -It turns out that laws of an $FM$-typeclass are closely connected -with $P$-algebra morphisms. In particular, $P$-algebra morphisms -preserve the typeclass laws and hide the law violations, in the precise -sense explained in the following statement. +It turns out that laws of an FM-typeclass are closely connected with +$P$-algebra morphisms. In particular, $P$-algebra morphisms preserve +the typeclass laws and hide the law violations, in the precise sense +explained in the following statement. \subsubsection{Statement \label{subsec:Statement-P-algebra-morphisms-and-laws}\ref{subsec:Statement-P-algebra-morphisms-and-laws}} @@ -4636,7 +4633,7 @@ \subsubsection{Statement \label{subsec:Statement-P-algebra-morphisms-and-laws}\r \textbf{(a)} Suppose that the law holds for $M$ and $\phi$ is \emph{surjective}. Then the same law also holds for $N$. In this sense, surjective $P$-algebra -morphisms \textsf{``}preserve\textsf{''} the $FM$-typeclass laws. +morphisms \textsf{``}preserve\textsf{''} the FM-typeclass laws. \textbf{(b)} Suppose the law holds for $N$ but \emph{not} for $M$. Suppose a violation of the law for $M$ is found using a specific @@ -4650,7 +4647,7 @@ \subsubsection{Statement \label{subsec:Statement-P-algebra-morphisms-and-laws}\r l_{1}\triangleright v^{\uparrow\text{FPR}}\bef\text{eval}_{\text{FPR}}^{M}\bef\phi=l_{2}\triangleright v^{\uparrow\text{FPR}}\bef\text{eval}_{\text{FPR}}^{M}\bef\phi\quad.\label{eq:p-typeclass-law-violation-hidden} \end{equation} In this sense, a $P$-algebra morphism \textsf{``}hides\textsf{''} violations of the -$FM$-typeclass laws. +FM-typeclass laws. \subparagraph{Proof} @@ -4711,24 +4708,24 @@ \subsubsection{Statement \label{subsec:Statement-P-algebra-morphisms-and-laws}\r typeclass operations (i.e., it is a $P$-algebra morphism). Then Statement~\ref{subsec:Statement-P-algebra-morphisms-and-laws}(b) shows that law violations no longer exist after the runner is applied. We have proved this explicitly for our free monad DSL in Section~\ref{subsec:A-first-recipe-monadic-dsl}. -Now we see that this is a general property that applies to all $FM$-typeclasses. +Now we see that this is a general property that applies to all FM-typeclasses. It is safe to use a free typeclass encoding (even if it violates some laws) as long as its runner preserves the typeclass operations and the target type is a lawful typeclass member. In the next section we will study such \textsf{``}partially lawful\textsf{''} free typeclass encodings in more detail. -\subsection{Free $FM$-typeclasses that satisfy a subset of the laws\label{subsec:Free--typeclasses-that-satisfy-laws}} +\subsection{Free FM-typeclasses that satisfy a subset of the laws\label{subsec:Free--typeclasses-that-satisfy-laws}} In Section~\ref{subsec:Free-monoids}, we have seen four different encodings of the free monoid (denoted by \lstinline!F1!, \lstinline!F2!, \lstinline!F3!, and \lstinline!F4!). It turns out that all those encodings satisfy the requirements of Definition~\ref{subsec:Definition-free-P-typeclass-encoding}, although they obey different subsets of the laws of monoids. We will -now generalize that situation to $FM$-typeclasses and study the properties -of free $FM$-typeclass constructions that satisfy only a subset of -the typeclass\textsf{'}s laws. The resulting theory will make it simpler to -prove that a given type constructor $E$ is indeed a valid free $FM$-typeclass +now generalize that situation to FM-typeclasses and study the properties +of free FM-typeclass constructions that satisfy only a subset of the +typeclass\textsf{'}s laws. The resulting theory will make it simpler to prove +that a given type constructor $E$ is indeed a valid free FM-typeclass encoding as specified by Definition~\ref{subsec:Definition-free-P-typeclass-encoding}. One important question is whether a free typeclass encoding $E^{T}$ @@ -4768,20 +4765,20 @@ \subsection{Free $FM$-typeclasses that satisfy a subset of the laws\label{subsec \subsubsection{Statement \label{subsec:Statement-free-typeclass-more-laws}\ref{subsec:Statement-free-typeclass-more-laws}} -Let $E$ be any free $FM$-typeclass encoding. +Let $E$ be any free FM-typeclass encoding. \textbf{(a)} If types $T$, $U$ are such that a surjective function -$f:T\rightarrow U$ exists then $E^{U}$ obeys all the $FM$-typeclass +$f:T\rightarrow U$ exists then $E^{U}$ obeys all the FM-typeclass laws that $E^{T}$ obeys. (A \textsf{``}larger\textsf{''} type $E^{T}$ satisfies at least as many laws as a \textsf{``}smaller\textsf{''} type $E^{U}$.) \textbf{(b)} If $E$ is a polynomial functor and $E^{\text{Int}\times\text{Int}}$ -obeys some law of the $FM$-typeclass then $E^{T}$ obeys that law -for all types $T$. +obeys some law of the FM-typeclass then $E^{T}$ obeys that law for +all types $T$. \textbf{(c)} If $E$ is a polynomial functor and $E^{\text{Int}}$ -obeys some law of the $FM$-typeclass then $E^{T}$ obeys that law -for all types $T$. +obeys some law of the FM-typeclass then $E^{T}$ obeys that law for +all types $T$. It follows that the set of laws \textsf{``}ensured by\textsf{''} $E$ are just the laws obeyed by $E^{\text{Int}}$. @@ -4794,7 +4791,7 @@ \subsubsection{Statement \label{subsec:Statement-free-typeclass-more-laws}\ref{s due to Statement~\ref{subsec:f-Statement-functor-preserves-injective}. The function $\phi$ is a $P$-algebra morphism due to Definition~\ref{subsec:Definition-free-P-typeclass-encoding}(a). So, Statement~\ref{subsec:Statement-P-algebra-morphisms-and-laws}(a) -is applicable and gives the result that $E^{U}$ obeys all the $FM$-typeclass +is applicable and gives the result that $E^{U}$ obeys all the FM-typeclass laws that $E^{T}$ obeys. \textbf{(b)} Given a type $T$, a law $l_{1}\times l_{2}:\text{FPR}^{\text{Int}}\times\text{FPR}^{\text{Int}}$, @@ -4866,15 +4863,15 @@ \subsubsection{Statement \label{subsec:Statement-free-typeclass-more-laws}\ref{s for natural numbers). $\square$ The restriction to polynomial functors $E$ is not a limitation in -practice. All known $FM$-typeclasses have only a finite set of operations, +practice. All known FM-typeclasses have only a finite set of operations, and each operation has a fixed and finite number of arguments. The functor $P$ describing those operations will be always polynomial, and so will be the corresponding functor $E$. -The next statement shows that a functor $E$ is a free $FM$-typeclass +The next statement shows that a functor $E$ is a free FM-typeclass encoding if it has an injective map into the raw tree encoding (\lstinline!FPR!) and has certain additional properties. This statement helps us validate -free $FM$-typeclass encodings with less work than by using Definition~\ref{subsec:Definition-free-P-typeclass-encoding} +free FM-typeclass encodings with less work than by using Definition~\ref{subsec:Definition-free-P-typeclass-encoding} directly. \subsubsection{Statement \label{subsec:Statement-compatible-retract-of-free-monad}\ref{subsec:Statement-compatible-retract-of-free-monad}} @@ -4902,14 +4899,14 @@ \subsubsection{Statement \label{subsec:Statement-compatible-retract-of-free-mona by $\text{ftn}_{E}\triangleq\text{in}_{E}^{E^{T}}\bef\text{eval}_{\text{FPR}}^{E^{T}}$ is a $P$-algebra morphism (even though $\text{in}_{E}$ is not!). -5. The $P$-algebra $E^{T}$ satisfies some (or all) of the $FM$-typeclass +5. The $P$-algebra $E^{T}$ satisfies some (or all) of the FM-typeclass laws but \emph{no other} laws. {*}{*}{*}This is misleading, as in fact $E^{T}$ does satisfy more laws for some $T$; say for $T=\bbnum 0$. How do we actually use item 5 as an assumption?{*}{*}{*}To formulate this requirement precisely, we use law expressions $e:\text{FPR}^{\text{Int}}\times\text{FPR}^{\text{Int}}$ -for describing $FM$-typeclass laws (see Section~\ref{subsec:Describing-laws-of-P-typeclasses-as-values}). -We say that $E^{T}$ obeys \textsf{``}no other laws than those of the $FM$-typeclass\textsf{''} -if for any $P$-algebra $C$ that obeys all the $FM$-typeclass laws +for describing FM-typeclass laws (see Section~\ref{subsec:Describing-laws-of-P-typeclasses-as-values}). +We say that $E^{T}$ obeys \textsf{``}no other laws than those of the FM-typeclass\textsf{''} +if for any $P$-algebra $C$ that obeys all the FM-typeclass laws and for any $e:\text{FPR}^{\text{Int}}\times\text{FPR}^{\text{Int}}$ whose corresponding $e$-law holds for $E^{T}$, the same $e$-law will also hold for $C$. (A counterexample is an $E^{T}$ that satisfies @@ -4921,12 +4918,12 @@ \subsubsection{Statement \label{subsec:Statement-compatible-retract-of-free-mona If assumptions 1-5 hold then: -\textbf{(a)} The functor $E$ is a free $FM$-typeclass encoding. -When the function $\text{in}_{E}$ is itself a $P$-algebra morphism -then the encoding $E$ will be \emph{equivalent} to \lstinline!FPR!. -(This is why we do \emph{not} require $\text{in}_{E}^{T}$ to be a -$P$-algebra morphism. Then we are able to describe free $FM$-typeclass -encodings $E$ that are different from $\text{FPR}$.) +\textbf{(a)} The functor $E$ is a free FM-typeclass encoding. When +the function $\text{in}_{E}$ is itself a $P$-algebra morphism then +the encoding $E$ will be \emph{equivalent} to \lstinline!FPR!. (This +is why we do \emph{not} require $\text{in}_{E}^{T}$ to be a $P$-algebra +morphism. Then we are able to describe free FM-typeclass encodings +$E$ that are different from $\text{FPR}$.) \textbf{(b)} The universal evaluator $\text{eval}_{E}^{C}$ does not depend on the choice of the function $\text{in}_{E}$. @@ -4960,19 +4957,19 @@ \subsubsection{Statement \label{subsec:Statement-compatible-retract-of-free-mona We find that we must have $g_{E}^{T}=\text{id}$. It means that the $P$-algebra morphisms $\text{in}_{E}^{T}$ and $g$ are inverses of each other and give a $P$-algebra \emph{isomorphism} (a type equivalence -that preserves the $FM$-typeclass operations) between $E^{T}$ and -$\text{FPR}^{T}$. So, $E^{T}$ is equivalent to the raw tree encoding -($\text{FPR}^{T}$) when $\text{in}_{E}$ is a $P$-algebra morphism. +that preserves the FM-typeclass operations) between $E^{T}$ and $\text{FPR}^{T}$. +So, $E^{T}$ is equivalent to the raw tree encoding ($\text{FPR}^{T}$) +when $\text{in}_{E}$ is a $P$-algebra morphism. -To show that $E$ is an $FM$-typeclass encoding, we look at the conditions +To show that $E$ is an FM-typeclass encoding, we look at the conditions in Definition~\ref{subsec:Definition-free-P-typeclass-encoding}. Conditions (a) and (b) of Definition~\ref{subsec:Definition-free-P-typeclass-encoding} are satisfied by our assumptions 1 and 2. To verify condition (c), we assume that $C$ is any $P$-algebra that -obeys all the $FM$-typeclass laws that $E$ obeys. We then define -$\text{eval}_{E}^{C}$ via $\text{eval}_{\text{FPR}}^{C}$: +obeys all the FM-typeclass laws that $E$ obeys. We then define $\text{eval}_{E}^{C}$ +via $\text{eval}_{\text{FPR}}^{C}$: \[ \text{eval}_{E}^{C}:E^{C}\rightarrow C\quad,\quad\quad\text{eval}_{E}^{C}\triangleq\text{in}_{E}^{C}\bef\text{eval}_{\text{FPR}}^{C}\quad. \] @@ -5096,11 +5093,11 @@ \subsubsection{Statement \label{subsec:Statement-compatible-retract-of-free-mona obeying the left identity law, namely $\text{eval}_{E}^{C}$. So, $\text{eval}_{E}^{\prime C}=\text{eval}_{E}^{C}$. $\square$ -\subsection{Imposing laws of $FM$-typeclasses via monad algebras\label{subsec:Imposing-laws-of-P-typeclasses-via-monad-algebras}} +\subsection{Imposing laws of FM-typeclasses via monad algebras\label{subsec:Imposing-laws-of-P-typeclasses-via-monad-algebras}} We have shown in Statement~\ref{subsec:Statement-free-typeclass-encoding-is-a-monad} -that any free $FM$-typeclass encoding $E$ is always a monad. It -turns out that we may may use $E$\textsf{'}s monad methods to impose $FM$-typeclass +that any free FM-typeclass encoding $E$ is always a monad. It turns +out that we may may use $E$\textsf{'}s monad methods to impose FM-typeclass laws on a given $P$-algebra. The required technique is based on the notion of a \textsf{``}\index{monad algebra}monad algebra\textsf{''} that comes from category theory: @@ -5145,7 +5142,7 @@ \subsubsection{Definition \label{subsec:Definition-monad-algebra}\ref{subsec:Def \subsubsection{Statement \label{subsec:Statement-Monad-algebra-is-P-typeclass}\ref{subsec:Statement-Monad-algebra-is-P-typeclass}} -Suppose $E$ is a free $FM$-typeclass encoding according to Definition~\ref{subsec:Definition-free-P-typeclass-encoding}. +Suppose $E$ is a free FM-typeclass encoding according to Definition~\ref{subsec:Definition-free-P-typeclass-encoding}. A monad structure for $E$ is given by Statement~\ref{subsec:Statement-free-typeclass-encoding-is-a-monad}. Then the type of $E$-monad algebras is equivalent to the type of $P$-algebras that obey all the laws of $E$. In more detail: @@ -5248,7 +5245,7 @@ \subsubsection{Statement \label{subsec:Statement-Monad-algebra-is-P-typeclass}\r \subsubsection{Exercise \label{subsec:Exercise-P-algebras-monad-algebras}\ref{subsec:Exercise-P-algebras-monad-algebras}\index{exercises}} -Let $E$ be any free $FM$-typeclass encoding by Definition~\ref{subsec:Definition-free-P-typeclass-encoding}. +Let $E$ be any free FM-typeclass encoding by Definition~\ref{subsec:Definition-free-P-typeclass-encoding}. \textbf{(a)} If $C$ and $D$ are any given $E$-monad algebras, the proof of Statement~\ref{subsec:Statement-Monad-algebra-is-P-typeclass}(a) @@ -5267,15 +5264,15 @@ \subsubsection{Exercise \label{subsec:Exercise-P-algebras-monad-algebras}\ref{su In the next section, we will use monad algebras to prove that certain typeclass constructions automatically produce lawful typeclass instances. -\subsection{Laws for the $FM$-typeclass derivation constructions\label{subsec:Laws-for-the-P-typeclass-constructions}} +\subsection{Laws for the FM-typeclass derivation constructions\label{subsec:Laws-for-the-P-typeclass-constructions}} In Section~\ref{subsec:P-typeclasses} we have shown certain type constructions that derive new typeclass instances from previous ones. -For example, the product of two types that belong to an $FM$-typeclass +For example, the product of two types that belong to an FM-typeclass will again belong to that typeclass. However, in that chapter we only -showed that one can compute an $FM$-typeclass evidence values for -those constructions. Now we have developed a theory that can also -prove that the laws hold automatically for each of those constructions. +showed that one can compute an FM-typeclass evidence values for those +constructions. Now we have developed a theory that can also prove +that the laws hold automatically for each of those constructions. This theory justifies automatic typeclass derivation for those cases. The next statements prove that the typeclass laws hold automatically @@ -5285,11 +5282,11 @@ \subsection{Laws for the $FM$-typeclass derivation constructions\label{subsec:La Instead of dealing with laws explicitly as values, it is more convenient in these proofs if we impose typeclass laws via monad algebras. As we have seen in the previous section, a type $T$ is a lawful member -of an $FM$-typeclass if $T$ is an $E$-monad algebra, where the -monad $E$ is the free $FM$-typeclass encoding that assures the laws -of the typeclass. Using this formulation of laws, it is sufficient -to prove that a new derived type is again an $E$-monad algebra if -so are the previously given types. +of an FM-typeclass if $T$ is an $E$-monad algebra, where the monad +$E$ is the free FM-typeclass encoding that assures the laws of the +typeclass. Using this formulation of laws, it is sufficient to prove +that a new derived type is again an $E$-monad algebra if so are the +previously given types. In each of the following statements, $E$ is a fixed monad. @@ -5454,7 +5451,7 @@ \subsubsection{Statement \label{subsec:Statement-Monad-algebra-exp-1}\ref{subsec Other than that, we can repeat the proof for part \textbf{(a)} except for replacing $s(\overline{t})$ by $s$. $\square$ -\subsection{Church encodings of free $FM$-typeclasses\label{subsec:Church-encodings-for-free-P-typeclasses}} +\subsection{Church encodings of free FM-typeclasses\label{subsec:Church-encodings-for-free-P-typeclasses}} \subsection{Free constructions on more than one generator} @@ -5881,7 +5878,7 @@ \section{Slides } Type class $C$ is defined by its operations{\footnotesize{} $C^{X}\rightarrow X$} (with a suitable $C^{\bullet}$) -call $C^{\bullet}$ the \textbf{structure functor} of the $FM$-typeclass +call $C^{\bullet}$ the \textbf{structure functor} of the FM-typeclass $C$ Tree encoding of \textsf{``}free $C$ over $Z$\textsf{''} is recursive, $\text{FreeC}^{Z}\triangleq Z+C^{\text{FreeC}^{Z}}$ @@ -6319,7 +6316,7 @@ \subsubsection{Exercise \label{subsec:Exercise-free-type-2}\ref{subsec:Exercise- \textsf{``}acts\textsf{''} on $P$ via a function act$:L\rightarrow P\rightarrow P$, with laws $\text{act}\,x\bef\text{act}\,y=\text{act}\left(x\bef y\right)$ and $\text{act}\left(e_{L}\right)=\text{id}$. - Monoid morphism between -$L$ and $\text{MF}^{P}$. Show that $\text{Mod}_{L}$ is an $FM$-typeclass. +$L$ and $\text{MF}^{P}$. Show that $\text{Mod}_{L}$ is an FM-typeclass. Implement a free $L$-module on a type $Z$. \subsubsection{Exercise \label{subsec:Exercise-free-type-3}\ref{subsec:Exercise-free-type-3}} diff --git a/sofp-src/tex/sofp-summary.tex b/sofp-src/tex/sofp-summary.tex index dea1062b5..89f9d45a2 100644 --- a/sofp-src/tex/sofp-summary.tex +++ b/sofp-src/tex/sofp-summary.tex @@ -322,7 +322,7 @@ \subsection{Chapter~\ref{chap:Typeclasses-and-functions}} relations\textsf{''}) \item Inheritance and automatic conversion of typeclasses \item Why many typeclasses have similar properties as regards typeclass -derivation; the concept of \textsf{``}$FM$-typeclasses\textsf{''} +derivation; the concept of \textsf{``}FM-typeclasses\textsf{''} \item How typeclasses unify and generalize both algebraic data types and object-oriented interfaces \end{itemize} @@ -846,8 +846,8 @@ \subsection{Chapter~\ref{chap:Free-type-constructions}} of the universal runner and preserves the semigroup\textsf{'}s methods. Later we will show that this situation is found in general for all -$FM$-typeclasses: a reduced encoding can be injected into the raw -tree encoding by many functions, neither of which preserves the typeclass +FM-typeclasses: a reduced encoding can be injected into the raw tree +encoding by many functions, neither of which preserves the typeclass methods. The next more complicated typeclass is \lstinline!Monoid! (Section~\ref{subsec:Free-monoids}). @@ -1179,7 +1179,7 @@ \subsection{Appendix~\ref{app:Proofs-of-naturality-parametricity}} practical applications of the Yoneda lemma to programming. Other applications used in this book are Yoneda identities for type constructors (see Section~\ref{subsec:The-Yoneda-identities-for-type-constructors}) -and for lawful $FM$-typeclasses (used in Section~\ref{subsec:The-Jaskelioff-OConnor-theorem} +and for lawful FM-typeclasses (used in Section~\ref{subsec:The-Jaskelioff-OConnor-theorem} in the proof of the Jaskelioff-O\textsf{'}Connor theorem). We turn to further applications of parametricity that go beyond what diff --git a/sofp-src/tex/sofp-typeclasses.tex b/sofp-src/tex/sofp-typeclasses.tex index 845c10cc9..d6b24bf1a 100644 --- a/sofp-src/tex/sofp-typeclasses.tex +++ b/sofp-src/tex/sofp-typeclasses.tex @@ -5628,7 +5628,7 @@ \subsection{Inheritance and automatic conversions of typeclasses\label{subsec:In Goes.} So far, it is not known whether any encoding can solve all issues that come from multiple inheritance of typeclasses. -\subsection{$FM$-typeclasses, their laws and structure\label{subsec:P-typeclasses}} +\subsection{FM-typeclasses, their laws and structure\label{subsec:P-typeclasses}} We have seen that many typeclasses have similar structural properties. For instance, a product of semigroups is again a semigroup, a product @@ -5663,7 +5663,7 @@ \subsection{$FM$-typeclasses, their laws and structure\label{subsec:P-typeclasse \hline \end{tabular} \par\end{centering} -\caption{Structure of typeclass instance values for various $FM$-typeclasses.\label{tab:Types-of-typeclass-instance-values}} +\caption{Structure of typeclass instance values for various FM-typeclasses.\label{tab:Types-of-typeclass-instance-values}} \end{table} The \lstinline!Semigroup! typeclass has a single method ($\oplus_{_{A}}$) @@ -5682,9 +5682,9 @@ \subsection{$FM$-typeclasses, their laws and structure\label{subsec:P-typeclasse the empty value ($e_{_{A}}$) and the binary operation ($\oplus_{_{A}}$) of the monoid $A$. -This motivates the definition of \index{$FM$-typeclass|textit} an -$FM$-\textbf{typeclass}: it is a typeclass whose instance values -have type $P^{T}\rightarrow T$. The functor $P$ is called the \index{structure functor of a typeclass}\index{typeclass!structure functor}\textbf{structure +This motivates the definition of \index{FM-typeclass|textit} an FM-\textbf{typeclass}: +it is a typeclass whose instance values have type $P^{T}\rightarrow T$. +The functor $P$ is called the \index{structure functor of a typeclass}\index{typeclass!structure functor}\textbf{structure functor} of the typeclass. (The name \textsf{``}FM\textsf{''} refers to \textsf{``}functors\textsf{''} and \textsf{``}monads\textsf{''} and will be justified later.) @@ -5692,9 +5692,9 @@ \subsection{$FM$-typeclasses, their laws and structure\label{subsec:P-typeclasse \begin{lstlisting} final case class FMTypeclass[P[_]: Functor, A](methods: P[A] => A) \end{lstlisting} -The code allows us to declare any $FM$-typeclass. For example, the -\lstinline!Monoid! typeclass can be declared by first defining a -type constructor corresponding to the monoid\textsf{'}s structure functor ($P^{A}\triangleq\bbnum 1+A\times A$) +The code allows us to declare any FM-typeclass. For example, the \lstinline!Monoid! +typeclass can be declared by first defining a type constructor corresponding +to the monoid\textsf{'}s structure functor ($P^{A}\triangleq\bbnum 1+A\times A$) and then using that functor to define a type constructor for evidence values (\lstinline!PMonoid!): \begin{lstlisting} @@ -5715,7 +5715,7 @@ \subsection{$FM$-typeclasses, their laws and structure\label{subsec:P-typeclasse the additional type parameters. The laws of type constructor typeclasses are also more complicated because they often involve multiple type parameters and arbitrary functions. To simplify the presentation in -this section, we will only consider $FM$-typeclasses for simple types, +this section, we will only consider FM-typeclasses for simple types, such as \lstinline!Semigroup! or \lstinline!Monoid!. Implementing the \lstinline!Monoid! typeclass via a structure functor @@ -5723,15 +5723,14 @@ \subsection{$FM$-typeclasses, their laws and structure\label{subsec:P-typeclasse programming. But the form $P^{A}\rightarrow A$ is useful for reasoning about general properties of typeclasses. To illustrate that kind of reasoning, we will now show that the product-type, the function-type, -and the recursive-type constructions work for all $FM$-typeclasses. +and the recursive-type constructions work for all FM-typeclasses. \paragraph{Products} -Consider an arbitrary $FM$-typeclass \lstinline!TC! defined via -a structure functor \lstinline!P!. If two types $A$, $B$ have an -instance of the typeclass \lstinline!TC!, an instance for the product -type $A\times B$ can be derived automatically using the function -\lstinline!productTC!: +Consider an arbitrary FM-typeclass \lstinline!TC! defined via a structure +functor \lstinline!P!. If two types $A$, $B$ have an instance of +the typeclass \lstinline!TC!, an instance for the product type $A\times B$ +can be derived automatically using the function \lstinline!productTC!: \begin{lstlisting} def productTC[A, B](u: P[A] => A, v: P[B] => B): P[(A, B)] => (A, B) = { p => ( u(p.map(_._1)), v(p.map(_._2)) ) @@ -5745,12 +5744,12 @@ \subsection{$FM$-typeclasses, their laws and structure\label{subsec:P-typeclasse This argument does \emph{not} prove that the typeclass laws will also hold for $A\times B$. We will prove that in Section~\ref{subsec:Laws-for-the-P-typeclass-constructions} after developing some advanced techniques for formal reasoning about -$FM$-typeclass laws. +FM-typeclass laws. We note that the co-product construction does \emph{not} work for -arbitrary $FM$-typeclasses: given evidence values of types $P^{A}\rightarrow A$ +arbitrary FM-typeclasses: given evidence values of types $P^{A}\rightarrow A$ and $P^{B}\rightarrow B$, we cannot always find a suitable value -of type $P^{A+B}\rightarrow A+B$. Later we will see that some $FM$-typeclasses, +of type $P^{A+B}\rightarrow A+B$. Later we will see that some FM-typeclasses, such as monads or applicative functors, do not support the co-product construction. The co-product of two monads is not always a lawful monad; the co-product of two applicative functors is not always an @@ -5758,8 +5757,8 @@ \subsection{$FM$-typeclasses, their laws and structure\label{subsec:P-typeclasse \paragraph{Functions} -The function-type construction creates an $FM$-typeclass instance -for the type $E\rightarrow A$ if the type $A$ belongs to the $FM$-typeclass. +The function-type construction creates an FM-typeclass instance for +the type $E\rightarrow A$ if the type $A$ belongs to the FM-typeclass. Using the fact that $P$ is a functor, an evidence value of type $P^{E\rightarrow A}\rightarrow E\rightarrow A$ can be computed from an evidence value of type $P^{A}\rightarrow A$ like this: @@ -5774,9 +5773,9 @@ \subsection{$FM$-typeclasses, their laws and structure\label{subsec:P-typeclasse \paragraph{Recursive types} Consider a recursive type $T$ defined by a type equation $T\triangleq S^{T}$, -where the functor $S$ \textsf{``}preserves\textsf{''} $FM$-typeclass instances: -if $A$ has an instance then $S^{A}$ also does, as we saw in all -our examples in this chapter. In other words, we have a function $\text{tcS}:(P^{A}\rightarrow A)\rightarrow P^{S^{A}}\rightarrow S^{A}$ +where the functor $S$ \textsf{``}preserves\textsf{''} FM-typeclass instances: if +$A$ has an instance then $S^{A}$ also does, as we saw in all our +examples in this chapter. In other words, we have a function $\text{tcS}:(P^{A}\rightarrow A)\rightarrow P^{S^{A}}\rightarrow S^{A}$ that creates evidence values of type $P^{S^{A}}\rightarrow S^{A}$ out of evidence values of type $P^{A}\rightarrow A$. Then we define an evidence value \lstinline!tcT! for $T$ as: @@ -5802,7 +5801,7 @@ \subsection{$FM$-typeclasses, their laws and structure\label{subsec:P-typeclasse def tcS: TC[A] => TC[S[A]] = ... // Compute instances for S[A] given instances for A. def tcT: P[T] => T = p => T(tcS(tcT)(p.map(_.s))) // The recursive instance. \end{lstlisting} -In this way, the recursive-type construction works for any $FM$-typeclass. +In this way, the recursive-type construction works for any FM-typeclass. (We will prove in Section~\ref{subsec:Laws-for-the-P-typeclass-constructions} that the laws will hold automatically for the new typeclass instances.) @@ -5810,34 +5809,34 @@ \subsection{$FM$-typeclasses, their laws and structure\label{subsec:P-typeclasse their properties are more difficult to prove. This book shows that the product-type, the function-type, and the recursive-type constructions work for functors, contrafunctors, pointed functors, and pointed contrafunctors, -as well as for other important $FM$-typeclasses such as filterable -functors (Chapter~\ref{chap:Filterable-functors}), monads (Chapter~\ref{chap:Semimonads-and-monads}), +as well as for other important FM-typeclasses such as filterable functors +(Chapter~\ref{chap:Filterable-functors}), monads (Chapter~\ref{chap:Semimonads-and-monads}), and applicative functors (Chapter~\ref{chap:8-Applicative-functors,-contrafunctors}). We will see in Chapter~\ref{chap:Free-type-constructions} that another -general construction also works for all $FM$-typeclasses, \textemdash{} +general construction also works for all FM-typeclasses, \textemdash{} the \textsf{``}free\textsf{''} type construction. -Some typeclasses \emph{cannot} be viewed as $FM$-typeclasses. The -\lstinline!Extractor! typeclass (see Section~\ref{subsec:Extractors-typeclasses}) -has instances of type $A\rightarrow Z$, which is not of the form -$P^{A}\rightarrow A$ for any functor $P$. Another example is the -\lstinline!Copointed! typeclass whose method of type $\forall A.\,F^{A}\rightarrow A$ -is not of the form $P^{F}\rightarrow F$ even if we add more type -parameters. Instead, the evidence values of these typeclasses are -of type $F\rightarrow P^{F}$ with a suitable functor $P$. This type -signature can be obtained for \textsf{``}extractor\textsf{''} typeclasses, for \lstinline!Copointed! -functors, and also for \lstinline!Traversable! functors (Chapter~\ref{chap:9-Traversable-functors-and}). -We may call those typeclasses \textbf{co-}$P$\textbf{-typeclasses}.\index{co-$FM$-typeclasses} +Some typeclasses \emph{cannot} be viewed as FM-typeclasses. The \lstinline!Extractor! +typeclass (see Section~\ref{subsec:Extractors-typeclasses}) has +instances of type $A\rightarrow Z$, which is not of the form $P^{A}\rightarrow A$ +for any functor $P$. Another example is the \lstinline!Copointed! +typeclass whose method of type $\forall A.\,F^{A}\rightarrow A$ is +not of the form $P^{F}\rightarrow F$ even if we add more type parameters. +Instead, the evidence values of these typeclasses are of type $F\rightarrow P^{F}$ +with a suitable functor $P$. This type signature can be obtained +for \textsf{``}extractor\textsf{''} typeclasses, for \lstinline!Copointed! functors, +and also for \lstinline!Traversable! functors (Chapter~\ref{chap:9-Traversable-functors-and}). +We may call those typeclasses \textbf{co-}FM-\textbf{typeclasses}.\index{co-FM-typeclasses} For all typeclasses whose evidence values have type $A\rightarrow P^{A}$, some general properties will also hold. For example, the \emph{co-product} construction (rather than the product construction) works for them. Given evidence values of types $A\rightarrow P^{A}$ and $B\rightarrow P^{B}$, we can produce a value of type $A+B\rightarrow P^{A+B}$, i.e., an -$FM$-typeclass evidence for the co-product $A+B$. Similarly to $FM$-typeclasses, +FM-typeclass evidence for the co-product $A+B$. Similarly to FM-typeclasses, the typeclass laws will hold automatically for the type $A+B$. A -detailed description of co-$FM$-typeclasses is beyond the scope of -this book. +detailed description of co-FM-typeclasses is beyond the scope of this +book. An example of a typeclass to which neither description applies is the \lstinline!Eq! typeclass. Its evidence values have type $A\times A\rightarrow\bbnum 2$, @@ -6045,7 +6044,8 @@ \subsection{Typeclasses, object-oriented interfaces, and algebraic data types} We have achieved a description that presents ADTs as a special case of typeclasses whose method signature has the form $\text{Sig}^{T}=P^{T}\rightarrow T$. -(This book calls them \textsf{``}$FM$-typeclasses\textsf{''}.) +(This book calls them \textsf{``}FM-typeclasses\textsf{''} for reasons explained in +Chapter~\ref{chap:Free-type-constructions}.) Not all typeclasses have signatures of this form. For example, the equality typeclass (\lstinline!Eq!) has the method signature $\text{Sig}_{\text{Eq}}^{T}=T\times T\rightarrow\bbnum 2$, diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 5deea1f7c..431774c6d 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): 06f84cbe54050f946a065946dc8aeb9666c209cfa7387802ac0bec527a14cf64}\\ -{\scriptsize{}Git commit: f3a0fed9306fd4144774468ecf52a5b27ab1c6ca}\\ -{\scriptsize{}PDF file built on Tue, 27 Jan 2026 10:18:03 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 17c2d1f86e2aac0ebfc562b046554be4bd0d270d4bd9d16edc9dc95ec2e73dd0}\\ +{\scriptsize{}Git commit: b9344d8278e7a114d11bf5c806c7f7500517e323}\\ +{\scriptsize{}PDF file built on Tue, 27 Jan 2026 10:27:58 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, From 74dec559d379d1406b86ca2b1d1e394776a5c3e3 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Tue, 27 Jan 2026 10:34:39 +0100 Subject: [PATCH 38/42] wip --- sofp-src/lyx/sofp-typeclasses.lyx | 10 +++++----- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-typeclasses.tex | 15 +++++++-------- sofp-src/tex/sofp.tex | 6 +++--- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/sofp-src/lyx/sofp-typeclasses.lyx b/sofp-src/lyx/sofp-typeclasses.lyx index 7c65c3595..996499a73 100644 --- a/sofp-src/lyx/sofp-typeclasses.lyx +++ b/sofp-src/lyx/sofp-typeclasses.lyx @@ -37185,11 +37185,11 @@ def productTC[A, B](u: P[A] => A, v: P[B] => B): P[(A, B)] => (A, B) = { \end_layout \begin_layout Standard -This argument does +This argument does not prove that the typeclass \emph on -not +laws \emph default - prove that the typeclass laws will also hold for + will also hold for \begin_inset Formula $A\times B$ \end_inset @@ -37232,8 +37232,8 @@ not . Later we will see that some FM-typeclasses, such as monads or applicative functors, do not support the co-product construction. - The co-product of two monads is not always a monad; the co-product of - two applicative functors is not always an applicative functor. + The co-product of two monads is not always a monad; the co-product of two + applicative functors is not always an applicative functor. \end_layout \begin_layout Paragraph diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 98baabc3ea78afb42d52b1f0f6a039dd08605e76..943cfeea72984cff2211c75acb4d8bdc037c62a5 100644 GIT binary patch delta 136 zcmX?Ra?E7IMiEwHBP%1r$=gKCpsbG~Pk0jzjV(+JQ_OXZjm^_GKN96;Vlg%Xs`@A{ z2WD&*mbk{~||!*W@2LQW@hPRU}$3LV(4UHZfs!aYUJkXYG*@8#bj+MX#it# BBiR4| delta 136 zcmX?Ra?E7IMiEvcb1M^r$=gKCpsbG~Pk7TTladV5Oigr+jm=XxKN96;VlgrYs`@A{ z2WD&*mbk{~Waj2%ZtUh_;ACXrU} Date: Tue, 27 Jan 2026 10:44:27 +0100 Subject: [PATCH 39/42] wip --- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-typeclasses.tex | 4 ++-- sofp-src/tex/sofp.tex | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 943cfeea72984cff2211c75acb4d8bdc037c62a5..4d18b587c4457b616dcbb60120a5d6128cf03220 100644 GIT binary patch delta 123 zcmX?Ra?E7ICJ|;6E7QqaMJ&Md2a%^7X^Dvj<_0Mio9~JWGBKH$PW~XS0HihxNnB@i tGIcgEaW*zEa&j`TbaQsKG%+(ZFfufDH8C+Za5iu;wzDCmVzRcBGyvfdAmji5 delta 123 zcmX?Ra?E7ICJ|;ME2GI Date: Sun, 8 Feb 2026 17:37:09 +0100 Subject: [PATCH 40/42] add concatenating zip --- sofp-src/lyx/sofp-applicative.lyx | 368 ++++++++++++++++++------- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-applicative.tex | 68 +++-- sofp-src/tex/sofp-back-cover-no-bg.tex | 4 +- sofp-src/tex/sofp.tex | 10 +- 5 files changed, 314 insertions(+), 136 deletions(-) diff --git a/sofp-src/lyx/sofp-applicative.lyx b/sofp-src/lyx/sofp-applicative.lyx index 928441cac..781aff4e8 100644 --- a/sofp-src/lyx/sofp-applicative.lyx +++ b/sofp-src/lyx/sofp-applicative.lyx @@ -22840,7 +22840,7 @@ wu \end_inset - does not lead to practical disadvantages when working with finite lists. + does not lead to practical disadvantages when working with lists. (To make the eager \begin_inset listings inline true @@ -22853,7 +22853,7 @@ List \end_inset - a lawful applicative functor, one can define a + a lawful applicative functor, one can use a \begin_inset Quotes eld \end_inset @@ -22879,20 +22879,10 @@ status open \begin_layout Plain Layout padding -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - +\family typewriter zip \end_layout -\end_inset - - -\end_layout - \end_inset as shown in Exercise @@ -33322,16 +33312,16 @@ functorial the typeclass via the following steps: \end_layout -\begin_layout Enumerate -Define each category's composition operation and identity morphism. +\begin_layout Standard +1) Define each category's composition operation and identity morphism. \end_layout -\begin_layout Enumerate -Verify that the category laws hold. +\begin_layout Standard +2) Verify that the category laws hold. \end_layout -\begin_layout Enumerate -Write the type signature of the +\begin_layout Standard +3) Write the type signature of the \begin_inset Quotes eld \end_inset @@ -33342,8 +33332,8 @@ lifting method corresponding to the functor. \end_layout -\begin_layout Enumerate -Impose the naturality laws and the functor laws on the +\begin_layout Standard +4) Impose the naturality laws and the functor laws on the \begin_inset Quotes eld \end_inset @@ -33354,8 +33344,8 @@ lifting method. \end_layout -\begin_layout Enumerate -Derive other typeclass methods (and their laws) from the +\begin_layout Standard +5) Derive other typeclass methods (and their laws) from the \begin_inset Quotes eld \end_inset @@ -33367,76 +33357,12 @@ lifting \end_layout \begin_layout Standard -Let us go through this pattern for the applicative functor typeclass studied - in this chapter. - Following the functorial pattern, we say that a covariant type constructor - -\begin_inset Formula $F$ -\end_inset - - is applicative if there exists a (categorical) functor between the -\begin_inset Formula $F$ -\end_inset - --ap and -\begin_inset Formula $F$ -\end_inset - --lifted categories. - The morphisms of the -\begin_inset Formula $F$ -\end_inset - --ap category are values of type -\begin_inset Formula $F^{A\rightarrow B}$ -\end_inset - -; the morphisms of the -\begin_inset Formula $F$ -\end_inset - --lifted category are values of type -\begin_inset Formula $F^{A}\rightarrow F^{B}$ -\end_inset - -. - This is all we need to start with. - All other properties of applicative functors are then derived in a systematic - way. - With this approach, we do not need to memorize the complicated type signatures - and laws of the methods -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -map2 -\end_layout - -\end_inset - - and -\begin_inset listings -inline true -status open - -\begin_layout Plain Layout - -ap -\end_layout - -\end_inset - -. -\end_layout - -\begin_layout Standard -The first step is to define the +Let us go through this pattern for the applicative functor typeclass. + The first step is to define the \begin_inset Formula $F$ \end_inset --ap category's morphisms. +-ap category. We define identity morphisms ( \begin_inset listings inline true @@ -33621,9 +33547,36 @@ noprefix "false" \end_layout \begin_layout Standard -In this way, we derive the applicative typeclass by following the functorial +In this way, we rediscover the applicative typeclass by following the functorial typeclass pattern. - + All other properties of applicative functors are derived in a systematic + way. + With this approach, we do not need to memorize the complicated type signatures + and laws of the methods +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +map2 +\end_layout + +\end_inset + + and +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +ap +\end_layout + +\end_inset + +. \end_layout \begin_layout Standard @@ -33804,6 +33757,123 @@ status open \begin_layout Plain Layout padding +\family typewriter +zip +\end_layout + +\end_inset + + for lists such that the shorter list is padded with its +\emph on +last +\emph default + value until its length is equal to that of the longer list. + Zipping with an empty list returns again an empty list. + A sample test: +\begin_inset listings +inline false +status open + +\begin_layout Plain Layout + +def paddingZip[A, B](left: List[A], right: List[B]): List[(A, B)] = ??? +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\begin_layout Plain Layout + +scala> paddingZip(List(1, 2), List( +\begin_inset Quotes eld +\end_inset + +a +\begin_inset Quotes erd +\end_inset + +, +\begin_inset Quotes eld +\end_inset + +b +\begin_inset Quotes erd +\end_inset + +, +\begin_inset Quotes eld +\end_inset + +c +\begin_inset Quotes erd +\end_inset + +, +\begin_inset Quotes eld +\end_inset + +d +\begin_inset Quotes erd +\end_inset + +)) +\end_layout + +\begin_layout Plain Layout + +res0: List[(Int, String)] = List((1, +\begin_inset Quotes eld +\end_inset + +a +\begin_inset Quotes erd +\end_inset + +), (2, +\begin_inset Quotes eld +\end_inset + +b +\begin_inset Quotes erd +\end_inset + +), (2, +\begin_inset Quotes eld +\end_inset + +c +\begin_inset Quotes erd +\end_inset + +), (2, +\begin_inset Quotes eld +\end_inset + +d +\begin_inset Quotes erd +\end_inset + +)) +\end_layout + +\begin_layout Plain Layout + +\end_layout + +\begin_layout Plain Layout + +scala> paddingZip(List(), List(1, 2, 3)) +\end_layout + +\begin_layout Plain Layout + +res1: List[(Unit, Int)] = List() +\end_layout + +\end_inset + +Prove that the laws of \begin_inset listings inline true status open @@ -33815,16 +33885,91 @@ zip \end_inset + hold for +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout +paddingZip \end_layout \end_inset - for lists such that the shorter list is padded with the -\emph on -last -\emph default - value until its length is equal to that of the longer list. + with a suitable +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +wu +\end_layout + +\end_inset + +. +\end_layout + +\begin_layout Subsubsection +Exercise +\begin_inset CommandInset label +LatexCommand label +name "subsec:Exercise-applicative-I-concatenating-zip" + +\end_inset + + +\begin_inset CommandInset ref +LatexCommand ref +reference "subsec:Exercise-applicative-I-concatenating-zip" +plural "false" +caps "false" +noprefix "false" + +\end_inset + + +\end_layout + +\begin_layout Standard +Implement a +\begin_inset Quotes eld +\end_inset + +concatenating +\begin_inset Quotes erd +\end_inset + + +\begin_inset listings +inline true +status open + +\begin_layout Plain Layout + +zip +\end_layout + +\end_inset + + method +\begin_inset Index idx +status open + +\begin_layout Plain Layout +concatenating +\family typewriter +zip +\end_layout + +\end_inset + + for lists. + The first value in the first list is repeated until the second list is + finished; then the last value in the second list is repeated until the + first list is finished. Zipping with an empty list returns again an empty list. A sample test: \begin_inset listings @@ -33833,7 +33978,8 @@ status open \begin_layout Plain Layout -def paddingZip[A, B](left: List[A], right: List[B]): List[(A, B)] = ??? +def concatenatingZip[A, B](left: List[A], right: List[B]): List[(A, B)] + = ??? \end_layout \begin_layout Plain Layout @@ -33842,7 +33988,7 @@ def paddingZip[A, B](left: List[A], right: List[B]): List[(A, B)] = ??? \begin_layout Plain Layout -scala> paddingZip(List(1, 2), List( +scala> concatenatingZip(List(1, 2, 3), List( \begin_inset Quotes eld \end_inset @@ -33887,7 +34033,7 @@ a \begin_inset Quotes erd \end_inset -), (2, +), (1, \begin_inset Quotes eld \end_inset @@ -33895,7 +34041,7 @@ b \begin_inset Quotes erd \end_inset -), (2, +), (1, \begin_inset Quotes eld \end_inset @@ -33903,6 +34049,14 @@ c \begin_inset Quotes erd \end_inset +), (1, +\begin_inset Quotes eld +\end_inset + +d +\begin_inset Quotes erd +\end_inset + ), (2, \begin_inset Quotes eld \end_inset @@ -33911,6 +34065,14 @@ d \begin_inset Quotes erd \end_inset +), (3, +\begin_inset Quotes eld +\end_inset + +d +\begin_inset Quotes erd +\end_inset + )) \end_layout @@ -33920,7 +34082,7 @@ d \begin_layout Plain Layout -scala> paddingZip(List(), List(1, 2, 3)) +scala> concatenatingZip(List(), List(1, 2, 3)) \end_layout \begin_layout Plain Layout @@ -33949,7 +34111,7 @@ status open \begin_layout Plain Layout -paddingZip +concatenatingZip \end_layout \end_inset diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index 4d18b587c4457b616dcbb60120a5d6128cf03220..f5a72212126c4ac275fdce359548fb78ff871748 100644 GIT binary patch delta 162 zcmX?Ra?E7IN)cWoT?2~{Lvt%*V=H5`$=gKq&_q6pJmEDrH!(0xOfk_lPBF6B{796I ziPOly!qD8<7^vl=xFmwNSy8nkO5TfYGC5#YU=1@;%aJU MXG2KEWNj&F0Nm*))Bpeg delta 162 zcmX?Ra?E7IN)cW|T_f`lLjx;g6Dw20$=gKq&_q6pJmF1COf)bzNU_j0Ha1V&{796I ziPO-?+|a<-1gPbsxFmwNSy concatenatingZip(List(1, 2, 3), List("a", "b", "c", "d")) +res0: List[(Int, String)] = List((1, "a"), (1, "b"), (1, "c"), (1, "d"), (2, "d"), (3, "d")) + +scala> concatenatingZip(List(), List(1, 2, 3)) +res1: List[(Unit, Int)] = List() +\end{lstlisting} +Prove that the laws of \lstinline!zip! hold for \lstinline!concatenatingZip! +with a suitable \lstinline!wu!. + \subsubsection{Exercise \label{subsec:Exercise-applicative-II-4}\ref{subsec:Exercise-applicative-II-4}} Show that $F^{A}\triangleq G^{A}+H^{G^{A}}$ is a lawful applicative diff --git a/sofp-src/tex/sofp-back-cover-no-bg.tex b/sofp-src/tex/sofp-back-cover-no-bg.tex index 8617496c3..11a826bc5 100644 --- a/sofp-src/tex/sofp-back-cover-no-bg.tex +++ b/sofp-src/tex/sofp-back-cover-no-bg.tex @@ -25,10 +25,10 @@ practical applications of parametricity. Long and difficult, yet boring explanations are logically -developed in excruciating detail through 1994 +developed in excruciating detail through 1995 Scala code snippets, 233 statements with step-by-step derivations, 105 diagrams, 239 examples -with tested Scala code, and 316 exercises. Discussions +with tested Scala code, and 317 exercises. Discussions build upon each chapter\textsf{'}s material further. Beginners in FP will find tutorials about the \texttt{map}/\texttt{reduce} diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index 9427fdca7..acffb9597 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): 6e8ce3da8d1012e0e175dfcdec9a2069ab658e9bbf6c47cf91f1c462d43df767}\\ -{\scriptsize{}Git commit: 74dec559d379d1406b86ca2b1d1e394776a5c3e3}\\ -{\scriptsize{}PDF file built on Tue, 27 Jan 2026 10:35:09 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 103898b8a435daa8867c15db77d94d2f8cda6345ea6776619d4ef90a055760ae}\\ +{\scriptsize{}Git commit: 54bb395336ce11620b4a9e87633442d25e92fd1f}\\ +{\scriptsize{}PDF file built on Sun, 08 Feb 2026 17:33:54 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, @@ -374,10 +374,10 @@ practical applications of parametricity.}\\ {\scriptsize{}}\\ {\scriptsize{}Long and difficult, yet boring explanations are logically -developed in excruciating detail through 1994 Scala +developed in excruciating detail through 1995 Scala code snippets, 233 statements with step-by-step derivations, 105 diagrams, 239 examples with tested Scala -code, and 316 exercises. Discussions build upon each +code, and 317 exercises. Discussions build upon each chapter's material further.}\\ {\scriptsize{}}\\ {\scriptsize{}Beginners in FP will find tutorials about the map/reduce From 82fa9245aeb24d3691be02c59e3f0fd0ac1f8bd7 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Mon, 9 Mar 2026 20:48:29 +0100 Subject: [PATCH 41/42] wip --- sofp-src/lyx/sofp-applicative.lyx | 2 +- sofp-src/lyx/sofp-typeclasses.lyx | 14 +++----------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/sofp-src/lyx/sofp-applicative.lyx b/sofp-src/lyx/sofp-applicative.lyx index 781aff4e8..b9f5d66d5 100644 --- a/sofp-src/lyx/sofp-applicative.lyx +++ b/sofp-src/lyx/sofp-applicative.lyx @@ -22841,7 +22841,7 @@ wu \end_inset does not lead to practical disadvantages when working with lists. - (To make the eager + (To make \begin_inset listings inline true status open diff --git a/sofp-src/lyx/sofp-typeclasses.lyx b/sofp-src/lyx/sofp-typeclasses.lyx index 996499a73..1b123d04e 100644 --- a/sofp-src/lyx/sofp-typeclasses.lyx +++ b/sofp-src/lyx/sofp-typeclasses.lyx @@ -36847,23 +36847,15 @@ FM \begin_inset Quotes erd \end_inset - refers to + stands for \begin_inset Quotes eld \end_inset -functors -\begin_inset Quotes erd -\end_inset - - and -\begin_inset Quotes eld -\end_inset - -monads +functor/monad \begin_inset Quotes erd \end_inset - and will be justified later.) + and will be justified later.) \end_layout \begin_layout Standard From 01885a59d515b3a2bda2f1cf129c443440ab4a01 Mon Sep 17 00:00:00 2001 From: Sergei Winitzki Date: Wed, 11 Mar 2026 20:32:09 +0100 Subject: [PATCH 42/42] wip --- sofp-src/lyx/sofp-typeclasses.lyx | 4 ++-- sofp-src/tex/chapter3-picture.pdf | Bin 6726 -> 6726 bytes sofp-src/tex/sofp-applicative.tex | 8 ++++---- sofp-src/tex/sofp-typeclasses.tex | 14 +++++++------- sofp-src/tex/sofp.tex | 6 +++--- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sofp-src/lyx/sofp-typeclasses.lyx b/sofp-src/lyx/sofp-typeclasses.lyx index 1b123d04e..bad2d7bb9 100644 --- a/sofp-src/lyx/sofp-typeclasses.lyx +++ b/sofp-src/lyx/sofp-typeclasses.lyx @@ -36855,7 +36855,7 @@ functor/monad \begin_inset Quotes erd \end_inset - and will be justified later.) + and will be justified later.) \end_layout \begin_layout Standard @@ -37060,7 +37060,7 @@ Monoid \begin_inset Formula $P$ \end_inset - and a function + and a function of type \begin_inset Formula $P^{A}\rightarrow A$ \end_inset diff --git a/sofp-src/tex/chapter3-picture.pdf b/sofp-src/tex/chapter3-picture.pdf index f5a72212126c4ac275fdce359548fb78ff871748..84c33229d6221674d7ca6ca38076e3a50e00a4ab 100644 GIT binary patch delta 158 zcmX?Ra?E7IN)aAoT|>hVBLgc#3oDb!TSfFy1wM#8OHCkr!EHw$x9OCwVwM^`svXEQ?spqP_|lZ%s)i;<(T Moed!sleML!0d|`xw*UYD delta 158 zcmX?Ra?E7IN)a9-T?2~{Lvt%*V=LpyTSfFy1wM#8OHCo?w#OLId@BV$WLBS#A$1E|*3z{Jhf)X~Yr)zr++ LhLDQM+EUU0MVlx1 diff --git a/sofp-src/tex/sofp-applicative.tex b/sofp-src/tex/sofp-applicative.tex index 280572455..ab99b411a 100644 --- a/sofp-src/tex/sofp-applicative.tex +++ b/sofp-src/tex/sofp-applicative.tex @@ -3338,10 +3338,10 @@ \subsubsection{Statement \label{subsec:Statement-applicative-recursive-type-1}\r functor if the standard definition of \lstinline!zip! is used. Nevertheless, the associativity and the commutativity laws hold for \lstinline!zip!. The absence of a well-defined value \lstinline!wu! does not lead -to practical disadvantages when working with finite lists. (To make -the eager \lstinline!List! a lawful applicative functor, one can -define a \textsf{``}padding\textsf{''} version of \lstinline!zip!\index{padding zip@padding \texttt{zip}} -as shown in Exercise~\ref{subsec:Exercise-applicative-I-1-1-1}.) +to practical disadvantages when working with lists. (To make \lstinline!List! +a lawful applicative functor, one can use a \textsf{``}padding\textsf{''} version +of \lstinline!zip!\index{padding zip@padding \texttt{zip}} as shown +in Exercise~\ref{subsec:Exercise-applicative-I-1-1-1}.) For certain choices of $F$, $G$, and $H$, the functor $L$ will be a monad. It is important that the implementation of applicative diff --git a/sofp-src/tex/sofp-typeclasses.tex b/sofp-src/tex/sofp-typeclasses.tex index 81949c77b..7ce34c2c9 100644 --- a/sofp-src/tex/sofp-typeclasses.tex +++ b/sofp-src/tex/sofp-typeclasses.tex @@ -5685,8 +5685,8 @@ \subsection{FM-typeclasses, their laws and structure\label{subsec:P-typeclasses} This motivates the definition of \index{FM-typeclass|textit} an FM-\textbf{typeclass}: it is a typeclass whose instance values have type $P^{T}\rightarrow T$. The functor $P$ is called the \index{structure functor of a typeclass}\index{typeclass!structure functor}\textbf{structure -functor} of the typeclass. (The name \textsf{``}FM\textsf{''} refers to \textsf{``}functors\textsf{''} -and \textsf{``}monads\textsf{''} and will be justified later.) +functor} of the typeclass. (The name \textsf{``}FM\textsf{''} stands for \textsf{``}functor/monad\textsf{''} +and will be justified later.) We can implement this definition by the Scala code: \begin{lstlisting} @@ -5719,11 +5719,11 @@ \subsection{FM-typeclasses, their laws and structure\label{subsec:P-typeclasses} such as \lstinline!Semigroup! or \lstinline!Monoid!. Implementing the \lstinline!Monoid! typeclass via a structure functor -$P$ and a function $P^{A}\rightarrow A$ is inconvenient for practical -programming. But the form $P^{A}\rightarrow A$ is useful for reasoning -about general properties of typeclasses. To illustrate that kind of -reasoning, we will now show that the product-type, the function-type, -and the recursive-type constructions work for all FM-typeclasses. +$P$ and a function of type $P^{A}\rightarrow A$ is inconvenient +for practical programming. But the form $P^{A}\rightarrow A$ is useful +for reasoning about general properties of typeclasses. To illustrate +that kind of reasoning, we will now show that the product-type, the +function-type, and the recursive-type constructions work for all FM-typeclasses. \paragraph{Products} diff --git a/sofp-src/tex/sofp.tex b/sofp-src/tex/sofp.tex index acffb9597..e8c319dc8 100644 --- a/sofp-src/tex/sofp.tex +++ b/sofp-src/tex/sofp.tex @@ -337,9 +337,9 @@ {\footnotesize{}ISBN (e-book): 978-0-359-76877-6}\\ {\footnotesize{}ISBN: 978-0-359-76877-6}\\ \\ -{\scriptsize{}Source hash (sha256): 103898b8a435daa8867c15db77d94d2f8cda6345ea6776619d4ef90a055760ae}\\ -{\scriptsize{}Git commit: 54bb395336ce11620b4a9e87633442d25e92fd1f}\\ -{\scriptsize{}PDF file built on Sun, 08 Feb 2026 17:33:54 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ +{\scriptsize{}Source hash (sha256): 074268751cedd672514d12d5d68008085291fe321ffd10453d933dc8ede7c0df}\\ +{\scriptsize{}Git commit: 82fa9245aeb24d3691be02c59e3f0fd0ac1f8bd7}\\ +{\scriptsize{}PDF file built on Wed, 11 Mar 2026 20:19:05 +0100 by pdfTeX 3.141592653-2.6-1.40.22 (TeX Live 2021) on Darwin}\\ ~\\ {\scriptsize{}Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License,