optics-core-0.4.1.1/0000755000000000000000000000000007346545000012273 5ustar0000000000000000optics-core-0.4.1.1/CHANGELOG.md0000644000000000000000000001053407346545000014107 0ustar0000000000000000# optics-core-0.4.1.1 (2023-06-22) * Add INLINE pragmas to small functions that really should inline # optics-core-0.4.1 (2022-03-22) * Add support for GHC-9.2 * Add `is` ([#410](https://github.com/well-typed/optics/pull/410)) * Improve error messages related to the `JoinKinds` class ([#439](https://github.com/well-typed/optics/pull/439)) * Port `universeOf`, `cosmosOf`, `paraOf`, `rewriteOf`, `transformOf`, `rewriteMOf` and `transformMOf` from `Control.Lens.Plated` ([#379](https://github.com/well-typed/optics/pull/379)) * Add `(%?)` composition operator ([#434](https://github.com/well-typed/optics/pull/434)) # optics-core-0.4 (2021-02-22) * See [migration-guide-0.4.md](https://github.com/well-typed/optics/blob/master/migration-guide-0.4.md) for more details * Add support for GHC-9.0 * Drop support for GHC-8.0 * The `FunctorWithIndex`, `FoldableWithIndex` and `TraversableWithIndex` type classes have been migrated to a new package, [`indexed-traversable`](https://hackage.haskell.org/package/indexed-traversable) ([#370](https://github.com/well-typed/optics/pull/370)) * Add `adjoin`, `iadjoin` and `both` to `Optics.[Ix]Traversal` ([#332](https://github.com/well-typed/optics/pull/332), [#372](https://github.com/well-typed/optics/pull/372)) * Add `ifst` and `isnd` to `Optics.IxLens` ([#389](https://github.com/well-typed/optics/pull/389)) * Generalize types of `generic` ([#376](https://github.com/well-typed/optics/pull/376)) * Make `chosen` an indexed lens to see which value is traversed ([#335](https://github.com/well-typed/optics/pull/335)) * Remove `GeneralLabelOptic` extensibility mechanism ([#361](https://github.com/well-typed/optics/pull/361)) * Add `gfield`, `gafield`, `gconstructor`, `gposition` and `gplate` for generics-based data access ([#358](https://github.com/well-typed/optics/pull/358), [#361](https://github.com/well-typed/optics/pull/361)) * Add support for generics-based field lenses and constructor prisms (`gfield` and `gconstructor`) to `LabelOptic` so they can be used via `OverloadedLabels` ([#361](https://github.com/well-typed/optics/pull/361)) * Remove unnecessary INLINE pragmas to reduce compile times ([#394](https://github.com/well-typed/optics/pull/394)) * Simplify the type of `(%)` using new `JoinKinds` and `AppendIndices` classes in place of the `Join` and `Append` type families ([#397](https://github.com/well-typed/optics/pull/397), [#399](https://github.com/well-typed/optics/pull/399)) # optics-core-0.3.0.1 (2020-08-05) * Add INLINE pragmas to `atraverseOf_`, `iaTraverseOf_` and `ignored` * Improve error message in catch-all `GeneralLabelOptic` instance * Make GHC optimize away profunctor type classes when profiling is enabled * Improve documentation of `Optics.Label`: - Add guide on how to effectively use labels as optics - Restructure existing sections # optics-core-0.3 (2020-04-15) * GHC-8.10 support * Add `filteredBy` and `unsafeFilteredBy` * Add `FunctorWithIndex`, `FoldableWithIndex` and `TraversableWithIndex` instances for `Const` and `Constant` * Add `afoldVL` and `iafoldVL` constructors * Rename `toAtraversalVL` to `atraverseOf`, and `toIxAtraversalVL` to `iatraverseOf` * Generalise `element` and `elementOf` to construct `IxAffineTraversal`s instead of `IxTraversal`s * Change `mapping` to work on optic kinds other than `Iso`: it now supports `Lens` and `Prism` degenerating to `Getter` and `Review` respectively * Generalise `ignored` to be an `IxAffineTraversal` instead of an `IxTraversal` * Add `singular` and `isingular` * Add `(^?!)` operator * Expose `Curry` and `CurryCompose` * Show expected elimination forms on optic kind mismatch * Use stricter `uncurry'` for better performance * Add hidden `LabelOptic` instance to postpone instance resolution * Add `GeneralLabelOptic` for pluggable generic optics as labels * Document monoidal structures of `Fold`s * Remove proxy argument from `implies` * Add `itoList` # optics-core-0.2 (2019-10-18) * Add `non`, `non'` and `anon` to `Optics.Iso` * `ix` can produce optic kinds other than `AffineTraversal` * Generalise type of `generic1` * Move some internal definitions out to new `indexed-profunctors` package * Introduce `OpticKind` and `IxList` type synonyms for better type inference * Make `itraverse` for `Seq` faster for `containers >= 0.6.0` * Assorted documentation improvements # optics-core-0.1 (2019-09-02) * Initial release optics-core-0.4.1.1/LICENSE0000644000000000000000000001071607346545000013305 0ustar0000000000000000Copyright (c) 2017-2019, Well-Typed LLP All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Well-Typed LLP nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software incorporates code from the lens package (available from https://hackage.haskell.org/package/lens) under the following license: Copyright 2012-2016 Edward Kmett All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software incorporates code from the profunctors package (available from https://hackage.haskell.org/package/profunctors) under the following license: Copyright 2011-2015 Edward Kmett All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the author nor the names of his contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. optics-core-0.4.1.1/Setup.hs0000644000000000000000000000007507346545000013731 0ustar0000000000000000import Distribution.Simple main :: IO () main = defaultMain optics-core-0.4.1.1/diagrams/0000755000000000000000000000000007346545000014062 5ustar0000000000000000optics-core-0.4.1.1/diagrams/AffineFold.png0000644000000000000000000007361707346545000016603 0ustar0000000000000000PNG  IHDR'dsBIT|d pHYs&:4tEXtSoftwarewww.inkscape.org<w IDATxKToqMPi; P t)R .B6Ph(nnfy+-+xIP|}_p9c ~9g8>D(/ߣG+K3;;ky-.pQavkkLMM^cy gĄ/>}2͛7^jMtt2gϞ5gu7o<Ծ/]dN:e}mii1u?7_UtL:UzyR-..S瓃ccccĘ&))ܽ{˗/nmbccs>*j8pM|5tW|>yywT?yO۪lIIImMWWס}Ѷ>@cccxYWWڏ7èqhgsssml0vvvLbb~zDk<=2###~;:R(w&{O s Çu;Q_@Jn$l MQV'.JmpLaLV/ܫ;ZݽgR- V@póU q"f{;YAU}!jSg\CAy|;[EVH0T]U׆Ir!SVGK߫pIRL뼽:WEWiѱ@ J0pTtޚsŐmF+(<޶=644*u9{@= yDUZ]E7Sj$9ꦡTqìΝ;{{E'Oܐ0{p=}{GF zflu,̚L \7e\ǎ&q8J~YHGQi[n짼ܮӏLJqtt),, 9 ~W⎎=U-7A\W;N꽡Z(j{FB^U|{i{ܶ2쥉~w qlqQ(h'Xv"6V [ `E  X#AQQÒD|IQ~s8{wV~`Pggev7ϩ15Zj1k?, 낭z ?P)vj z^BFU޶TOj?>51NU lPz1ZDz=O>ykUJ:F]]ׅo2ΩL5dGU5!ZA_Q]xu]=ٵDW]8Ak+W׿{S}omm^RU}pgggҶ6@Fz]TTdm5 wOO[S%o6*j uVaThZ#MW~FkZ+)u\e5X-?K+`+* WHmIs?SߋࠝGWᴼ܎֬OM ]kllOK$ݻw6,k$) z`uݞ#}T?@悯B֍nu :S]EX(h4jyxooТ@Bת{@ϟ>A877477A|`߿s/#nïJoJ$wqqPKROWWWD@t߿O ZԺvww Bh:UyLqq~2|X f2 ʣA\0WWWB6z`ox׌2d/PYY)^^^zښ ~3F_[}5%WX`W ކV@E&:991Ғm>>>dZ ?W֔[aßj;::Laa @_dZt%ZjEkMi¢^۫D >T/^_1^(,^(pҡQЊPp Z%D%Q%"HDɻL93kW'y'HT{O6 ???oW+++X/ `ĝ٧?{h8w0|I&XQM e`a `$'ۏKrX\\\U,×0|X;;;}y _𭋫'''`dk, 1"uttTK6Xޖ&uzz<K6X`$'[ ` / ×l0| _&@A %9, ~ _ `-// `d)e:65??_ _22|0|X/uqO~8P _22|핹&P _22|'XkkkX/YuX???#X/ɵX/E$ѫ61, _&`\<{O _F0|In8?&K21x,e2Z7%,×:,× eR'`K?0|*5 `Ek}}] %+,×6PC _G@6X/uX/ `Խ `# 3,×~22|G 0|!9,×rvv&K]c g΄ǻvE'CŏP …)9un辰1~ӗ;fvȂжaCh],>{?=|ʕo6_7o{ݻA}}fn{gOzuH_]&GG?ǎǘС۷twm޽qq#~BwwYiSxv7/˗/˾{Πŋ!N159z ˗-[ʺO4[ڳgzz͛Cѣs7/kի qDxǏuŊ|EC*p|}||yR¢̲!Ĺxz>_"y\_^5[kC*}?H-[[g~FǖHw׮\{75!W={SEQT*2q p_< ߸U?1- ^"*?7G~y[NǶ2sLڵ\)]ļ\2ƍdl߽| 9'O%!ܶ-v֦%t9SZ*%8-[\ĸ+?ܽ+U4!̟k0H{6O80{^x( _EQ&_Z}1VwwpZp9tDdMLrLY8"L-Q2lT-D&"QuU\bM̛'B0%9Lrꔌg(Fﯦ&1߻ukmْliطo$7KQEQT*K+׊T*%N1E,Ȳi_r,AT MQQI&1Ж~p &֍ϲ@80^ih/ +}t↿"B;]B0q>z$!ܾ &>8tLz?-(1ô`.^(WQ_ﭯ8DA#tK,//lH$B"Jl KD'ˈQ-xXރ:Ÿdžoӎ1drsj]9эضgLE,iO 'ҢP]~I_$!x"3"kͧC[*ٹ\XIF$7k׬ ;5,0z9c;wJU8b{1X<_0-] j\JIQEQT*+6`N+MW2-na[WZ7l:UW26_Ҧ'L,#tl7ن*[h[f2nlCpW@s¼ "p>ݏ }FmR G"ȅ-;7"(c0qǏ%\zpbtqjx1NqsGk|9|LfFŊ '眍u^EQE(X/ĸ0d+Dυ!mrO"wyN!\We[(_,+ _ 66钅+ HXDlK//K,xFt jL&HTgtu0i<>/9}핢E3Rq's{BYgOOOSo8)Q$GY'޾lZ{Dq4Ɂ-_7W֯J|ۛ&3EH#4[H鯋0.:/ R7kHòS!ۮ@,|^8вؕ+Af̭-?X>MM\((SQ{iBOkν?Z3o0cϟ݉kƾyi?~qyMY~o\~={RQ-|:Fڹ{Uf{#DaΐFIΑ>sf/{.cp|eKonݚ &lڇ&}L~\P~o]b~oރ@_<بLݞU;}ЫCHrJ)ӼKW9K$5ݿݻ1;[XH(v|yd """ _fMnjl%P 'JRA$ьg!o2# lr$X<~I g~ϴH{ \TL2xճreplb"#wRr\'nܘ7xսlYȡ>|s)&)alȭb LыCn_>u*Tl~?:ݯlZ.! iyf\ӧᚴ y152 K0҈q|7sScr*ه] EqnZd^(J#SWS~/ű8Oa`㤭 wX-'ywreaCڨ|<!ɓM)WZ8 =£\}掜=YQ؊I$B!.GII9}󵰱o $._|LXBGXS]#ׅ7ϘrO[|ɝq(|E"ǒp_D\t1sWlN!7"TY+UrmLK,̹̅ΑN_M3iK^o\gҀua՟7l(a _WDCи 5;H&w2EpgEDȸibkȟET@3^sK.b8q6_d͹\u1tz ՈN CϽU#G^pK~Q,*K+a֬>{SĉUrmjű(|EDD[mM;5DDDD+""hջٞ""" _WDDDDDDD+""""""(|EappsNu޽jիWjrr>YWDDDD"X}au]ݽ{7l0~X}}}>133_n*S!<2{Req,!" IlцZs2 Bc[Pa,ӡI1? p=\(Q,+>8p{swqGqVWWC]]]" |2>}:\t)ܺu+ܻw/0;;I"/@Q"n㵽o߾ ^r3*^yp555gtw{ƳO> |&E7~>78~miiwͭUUUkkkwoSSS cׯ4/q.ŋÇamm͝e<۷Bߓ'OFoŋS>|0(+SSSi +^PZs. Ǐ۷o1KWJ'O W^ ?~ |r/CGϟÇ?.̱.,,]Ǐ088^ߟ/@Fbχׯ_b_ݿ?ܸq#\~=\v-o|qݽ{7grr21/;77$0ȕ,oyX kBmVZ/@f `!|3Ȝ,oe ` |2g [7o@·<X_$f `!|f 0- sk e? _BV&`]r%466K ` |2c [p4ǰ@d<{Oŷ=:uTz; XWW:ۛ^  3/@d2Z__w |rbKR6X_\eoX]]]92%| s/@d.^lKR^4ȕ,Ke ` |p2%|w޹S>/{`'@d<Xwq[QƟ5 Kt Z P%)4*CG$yWĞmϬ}>i`'eRN^,k<;;X'''X/XX/UJCաZZZ0|(cl4X/m`T@J'f͇ݝC0|$...X _  ",×rؘ @&e^X</V ` @`t&`K9X/ ` `DiX/} `0|Ft5`mm-X ,×Rkee%VWW _2|)0XD#eRN0|: _k `9h _:0|2|iC  8,×r _2|)'&&& _z||2|`jlzzZ  ",× _*`|KYC0| _Qg`w `S, `w `///?vww @4U` e/T5e7 `Xoz*,× @pXӓ (X###X/E+~ _ @}驖A  *X)e¯ _KO{# _J _2|j)599)U _A̦M _Ikԡ/Df `O\^^߫+[l6/,|CI㗗j+XCCC֖`P=ͬVe0|ZW _0|wv!Q|a7+.1/. 0DBńL05TPʋJ"J" O4H"K>#KPx쮳V93sάy_ !B! _B!B!—BM344*B!PBWQ>}jg_. r9}=zT޾}nݺ%))))ĉ{W-^*++ennUUU%r5! _B!-222N,$?~P!h]]]~ ^c]bbU JHQQ:uǎ=s͛eڵO^<\._ƮB!— >|X|IM }}}͝;w, }DDDHYYZJݻg?ܸqjzlڴIFFF CxN: qAg{zzڽ5m VPDPʒ\urD-DŋUQ.#b]ػ֪ "HR 5etV h@FK 6E,*XI XIl# s7{/zB=={=wyff#%I=rHSxS\oڵk {ޞ! aN=.fnPr~zS-j1n[wښ9g9ע@F/8Kܳ X={9FЇ9V( E| "wDlRZ#Ǐ;߿otړ }DANgj^"9~Y/}HY5Hj_'VXW 9 gJ~"X}a(xAP!l|_rV'pҥPX[[k}p,{WVV)߫WZ[I=EǏq*2 6e5"J'vݻ7Ӯb3f{T)=jϘ$ ѣ-;3T*{80_0LƨX(͛6o޼Ƴ}Ԉ\8V "BaA!˗a%*Ȥv(; meBt&@5c ٞ DF5.Wf @1ʡqL|.9?0Fn߾=R>j˗lҌ4e*D(̙Ƙ#TI7LNjlVI^^jPF@D/ׄ#;v>mYLy18 ?~ܪ@85'{k g*^O"-ciiigcccf[\/PJS8 ={!9J`E~o8Yz>}9Fۢ0^.z֭[o0}iK#9ը BB C*,#_ q엎ᵏPD9^Sa3osQxFP71CWq0ܑbۂȤ3gզ@{p{ΏdS-e)Ǐ͐Sme^x1iwP)1@$\9vÇo~ _?˦,!#HJ(|[U[(QƩ廿x8} T~B{Τ_8ո 0Br9O<_gNGkyD-OQP([(QyߋNo!h VFm(aHB7sRiMۜ+B#HΗɳ6bH~/X;PUA(5B`;ʽE> pcpRHϟ?WBM}}>g_8z\Ǩ(]9spe(s!E$a}a]7n~sn<'GmS8.NC88y&7Sckޡ8VW08)U*0&KYo-$|P(- >؏F Q2C&90 7*yDkBnG`1FH۫ڛjr@aN rh؟D>|h9C$ 7Pb1#޽{[<4!#:Bg KE, f7;"=쾈U>̙8Lu ϹUĪW >ydr\ڜQ_KǔX:1?;8(,]-XxIb5X2B@$7`N* 9yg/_$df^wf_:F{=gMD:?ӱ^1 "{k)Asܻe\K#hE6;x]mj$s*(~w*DDDk|Bm'<;p:FrO㴊|Det3y )l6_MoV}/e ^ LsSSS:XD"! D}o-U:+94sDH8zRw>aRasAjYciB3:ԮtH#ex YX`&.vCĆ!Uߋ&hDnk^U%/ F&k0gFܯ_FYӭdm1C7),h֑!u~@d' ">wB}ohcM, 1ڊ{D*et x༨eLpy.M^V XJpHQr4Q\#8KFcx? O@\8bБ9?8Zr9NDEB uiCDbb Oj}I'C P X-@}DPGFsAu c /r5e45<>> NN46\D~?|!ATTzjߩkـ*!ڻF}f) [I[4$ԓy>iA4H(Xm#." _KA\"5H4 CM?6A pla Ma 啴F"8t0;O>+"Os?R]kQ>]P(.Uߞ(|EDD~䒩@m,85zLXRIgVDDDD+""RIMӈ,eWDDDDDDD+"""""" _WDr1$oG(|ECvGsssӜ7gggCoșK?Ϭ5C=&B{nnm677N)j"!vIsxx?>>n_s{{;s;==mJDD~ǏLa^ڟfrrk_zfffY^^nD""nk?롟dd JC7x4R(JVM@"GN,ڑ%k5rålV@~9$fkd(!l> |ݰwLJu}6311KB^|i>l!100`æׯMjjiui4wWwuگD⪉BEj HÇ˴j2hlU冀_~sS\\ljjjӷoߚ^ƀ!PLJJWCCC_Gݻwޔȋ|Mw'd/>}W=  iꌶ,~rQU 7fOUb]ϟ߇vXi!Ν;gZ(q#_> *[ gX#AW^0͛76 p:. !P:ழc5e{ع-$v/[cWZ=:hll4nmmE,+{Ϻ^8FЬ᭳@OO{.==ݞom$}}}C!k|;ی  Y[V/M2#}S{XL: A[uW!9޺::_gTٴT/^=x}ȝǏ#v_^}5O>B#v@&V zɼBo$'sss! &999.Wi?/CCC,iEJUYf?~l6E~.Oڀ+;;~^UUՏ޶X;'?n p7RTXYY!hwztV}} [O|`]}tQa.r~jmmb677 6U_i}}VQjEm=]4~:Oɼ:jr*<5*//7yyy4@bS*mո TUD߿3(QA,|Cs7z= $ m{qݸJ[k.D6@U_DLIUw*DkF,|ã@ӸJ[cqAЂWQ=MTAo#^p Ķxi\ETA\6WC, ļj\EIώU_XrN"`_ vk*/nLX&{9`_ f&ܸB~KKKMAAM@ XJҸ7w D, DDj\Eu錻sSU=4FFF4?F"6":FU{٪^X,"{X @ȍ*qUvvm\"2 Vff&[A C۝m>qiE!+#Ӯ63H QY ц = Lf?oy.Ꮾ5qy͛7 _==2|CZ5666  _Y\\bהX /2|Ib/#G`T׳!,0|*×xA"e,/lK%1\511!\žփ _ ` 2|'C٥K8E,×j֣G'%>|(/*)U/iwpmԩSX/X1]KÊpUpzC1|L699)/WŇq/᪕Bۋt,×jEܹsH3 $BnrYzC`+{ׯ /t|bs|cҬn2| .'~/ _*,,,dw򿎹9D}&(/͖W[0|SWU߾}s(t-,×zrM, _hgU/iUrǏ1uU, _hU/iwUh>_~ _Z62|IO *h݈֙3g _Z"\eRpN2|I+P0|ay*×քK XW _҄` _O: _؉/\eRW|X2j rݻwȉ7'U߿7(u<}4N< hiJQV_#ovgX3|iIY\511 ,X墳#xHdU\ubzKe%,_V[\!!S[\uU,VgX ۷oѣG|Q(+ÃzK_ّ_W!6Gq)5X/KAqI^e͛mSSS/aGqU ۤn077! _q% U1n1== _W\ۘ``##GWխk*B@rS\Xt0j 2P..W!rs` %X/]Fqoc? )K fgg_#=۷ϱ'N B|CkKkrrҠt… jVp;bǎ[%ޖ`}/kLqosFGGWuk)@Xw u|YIJqoco޼)VgMRb0iX/fll,N:Ke)Bm*Wg?|Є,,.|TeV__S/ -[XV+o_X,ھ}{ )|iU~JWͼ@ǏRġCݻmPV?v###/ԑ;2]V4~|Wy7nPLk-ϼ߸qCq@.7oÇM333q=! /   /5~~2g <˗/155ccc1::ŋcX&,1qcRr"ǟK?69\r8^?3p||z^dJGڐGM*b-BhCy5:dV,گzMQ ɈOVm0!և`wMy~c@}׋x^}OXj' `[ YU޹b;)Krhƃǡ2g=\IW㙦ׯ_+~}i `9??>+P; :9+^5}y}}ggg+++Tӵq;D3{I!8TDP+, be p(h͜@lC€!kYmnn>:L䖣%[[[OUS(`[!8Z}c!\C6*oM;FQ' >|𰷷7\A#.rg" 뜰?|v/☰\Z?~xK^-E!y5M:A1n 1(TEO>h7S8xWmaȡц_WU9J|u` NwЭdǢmoƟﵯkuigߐ8 An߱j_/Vǿ'kd3NƜU&2DLXϏP~umll cyK*oƙm=^"&莎A%7.IQ"*p Z\Oc35ceu=g 8{!ϟ?E |S'1Bׯ38{ ԗD8'r8K9-  TtmϦjDie V7B8wRMO[)EX8%!R]!]j; Ea!(UqlU _J|N谁F 7Emsa:xig,9ʎg71볾k[%L+ L#E}Wzȃ01^s͝!d gBh.dl A0W} X[(`nLd`1v^U!Rؼ/(O'r,DQzտSK3{DU FqP(E!C잌1Ȟ~R/_<\__?/D tZG4/~x6B ͑)Dj "V{O^N DeH "vuf|9GA?\GskN Tdь&S&%7%Y0"&p^&ܪbI0:m0bdl_[֖s nCF[y{][6)˄OA?ׁԏ`Q8*QXNp ~MAT5h2BLL%ǥX c@0xIє{yodl9_^aumj-W F9oՌKF.7fp b 6OuXH4gLš~{DjIحPXMB%c׆{n[EKMĹZ?ΌUd{k" . ?n>߿) c)yfmm( c~ %|bkBZ7BYhSԵ9>S j !mA UJdp*o XxO9bNMqо d3X__B|^ZL ݜ$T'I A>X-ų^T]έBk1FIOoae. }6A5X)3a_I*ӱ<[ϟw!-+(Ӧ-"YdGQE@ FX%8G?m[aFL9Rȩ09xHĘ9C`gi]=mxjR 7]>U/CW6EE"u\~͕ ɏsٞBwN9O7u t~b+,>$*o{w!Z(v$ܴVcWt ;7^3ӓ'V9Of5@?~ܣI v{y-v$"\ׇm/3]fxt}ќp05<-;ZW^YLƵk YU:x2[$wB欬b yR,EGMU ՊRa+II]D4+ڃ ~U.Of;Ql'7v3"SBcyD(yޣnwc۸]ǻ˛=fr^׼cȍM.PK >&Z#Z'v"1cꔈyUngN/1L 2!]1ZN@!^X,,dChmݼl{T?rw^ _v'd^@)Z$(Evm:>뛞;s]~o %D:E+M$}$wXʳ=j{iv.w#%Vbcg۽0gLRJ=$wNi2SG|)fh xqN_~fœ_?FI#S{]h `! W-IbzrGh晴Zi]72vP% {5DpFN"`5!{ Ww!}M:9U[[IAj+剟bۆ(Ĉ]kG—X"j͊i_/Obob<^ nzgLpU\* {.O\uOy!Ӡvbm3Р=lL x}/bN9B,fyʶCGmcR{m7uuWc'W}(MaÕ2 {UƭZaߍ8}M{{]~ǔƸ;Q}iJ)zUaǞowwwZ#8;Dv K1E}?W[.=-o `Ņ<ؒgm#؞&lR̘2B(6;&>VxUaƈCqı юluB4N)ۚiWrcװLsG9ƺT*5fy⹜'6k&;c5C(kS|ʵ( 6“Ԅ޺<GA/^wY[BTg^1{.'|WZx2t,wQ:K`ճr45Alٕ֑bGfˡ5/`)r#>ʅ$/m92;e݄^t*2_Z]!1:]H}o=~N>m]&Oz'۹p9k?'nZ jnrWӍZRJ)Kg̹eW'oRX&.v6 [Hj˴7δ"wyW[<8Ziꟈ)'Ħ }^[2Ex698u!Ž fKyM㏘6!<$="y_rq/ىio"ǏG*<+|K)RJ) RJ)R*|K)RJ) RJ)RJ)·RJ)RJ-RJ)R*|E;-RJ)jҪfR C>^zkӧOzi ki#7U߿CRJ)?>޽{w[OJٳ秗/_O_>}_|9[J?KK[Oqox PPADT ( } ƍ .܉.ۮtQp]Ъ[EѕK( 7p'Ib|?!p&3#P{K3 > LIIIՙ~{=|vv>pׯ_UA1::jׯ7Ɂ{kWW ./g}EE988`@h,\ѫ{Á iߏ1X211aO*(={fjkk{(dvŭfw{mwTxů^999;+:.RXX򾩢W;Dʊ yMKK3 (|ݤTU Et+$Ɔbjj!|ٞ; vvv{xcLz?44dשrΠJϟ?ůZm$6XHů` i(ܥ/_ }ֶhV0z^w|՞5s սkaݻwlg^_]W$ٕ:9){ί&O>vLiό 4\gPi Nj_ueegffEihhSSS/G+m*#Vi=A77Ei񥭭NյcrssDQGuNRo޼M!Vmii]xQѫ9Y$ԁPҪQtxuu޴NHbNד®i/Rzʞ #^|i^xaossӔ} 1.P۲V;<,IJ G,*zX& NwcuM Bm: _.T/X! @\hJP .$ #DBA% ]ёwp:xC233 (|]ABXj3eee`\sS(PdּXf M{{Ϸ;t-JJn6Bd-Z* Xb\K9T6***JE@ D,Do@DU  gjg,{pB .%]PמɧSF$ 衰CQ`+m|8y.A|`' W=x@iGiQ} 0"Yt#spUE*nGJ P1Zd]__ɪ9, O Q*0B夑8GE) `N޶(P3_~lh$Q& T`B GRm_8GldH|q|ܹ Փ.]TW(R @ɪ8v$ȱKTo;U7o|̙3ɿT`HV}İƳ'7=r,,,WUT>JijggHVeXq<.>_pUo?jF(|!ɪ"K tǓ?rU @AɊc߾}M*>`AAeUO<}֢(|ɪ,(ϟwnܸ!\URq1/R|$+wމd^6\QQϋRn?wO /U ᪒G3ǗE/\H#ŕ`3j`pUy~ϲQgR9|C"Y`Ŏ>П|*x(U_x1LT_|@W$˳m{u^*}*^Q* @">}$UPV\ x¢ ᪩)G._| *|kkkˢ@q.ƻ[cn[GccTʩHV`AwUD/PJi$+`ӧOF(ճgϒE 0d|R$kD4\u-!mTJXFCxMUCRŎnZ^^[ K6ի#߿[S"EW O6JuuQ* ЍH `QEpFO 0 HHVĎ%G,JOt{s(Յ D/d V@1۹9 #v\$+Ż8&C6fQ(,JT@R_GͦH4ߛLܴ(p`ZFWE/@ #Yʞ >.xFE?TQg0P6#?Zb[UqT9~Q0TP "Y.X󝙙," Wݾ}[D G8|$mb4MGd.rJ tw_C"Y^X Z<+\g(յkD &}wpd%vb`_rRF(_,ػc801Jh#i,R$\uz z ^uR$LTl9|֌x<:T13;q_H`bVlӍ-1 WzyoQ*/@iDn_ zJ[5M ֊-gFGGe Z9"J`,?9Qm~|n#\_ Չ( IEbkkkV,z+߯qR|jHVV⸋+~Xik_\η/u]RE`FbVxf=ֳ[Tu|HV|||ȈV"˛7o$XɎUnQ*/UHVRW\F^xW /,jJ1\URӧOE -HVsnUT_\lݽdU> ~᪸7{ii!J`ŠخYHVsCV*ˈ*Tq]Ǝ|_*HVZrUuysٳgT_R׈dŽ땋dRrMQ|rJ5t QU#YXJ+}ᅩR}`E~i=շEb+  @IJ2_"kE[ /8??oHVjϕ-K;n/Fb @nduxxXwSSvrrPGjpb;}x&p___ӓ*GxX͝},`ׯ<5d YXXȞ>>c@xR~,n{_~_7Ɗ6択6̄0;;[燇ezzz:///_|@@>RJ)RJ)~j}᝗IENDB`optics-core-0.4.1.1/diagrams/AffineTraversal.png0000644000000000000000000007300507346545000017651 0ustar0000000000000000PNG  IHDR'dsBIT|d pHYs&:4tEXtSoftwarewww.inkscape.org<uIDATx[HT]p-0 {B!AH1HTDA3SITBJI^k%$!BJFDCA)!J>YR>QVZƹx/?s=""""""̎""""""bKDDDDDDw{<~X$%%Enܸ!?_~ɽ{xt쬌errrͺKKK;>󈈈/,,,HTTܜpΖK.D^$((He{ѲM)>{lͺ̙3<0DDDD#R]]mQv}hwttl{2ǎC;Ʒodr?~赵Y7oyqqqݺࠟ!""""ߦ&9t,//[}Avڥ,bjjJf婩3vO9g΅ gmGGGɓ'7TKNj/xP/:ΝZ633#[n/:߶rŋ=xDFFZ-k׮mm%zzzZ-h2v9c,O>}UFGG-nDHH1rlQb;_|g0CёWʏ?lllL*^^^Z^__EG>##C_|i=XQQQ!W\@9.\ OLOېߋZU{ʪO<ёRikk6ru6V)..GGGA!""""G! 눈 1m_՟?>,^7|]޾}+۷u0}Y9ztx1 {zzZaj(F Fmy!,,LxF_e5uK_ԩSre=<ƶ9[O>7{3~  15x?~0R FUbѣGn1Iuvv^:x!0F=X! >>JDC~NgF<[Pa(7LG$3ڀUzxxhaU94cWAJ߼y.0#xfsB^UUe܇Qdb4 ?t$h:0u$%%Y-,,70mnF{Mo@KKTiS'N`~/1]Siii}Qcݫ\ZcaQ+,ne XUeeeig1…@~/N#'ػPʿ8xX0ЈSb5E6[،ƂP6IɆP)Eʈt>`g~r{w||߶6>*R~uo~DSZZrQ{ ԿW4|ssOco_"Ǐ1p[+S?zԄ!Ҟ?Q,O{EU]BTzCsZ4u񨼼<>}toKrycbbꓳc'ںVUKwԿ lmmڻdeeTOJZ9sEާjooؚ(//濻‚=hie9\hU lcccAؿk{So@yyyiW\ LNNnkrvvv?l>^ hwgQQ-N-WB MxP/kʧwnUM;'x/8*𝟟fmw^vE)&S@\VVfU ^UJ,UkE u\~>U[Pq6]xVP^TNEu;))X Z\sU ^JNO^8ޛLO5+Q!dUixxضrY\\iuXUK66###F ?(G^GWUY[|ׯ_mɉY[[3X *(I xkog{ o,ZEr=>*/P9ZMR^CT5vvvLMMHԖE ,fzz^R/MU1Z" NOO|w{Wr^344d l[wiok)U-U@ _|K}_<۫xoo/ؘxU߶6nNNN"@III1QQQ&66ּyDGGTgJJJLSS6|`]NNyϟ?8q?/馠TTTo_/^#|oRQ syyɇ_.lll<Ą' ߾}k>ߗheeNM |UU3ڗPYYiÎ|Q }:;;C&ZY0|@A<𮰞=2!Ejֻwym댋3UUU|@ZyMDea8+N^@LtB$,8::VX/ V$ǜԔB>8_'aB¿o{ C/>}:<|Гỗ5_͊WJRcIY_vEX44vóg^#ѣaxx8yƓ`WU4r>~RI#߿QxӧܹWPH/Ez=@p|hii`MMM7oxu-ĉvGOX/u$hzz:wuB _P. _B'eRݝ`:!KԐB&e=X 2|# _K}q+~dQB _P}zzr`|i$tP(8K qk||<| ,$"eԔ`Bl6+e,&FFF _>!$-.. `|joo _`/VTr×tkooQB:;; _>Z[[B%eR`B\.g `: `BHŢ7`/N$'VtQB?_ _{,UfggCj _se+j_JLLL`/*`%:֚.e'T&'']G _q4??t,×?I 0| $`GG _I:upp`B 畿 `/X/?! ` `/(O _h! _~ˋ`BgcccA _,%hffaX/[jkk _Q _Eu+QM0 -U, _Hny`%( 999ʳη7Rre2huuAB(,×Fmmm9`BFe٨P(`B)Jg|v  _0|݆DFq MJ LCDYa` BL {%AD$,H.I$`dHڛh A!y`ugG{V32gy!"DDDDDD%ǏLl< Ç244d۪ӧnyX߿ӧO؈/ev}~~lڴIn޼)O<}jjjSڤH4P,ѧUVzj[ζmNMM2e?~Զw>},Z1%""l7nnÆ .ohh9s3 #/____Ç=^~=o׮]޷n2mC;44T6n8^~]3eݼ/MӧOKffKYYO4Y~,[L.]&e2uTY|K [m۶?~]\p$^p|Ff̵kƝǏ%V>| ӦMфyxxxHzziϵY YG;m\p$%%Y@+Wܡtʒ={,X`2c 9yi۷o?EOO V Q*jy8kŋ興/M,whϟ'9994///OT(ŋ̙3޽{Ulի'Tس/Fx=={֥)))N1%d͚5۷07 ǎӉzJ\7o&=`TB|ikuDvvEcf_PmZt_xQZZZl:::jIz{{5X10N޽{sݽ{׶޺uw϶*bq,h{ѿR%+Vx^tDD&n9bZ9Y-))1mC0'e4"9uO@qۆHnyi{9sFV\KIHHi}XX̛7Og|6ɳg4\__Qw099YvZ322t_[K.>.//Y(anjj2;wJ^^h{]Vyd:{!""bKD+z [V :@xMƍ˗/-ag:cc1C9=dc=2T|쏀?รYhZv00cc ḁN^?x@3ǰd ]2dTa#vd? sllQƣag[ݭA+X{1)#s]JLL~XDDD |7*X>xf/oL o>ٳg-uš'N?;W(O (&L,dc#0Š>7xt^uܟu=]zϹ~* fytt$nu"{8<kgM&/s>>>2Dux<FL㝕{AAo߆*xzCh-Tl^ORyrQZ yTޱB``{rrR8S̾K\ M0H>?%OJAd[d;寠미pJ/*7L>IAA-h~occc4w/5&e`C1kAV9Tmu%TPcAmr=R]8Jv_ Q>[b&YYYɭ~L:=+3U[nii),,,dQ'j~/B16} O P/_B~yy)R]B8=9g>]sss^TQ  7o57y4w/WwނI!!4Je_|J \)bRN`%X L"]rkTc枃 m[-&<>88uk-lS4;0i@ځVSƍPWWW2D[]^^K%ߛE8mtGrkjj2yU(O :zU ?oɉ jEB&~SMZh^g"hr^^ixzVmW}@.TqŲoid}Z"^Ngy `zEC^}ӹO] 4__HVx޿Z;՟cj_VEG!T+++v2(vvvVc=?UmIW'QF9~W Ϊ<}V9߷aWETRYFvQ Q+' R l* 9ӱ) +i\=窶l) D,'/!EäTך2HzЦV;gW ^֑_| @Ѳ4W###Mzz0 9spp`9P M&''DŽ-<<Ǜ$EDD2Cmllp 9;;3iii6:w1(͍IHH0Aݏ+jvww]__ۛI|TEzsssz{{y}2v6333U_OMMyf0_p![Ϸdffy{{ onnڰ;11}Š'_xޟ퍎6ŦA.4t,ņ[UxCq/ӓ)))#**6g^M~.--W3pu{{컩Y/ɉIMM-&99.}—Іe\ k‚9>>S@7ZZZ 89WMMM&..444}..;7kiiq>z^~zB m/"A֚D@AҌOJIInu|޿G% @7EEEvV__K ƴ?::}UWks٪n/ !FawdddeeXzBOO6UUUrz?wwwZ*3 @,K;V"_B4h*̛$fٝiu“R ÷/@loo `a6N ÷, _, fXUXOOO[C  j+ oXXĄoXXޞ`H o6p GQW0|m'EVa o7Qz+ k6+d HzXX/``t` `4N, _ம _``tίT ``V `:K , _)522/@p)S`=>>:K/@`X/0|: q,×>0|+2|' K;XZZ]]2|]0|JCX/,zҒX/lnn.r×X/}~~fXgggbR#NNN _2|i]0|:`  `QVz @0),e2 @pKX/ `#`K;///ё @T_q(/ `4HߋX/UXbR#}{{+`M2|~~~ wCCCyQ _j`'eҬz}}uhRkee%2|C  "5==-e2 @p驣0|N,nnn _`tK3,lccX?&4&zŢ&pp717jɷx0&Dbb<1zzScR7k)o˖B`)m"[e "Bj;3|?I y2igjߋ, ln`|Q_m,/~X@8@gg V`y;qr?X@؜`鬯rLX@,8|  ! \*`:dNl,/, vKCC)2,/X@\P0XuuuK ~Z``sv)"(/t&X_XX8@WW477+u_X X؜jK}}466!,үz<|A}[[̳DkfffF Xp,/d@,c@|LZ7 @ /S))  ˉo>lgOٳySqCB/zRpA"WJ-<|MLTu򡐤_-捔!*ȼ}+kdU3 /^Ww6֏߽+'dq~@ۿe˔~ ;W;vL:0m}|<?7sG;wJP`ߡ!xÇ  T*%kndR7j w@~zv*[w6ӧ%xoOO$qI<}ZCRHۚ}/}}};:n; \.'PH% dYX,J8f|SSSJww3 đaFJRubdS;FϞu+}[>\RZXv Gʇ;e3_${E7;;knOOyY~?ѯh|dtiuo-X5@ 遈߱BLCp5HoooՂ6OIsf rk,x^b ̗'uaBmHF>Jդo7:%iwvCM'NBSWRȹ }V^-P[|Mǎ nJ9ׇ3g_כDS(Qmb⵵m$E|x$L2(qZS|En ,//ϚbL;44gr  BB1 ;AX XuT9NB1 j"V}_U%d%|}D ji}>5>F'VLM2DRߛH?]&\֡G .oy&Hjli1.X ֭r}HjDϒ"|ۋiėx!)*2e珟$&K*g6T|/gok^Rm}8{tݻvMKMv_rs "f.7wAj3hn6LY@r?^DL!S>n@vfQ[_JޥK'LM|ݼy9ys)-eyKdҬ,U߻vmq"أG'֭uI=QbrDd' w+iύr_DzK3?.iD?nߑ%K$5^5?uW$ݦxIN ޟM^;M~'#Tx<b}!ƈ246;>rmH1Ocgmq!'1l a~p.mb _B{''YSS#uSa>l I!-7 %il R؟p's`J)s9U8@(㿞K|AiȜ4<` -QL rѢcD#k6nfHK@ID](3L~bD%!KMDh% ÷gB{!ͨUƦr6 ޱo&<c'cVP *|GI#c,Ir`λwe,p,&'( ҾIvY4?NV;w1o.dq*`u&)]R A`ya5™{i"m"IY6rE!ؒF _B@]3P1 Ee3̉c[:K2G_547O*x<^ xԋE/ $x0`.*nXvn"DYVLaTٰ ԃd;^zU3x2ƫG\_FP٫\wfN*I F':B }iS!`nq돵d2[GF,L#7kP{e%3YK"I^mx}eӷnNٔ*r|G)ʷ83%ޔR_ܨy}*c2)ۿk݇+PUQ}enҒG+ JnYPubMelSO$I|DA;6G^x"@b!vGU=q^v  2픈 ۺϗ/q>h7oMԩ7ڟaƍUg{tZ GZP}tO!tiO*\yPT5}99\Κ uۇ R"!|Ȣ=vT-BKy-H/kv̹ΰdD"o"Xh4D\mx % E-WVplQg r[ P!׫/}QBzJcthvU<|8cl#6^TU0J'{>Z(z޽z/cq):bb~ә3΅ E` f=YAQjuL(ҦLu{Em}$פYӷv^RsoFaaزD&"!ui I%u{s$c|8/YgGcDD"^ Bpy .2aZ^(yqSX+Wa_!ÝyoGGv^|W-{Fα|m\BJ DMݲ%F-a;#s4f]{իqJ$1^ʃҌ{RԊta|Dx۵>2HtPR E5QW=_'(MBiUtsx.KRTb\H$&>Ah!g |R<=V%tjj⛓Pzat Y}-3|/ SϹ}6 *h ~k."WrGNޜ:%>(f2oWIl:<@Ju-Y]QL%k(-ڢf QS!oϟFYO7oɵ Qkפ\;%Ğ >qBÂigˎ)ҒϷmkt&QR 4L]G[x 1VP!DeU2ۋr Waקbn|\֣D"7H0tD^J خP-*9'e3jὴ~<SXUx۠Ƃm*CTFWt ۉΝEؽ{qG}&]֯o)*BL;wXlSlJ<3#,$/_ٴ hyc6FIKBɼ݁ͯ =96e;gOg·I7ׇ aP\ &/]"LWk_v1YrwU ~4w13Lw7G9vH'=4Aڭ2Hm07*RG"Kdirhrׄh]'xMz2ni2hҼ-H$M$} -%J| VJǗ*CZmc+<^-w-g&geI1 ! jJ@3?؄Xr\[{gSEaCAg66jc_? &Fl!V&6 (*A +ȮY;d{*Ey;s\ޯ$ I40לzeҖKԹ}Vʔ,p/_3~Z/ӗr{_iQ5 z)! 8)ixM'D\flll39xWD6Y|=RqexYPDhoo/^ ---رcaa˖-a֭]v)ӧOa޽ppԩp…pڵ+'L jb2'~u(|EWpODf ո^Zq!EB Ν;ۣ;ȈA-5g;R(8e6eqqqPKZs%ID"A%}*O4I"~`R(ϟⷔu떓ý{J: C[[$BN"oWUc%=6 &ED+"N۞XC'ݻ+qxΘ܆B(QCCCx;{TK.ňxvcdK !ض817NlYNƞ8m(d~~><~8Fe^~ʸQC\My5PxY "rzD?~Ei*p3| , ߚ ϧO0|s'U@DԧX/^* |]X|W,× DŽ0|A={X}$tU▧/^W}9#xss6 _*~'\ݹ,×Ib0| W ׼W _JL 7_s*|WuSK`D^ 7_j/ O=zTK `po1qRsuSnXlnBX/=:H Wa;a: _,}LJ WakWE0D'>?#`"er0|eW,FFF+7!ܫKe>`tCJ>lnnF<O| br[ o\*g_-y_YY貸luu5@TBzq //w.9mQ/)HLx%HsIä10!4Ф b BJhUJjn~+ٽwOFF}gk !+B!BH !B!B!B!LoouwwB!B>O _;wƮ_n7o޴wO}}566ׯ]la*[&Z?֭[nӎO ϟ[AAMTf)`j鉖6~EO}`@Zf8—59SCCk'>׮]K%e0"D.``UVEϟ?ӧOB SNd2șCkIb%:an 0M+i8:f@FC1þzeiJ<(fSIN^G{uVT=Km P %տT>&GoS>`klȱ@QΝ;=9vX|Ŋ>{پcyfۺuk1kϞ=~^Z?~i&?6l`ɓ'mƍ~MHǟwuݻ3OBzY7Νkg yd(}v۲eǐ@^ZZj֭n]m6w#n=O|X} -$ce:נ=R4@Y|.6u~2cKfn d5F[[[Cs勷G3wnOM q~{8~B]l :& do߾4?̎Sol@E8mP?áh˗fK{ U;86m~ NR.Ka[v τ>WYf5Dl2 uڨ`ɒ%| 1s?:zرߖ.]~6c ۿ\.\eSs׮]{"U804AALALPT3EdYP00L3sFb|<ޥ̮ǎtan=}>޺tI4hРCH/_)>~8.@C'Ov~gpN#xtGN9-ѓnܸkŋ1AkNpk{= PLd@W,CgkʰϽL:i_ٳX@Ϝ9kmllL`}vzwj~mߺukЛ7o.];hРAr]?#=~zqȑŧOvqر)j7o.}ykkkAKuhy3MNՈ_I:q%؅.Su~s"8¢3G+<?݀[k*^ۄ^Uc{!p삛kxA)&1?7`ͅ%aըkƌv~ fz)-6`L'DhaiDo&"C:$Z<5;am J?0Pbu ^W/~V<`U*\HĠ!F"'=c x`ϟ?痬ԩSW^iϟ; gc<ޓ3`_|o}TztA :\}zLyxx۷'k5shOM%?t:ڠ^~so{pU\G%1g(Sݜ-2]w9#mvK?rej8ۍkw߆][GfSZd 띙Ͱ?7YqUkE\ u&0`3BB_^mY1aVE^s•Փ|elzn ҟ߬/)=^["\^7oXy{Bh7BuƦm{tV6~c >=PEoT>WD?ڬ'jo~/L_ ~Wh;67?Zk<k;lnZ[w.7dUhnxykۉ1*H$ %KƼ*آ6ݽÛyl]i]psg:7qW T˄>pBA4!AIB{r:уfwƣ;w)C9})+=s3;) 4W.e3… !B[=OVz*#ϋwNXg82ri.7wj 8kS 9P9Iooh,R=}fcʴQ]{P> ?n#][b N̘E(ƒUGY;'P%!~¶*κZSzۏ>bƲZbY9Ǫ2k|4"ts7cXHfSw*QLL0120LP#3#X#C#T|sܹs]Vwf9 twuuu=uNH5[;Eq|XY__r|ZWxk[Bʹf(IY`YGGGS]i\<O1ob7sME祥P+++]?5f~m[.]E2a2dFYswXia-tTn"ߋxdSвQۡbSܧix}Wy0?Bd嵬(lra Yq~5lKG<]U/fXG< 6< mn("{/^XO+[HA9zG5ah6UA@~v;,>{JgO #<,PZ̲Fooo3Cs 7~6_NEDi2:шܵ {wo3ۨvM2>ڷj ؽ;PrSy1L: ]YaI^JyyehC)ƀǷXXyƸ}6O ًݫs?Z**Q4\?ݩqf\\Ȇ ^80ߛ`\gz*aH-1sdot+| UN_ƙ*WI V;RCt;wQ~o<kɳmq||GVaD 5 q777^x1p0lcϠ1-W'ϧ,tkGۉ]\\|9ct?t#L"9lSM\=c-jϡԈr-@+sah8Ly)VgtB⼒ZvI"V~4JEV~oŎa(K#sED慒{ ){3j0sT; 8fY fSQ'^LTXdV(\,)qx\@L3}ˣv봇(I]kza}9TYus;9$V훶y9wuAeMI!^1DåxHUooL~eÙv?&lzU~/f<j7Cm3 Tcde4Dv Y=rу]/ ܽ%9L:m>a,+ c';ŸQƊ&* lc+38VU6!=6 YE/ssbDхB{űy+B 8Eg/8po覱UrQ3gZ+dFѾ1p;)`C`q!9kgH81:4 XNN瓍߬هCx?NʡrTEss1I1m`\|tt}}}VlàUZ9wrƧ ^glǻޙ8Yu}Ê ]5P2j&>c1; ZE,SӡiHma飼(y_=.3 vE5n!-!-җ;iͫq}Q'!ek1EHG`ibHү[>ߓ^sSB7U|z^* 5(|1c1Ƙ _c1c1c1c1c1ck1c1Xc1c1g$:[e1c[D)e5/kfk7[7k.,/\Qx)iTt+ o҅IIv݈XX؉5  FPLNC,<'k1QOrSV's}>|W{{{Ȉ=MgB7uؘEK:Yj=u֧vMuu===e@ዻ)N,ޟݗ>&Çɓ'3/_4.3::jVVV,pY__mwwimm5?~4޽3&>>;B̝\:/[']SSS JڢY9n綶6 \:::y]:ӧOM~~dp/ܺ6պU(PVw{sMNNh  ׯ"YYY~MgS*dnڙ~ZU/B)~ZwkkzߗDbecc$''X%%%/_0@ILL1w3XP[1_]]]g=kR]ߓ ּ49)XHůFOސh6 v, \WWghJ]W@4ך }ࢵ‚۾u]^^&?i"RU0&,ĥyno]3KNc&%%| z>{4551HP݂ܜѽkDJN/"NIZsa/vjkk͋/Lgg'? z {ΛEEEJEmc7 _[pEyGHI']|?_۷իW.澂gn}: 577BX};;;]Zm >P}6B6٪6%%%3TpTWW;]͛@0n RAd!~ϟ?7`o8U73`C _ڑ#$ Ѣ.`_ } (| \\\hA$)KG9X g\UVVv- EP*/A,M &$ D6g7o eRu: @HprrrLqq1X%UUUAWJ _Oބd!|t U;xT˫M@ <0d!\kW!RxDdd`(K;`R'P*ڀ(L s; k]C(@ DHo3󦲲dddu,(|L!YUZE28==% @XW2(rBtJ !Yo (U?dPp,B _ |CaB :>,7{p%  &jކmp-$t(!$$ IݞXv󔔳|[ W5M*5FU|Qa|a DD 1??/\eliOwRJ!ݓdoDM B P[lWɪ4ud5w᪚j`jB G~D d!6'<ɂ ՓƒpUF<տTU`%UOYXXHX@1oGjvvVl* @D#G0l---%' ᪊GnGg _[j^z|@9FZYYQ*0$UmIU ϟɠ{޽_:(%&J_E5XPPprÇJɯT`JD$z666@Z333U%uݮ)X0%dy? 5,ljuuն/O `AE׭!᪒p0l*|ApU9x0]*|+WœB\/PA=n[Dɓ' ,S~sM,ޗ*0 `-..677RzpUR_b}:wj4~rP(Jv |eQ9*,L8Q* RK< ,,+ W^|)\5kD6Jr @)Ƕ5pܜpUR_vDGw޵?.\G:?~H|./E;"EW(`HV `QEpշo;8_R_ɊV}rP90nX;bD/@ İ+uszik||\HU?(4 ˆ#YeX1 `qԳg.Unt.J?;Q$%E{UWFQ*/x+u`ŀXSkGT|`b9;;sP+-ͱs@|*E "Yōf)ŕwŅ0Z6ۡE5SSS/ pÇk}sD PŬH֟QMX 5v{U}v6-HW jhqVh`PEH*BN.>cS9w=̙͌{9߳U,/VĤ @үJbݻw*Rmx?ܩT/@WՅx?Xy+gƊ.|jIV)X*x?(ZYYV+|/Ւ@W .\+qYW>?.X)|/]X2+9W)|AJ`SURR*\_eFr+RJ p{Z_AVTbo'OZ:Rq_V_֐/ (_V^m]~s|:ҞdXd}|Έ)6Ͱw/_N0Did6MT紇Z[p-J|E9\ٺ4qٸR*_*C-R4::Zӗ/_yRJ @crammm)rfٳC-RJ @|EzPd̡UO>Woll(@ ǕdujxZYY{(-f rxTdm%Y]+/SJ }Fb6 **߿J|7.ʭ*T0끖dELׯ_oxݸq#MLL{ΣJb7.(@f]˘=qPJ ywՒw\)U`|`ȆUR2rx @]J@o%YMR-Z__WJ/]0f@Y½z粒tX;w_|Y{CzUow˽u Ǐ1sll,QUlr7o'B0 k:}tr򳸸N:ݻg0@ܼyј t̙#cO~\qRּ /4Bի|ѣGiff&-,,۷oC?]V|Nkkk_rok/xb88ZҥKU>LΝ+#*-//d|`xϟ??ح[lgD[<22qp<Ǐ 20a,A ĈŁh .-. A9pEro[NqކFV-k*~$ qKs6M6&n{?n8gq+5U|/>ftVrGQL&gߕpsssRUVx34Ͱ^OpZ=yyI߿nC& J$ S(.ǩ񇇇0NEz/^du9r9uĢ\.bVh۞mѥR)|}}Vr`p۞|0uۘxkcNދ6t:jn{fLPjn3 //9S0z222"KKKfe||.&J>qG"uu96NK*hSD]./ nz"tuu %ZG}i?~\۶F:NzxQ9v}ϞmؾץA}ϯ_;铸kk:!""""_Tt;;;exxl*v]G,!\C[r"!u;vHˡCB!iؿ__<~9L;c;wspr4}I_XN؋IRwm?|Ѫ͛]&sN熏pA:O:l6c|Ex"mӨi+tg+߫Weo =|Xxw> m/JYNjnngSSS|ЖqطoL~r<. 7=LfCEV{mw9b"""""Tt@GGGeEOLLWCCCzˬ~O&بJ4B!}_cXyhXx A_҃n:߄^ն>\/ ?@Eg?Jqߛ;6Qy}޿{2,E"ؽ[~n 5/aO< ׊qQOwƍ_a8#G$G@>{VoZY*G/ߋ }oWmkBDDDD m/&Jmd:&0B&Bk!\ګ'^___mM#٨oߊN{1U:Nb/1So<*lziLG.볘 fz$9↩ӥPiDbW9Ksq֖g[ c/_U޶G-Ʋ|ez+j5*XLj=~oIvX _d߫m6Y\``!* =^vݻ/rݼq7BQ `+n w[+VBծ JKw.Ъө#cKq_3:0$)~?krsI9W˙]T);= dhiOZLשW8Fʱ;T+;Q2k UzUoN_/_ѣ[M߸a~~=QrYŏÇqUTY \[@nZpzǤlze `0~_j8U@T{d{}>ţo߯glh=/^ď{Sݝ?~p[KwDxsp9Ύ ZLTﺧ$;PӛT=WNEYTC?p Zî^1 Nm͛_P`>RUow&ӫW6j#;>{\_\1}5K* WU[_WYQMJֶFڮD`G޶ZuHrJG[g+˪Jz Z*Α<ڙL/2[p:y횝֬_Sl=~l{wOb+cSos%uzՆemuCJCT'O_[[5h{@p邯BSU8UVϭF>VTXHTZu?[=sCZcoIa4._捽i"sw% OR{gǾ֖Ig[zi`^ .u @ /:99csOa [ ?o2333fkk7ߟBn 0cccۏMLLi Y[[3GGG`ȸSZZ0999[AA4uuuɴ>3<==BFmll\lڟ%`w7Q f]3>>|u|ss oKKKFz__, <Ԕ(dR45eee p8P|mm}o[\\LZtQjUTTŦ'#ײjJJJkzyuu7i(Z9w~~D"|S}+++"#nUUU[0::*^SQQaoJӛ5J ~|oog b3E+J<22U^^n@w8JdzL&Yj ׿_@eUb1I)H}9ǣt /|Z9 ?@×(N~boo3|}}bVVV> JEh+3??_4w_3KKKEggg9# x$:7 www.":q5^}{DSSSeksst`sy7XX|p#...s:鶶KFX_ӾmP V%`EV sX/o5,×0|0|IN ÷xO⡡!,×0|&''$#[-5F%` `a~!XEGGG*`o=tpV%, z _6`o5,×_:88KrX`$'[O+500 `ÃBThzzz ,× _ `X/|{E0|D𥞣bff.XOOO. K&X/DkxxX %0|I)2|ym+XK2j"{X/xۣ+e9,×XqE1|@+_0|I&o _>6OL`K5,×_@KrX/DkvvV %8(eR-X###X/Y `Tkz{{b{{E _l _ `d'eRR 0|]22|X 0|!3,×z2|Z4M, _E+{O177W( `Tk`ſ~W2|'7 , _hWvT0|!,×j1,noo1Ho\t !!!ġ6[tiurQ EQPPDp -QE|ӷnqq  Ez ;1%|J6UYYi "X—/$.2%| |!1/;*//7_H, `wy+ —,cKX\t :?G_E@Bjfgg,M `v~k~~> _Xĝo߾e3X Xkkkt/VCCC |!1:%|M E/X ~Nv6~Vx|PSS|Sp9=~jj*TTTݳ=~87oބʰw9===klnn^{rrz.,,.o8/p‹/r9h/9tD^l~5k_悂QUK^Hw?>|hEĺ ) q59"\(WQ? )E'$R|qC.cǎGFžk.)XsYhvإ϶6tk޽|}hiiתvM\W 9Ӳݻw% tlFwwWH}'zF]nD؁($SN8c܇=c7(ՊLyp E,P*tX];\~õG'/^洵\3wjB<,^Asb8pBT;vÆ :EQyl~oX %0#&b$GlLd۷oc>FP590hrK`e൶{)/5__+ǂtYL;(|EÈVXpou=b bH/jZ`jpnLlghfSGD2p;*]6]A<4>/9ipsCH潷Ō|nvww;Sߞݙ-ONN;FS~Ea2k5&ɓtޮnB~uuUKw1GD}o\SS9٫Ej(|ECm LT ]`҈G7-CRO•&VELk95DF ίvi@gfgA{E5iY.agϮDlI^˾54 7'0ЌY )F{X)V}o,tȋW4{C9H? iRpýWD1ov2]8í{P[ä6{\ob^&AD;TOp5l777}qVVVz?=y\GL҉QKa;MH6G"ʘQ,ТI[q` ., ?ṋ^ LB0&z'iŽBZx?5qw$ J| 8|_y/s^SoDsDɹfڸ&*Qȿxy7+ʉ3"Q桡^>w5la۽8h+;ȑcQL̳eD6#`Q/{ \[>'8ѹtBvLrԒI*NˌyOX r ڏ?҉<k cTppF׾|-<8Fù,{X2"Q wn1H~WD6LX$ɤGGVl{FGXuyff8j4c&gggoޗu qdv|[dktmf_zጎθyZ",M:7X ɐj i """ _xa R`u6A Օ$'']0`u%^B}g SdvvV쌳_Ej-<<ЫpNN ccc4448')))RVV&[[[<8|Ԕu;YUcPUU|RB]YYY|״;b9UИd 'F-#V{{zxxɤgxC]\\k뀡f̖ D(sUUV__uxxJKK/sILLK]===I__飏,www?-W>q{w||\y/U]sn67 6g޿Ǯ.}O*755m333&/-- _0 Q٪B ӿ,JHH}խ3v:+{xxXJ]* F"K-#Iߞ1>{/V~}/_0vղNu|*Z[[cPGH]]JMM!wu sttWJDGG L C?+ܔr _0* @̵+77s_0"u)X {@Y]] _(|(P  @lkk,̽A X/g_7`TVQQdddP7(|\ ,XV/Yu  kTVEE$&&``0`{l6,j/ X zp8$Rf1(/ X_gX#/繦&,/~,("³`1(/;٥e8<7! #{Yp/nhFH]0B =bP;_%u],}N>:K @VVVB e,e+s×ggg+s1,(/9Bkhh(0|d6,3f52|]KX[[[`2| @XX/0|`DNsτ `D4(/%XB!}oȬ `蓓Fǎ`쬣U ,d*,×lll$ikjj* "}4...%Gjmm0|KyeG0|M`' X/0|\ _"Wq×X/2|0|KY>0|KyX/+`utt$333/8??u|ߵ$iQ _bX/Ti+<= @DKx}}}ZZZrج}˟P:::r|˟$` ~A  rX 9VKK @ ,uoB ,/ G÷c `_ _b7== 8>8Xir GSj-&MrD)Kl4@lV+Y#QfaԈ}}"7?cyw?\}}뺿1tY'؋X@8u ޽{'7nܠ|Q `|qܴ˗) X_؃X^^^( /W `> #%gikk+033]K3(8-SXX(XtYg5ÇA,_l[|||ٳg@ɣŋRPP de,@ /_] @8KKKߣ :UUU O< {LMM:INNGIvviiFFFЗ/^&fIOO۷oKee% Ç̙3v$$$Dh<~ئM-11Huu6X***cо+.]s:a)))1cWZZʀRϟ?9Ʊϛ@xf߉ ZqrrV|E.\ G֯i9^{3vaz{{%55Un޼)QQQr-yiӿ7g|߾}Iioo>sB>??on_~YXX!vrIII3:yղ圜qwwcr,ittԄ/--M<==5 ӧO)碾%*_o?e ] [I߅6 GǏI)[ϗO0D?c٦3Kaaav7}6VVVrk׮͛7AW^XNuuuϟ?- 2|?CW}tttX߹sn^|Up\iE]mdLLLn/abTr[i,aYU%;?Gvlڲz@oUlbªfAۯoV_=ZA3|gϞ2}/P}/۷N^g:Uod ?zh+uӧE-V\WrEe [l)6Uɓ'K- RbQݾ}{qlDm ޽.>}Ty! .]Ξ=;C>tŋHx}b._[ti3Zٳgp}lڴN'u$D"o"ؾy^j:DoىfEUfk׵\ jS!tϟ_߿߼ysvnpΝ4Zuj"ׯ_/MS4늒$uܹEUOr={cP(w{ K6dɒl겒޽{VQ f>wލuܹ3ij#ϱ=P#{%>K'XjUI ` CX"H$M$D}oزRZׯǏK6Aԁ>"# 35/xbddάa,e}Kֹkm}u<1n}u#p-o W\)ݡT:6wUk@'ŰqƢPqr{_`,ׯ)!ޭ[6SLG1omMT\ _pሌSVa^:^7@]hQw…e+8ܼy<^n]Q\SЯ]VcbIu޼y% o}؟/Xx=:T@ 9֓'Oʼ߿=7'H^yzr-xlYygspC؟xy!p㵶z"HH$QAЊ"_.5"kA 2i;mՄF'lLdyM qug^ی [ ڊ%s̙33 \Z*l`]fMs5rǎ?,giFjʢ Ɯ#5n0 *Z%`}y[587Q߮ GslJ51w8qb\2+I[nSKPHB޽;xlp듢}KXvmwԩˢWGx2_{J"v #&XQI>VXQA-m=ru(a䷆Mw2˕pNi7D"7H`G" e˨B+"eȩ5lzF F[^RMHԔ5tʕw۶mEl{>&l%ضS5z`GMlM"]+ ,^]_gk<|(AH)sRܲou5f:TZUr7l0}i^c d}B&IT"8\-D}o^ `kE]k"ZiH$&1Ftln"C-$X* 7UI1rvӷoO*:úF2 q jlbH~^0@W Z԰(5U{| x*d}+w_5xiH (V Bv CL02߷=7H<^fAY3k58~?^Og{QM}, m@y҅Y+C'Ѥj O'''qKn|g#^ ߻}njx%E%&,Y:ce鼆iS/̪{LBqsGH5"7ݸ$Fķh1{C]e^ZT%#_Gdoan*r; mvkufh=`Uk%AFP|gh2AvFJHxI4P$ï_ g,!$2 !*E@ìGMHgt Z%ڈJ"}8zzDE4xyԒ>]uFl}ddS_QXϟ}5fdapn8s~n46P_H΀րW]X2gcAsӫVbU+ׁn777lN/k,2FXGGـHַ<h݋4t?ٷU_X.9[^w>0)&<9\!t5@G`>ԙyVxl܍YI,kndg^'4s"dݻwd_Z>s#tn# sjj4=??8>|M3HIȳ-R0ydN^U;I4 |v;oY UmFT}WW7k + )&\4a{%y":-Ch7puhh4B#j iyWbQLtֶQqu|h?HUg^݋:Ԁ]KKklltUUUVQUFuPwmrCʊKJJ>GqgΜ) ֭[nbb;e׹s<}}?o7 7u}!3zEx?zL`޽!ݬ:)_(*nfjOUһwSuVY@ @ɓuU_=֗t$h=q(S׮]YIl߿送]/_)-I61[k eeel+W _9a~A}}}ӧqimm7QСC!իWi~Uăn~ׯ_mCEMˏČ&{pH3$>l\zzqm ` ݳgϬ*^w?|`!37ȃ.ӪN^zUWޒv l^K< Oܼy3 5bUWWgn[[̴4 /Ҩ6R.͡+FSu ᦎ:ʇv'NA ZďbmS9N3L ]rr ,Nn\H |R]\\yPUU^_yUwpp.ʴvfرc.##¯oH.VB+f_GGǺ͵pQAG8hSAA\]))).55Y ǚ9QYYi qd6ڊo4v::ٳV!uɝ;whiA@2* /* _.SS$p7mM _ii*nij" WzXMc` _^ WtR>\WE.ec#/Tޏ?z*\eɁW? o4#,0|:z5\er߄uKl=÷P/2|9/"H?{188(ZۂЕ2|9+?{C?j?o >}CU/ϸyUC, ߒ `yq *× JqE< y{F6{ _: _JUI*NA$umc;͛IkccA߿k2|)Cx `aZeX pzU/嬭 Wqn×fX`™ W _ڈxX`B9U/*.Kl+Fp"*×bpԔp*Xsss,×fX`‰ _ʉhchhHK- `ly&SX`RWO2|)W^ Wu1zݻ'eF6C0|x>, WQ _ WQΎbrA8×fpB׋t,×Ǐ###yzI4\,Kx=Z\\tP,×bi}8`Bտȧ(6=/*ؘKXPq=?| \ej˗;w$Wǜ$(/ͶG[]& U!\eR,B2|)'(333Ẍ́ _ WQgׯ_×lkxxX pKl*~B:C\2|iM 苼pKVWA{#XX/-`a%2|)G O2|)`ANIU+++U/-|E _~ `, "\eRL NX>;" W޽p6i֭[X/-x`a) WKUO>V`g1|A+Wޞ W#\)N,=|P , _(!UL2|iM .OqFr[gŋ0|!%\eR68߾}KN< `}`2qiEbww7ypp{n<0+JIRI ]vFZpAO÷4\ KV< _$<1v0|{Nnܤ" _" `aҷpU/=\*1er/~Q|!ypoe*.loo&e򯼑_0|#\ z480|iu+ `^| ]xx[PpokR@|m$X/oAWaf W cyq||``ITJ>|lmmA @H*J255u72Zo=}1|Wq7 yׯ řgϞ W Xe[gllB|1y a /`` sf!YmQ7Q#BLGMAALJ}Q|(R)|QQrJ5 KY4iRV}]P|9뜳Ϸ\{-   W0ׯ_q   +si``z{{>}J^/^ }`7fׯٳg=}:;;+~(9Ƽ9 P:q 555y`ppmeeѣSy#D6$$ᦦ-=÷ohddd_o߲7:@,D OE8"''?xfXt便%rppGAݜ?Zq`"""hϞ=4>>y D$666ht޽{&%%___\!_jm'|{zz])nGGGYMOOK~ċ+~ FIbϟw^:tG#U  XC~9i<g\Qiɓ'J9::[n3l+ 86߿3L/,?T$ooo'Ŷ,A/ gV˗,8ggg @埽=W8v۷@ bskx!&&&tv1fhhtEI[[ 5 >VUCAŋ j1V^^9rzynӺR,”1xt_8[8 xYhRC$}쟡'1ݎT ^P։lsqi6F8Pj 1m#*p/l* >&Wlgo4-;aشQ>1\'4G$//?XeeeJٳgyFhҕ+Wիtڵc7nyzeNIwK.q #ު|Vx{ܼysG|tAv",To= S PAClFMC5Ws߁=,9No"bccBk444PVVUTTU!f3aI!($ h۷o=;::l墢"Zׯ_z{}<ú>m&CaM.~'tfl y Gv޽{4)|堃ܹC#޽?"7w by?U/줩hD&T.lQ Bᣄ5Ć"mmm5ax삌61aS %#p.>. bxjDo]'/ xaC),0`, $&^ ;B$Mt+9y 1ɚ%3og}[{md55 '''OOO Ɍd`k}:SoV|{pۥC[u<$֎!]KTo@>VW3q?.dLDNM~rLD5$J}xя<Ll=zT٭[Z&.!ׯ_/}peew0ի֨  [v`,T5FBbYf߿_H2m722R $h#,B\I%D7ӧO߳%bXCu"W\nfg7{f{{wpp?˗/޽{۵B',_îb8G 8q" rƹ~Z߫r;A$םU ˪߻ְXcFŃ~Xqٞ3)+ji/x8za!`y]y/A˗;k۞@ϓ u}gɼ|y޾}ۻtRQ2FGGc:'7韷h6ЖTH/DW?yuw*x"z ޢm p+)h͜@lC€!X+#r}rujjj@QE9l+3;Go sHPQ^T֭b)g(Ĕg`aawrOpp;Q۷o"XcXsKQ9GL|#AS [sARILTxOwL5~ӧp:ՋAu::Үgs8wq Uz䱨ś7:ֽ3opԝܱ]a _V'K?rVY0aI?2B}7>>^< 92
|( IP¹cU<~SVJm",C%!Raw^71t CFU k.5#tXGe|#l:h4FQ.wa*xi+9•5)Ύ7]ʭ,{ıޫKJe喙2@(HBߔA W^-a&]~&҅B<<<,(Y_@~ y Ϳ[k'c c"eǏf9,,DQZöf$h$@!Cņ,RCbD"Al ]^^} <*5,rD]! NRj "X?8Bx ډ~%92jD "ryf|9GAQھ%dȢL|5)ide{ɍz^z ^y{|s ;;)3O ].)(*#?A؂wΫ]i=h" 3+0hW҈fcDlgHvO=ۿWG-i)ˤ`u SL6qel&x8'by(󶂚T)o&mq _+5uwDS66666~72TLQȑNarlOk ѵ^rFҌ[F6f;Az]BtXJ4gLaMߏ=gdRv j2* 1Z$:/(Ĺz?ΌUd޳ޚr|ҏ㫤a*PkVֵ2LGF${D|ZVG|@*KWF[!OxL Ǭ"RѤs&h%n 7t^x{1M "O Dpd`CT D֫d D5yƾOEҁ^%+ W_HY:%tG|8iQ`~MbɊ_7SlEVDˢUqQN,r] z$VQg] ɺw%+Ov;F3!J"{+\V$>Ak}H\t"~p׳q[H}okOOOb+ T:|⭬i,uX%֐ųz_76666,D۫tJs}}_!BU!TgEdRf V{Iyvv?H؛elgdJYh*vnwsۼP[zͮLk;Iݶ G%xR|fMMJFNDd\ļ~%N7ٷ=m5Y&wgQ2~'B\/X.xA{<>el{WɝU NIv.!rOؿU$("]1w#wncY'TᰤHGJQi$uVUP_ٹڍHb1.~[w,l߃N锜p ;F3"?ɜ+q;PkMv}>CM++;`A +G)SLw^i[[HyUsa+nZi]'D0\9ܯޛ|M9U#[InjmbCb.ڪtI|%d.&[WLy%""Ptz$^D3*~ •\J S{TtV..V!&D'mD}/d' )B^J4=UY?l~DJ=7u皶sHص#W@⍼Z0Wt+D"rf 7<{IHXF7t~o^OծmX'R='Q:Jw.yxLwgWw0WʐS作T:-x!4y&<,\L6 [Hi?+_`$QkF~$Rhdʿ@J6v~ ,FlY5CĐX D~D݋Q{bs>s}ԧ{2}M `?֗!|~DA@hvb +@E3U\癶R ^C ulf`t8w0M5k} 9SޓTPbK6}>Lk@H!;m3|tLOA=!ϧϩM>M~GK|w>Z| _|JM[Ti_['Whi/U͏?^ZV#Uml>99i~m<<<<4fddĜ();{Ę,S]]m݋V fs=6vN'p###MJJ)**2---v{mp>55e7 lP_bj}yTЫ_S"Դiuu <_~LLLX :ŕ{^(]ZZUp@k~)xP޶wki a||ܮv5@(۾^kwtt8y~?33lnnh imkk*ڝFruue ){!w}oB6}pG} Zp R.//̌]kggqKJJs-s k`I"lЫW'''vNi)z^3Nqll5}%m[wqqaL||ES5\gPi4NJ_ϟm?7?vP{hhJ"x4Ҧ*tqӈ‚}׮iP_lXYYy]Y &))vea)}T$UP}^7TPg n^ɚ$y*m DaKrJGZ൵5{'Ep:TJO{S*Uaa]4::h17A׾kkΎ0GGG4B- h]e hV˞ @oF5`d!?dQЫml6xxԘG]nO(^Ad)zcc"YxZ?Z8T@3lӏ>(@ %ER4B,U7@rRpwQSsuGB0>r `8 WUTT+\D?T}zp e'E7X++++*qmˢTwMΞ=.o_pUo?zG(|ɪ&K ogg'tҝ?rV*J_dű߿&Uؗ/_gϞ%>}(!J_jDgqqQ JիWĄpUEC8,J_FE*F /R (ŋE ]HV'dppP"~eQ* .HmyX]=(\UY>JuܹCQ*'/HVXtC(,J.]J(ښ @{"Ym+`=|0WW(ߴ @"VVVDJ*ׯ_[8,\ue)F^7JO |%U^ϟ- lvkZ>*FccT軸ʩHV`AkUD/PIY$+`d᪑U}pTŋ"J|J*F޼y#'X4]x&J|F,5>>.Ec,--%O<|*vt(B/ |fG޾}{(oNM \;(Ս7D/@+"Y'EU>Q* %"Y;ػc(( 1ؠ#ZJ$[JBH(h $`(ל5 ,{|_ ̽FgssS Wݬxnn(`5zt:3XՁ6gϞ W(`Av7>(L,*TG D/F>~(5k{g]&phntQ8-J|Pd#{Dq9`\(Uԙ *G>|&urr]T W}EY[_ Ű+uu `Q"\j.A pFɊmɩFo!X7*7YWR=|w:Og_>^XZz(jgHſǀ+M1`qQ[nTE0\_F!~o6Cp(Ճz0F$|qcիWX UC 0ʑ-wyiŋvB_zQoR|%W|_|ϼw^:{4ߗgϦ{2L@5~Vccx/x'c‘#GҪrlU业{0<</Pzj!/8ccc*ܽ{d ϵkRw /8sѣG8.3~b@9{GGGCgggxyxA\:wޅ .<{,9s&͙`|vƫ~ZZZ5JǏCkkk/p񰶶{UsPQ;{gffv=~zʿ O>}ʏsݗ/_}6ĄI*g|ov=?LMMw=NÇ&_:4ק+n{)|c0pzR/Tߝݱ2L|ɓ4ŋ]* eS|f+++Eqeի׏=JfEs W\1 @:uޑh_~]4~ܹ0>>͛ȪЭ[BCC^|2b}m:ܜVh ΦnυǏXlh[=~8?=8q",--h|yx6V|ҥ޹s' L߾};ܸq#r9 /  (RJ)R0\IENDB`optics-core-0.4.1.1/diagrams/Getter.png0000644000000000000000000007047507346545000016037 0ustar0000000000000000PNG  IHDR'dsBIT|d pHYs&:4tEXtSoftwarewww.inkscape.org<pIDATxKToqMPi; P t)R .B6Ph(nnfy+-+xIP|}_p9c ~9g8>D(/ߣG+K3;;ky-.pQavkkLMM^cy gĄ/>}2͛7^jMtt2gϞ5gu7o<Ծ/]dN:e}mii1u?7_UtL:UzyR-..S瓃ccccĘ&))ܽ{˗/nmbccs>*j8pM|5tW|>yywT?yO۪lIIImMWWס}Ѷ>@cccxYWWڏ7èqhgsssml0vvvLbb~zDk<=2###~;:R(w&{O s Çu;Q_@Jn$l MQV'.JmpLaLV/ܫ;ZݽgR- V@póU q"f{;YAU}!jSg\CAy|;[EVH0T]U׆Ir!SVGK߫pIRL뼽:WEWiѱ@ J0pTtޚsŐmF+(<޶=644*u9{@= yDUZ]E7Sj$9ꦡTqìΝ;{{E'Oܐ0{p=}{GF zflu,̚L \7e\ǎ&q8J~YHGQi[n짼ܮӏLJqtt),, 9 ~W⎎=U-7A\W;N꽡Z(j{FB^U|{i{ܶ2쥉~w qlqQ(h'Xv"6V [ `E  X#AQQÒD|IQ~s8{wV~`Pggev7ϩ15Zj1k?, 낭z ?P)vj z^BFU޶TOj?>51NU lPz1ZDz=O>ykUJ:F]]ׅo2ΩL5dGU5!ZA_Q]xu]=ٵDW]8Ak+W׿{S}omm^RU}pgggҶ6@Fz]TTdm5 wOO[S%o6*j uVaThZ#MW~FkZ+)u\e5X-?K+`+* WHmIs?SߋࠝGWᴼ܎֬OM ]kllOK$ݻw6,k$) z`uݞ#}T?@悯B֍nu :S]EX(h4jyxooТ@Bת{@ϟ>A877477A|`߿s/#nïJoJ$wqqPKROWWWD@t߿O ZԺvww Bh:UyLqq~2|X f2 ʣA\0WWWB6z`ox׌2d/PYY)^^^zښ ~3F_[}5%WX`W ކV@E&:991Ғm>>>dZ ?W֔[aßj;::Laa @_dZt%ZjEkMi¢^۫D >T/^_1^(,^(pҡQЊPp Z%D%Q%"HDɻL93kW'y'HT{O6 ???oW+++X/ `ĝ٧?{h8w0|I&XQM e`a `$'ۏKrX\\\U,×0|X;;;}y _𭋫'''`dk, 1"uttTK6Xޖ&uzz<K6X`$'[ ` / ×l0| _&@A %9, ~ _ `-// `d)e:65??_ _22|0|X/uqO~8P _22|핹&P _22|'XkkkX/YuX???#X/ɵX/E$ѫ61, _&`\<{O _F0|In8?&K21x,e2Z7%,×:,× eR'`K?0|*5 `Ek}}] %+,×6PC _G@6X/uX/ `Խ `# 3,×~22|G 0|!9,×rvv&K]c-iٳg}|5>>o޼)Gׯ_?=zJ|=Μ9۷oC4[}Ϟ=˳ϯoܸ%1Κ^r޽ &.]_>{=>};v/@6MZK655˗xIߟ~~a|#Ç}a_a0'eA,ڟ"aaCJ()d!l BFb&S`O,9=;S4{>{s=ݫy<8nX%|;D? |IS ABBB}wp; xU8sfNCCCÛx@oooSEQT*PPh88Qma%}ҪLx2P| HTk-k¢`͛v>{{{Q{rr҄Ti U O7fs^?~xhc슊+A ?  .connT&:777hhhЋNQEQ("ַ&QE kIoWyptvv>l!wqqOpoK~222ϟ?G)))&B7NqD-nkk *++@vww]3_hvv㶐^ZZ2U}P}fu^TWWQE!3b{gffSEQT*tۨvբ ~&ZB"'q|qw?B }uss-#g<[t z0. Ng8̹|]^RRTUU=l8ǐeD1"V d:>>>:E"*k"߿7B0ՙe^g$2hE ) 悸MNNxdX(WQg^''' _ d&4MKn0bA<)a @_aL5a|٦/` t}xxu;a ,0q}=BEqƵ.ї*"syy9]aQDK@_8rmJpr ;<9"!ׄ}mnB]A}>'pC$&&8?~ OQEQ(#GGGigH$+.)ׯ_T6&_,NŲp u GJ Ƒm1yWT[:@<Eܺb~2o3)h~ׅ/_LH|*2s чkeuu|ɅdD[M1ˋhKjjjs?~= jjjLUj^"#p] :c sr5rrr9)( _EQ{YTœ"W8%m+,pe)E”>L&!t.l;YBڡb0K |a7˫p>폄ΆK..'u#ȅ}7ԞcĦ+%4'@ 0brGC3Ë滉sJJJ8WΏPO>Eo((*|Ey2e-U]0d({'uv!\W`ξ,kaD":/Xɥcp,_3繳!HDT4ۈHYy6T"FFFB$QR :cnDښi'|O}}f₻Ԓol?r?3W5EQEQ(ʳ+~ʶ;|VMes>W,ϲ?a]i?H_q!ERZMZZ\űf! r0T]UZ])5J[لRx8ׂ~?/sv={ͥ 4{}}=n :=_ Uþ9|Xv6j7>>^r hT3;sn===ӧ saSCa˒A9߻w/̨/^ğ[?glqq1ޟyu/ݥs|b?z=ߛQU?y6\TK$Ij*Nn+;R-&TaʦѨ"]}eP9.u~Dp{۷ocp#xVͰ᪥}xX֭Qz`822R--#@ڐ}>w܉}>66$砭-Vs,Dϧ?lhǏ;+ |N IW_h~o.US**ÉӰLcRTUaTnռɪQ" 6_X~ͅxx~GK/^l^-ґ3Vl! ' @GS)Gԫy&ޖ'Tao޼NNN\5 f83"=88X;D)˗/k!W\inn.vldO#l\3Ɣ*ͼ^ ^:7s019 %Y2a%I2J4ߛkTMMÖuTO^e[e(7K6ۨ*MΫK9sGvRE;e+mi^ Թeʊ)siTvZ9s]{ r?{엹3Dc+L?' OMM%y缟cu3Jbii)Kg%WP^ט9>7/!f\$|%1TyTKKURsMH(_r˥\16U([Uu aeuQE:}'hSu#3Ef8>ey8IӡOTV*o$IWHMsQZUeJP!M\B#͗MI<*q}*ka.PNW}B2} ܇GJah5Buubb"|+ MKN%IW+upʉwƪ?]iN8cId$J>|Xkƿ4m͚$IW+|rt$+I$IW$I$$I$I_I$I TS$IdtmlnnÇװQ8>>?~k$I .*>} +++Zx];˗/`5߿"Hd?srr+<AJ,CWWW avv6,--ϟ?}OI Ԍp/_"f۷d8e{Ahiip֭/߸q#tww8B$$5_e,5N Z 奧''I2JR3enFׅ8^,BAp-й PI܂B;` шJq6ߓZL7?+ ی=s~YYYq3;]˗ޗ... |M"zp_=?{{{e·3cu(b'nqBqryy9\,q3v[`~~>s+y; |LVrn@!F.oc>x~\Օ dKKK~_mлࣣ#X3q3^UR544^O MOOg---ٷo߲m?P/@jμ[8??zqq̼}LMM'&& xXM޽*i|rӤlll,knnC 1׿_\y /DJФ("=Ӟsл+i0t, @0%|i q/1 |H,KsC__, @ ` _{;5<<]/ 1/KVXt(4&&&BGGG4 |H,Ks666H65==99^X4~+; @j ` _3 |hqkuuo$9/3%|iN7 |HUZ5%|i>А, @ ` _3 |ho7%|iVNݝC` _0:::;;g |Hw[W6 1eK_2P/i,˟~+ @buK'$.`W}l, qouOOO~>c @q>~/ ?5)%|,/W8%| `__MiKUؘ, @R|8500` VVWWW KKKVXBRsss `J"|7J\.;@@JjZ8??{{{_X+j @{`uww9Xِ̌/1_ |@ex{@О[p\]]prrb8:: }0BRVmӷr,?&>s(]XXJvvvwwCV˾A991hLaee%{L2{ ﺳ}o1@|R]5$þ6 .t(ŕKw ܈S"*BOp# q-p1t̋ !$1I'`'Tvw&烐uW眺a _0`Ӂ7>>.bQUQwr9'hzVK__k15|BxPXկqrrr~ *@Qw3|zUzNӧY|[H~oFn޴J2 ÄaԔ1pdX [ Z|5s[r͂ oLhwuu9.@5 Ne>都NIǑ#kYZ\tev _|ffRbd0  t a" Iggv603|E(cI+===7ʱ5?!x 0VP܈VsmN:E01ϔṟ`Z `a AYR4F1Dj.铮ZT${?wG6y9r^L8"b \M͇v"hw!IړK߫╲)/lLijE!WtKc}JZ~9RwjIˠ~|틜 C5^XDZl-y~m#Rs,%/\p{X8?/_Μq"QGnᬁsvۡCҲs̾rR|{W/]/۸/I;Eȳap.im0Lu4W+  y(iKoM:btk\JiTM Im0iƽR |ˀo5J; QW &\\BҎCEJ_n>3LKef.JIG}uMyߓ:2Qgb`LTnna0#Jɋ{~XjM'+틡}iʼBX|ofC'D/\lnɛ|ΪE4M /#oDžuR8p@ƞ>o&_c]8j!ZV "`݊ ATmBF.ȺM4. BnưhM^s}g|yyw~;|sЃxޔ֭iJ&l+w5@ 7 T!H(/R9|Q \iU^#>zՎY>TIɫ8RpY&qpH lĿ 6j%-/P- 07p;}G}M roI$Bڃus)hk˶?w?xَ 6X]i۷'ƍOncƯ][-XF~Mv;wc{OZ)=:WǏoؑH}%wu\_ A|2*6{!_· $FA PwX>rJ*/DbwS Eo.;6}(k ii*&uB{l2Te '!T* f#2jBs$W9&%ڣI0+"Ց;<]6!|_뻉6L3g-8A޳#Gj1aCQubt)ʼn8Lx4j]HitlLtIΜ Æ^)Y^MAa9 *g=z8Hg rk" j۶r(:M{6j۶v~/M# +Vcՠ&v9cb Bo]B[~'~9{U0K!g;MJʪ@FܤHrJUdAAul~/(^>@ez zwǎ%b |{w k|m)ۗNd='u֭쾞 VJ|~MN a_9H 9\_ E+@S4 ɳ ,JTd ɩ}~`%("lcm u Yuur2Ohݶ}T) TڷwOQŭ\.9YhRc˵d9389>;PVJXY6@Ha9[ު}0?y`"A|2o)LPfP.{0V_z#"h$D*T , MIy.!\;xS)Ϡ>/kWR*`l 9T<-MMZ{rM LJA藖zR* pcMxX}/ʮBtW|IyQ , ߟH }?\nOW̫)l%|z?U1g ٹ}qs @`ؠ9D KQ@LXgG6cGRRpnۊ8ÖpzRy-MY:^ YADn#lS rCelAư!oH@Ԃہ۟?r4nS+/m^d97%er6Gs~[iQ7ES p/hclʑ oMNj|j&XZ۷_mXJDjS߼|9-끮ի{g.&U>w^, C49G^W*T#USp;V[ ̫|W83%+"_B fȠ0QHWN  Vl:GD?k _K;]1~X}I+A}gO sS 7ys" uEx͙22pBҥTh+JƜs&zS,|vT?L_4kOޝTa}  @OAhh PB,mцB)A"1A RPBIBLA`a+{f6[Zƻw‹=̰U{'=Uׯӧ6}zիj=ʭ7o¡3Gs0j{Y3H}~ri;/?¥ڔõmnҡk'@'" %wUn/_H+TzWt6LgG**(NMTC*!*< @| @3,]ڦ'''vԭ-d}}ۅ ɓ'T.,,4ڴ.k|D˺LOOMMoogֶ },]MMM5466-))ɤ8szz1Ŧ' p)/.._Zy_DP *5jTW^0_qN6uwwuuu&11*{m rj鱿:33cCEmրl7:fggԍ xTQӵ}MNN حhyyINNxLYYO@m8'MW+zL&UShz__ ŁpL~ZYYj-֦:M||k/ ]ذwxxZW%UeU?-//סɃ& q1toUUU*077g;\;ַ|' /]WGFF] Bۋ333hެDWvq^^2MMM/4ozznnnړ@ 'U AN{,踛vnh ~imm5)))7~~hhhn{{y]H_?HW5Z N<uRAD(ܸJ@!:j n@hNuc o@U Ѧ*jY }TVVBiz[.))a={ :IWɧu8ʨJŴLgvv/2-q<|pp-/#19P09{?L*@w2ub\]]*vCWMzJqnЍΠ/_zܕ+0|Ekmm /[vp V\ٍWr zȟ-`mllt _h,\evE*'_-WU/ŔzUg&۟0ֲ(L\ij7d*WY*=oG8pK  _\^^v677 pU|^*×!W&2|):S/ /YYN×"*NGOƋ MWE9>1|Lq2|L .w*×guŋbR /4pK9*D%M4P0|΄ _pmgʊ/ԅpKځp]/ԄpK*ވV)$cRL FD%p2|I1`BEpU\2|)&\_'e&"L *"\ev.\2|):99`0"@"\eR~Wʼn"`?X/ei, _*×4UP{, `s߉nɋ Wc7N,ųX/ `aBB?*,}{{ܜ/d _nъqēKYkyyY ×v2|I;pUqmcPϿc×zX _ZA%M[-\&eRN ×2|IW{A4ԟOKT]pB-E*]T ވ;_8i  PpswazFޜqf$!8;~|o1VK/եJ%_W.UP> _M | U/WA(|[5??AA\W {ljχ _. Q\% (ɢK%,_ƞ*bWR%R,_ƒ*|qnWq` ;`!2ZQ\l6mB(|-w^VP\[ll?Pt^U%rX(޾};+cC rc8tcb2{5Uu(|[AAe0bY$|V+KK1x[s0\7*`` --.`G|'*®VWS\ܴI.| |)No>UYet `!rW* S\$` s(BU($tp+q`! Uzˠ.?Xr =WeQJ/-S[e|)/[SX/UW!S\TAU^I(r,AQ\TQٻ<_AKC*|+_IK(BWǞ_F! ߿Ke\)Bͧ PQXǡ|Sqo>Usfsw xAeW!S\pn'H_,P\[|۝cap_M,=zHMS\*m(˸`j5X/ 7X(#p|n֝;wғ'O` ng+V+@ۏ?#~ǩXU4*2kkkY|g҉W(l(t: X|~9[`@)|)~@  / Kx'ٙׯ_۷ooo!5޾}?߿O#q~bqǏl7odݻlL~jȇ\\Oq5}kq˗trrb&T%ivv6ݺu+̤ŋt }5VݻwÇӳgǏӫW֖`cc#=x MMMs˴o'-  Y(Dq@h DJA""e4PD KAR-- -J R+-pRb %[s9}뻐gݳ9u^knMII6''G|x|||[װbwu033#?/_JP7wYeBDp˗/bcׯ"[HcLMMoߪ sI=44PEEE&"",..=&&&L||P%`ssƚ:|xxXA1Ej#^]#]XXV[I:zSbcb et㓡 B0!P۷ϤYO622r\266fCx?{*ONN6qqqBCAWW\Î"cWA-H 6Ӌ|}}] Xbʆ_~ B߿7{1٪ EXk!hgΜE֦rڵk&**ʳ,&&&FJlHLLɹ/5ǤMz#rOܜnD&PYǏ"WP(PC /^Pac}}}VyzzȷŶqQ)@ϟ?NkܵGl䤐_/Ga3yyyYR MZCEng7Tbrv -V8H5j㞓Mkii77 {IB47i=P3YAcٞbg©el˪cCϮ^/µ5 8?pIW-dGy8u]* ş-)m;2S__onݺʕ+QbH@Ц&skPw˗߹sgW슿 Aj|'NXυk<~ش~@qdɹA'Ocz{{e/^ɰ۷o˂1 ZZZhX?~yyȜ^p6jrOx;^ R544XQyub;6Wu7L):rWOZ#oON_܊s z!_]r!tPat7o"7/%1$q? v1xvid5]N8\3೼41.A1k UFj!c$D 1>?$i_2.s ݒ3<{Y -: 'bvXe-/6gga[WN/Q ?b<_u|y`د1R( ş-)n:+Ł0@)lssd{nf3'э" !9{>@BBIMM  I%<(y1؂XHcRRRP Y զJ|ۓ'O $F{2twwLS Hl‡?/nV#ݻΝ{fr3 uM7P|f;WkRTF؄,7Q0jI0l8է#&lR#,!^f_;>{]wY}{Kچ6X}9>)eܳL '#곤殲B;[ xau_ "M0JܢrrTo/(?}_6Ե\3rN^~}l󪵝>|wH-y*Rc*>}~K VXXMB%SnnnHvݾ}]}!D:3W{O)ǫ(X2{4L|?V{wOوJMIK"~M-ޔS+_mQ?<'03T60&JU% vE՟ˈ9,^XeBN SaC˜b$hn='o|أ{1~w? ^Qz9X!sT,3G*W[g`}Sx_~m "oU@ulJf1Z`uU2ɯ )bػc) X8 qn;WAB09FDX\p^}#=fM7+2zbʬ([nk^Ȯ=./wSfu}/^8M«m<ŖXs\Yx-wbX;ZZcNa!7koz24yn # ЍB= fcs=;qy`G">!uj/+]Vx}h.8XSY%3;y7W'3sJ;;//=[*ϛ`d.eL=r;-bS 7170+<0_|x"3^ wc۸]wٷnQ; VhtQɓ߾»>|xQFNp2W)wD= 'KD:\Ǜ#͝0wkdЗMⰄH' : >߻.+3ĘN8_ ᡺&#bG$WTYp"jF[Y!.p][%wZ8MѣRF+_y-AXN'6 Ɏ=F0gN^(d;MWMFwK_JIAl+BN/69GZX;Jz(|%b._ 1-!<Ptz$G3*n4A@zQBtIy'C~lXmF4yNd<^(\ĺNva*kM߯5NnvQw9suĹvҺa|yƑI^|^s1ohϸ0X4υ&ɾsυ&*)?#영J V{͛kCz?J\I~\V+yUۍec?+dzF; 89kM$;)yX*QƬ$O<Ć7gb,"1ϵ,>?Ͻ.1wgLt.-<_n'\/~,\!8[cDvSߍ_RJ)心&u?oz0%"w29?e *{:Z݁W?55 "}Yigg7E$ N o*SDN1lu, 5;=Tl'{g\Ĵ!h Oa9իN2}uȹ>vO_rʛ{aH(v {SRJ)R RJ)RJ)RJ)RJo)RJ)R[J)RJ)TRJ)RJ)E.J)RJQJ]IR*|?BTuRU!_>|]KӧOׯ/ԏS[KkRJ9|Çߟ~N)u^ݻwǧOo߾Eoj r/_n%Xnw7оq&Ss=9dttԆ TUmhh / $Ix$GQ=JrЦhwn0vvv>;e禱H-(j@cZXѮ̌9N*(*%YH>ÝΣQH\0А;k†d*k_T>hR3Zhљ` &*j-ޙI1DJ/PR :,&JR*5;KHۛM$ DY\Q\$YJU__QJ]_ M%Y:`JJ`I4jLkkk*+ܥTzƳƘ5L)@Qtp`[6 &T\. _ QT @ rR]^-0=/PT @Q\dPJ|Cdr) |7-94|]Jx(EJfW PΕS ]U@,Ri$ _.T;tD,*++(4/h%YV|'(**^)TJ{SJEw @BI.b@U~C7(@FKB;}dA X,笠 >\JUWWQJ3 AIb @<Y蠸*ǩJ * ?n wwwG7@)@~PIƢ5MIVn `iU, 7]]]Q\م+8@hU#^CЭ[pOn-nfS Y1ɰX=r'e̜ٴ1Foj*s[!J_,~(Օ_zp*HVD+=prr"pUzEy tD*P ijyyYQOQ*0A$>b؍ō> `Auׅ**4Jn= 0/%U}V,rD (4\[cOQO>R$jf)%'4bНHv,WQ*0u_$+v [HV `AqeU}...D HV`AvJ*(| Gb>88*,l*vK9dTo޼/Pu"YoVO /U[[[I᪒Nv(`{,Niq `A>FR9|.ˇzœFb7ݻwn dV,XUXg_ni WqV$p $F= .8*;WWWTeQ* ]G$*"Y" WC,ԉR_HV [,5\XW|]jRmnn&Q* R>"Y!Eݥ᪕1T/D`Q7?쬭 W P6J;ijggsyy_^1e#Y+.@`QuUR}Q 0"5xXTQ>\hR_>Ɋ]6?XTpMTo߾ &5XUpUR_!/b,+RNn d5 XpU;!OTq/Z 0@>ǏޞH3 `Q$U/X*_Fj6e|ׯ_E**BA>J_ aW$b-v4\W'0#d1#Yxm( W+G;бPq|D! W=,(y_x.qtPg_>J5::ڍRQ ПN$aV Žԟ8GcR$0 HVoq4u_" W0Z6ǡEx&q'Rijqq1Q*/@idw[V7u}}RcGGGq4\ Cu"J`"Yl6kl*v4v-nQ*/@-=ɪVG|t2kꎏ˱_w6JuvvEay 1HhFl((Jv%& )ih 66~Xi 1bh1<7Kٙn]Cgϙ`h?ɊҒVM5UϟƗ9R{ >GEf-C/oFFFjϟ0p\:~|(_N@;D|*VϞ=+J`!,j[J @mѱ]ɊfjMpիWӋ/*:D TX>5j9T9\϶/ 0PUud `+vT1\0PwHV\ ۈ*VUGE>|m_S /0HV1%uU-\Gz{{TK SHjV W)J[p_ RHV e[Kk׮ WR`-:V WT1R`pGEb2 `bU߾}+R`5Gb,;+ `W]ppU>JE /zMZF$K᪗/_QT|?EFkqqX1ؾ܈ReQ* ^v `5NƗ T| 'ɊA4Vd=UT*@ѣl۲(_HVXET/^܋R}?b il^YY9Hfz}Uv޽444N1R*oR`iG>ŊI(Ugg(U|I_(hȋkWˈdM>Juҥ}QO>y0@ʊdUUs#ۙE0@ɪQ*0PcEEZI>Juʕt9Q* AY˗m^ZZJiggX999];>> cccw5sqF6 gϞ->_ohww7[ 0Vl>>ӓUooN~-`,5d ɓt̙411/h6ƙj'Gc80@޼yПΦ;wǏ|qB ֭[ٟKׯ_Oo߾ո7jÇ488pvLKkkk{g9 P_>炙w~UJ~ڻ/ sw>}ƹn~YS8y}mbae2aŠѼ8A4XO[B^O&_P|@@_ۺIENDB`optics-core-0.4.1.1/diagrams/Iso.png0000644000000000000000000007636707346545000015345 0ustar0000000000000000PNG  IHDR'dsBIT|d pHYs&:4tEXtSoftwarewww.inkscape.org<|tIDATx[HT]p-0 {B!AH1HTDA3SITBJI^k%$!BJFDCA)!J>YR>QVZƹx/?s=""""""̎""""""bKDDDDDDw{<~X$%%Enܸ!?_~ɽ{xt쬌errrͺKKK;>󈈈/,,,HTTܜpΖK.D^$((He{ѲM)>{lͺ̙3<0DDDD#R]]mQv}hwttl{2ǎC;Ʒodr?~赵Y7oyqqqݺࠟ!""""ߦ&9t,//[}Avڥ,bjjJf婩3vO9g΅ gmGGGɓ'7TKNj/xP/:ΝZ633#[n/:߶rŋ=xDFFZ-k׮mm%zzzZ-h2v9c,O>}UFGG-nDHH1rlQb;_|g0CёWʏ?lllL*^^^Z^__EG>##C_|i=XQQQ!W\@9.\ OLOېߋZU{ʪO<ёRikk6ru6V)..GGGA!""""G! 눈 1m_՟?>,^7|]޾}+۷u0}Y9ztx1 {zzZaj(F Fmy!,,LxF_e5uK_ԩSre=<ƶ9[O>7{3~  15x?~0R FUbѣGn1Iuvv^:x!0F=X! >>JDC~NgF<[Pa(7LG$3ڀUzxxhaU94cWAJ߼y.0#xfsB^UUe܇Qdb4 ?t$h:0u$%%Y-,,70mnF{Mo@KKTiS'N`~/1]Siii}Qcݫ\ZcaQ+,ne XUeeeig1…@~/N#'ػPʿ8xX0ЈSb5E6[،ƂP6IɆP)Eʈt>`g~r{w||߶6>*R~uo~DSZZrQ{ ԿW4|ssOco_"Ǐ1p[+S?zԄ!Ҟ?Q,O{EU]BTzCsZ4u񨼼<>}toKrycbbꓳc'ںVUKwԿ lmmڻdeeTOJZ9sEާjooؚ(//濻‚=hie9\hU lcccAؿk{So@yyyiW\ LNNnkrvvv?l>^ hwgQQ-N-WB MxP/kʧwnUM;'x/8*𝟟fmw^vE)&S@\VVfU ^UJ,UkE u\~>U[Pq6]xVP^TNEu;))X Z\sU ^JNO^8ޛLO5+Q!dUixxضrY\\iuXUK66###F ?(G^GWUY[|ׯ_mɉY[[3X *(I xkog{ o,ZEr=>*/P9ZMR^CT5vvvLMMHԖE ,fzz^R/MU1Z" NOO|w{Wr^344d l[wiok)U-U@ _|K}_<۫xoo/ؘxU߶6nNNN"@III1QQQ&66ּyDGGTgJJJLSS6|`]NNyϟ?8q?/馠TTTo_/^#|oRQ syyɇ_.lll<Ą' ߾}k>ߗheeNM |UU3ڗPYYiÎ|Q }:;;C&ZY0|@A<𮰞=2!Ejֻwym댋3UUU|@ZyMDea8+N^@LtB$,8::VX/ V$ǜԔB>8_'aB¿o{ C/>}:<|Гỗ5_͊WJRcIY_vEX44vóg^#ѣaxx8yƓ`WU4r>~RI#߿QxӧܹWPH/Ez=@p|hii`MMM7oxu-ĉvGOX/u$hzz:wuB _P. _B'eRݝ`:!KԐB&e=X 2|# _K}q+~dQB _P}zzr`|i$tP(8K qk||<| ,$"eԔ`Bl6+e,&FFF _>!$-.. `|joo _`/VTr×tkooQB:;; _>Z[[B%eR`B\.g `: `BHŢ7`/N$'VtQB?_ _{,UfggCj _se+j_JLLL`/*`%:֚.e'T&'']G _q4??t,×?I 0| $`GG _I:upp`B 畿 `/X/?! ` `/(O _h! _~ˋ`BgcccA _,%hffaX/[jkk _Q _Eu+QM0 -U, _Hny`%( 999ʳη7Rre2huuAB(,×Fmmm9`BFe٨P(`B)Jg|v  _0|݆DFq MJ LCDYa` BL {%AD$,H.I$`dHڛh A!y`ugG{V32gy!"DDDDDD%ǏLl< Ç244d۪ӧnyX߿ӧO؈/ev}~~lڴIn޼)O<}jjjSڤH4P,ѧUVzj[ζmNMM2e?~Զw>},Z1%""l7nnÆ .ohh9s3 #/____Ç=^~=o׮]޷n2mC;44T6n8^~]3eݼ/MӧOKffKYYO4Y~,[L.]&e2uTY|K [m۶?~]\p$^p|Ff̵kƝǏ%V>| ӦMфyxxxHzziϵY YG;m\p$%%Y@+Wܡtʒ={,X`2c 9yi۷o?EOO V Q*jy8kŋ興/M,whϟ'9994///OT(ŋ̙3޽{Ulի'Tس/Fx=={֥)))N1%d͚5۷07 ǎӉzJ\7o&=`TB|ikuDvvEcf_PmZt_xQZZZl:::jIz{{5X10N޽{sݽ{׶޺uw϶*bq,h{ѿR%+Vx^tDD&n9bZ9Y-))1mC0'e4"9uO@qۆHnyi{9sFV\KIHHi}XX̛7Og|6ɳg4\__Qw099YvZ322t_[K.>.//Y(anjj2;wJ^^h{]Vyd:{!""bKD+z [V :@xMƍ˗/-ag:cc1C9=dc=2T|쏀?รYhZv00cc ḁN^?x@3ǰd ]2dTa#vd? sllQƣag[ݭA+X{1)#s]JLL~XDDD |7*X>xf/oL o>ٳg-uš'N?;W(O (&L,dc#0Š>7xt^uܟu=]zϹ~* fytt$nu"{8<kgM&/s>>>2Dux<FL㝕{AAo߆*xzCh-Tl^ORyrQZ yTޱB``{rrR8S̾K\ M0H>?%OJAd[d;寠미pJ/*7L>IAA-h~occc4w/5&e`C1kAV9Tmu%TPcAmr=R]8Jv_ Q>[b&YYYɭ~L:=+3U[nii),,,dQ'j~/B16} O P/_B~yy)R]B8=9g>]sss^TQ  7o57y4w/WwނI!!4Je_|J \)bRN`%X L"]rkTc枃 m[-&<>88uk-lS4;0i@ځVSƍPWWW2D[]^^K%ߛE8mtGrkjj2+i"N5U{>E{:a5FSsssmEMkGZ[A>L=p>,{W|M {Mm־u 999T{ ### y'zyCZ>bJKK/ n111a᷹\__spyyy|mTQQavJ葑yܦų7<<vNqZ80j#5/...//Mff^Ugggy_p[{0T޶-^M~.))1˜(~ x4g믣5g{L vYׯ_Mvv]<77 @Qt}}f, ~G%&&|7PUV4??kfxxM[[]d ADaWmھEñ8)+LMM6UUU6j!}GP=])k0_2 ¿|_ºUSVV,?ٻs]8ýPcjEGL9T@ :VNu{<%Q^/@0|++`z//@;N0|`a`fyyY ÷, _ `aVG , ʶ0|b`9 o//`9 o//XIkk70|"WJ÷e:|_ _NyQ0| hА~Z  2XՙO:::V#}>1`F5|++`H^Ӷ6,×\]] ``> _*t _`T' ```TԔ/@VVVX1VWW/@םC6 `;KKe`&,×oX VX/0|"'eR, _V4+§[X/BS  V0___%<599)`T* `@  rY=Ou@MMM: &i' `9KO _b$eR,-`y콦X/XMMMikooQ _bXX/?0|\yOX/2| @ _&L  RˋJR</2| ggg? &‚Q,d:,×&iknn. "kX777bR `uuu `H|k}}Q _bX###Iss7 _"eA8P"Aɹr rk,5Z?4DBR$RCBA%PF @ cǎYVZ))|ȹlYg]]]V566&B/_*|ȫ` nE @^MMMm,`>vO>5@/`//Z]C_ȓ?6|ӧO'ħ3>?KD x9rD Pٖ m=== ʓV'ܾ}; B\~@ʔ[  /lh>|c_*B(bqsN?~<._.]ӧOtv/N<ϟ+WdϞ=z^5o>߿ xQ\p!:::@|ȗsEUUU-޴iSk߾}1<<\ǖ-[ݻv^333}cӹ>~dWRfcSNšCѣqرʎǙ3w6!UtaP(@ J SE+ ?2 l&*ha6lBRT"2Li"$+k!g;]pgܙ33gyHUe}5qPʺGgmHQ0Ξ=kJKK&[2"LҜ}*b:+r΋(RMOO*7 `p[ʹ_XTL$3>|pD^k׮i ĉr=44$oG^ /&>>~ $x~22N|bEQ : o֋+X~;v&Ɋh{[QŋʬnXf=ɂ |t>G<55vͼvs )j^C('j'%)n Y$벯gBFFFJwjjJ"Zgs$!kݾKt Ѹ8g;+6& dWEȈ.sL/&ǤeΏq.$1s{Kg~ZHJJA!?CgLQElxGh0aK&::ڔ&b ׯDo޽{'b'Jz%lubYC" ꈐg=Q.D 1dH{pv{DmHJE`yCACC{Ӿ;#(J 'žm.)ތ r"<{}{kݢ(1QMq8Ϧdh,ݱcrJ~q.%n5&Y\ m۶w,< +10fwo{ mg[=ch̓g6@ W,ݻW>ΛUvG;]-\ԇeö늢U%Ala`.tB䝢XO fC6*wq$b'nۂf4)˗/Kk?}p,:0tnILb}NǏ쿼۩ٳg;;ik Ԡ4PѠ(4D:Q!) TxOߕ ?o[`9"9OSp[ cXqGhֻѽvf)P]0g3عwn)NQfta9nZ5xo(Z= ] G{l{mYL5_aM?Ly_NAuU4ZRoMͩ^ *"!%i`E77<3֦FPx=rttrji٠v1Ή:P(- S'roo߿O6~߿jFOk2P/ S|b5Ka6Ss l t+z!  hqĵ"gd BB@0{^ϟ?'rڳjLm~~>)eADO,Hr;͖Ya*JfZNQnr$bRs3y TVA)|< R13djl/{|*x[2 ]Bvpp0<+55I} m?##6g o!ZU{"@řan[s#`!w;qapR{Bיl>0N ñu4i{̹F5uUYÈ;.7^;%SP(- y|o(Ym1`@tSSmPu]2`HO.^d{aWEz2f(c*yVfu}zz:N=PqQNP9'";#{z@zZE2ǔZHifuW:B{5Y?Vy]&AIDQɹ]MxI1:{6 ?(>GtcΖ^׎1\yoNJ೾Fvfn ׏zKqf;OBoPd@"GkrŶiK$G`s`Yne2Ŕ+XWA~)\zyy9_>ͩXM  ML[d,1&,ǏWw&Цit6J=뼍|oraQNεqŰ.mb-ٖVP]/opEz|~Y *}oVA]1iXP 3){k{5l.Aө,BB aHԞ . jA"`UU0J;Dp~N]E`§ruGcVJ[8pȡȣc?j@lI,GBvEdb0J@֜_a#7\+Go,gaΠƠ_~ׯ_'ic2 Ζi#Ce,E:]NzgD74mf5(챴҂0i.,nf5@Cp{Kb̓!lyxh;}O#pֹ. E| ’C)%cWXqIe dr6rab(NnQö΄Ut ,5.IucN{0t؜93s>ϓ11d[Cf#`p\;?T4.YRc)ͥHԯ49L;}3l0\i 4` |$_9!ĹEn i0Dc Tdg(N+A#l1Odo2hS:0\3/P*&C=F|7Fp<+h=ΜNJ'[aw#sy/E$Քplm{+Ae(6ͭ'db㛎"JOu^8/j~+s3ڄ@ 0Q\@"l@KZ{@pY ]X1.V3ndd0J#;/5{4 3G0e)58d"8q_yc:Co <8i^I6ÆZBfQ-' 2dfcoɴ\U Hg4Q=Yil^F5f*[Fgxi -kk k@Y#k J TQ$X46#":"rDT}o cAQj3TdvSLtUMa S c 5iX9|u#54ڑ5)s^Ga%pVq0`*+""R4W"X1}22x_91 qF6*ؠNΰf4^BDDUH#_.,,?W^pl;hFˋ"""Wkh߸q#\v- fSd gϞֲMLLxDt|E0ɲE͛7Nݝ92k2YYY o߾ Ϟ= ϲ1deDUpҥO[[[uV&1}ixM'LJ{ /ݻwK}̝k-{yDt|E!;eWqp|ru@Y/j8|fVZZZd% !+e_~Y (]z;55Â/^pʕ̐ 1)2裀zbjc!&R&###[ɁC:)ӧ]$)JL+i4u,..c5ɣG2儈t#][[ ?wqрLsw/( ֊Ǐ{F=?R&[[[YC,' +|o񽒐.JKBmdg?SvVVHDG\D_13拹,3g|<`WVVZ999憴 |ٷjZ/i{t|llо]{ޯjƢO粖b``zzzb>Wno{]uxyyyG@ _iO]OO CCCقN*Ei$ʬlveBIP֪Zkii*++3WtAW1/--5K9uNk666V+%%XlJE\x$?k}j궶6k ||]ϣ*PX#ʲz{{9)wtt=f!)fff㠜BQ #zdJP7EWF7t, .*..6)P6(lJ-=?ֹm?==e@AXUUUVvv6Xp7W555&Zgq?hifW'=99aP @ͻl@\W/ !/*-]YYaP6X ~Y@*/".S,wqQ`_ UjVnn.e A@jggǵcAE <]U[[l?~Q|BWW|SWWW}xzzbP@AT */~lHHH0 p`1( :h[w<|qsqMq*odƒ뇖;HJJ2X @Ã닫UX vAyWΪdkk*g2B`_⪒*]Hʢ Y__=U|y|3U wB0XIv)""0⪺:V*`2(_8P|(""8**++(Bߋ`| t}O@K+-i T\Bq]Ax`)k /\SPP`/| Yu||̠|ښU__O@C ?Uggg IO]=!HāʰШ$Uv""(& ٸ/]S]$=nT=',×… p2==P0|j?1\b:>}Ph9X/^+bŋZY6\?v(/*h###X/ `aB7MښC1|)LNN&}}}_lkbb"yC1|)ݻ&'\eRM>\7B2|&nݺ% laaAp,v(/9ֵk0|YWˆYW޼yW>, _hU/ՄO *XX/u`a)2|F `T`yNH6\9yC1|)G*8_~ `T*Xpd _2|)`c/j _ppU: hb+V#eR,/P WŐpK|pX ` N0/oT#\NbippPOaB T#\'zzzׯ_;×,P痣:Kc_~YMCS^< `80|1|) Wݻw/yC&Xs;'e_55Kg+\P _ ܿ?tp4~KXtxw*×w3oM.OKZ? _S>\5==P _ pUJ3 \GgϞ `a>煫 _J|E L>P _rW&UW"hQip`CS ׇ&Zb]/ _k LJ w?I]_W2|9n^WU޽Rqȵ""# HPF2`">p 1R(z;{g)go{ gٸ8|spG! ')$$#qe?}&E׀'55{ 2ccc6|?|_˛XGGG_)$$۞h\_7Pg>hhXS,/|A5Z]](_|5W2Uaaay$>>>߶_ͲE!Ѹ ߗҸV?L %""Bz|L%..N&'') vvv,)x^n n%--X_|4ո*::U >üqZ=<<P Ou L BCC}dٸktMX__ W0o%`j%4"kUUnd|433[%|&&&$66V_i6>>N XJ: B[:VaiiIFGG?}椣UmU255M @ / / nnn_ <.եzƊG)--Dҿ,Cfz ;;;|)..s\\$%%IwwguuU666(8بΖqww???ã# 7XhhS'$$9Ϩ,RRR"CCCBooDFFy`JJʓk)**x]SU[5oTDUT3_r]'///.[< fgguMsss)>DSS:::kiicWWW8VUU)}}}"++KP5u2i||\\]]"YP'&p_555O^WYkPµ߰00<[__ fX㍍ J֩mh^_Mp`\\\P |HS9$<(eQ$ + /=}T)BЗ ;*FD(g393gY{:߾}T\7֊О>}j4LëWD.h0ce(hDDuqOXB GGG.l*'\UfjWW2$K ]H#޵ť˗/eݮ2>33c4LÇ۷o9 bbb ޲.2NݾIuu8t Nↄ\πԏ?L+KtƉϟ?[B~arԄo i|2F8NEyPSSSVgg?B9<W9z\F]'O\Nl=> vw >YH566Jv *wMwqsW5_QQgstf3L4A(:偁n]kwwW> X t+5ykkKxcB& ? #8rN)c߿σW Sr88Ą𳅅WWŋvj,<?/M|ɧ;{y8AܶIKBAh攕e# >BF`A(F b0ǹ\"tn*šd.<9(666drqQ}/2^l(rC3Y[[a.Ȗ򍍍u$`('nnK1E$u`8aq5ƺe`8%%%bX1`]}}(b@ߕG7s 5ě~_Rk8N> >$&&^N~~jߤ lKKdt  1"?#9IoݺZE(܂߿6!84gX4FGG\=pϔ WPxbffmqqpݓ9088(+_8 ܓ!^l N-]"4bݻw~cp#ۄ@Y+=~aEP*..Ζ#(55Օܽ{W:F~8#`[NoCa~-_ՠ 2ǖT^8*l^?#L^)=^D}$RR@(Izz(rىf @sTTONw QJ-8%22'ҁ3Q}//[KyБ"̀]y F"=_ v]i>Ͻu '0<]1Al錸Tݞ$:F_DUIGu]G)Huuuv@ <8 30000CL 2|~w7),An@@pNDp 79s;NN?#A%{m`ofU8'"g>؍Pqrr2ӵv'Kl^ " BDCP+ H/2ie b $WSP>@Wy+///˿q\$ # :gY5[!58Z}c-!e_Ah:8@<brN\ίrggy&\]]-ILtkq xU*"&iT5u.~ <|FVXC&>kY7` ܈)Zا^$%50t(q@sTo>H)dWR2fVq}3 MpשꅔXԁK!6Gが9e\x8Ǹu Cd~~d1%_ >>>֗ 9THVx~? AbWmKҔ J_?Q'϶4qȲ:[baJn#$^kH*>sssΝF .N͟X4{(jq/i\8HUD*Qcx}.!vSN+: a\m!V@p-)y;sR\Rr-A}߉KM|v[Q_`5 KS}Qv!qA }ـ$XϿқAN!T{mO]&vXMvnY4|$jZaHe׬|7Բ/>kr*21.IWyQYطGwj큱/d؈Xhl_6ּ<,̕ߡq?1111ټU+&Kd` v^qTUtW~/( 6˵.!$?;4\;N ( cx8 'cdD5/YAdスdv9QP3gggY Ν-#)E5:,!8y0BH<{oFI3q>3]sP#,:>׹Ƿ~ė{ͧAcǝdUˆ!k p1N|/ \0-G]Lj|Y3yo]'B߯ 9p}}8DkuT#aH nf 9"~:X-Ya`[j\:HFJOe 4M޸U+P;E'IB8p\PDٰ󸱵4j#PO]Ll]%"a+w\W5ؙ5ﭖ=؏Zu9gmRӿܯ9K"L|KԐZؕ`5qЇPֽd%_Fb0r0qQTٶ{K1W:$Ez muV{rn xd{ bbC\/YڑFd 67 r1JX#{Kr~STY}E#kLp4b*GZLi=t{L^ĵ _zSekh q(3^ײ84U/YsBFTBXR[ 0/ Ϛ}yn)MkI~T"{#EDaX.؀ ;`&&E CH, WRܬj̓GJjǦO̒:iտ2(M ~7Yl8墲"WlZVW̔i֖ܳ'Bq/8޽itmv3vTuJ-Y5jc+uB O{+wkLzl q*q?Sz/v5l|nñ :7W*+a<Cj}u _: I/|aSZQ/j5H&-\SW߼y,%eB{].; YeW y52D\i]ϋ~=mݨ=ـDp vgCߩ,L洅B5T}*N)0,&}t_}4̸ٜd\L#tO˃^klͫU ^Y_/M!gf[ͼxcN7p갳YFi+aN"=(@BuMBjN{+h>vQUVľ()HtT}Hog6d!X[<*|턔G$6:_fz]EtTr*.[dRQ~J]k8 {ͫhp5?,VYe|臠R2vWdjvW 3[_.X D|_Kc5 72 ܼWHpjWրm݈ݐ-!xhWY rTm/ۋȱ5CVSRkQ]!%漱EcDpN{826؂#Ӯُ摺<ϟUjY:'FXl/Zil4mwqNO cE־0 餯jhyrVݦ1\%bEeHEޱX-B6_"k}UY3/wqΉ7=jiMvUN\A, xWB!B"|C!B!DB!B!B!Bo!B!B!B!D_ZkB!¿UF"|?lbsJ3ŋwnܸqr͛pmwﶯ_eu!߾}>|}vGNJPy-۝;wGmϟ?^~}Ek/_vgͽrʕڵkg7?愅 ɓ'gҚuӧ0>| l /_nϞ=>|ݾ}{zٽ9YK~w9H\]q%""qCB tbe-iXZY[IVZXH:ZE8ρ;sgGr}=繠EhZ%Slp';;4<z*]iii硡!.###v|8hOHH0uuubA(((zokݻwB7g;zꛞnhb!~ej~ʲGEjz5cZ[[G]jx$/nooo`RSS͇l[RRb& Ss>}@Ą=/; BLڹ.^~~III]:E/ =Uskpͯ mC7SSSLOO$'^߾}k.(P+q7 ^svv֞5Oq_xa_XXǚDm14,_hyyX,9'h-hR7vNm@;Mi΢ P$Djढӡ|.j#̀Ql>~HVbڟ>E,PGG}oll7oޘ;r6@_T(^~mM5!VmqqZ_|nHp5$`=d)dKaW^ LƾzSYYiطmJKKBDhE}]}rbt= _č߿V4j{!Yd yf3??O-*N))? t,K"׺/UNVl-Ju֭E 0F>,'X4]x&J|FڎddADlchU=T@Q* %"YZ[[@]s,*O`Q!Q* m"Yq޽xUlϟ?/\ETvdņ,VO֙Xbꮼor (`(f-dQG۞x~ȑ[eBiWuϟD*ER_ H#Y.^(Ƹ{~/U+Juf/@#YNz',) W=}ԢSq</o"Yo޼@ ,Bb̙3T_@"Y~HMxKiE?#\4JSkqϟ йO>d d%`bُ<\G3%\4Juر(T_joaa!z;v8 BC A856{-QC{[sf[((B,+24 }ޞrt3sy#}0b$+n߰95OΝ .᪸{R|*f6nK:G677"orXpj_ HÇmõd `[1\_Z(xl1 nvv?+]]]u>991yf{GlߢpԩT|y$'HV5*Fu&J`D"Y}MU09摬JĄV*ُ?qR|W-ꐕaDU)~@c$+nb$y[V9JU PKT%bHv}`UuEL`Ui= |(y=UTa  kU ÇZ @){NS^ٲ񔿧/PT=z~ڲ&{>~<---$JɊCgWǏ4\UR"JJi'ɓ٪b?}TsyV9\5::Z/JdɊ*mg{{{H^ϟ$\5==E0VFjW^ /Fq@:rH)Xej}|n߾R`Þd*#\^/ɐul"Y1t…088Xup}_|1JWyT|`lll۞[so yU1JuT?v1`2Vkٲ,~ \5ّO %##[Q!o䤧G9l{GGeP.WWY`]omznD#}}F~fhH\rs|l'&XO@NFʊe {uhaA>4T_31Qލpp?5"@>F5Ӥ$9lnb-<32r:u=e `-+:R۞3j\ 9|ů{Oe% ~ 9wY8LA|xPuuq{#WWr"=Ӹz3Ƹ>_ond)%EXdg-++nVQ''쬾Od먭M/PA787{srX.>9]Z*c@+uiYȐB@~]Jڼ[^6/V萗{߯LI` @ 'EQEQEQX3u408IENDB`optics-core-0.4.1.1/diagrams/Lens.png0000644000000000000000000007143307346545000015501 0ustar0000000000000000PNG  IHDR'dsBIT|d pHYs&:4tEXtSoftwarewww.inkscape.org<rIDATx[HT]p-0 {B!AH1HTDA3SITBJI^k%$!BJFDCA)!J>YR>QVZƹx/?s=""""""̎""""""bKDDDDDDw{<~X$%%Enܸ!?_~ɽ{xt쬌errrͺKKK;>󈈈/,,,HTTܜpΖK.D^$((He{ѲM)>{lͺ̙3<0DDDD#R]]mQv}hwttl{2ǎC;Ʒodr?~赵Y7oyqqqݺࠟ!""""ߦ&9t,//[}Avڥ,bjjJf婩3vO9g΅ gmGGGɓ'7TKNj/xP/:ΝZ633#[n/:߶rŋ=xDFFZ-k׮mm%zzzZ-h2v9c,O>}UFGG-nDHH1rlQb;_|g0CёWʏ?lllL*^^^Z^__EG>##C_|i=XQQQ!W\@9.\ OLOېߋZU{ʪO<ёRikk6ru6V)..GGGA!""""G! 눈 1m_՟?>,^7|]޾}+۷u0}Y9ztx1 {zzZaj(F Fmy!,,LxF_e5uK_ԩSre=<ƶ9[O>7{3~  15x?~0R FUbѣGn1Iuvv^:x!0F=X! >>JDC~NgF<[Pa(7LG$3ڀUzxxhaU94cWAJ߼y.0#xfsB^UUe܇Qdb4 ?t$h:0u$%%Y-,,70mnF{Mo@KKTiS'N`~/1]Siii}Qcݫ\ZcaQ+,ne XUeeeig1…@~/N#'ػPʿ8xX0ЈSb5E6[،ƂP6IɆP)Eʈt>`g~r{w||߶6>*R~uo~DSZZrQ{ ԿW4|ssOco_"Ǐ1p[+S?zԄ!Ҟ?Q,O{EU]BTzCsZ4u񨼼<>}toKrycbbꓳc'ںVUKwԿ lmmڻdeeTOJZ9sEާjooؚ(//濻‚=hie9\hU lcccAؿk{So@yyyiW\ LNNnkrvvv?l>^ hwgQQ-N-WB MxP/kʧwnUM;'x/8*𝟟fmw^vE)&S@\VVfU ^UJ,UkE u\~>U[Pq6]xVP^TNEu;))X Z\sU ^JNO^8ޛLO5+Q!dUixxضrY\\iuXUK66###F ?(G^GWUY[|ׯ_mɉY[[3X *(I xkog{ o,ZEr=>*/P9ZMR^CT5vvvLMMHԖE ,fzz^R/MU1Z" NOO|w{Wr^344d l[wiok)U-U@ _|K}_<۫xoo/ؘxU߶6nNNN"@III1QQQ&66ּyDGGTgJJJLSS6|`]NNyϟ?8q?/馠TTTo_/^#|oRQ syyɇ_.lll<Ą' ߾}k>ߗheeNM |UU3ڗPYYiÎ|Q }:;;C&ZY0|@A<𮰞=2!Ejֻwym댋3UUU|@ZyMDea8+N^@LtB$,8::VX/ V$ǜԔB>8_'aB¿o{ C/>}:<|Гỗ5_͊WJRcIY_vEX44vóg^#ѣaxx8yƓ`WU4r>~RI#߿QxӧܹWPH/Ez=@p|hii`MMM7oxu-ĉvGOX/u$hzz:wuB _P. _B'eRݝ`:!KԐB&e=X 2|# _K}q+~dQB _P}zzr`|i$tP(8K qk||<| ,$"eԔ`Bl6+e,&FFF _>!$-.. `|joo _`/VTr×tkooQB:;; _>Z[[B%eR`B\.g `: `BHŢ7`/N$'VtQB?_ _{,UfggCj _se+j_JLLL`/*`%:֚.e'T&'']G _q4??t,×?I 0| $`GG _I:upp`B 畿 `/X/?! ` `/(O _h! _~ˋ`BgcccA _,%hffaX/[jkk _Q _Eu+QM0 -U, _Hny`%( 999ʳη7Rre2huuAB(,×Fmmm9`BFe٨P(`B)Jg|v  _0|݆DFq MJ LCDYa` BL {%AD$,H.I$`dHڛh A!y`ugG{V32gy!"DDDDDD%ǏLl< Ç244d۪ӧnyX߿ӧO؈/ev}~~lڴIn޼)O<}jjjSڤH4P,ѧUVzj[ζmNMM2e?~Զw>},Z1%""l7nnÆ .ohh9s3 #/____Ç=^~=o׮]޷n2mC;44T6n8^~]3eݼ/MӧOKffKYYO4Y~,[L.]&e2uTY|K [m۶?~]\p$^p|Ff̵kƝǏ%V>| ӦMфyxxxHzziϵY YG;m\p$%%Y@+Wܡtʒ={,X`2c 9yi۷o?EOO V Q*jy8kŋ興/M,whϟ'9994///OT(ŋ̙3޽{Ulի'Tس/Fx=={֥)))N1%d͚5۷07 ǎӉzJ\7o&=`TB|ikuDvvEcf_PmZt_xQZZZl:::jIz{{5X10N޽{sݽ{׶޺uw϶*bq,h{ѿR%+Vx^tDD&n9bZ9Y-))1mC0'e4"9uO@qۆHnyi{9sFV\KIHHi}XX̛7Og|6ɳg4\__Qw099YvZ322t_[K.>.//Y(anjj2;wJ^^h{]Vyd:{!""bKD+z [V :@xMƍ˗/-ag:cc1C9=dc=2T|쏀?รYhZv00cc ḁN^?x@3ǰd ]2dTa#vd? sllQƣag[ݭA+X{1)#s]JLL~XDDD |7*X>xf/oL o>ٳg-uš'N?;W(O (&L,dc#0Š>7xt^uܟu=]zϹ~* fytt$nu"{8<kgM&/s>>>2Dux<FL㝕{AAo߆*xzCh-Tl^ORyrQZ yTޱB``{rrR8S̾K\ M0H>?%OJAd[d;寠미pJ/*7L>IAA-h~occc4w/5&e`C1kAV9Tmu%TPcAmr=R]8Jv_ Q>[b&YYYɭ~L:=+3U[nii),,,dQ'j~/B16} O P/_B~yy)R]B8=9g>]sss^TQ  7o57y4w/WwނI!!4Je_|J \)bRN`%X L"]rkTc枃 m[-&<>88uk-lS4;0i@ځVSƍPWWW2D[]^^K%ߛE8mtGrkjj2+i"N5U{>E{:a5FSsssmEMkGZ[A>L=p>,{W|M {Mm־u 999T{ ### y'zyCZ>bJKK/ n111a᷹\__spyyy|mTQQavJ葑yܦų7<<vNqZ80j#5/...//Mff^Ugggy_p[{0T޶-^M~.))1˜(~ x4g믣5g{L vYׯ_Mvv]<77 @Qt}}f, ~G%&&|7PUV4??kfxxM[[]d ADaWmھEñ8)+LMM6UUU6j!}GP=])k0_2 ¿|_ºUSVV,?ٻs]8ýPcjEGL9T@ :VNu{<%Q^/@0|++`z//@;N0|`a`fyyY ÷, _ `aVG , ʶ0|b`9 o//`9 o//XIkk70|"WJ÷e:|_ _NyQ0| hА~Z  2XՙO:::V#}>1`F5|++`H^Ӷ6,×\]] ``> _*t _`T' ```TԔ/@VVVX1VWW/@םC6 `;KKe`&,×oX VX/0|"'eR, _V4+§[X/BS  V0___%<599)`T* `@  rY=Ou@MMM: &i' `9KO _b$eR,-`y콦X/XMMMikooQ _bXX/?0|\yOX/2| @ _&L  RˋJR</2| ggg? &‚Q,d:,×&iknn. "kX777bR `uuu `H|k}}Q _bX###Iss7 _"eA8␅BC49 Am FKdAAD85TK]M^A^|Ij=]ys _~B @έ-0`,IXW W _~a&8 @ ` ,1_(affkqqP_d` [O>Çǎ;ϟ? @l,jmVZ= @l,ceekttP_fll _~Xӆ '\%;)|ȹTܹl _X/9}VZJX-ڻw, PlmԔ/IZy޽ϾtxxXfgg`?~4@׮]^ҝt':`l^|GU={,@ n݊5@}:.\W\Ɏ?>fgg7&''>|_~uAѣxb:u*n߾m KWWWTTTē'O8rH|%{mmmmw%sCϫ%vޝׯG___ҹ:t({WFcccTVV W^ō7ݼy@|RҹQUU:޾}{s_~Ǐ;wĶmbxx5Q]]v^333QWW>|(ڟBp:Ǐy۷B!] lnq̙hoocǎʼn'bhh(;ߜ;wΐalB 0 %AB"$\ Z(ư[P\D-\F,h!*jVfI"**2E4|08kv{93ι;;UE388h޾}+O>@|~͙߿oK{>lڹé E|~FÇr϶lx`OJ?I[@8O]\D"9&|}d)w‰9o$[wN/&&ƴy۷\|yݱEb]v_a- ?~'%%y1EQx[_1l9[F!ڔM%`ߙ3g2"n&/_ S^^nZZZdu=$pB$K.\fmmyn/ld;99*ڮ7XPP F1I6WQN'߿/IO4d]vK"uϞ=e>-k)..>PȂf>=}*KthBBB<+6&JJJ$OE jپP]7o4I{ٓm/p %|f~fHIIE!!3(WQvvOb7%7󧙞t2waBNǵ1 g#FJkq͠񻯮Ev3gO=< "3 j &;wHv%;f|>}Z&UPѣG%BҥKDv|mIOO(Ǐ{ˉ"Mn+E`!DV@h,EZ8p444[1g=#G$n5{wm/Ău޽b%(<z%{F|||X{ " cgGٳge,p&X$Kŝ;wD-n#Ϟ=;F5d ,g#ݨFF@ `k!uY"" *l[1*.;RlYw^HzJDc3 TM?w]G-Tb_z5\l٪,ec %-[uY#i^D*!DH fiܺu/eٌT!@b޼yV)ɷ|]Ǩ3|&ޤԶʝjZ\xd\{l"tW5H{FC/y7>:!q1V⍉{ZGih46 Ftl{ә| ED# j厁$[Azʫrr_~]:*-ahZX!uvAvL3W ɯ~@W FP!Q=k{| xk2*e{pT=U!~:.|1jJ2g MbLmI:@FOyj`Ge`/_ 0#;3CϟSqy8ϟ?n46 ߛ;"H΀րW]X2gcAsӫVbU+n'''ܜQ_ UYdLbeFzZ *>tl 7x$9nz5f]9Jy$T{gz %MYvtRӒV1B影9B fS>}G0z&8F9Ϡ#۷;h4m4"T{GRAu|ub\4o Rx'UTä@ru5ր'{ 7PgrHWpZ=ׯ_/T0+so7Hl3/B 9fuAFE36M60gFܷoߞ_FY[ks$ٖPI)udN_Hwh*yzO{@ǮlVB=2&UbUՍ)xH^Q\ {%y":ChpFķhl8TTGG^ LTD39XGbdP R!e8;[Gԯt;s?HY N֕]###|"Rb46%Kd+bV O)"ZVb)c\#fņY7yC'oS\*E')7OM0>0j*-ݨU7% \KYbwMk/~kAWrpe os X-++!ť!-@𒭑G2e{O*<i`JKqSAGK^{@WDDEB2hCDbb RON-3@1`i¾,tLr:VHukj.T Jur ^tLoH +c= NEN4i6\D>ɐ J*=cڙf^v-FGGGcBXc1ɸ3<|"r&zbh2-F; E'ݻwc#. .IS"H4 CM=>"tr^4O0]^Ik$CT8=%VDO}&b=pX2ZS|P\ BYU(|EDD~䒩@m,85zLXRIgVDDDD+""RI̛Y"""" _(|EDDDDDD""""""" _aɈFA;;;qI#unmm>ϟgϞU-KμyEDD088XkbCOY+yz"S^^z== SSSǏsmvv668u;;;COOOs\ʜ|GV3"#A-R%1LwhL1+"EkLWpʕp…p+\z5;w񰾾&liiכr_.O(|E!2 |#ո^5#a}/q߬ -b[]t))|RVWWc7CIb戈WDN"QD4f@-?n"UR~(?M*ɓ'Q ˗/[n&I ű۷o7\p̑t/I$sEE0ڙl>}khDqxQhpNt PD\X@ڌ·ȖT e 4*Eє~yyaa!EME"/^DT|r$*jc Ty TNt57n8e#H͛7×/_|ݻ:::N_~711Ѵbi#+y?1h2mDD+"^oX! \=eE6LZuDE~w:Q{"DiB B#vz T--lKEW0杜=5˲3ϓ=͉zvo)9uNe۷oGɃfzeLoB ytxx8󣣣v[Na=Q _|H͝h[&9;Sn?:jq[]껭5F4Z9ޜb+c,DN1}b{{޽ktq޿ӹHt0|᪌e(ݔ|H.ˤ;0^دBE9F޼yS^E:==-CW&rZ _`hjU,R.Ju7eVw}օbmmKyB qX`I*ǁ' _7bsg7wOr'wï_2%;ky.\ewUOl0|gzeU/˔#3h/, zX`BUi^pcUeZʟWukk `Jer#Ǟ/ WX/@ `y VK3UtMXX/>'KwiҌp]/X_.?c2N VpK=*D- _b Uh~S _&2|'\Y2|cc /WdUŋX/>oaBiҌp4{O2|' Wye:*߇z,×z*E5|J 'eҌ/< j _ꍆrOz?9 )4#\5m0?W _}o  NaB1|'\PcǏf//[#޽BӆaX&h 1SC[ ;0CH!D"qHSI[SwUu%6PR u{{*|8|!1#GsqULj3P qqzz:O2??oCJ |,/x+b1X/|K^UqrqdmmE|i/KqK(]ˀ*(X/xAC bWAi-vQ_h`űG|)U/ZCg,9K(.||WA,//XCCC _G"RVv|Q\^+` dSK!)B㍊Z+X!5|5b?DźK4 "+@@qQ5>>K%I*_~\,U. oHיּQ5<1#_>*BL!`*` X|qQpzz~R\ۙeVVV*S%U&|*|!"?U(|.W!Z4j` X{{{/ajkkKqIeG0K7Ǖ|+@qo6@YUuOQ\`D{ۛ -Lv!XW!fs7XWWW_hCK;U;w.kK7|)UbxP%XWWW/tW{|)0UZUW, S\\b2ljj*,lK)|)U8^kdd$M_hC'K)Ub|1o, W%R4OOOtߦ 7[sqU'ͥX333=/|)/P\-}m+½z Yk}}{OH\_@c:www?^'Z-JVWW_h#R.W eg_b$ۢ*FY\\Lκmmm-eXxB_|@"}}}u!Erdoo/L666d?M4ת^׭a{gq@O C hA @HHT8+(gj0߈Ɠl,rIr̽7sf288hr.[e5mY^J𿕕4[[[jpB8&1٫WM&{}|{Ԗ@j58 "###E#7x :pB 6Ŷz^__o fww7=W066f WTxժFR{8hĦt\> bKiue_8 B8(<|h>;g?1|ྋ chn355Ty _lG!S'| `($ngff"ЧZ-*:MQ0Zዡ!5Ͷ>>P(ܵk&sႩWj EG:-љF]ւ'R5&7έNnq(C8fuC'''F]bS2rRt$ Fk( U|KHMM5P(Kd*_LF@8 >xd3-&[3 >tlB FRNKFAC`OJBP(҉6y5c΂& AֲK2:dnaD1:..6EĄ8*\73{vyy$v_niyaBދ/^ǏM%i;&yo^"|{syO)'bKqnxܽo\߱͝/pf[Dǐ\+!$>͢@EpP~ZROflQ!P T*9/:DG~]8[6|(O][8Ծ qBG2N($lxxi pLzG1C'Bt( h\ˈx[vCRBCc' @:!D> SHZKOe';i@])?klͩCy#qnTv:l}/aqYcƷph+y0ɋ-;}~,_ !]JP('MES?.soޘn0KqcrϞ aGwϔ^" y&瑩Kv qu^cIz_); Pd&NN𙉉 uߔ ̓>CEPʁ,:y܌t=kxyb2ﲾw l (v& .b# IJLӐ/mu~E]7iئؕzE88""M 8bh_la(TʋC$\f\'Ɛ\ƙ(2̵C2o/y r4;=nא;Acȷdrtk;"<ܑwS#Kˇ>ă.\nc!0~ pG<#ܗ/̉mhP(읻TW ; QA+ ?BD[Zh} @HFܜ~㚕>sr w̞}ٯ}nywsy{#Gul=re7o^ܸ?9x޽OΜ֛^ ߚ&$#'vQ]nG X Nd1?E"a?)k݇+| r5pVb'{syb _Ͳ[nc|DH_ܟ8+iO h rFa&׏պ4Y)Ab|RF`8'1tw5x;ܸ vL*.HKYVXiW_oܪ;q-1IY\Q|^|miʘO6c3VX4^{&O{7k56(νNIIIIy;wF ,)Y]힜==|-YY)&2yg}{Lݸ4S7ׯkݻݫ,DL B$U$K0"|00yﱷ`|@a! B9Cǣz/1Xi^O*Q(cݹ G^})ZD&^R2,@27`Q/PQЄWJgtn\IN܈Y8]zOYJ-L߫V"DC{' ԺZ4'63eE Q, X$"йo~_پ|0߳~)jmJIIII8^,1O*e<{~Z!O^޼Y_Y,__4Swo:~ U{o_ti#/f`#w21P[ xID+|ypR Z+ C˱﬇?q^}0cIo-W #̇ye9ÍډD3n(;:K vX^-1(SkxM'ܑ+"}H;ڨZڙlЬSȃ$E ZgХlL}~j}sg+qs,Ǟ'Yyxp7?x%߮SS[j,QA~8#Ḋb<ADf ݓH?,qk.׌ Uة;< c@-4< ,j+(ėέM(Eڔ(8YG:c([XP]@ڠsl6>"Qd-2esdҐաcMɽ׊T4e?v ZAYR, < ҈ז0R kW-V%%%%%忕7X{[޶رQuyy˖RǴ>m^_BRz|…B~_&eqehFxӱA nW2Nq&EȽ .ʊGvц{!-*_(m+L"+v䦾.EVVˈd mO$_/Zd󠚎r#2}DPl\S&`uEi)^lH\%"޵)!>X`,'e1Q2&NEZ82K׉h}vv"x7l7c7O}MIIIIX!.-ߓ'cHwKR*2/ym:^&a@_|%bP[""Cݹ>ueϞj޽ۡC )߾]-=j%V60҈!v8pjKp|>1|r'{ !wyEn5X3: tN~ ]7|{%z+t b5_Nɧ.-b5Z _ WDdjLB!G@c ;`^p覑zS©(8 -&:љ.C:1)T qHzT`\,z28'e NzN8GL/6ʱy|g4iP1NZܤ4Hy1+,&mvD} h;5/:m{v~g=w4q; gӎL=~{jʕՙ3uX!~ۿ{E_E맗Gĉŋߛsr%wׯWN>s=Fq vE,†N|P 6CMM#s!ځk!M8Xmߋ}i%\'}B ta{<3Tk?)ve]Àla'!ƿr. HG#BM(?ƿ yLqAs*!!ch>ĒA -ιl [* XɇBJE84De&eD#Ddpnn.縨m}i!1:YrT})}t\Zǖe8Nd#J m$nkv{YjKgg|?>ܿ_ݽwXX'ʊΈw׮~9ء/w֡S1>ʏCD4qoè ?aZ$AEDbP  Kc;p>l"7MONu1^'k5)E@l1iD ʑ\7[+n05'.ȒJ_|JYPWDDDDDDD+""""""Q(|’,kxo!J=#Wb3^_%7 MpH6 b8pqoXDD?_955UMNN֢Cd5lPQRϟ6)v+q]-,QJE{Q2==nKP'OtToE0&|fii.]&&&cǎUƪ]vU###v KFO4 ܴD+@04=\fgg-$ ]XXhl333e KD$ܹsݻwoЍmtt,, mS:% _bVWW$TL0}%2H0mthtkӾ}vXP2P2ÇETg|K]ŋZW2(͛ݻw_~/2̻ӧu5nL|Lm՝IMޮ={y $cYH0 SP;AXjgVLP),lB"hBAYa';; ɜ33"my}<~Z6o{C%v<. ?St7MW|@u`r%k?ueM} _:<~Vw~zu򛢸C߽={X^^.>|X~8}t.--O}j46TdEH]hXG=*utP*B )GS0b. zp۷\1-s Ci,$ W]~r*8:J1j: /!Y̪WX)Egӽ{ZW4BBB,`Ve~?K%9405zFH]4UP*2"B~A0OhWe |oRdPd R`e1! fpJ_JHGYdܳwΝ+2MB@ zHVI;t\%Qfvʽf(cE,'4@[] ]J_fHVu'$,zp*5Fu*߇z(U !$IpյkWYG#TP*B/[, X@*R]2$$k,p`8}EpՈk@3jkk˦8h|ad! Gp/PSX|s5 ( w`x .Ukz3*RA KH8 zz(Usˆ&h|dk͍9 ~K;wW T3Y zV69~CVVVuUz. /pBd [62/it٧RX`Bj,X\>| /#BG,ҥKz갩)z~R? Wzⅱ9('C(h|ş$ /U=*WYi%^% f/AUZ?{જf_`=wmnZ\^h|˘Xu_j1 Ο?/jȥ4 w%U+++wΐlaH$DHm#_" FP&$JId{5{>&;EURE c_vSf񄫚C 0G%VG%UKKK}GT 1w`Z4?VE!E᪍ R_sD!EzޞpUu a`:{s1b$ 4XNk(`HVHQ9\uwwEZ 0HVhE"U\#JED/dUCpp R_}ɊXth ʻ E/@oHV|6HjM%\51GJD/@#Yso `U߿>R_#Yqvɲ9=,TW]^^zQ[1TbXqt,677 J`<7)G 'żC*p,J;`ͣHt8+\5Y1J/D _G`bW$7w2 `OOOU}z||t=0nɚATيpUli>88G9JU܁"J`Hx5 `1Q/"V%\A hHVl5혐UjoWwR|Z3+u; a<\յ( IEbS,n+ЩQ*/@LduaG[G|bz"sfjbjkkkt||ʯC @Moc$K9pU00J#%Uf`qўDնpU| 1*o~``CD@ `VZ]]ml*3|0`L%*uc{{{Ҹp(_*9&D0PqTbŵΈt?pp8lI /Q^+yjaap(_Z|&,[}Lևrx @2&EϫxV\+:Uooo٪$/JZ+JJQb5HVU6[ S UFR `U s\#YWf?w.UqBhӜDIɧ Bl D0H \FSB@E|@8ޮ3^l9S7֔*Д H6dq AS*_8"!/]US@"+V>_M6@#dR ?v$)՛7o4E >}Jwfr ;;;<۷߿VVV۽v~Uvww[蟈+1`VTTgϦUxWcx_]]MO fcc#k׮ | N &_8y:::RNK.^ >K̰ 9а󑑑p088·o ޛ pհd@ʜ(^-TSSN(^-tʕ4ӧ… :4e@ɜ}uښYR>QVZƹx/?s=""""""̎""""""bKDDDDDDw{<~X$%%Enܸ!?_~ɽ{xt쬌errrͺKKK;>󈈈/,,,HTTܜpΖK.D^$((He{ѲM)>{lͺ̙3<0DDDD#R]]mQv}hwttl{2ǎC;Ʒodr?~赵Y7oyqqqݺࠟ!""""ߦ&9t,//[}Avڥ,bjjJf婩3vO9g΅ gmGGGɓ'7TKNj/xP/:ΝZ633#[n/:߶rŋ=xDFFZ-k׮mm%zzzZ-h2v9c,O>}UFGG-nDHH1rlQb;_|g0CёWʏ?lllL*^^^Z^__EG>##C_|i=XQQQ!W\@9.\ OLOېߋZU{ʪO<ёRikk6ru6V)..GGGA!""""G! 눈 1m_՟?>,^7|]޾}+۷u0}Y9ztx1 {zzZaj(F Fmy!,,LxF_e5uK_ԩSre=<ƶ9[O>7{3~  15x?~0R FUbѣGn1Iuvv^:x!0F=X! >>JDC~NgF<[Pa(7LG$3ڀUzxxhaU94cWAJ߼y.0#xfsB^UUe܇Qdb4 ?t$h:0u$%%Y-,,70mnF{Mo@KKTiS'N`~/1]Siii}Qcݫ\ZcaQ+,ne XUeeeig1…@~/N#'ػPʿ8xX0ЈSb5E6[،ƂP6IɆP)Eʈt>`g~r{w||߶6>*R~uo~DSZZrQ{ ԿW4|ssOco_"Ǐ1p[+S?zԄ!Ҟ?Q,O{EU]BTzCsZ4u񨼼<>}toKrycbbꓳc'ںVUKwԿ lmmڻdeeTOJZ9sEާjooؚ(//濻‚=hie9\hU lcccAؿk{So@yyyiW\ LNNnkrvvv?l>^ hwgQQ-N-WB MxP/kʧwnUM;'x/8*𝟟fmw^vE)&S@\VVfU ^UJ,UkE u\~>U[Pq6]xVP^TNEu;))X Z\sU ^JNO^8ޛLO5+Q!dUixxضrY\\iuXUK66###F ?(G^GWUY[|ׯ_mɉY[[3X *(I xkog{ o,ZEr=>*/P9ZMR^CT5vvvLMMHԖE ,fzz^R/MU1Z" NOO|w{Wr^344d l[wiok)U-U@ _|K}_<۫xoo/ؘxU߶6nNNN"@III1QQQ&66ּyDGGTgJJJLSS6|`]NNyϟ?8q?/馠TTTo_/^#|oRQ syyɇ_.lll<Ą' ߾}k>ߗheeNM |UU3ڗPYYiÎ|Q }:;;C&ZY0|@A<𮰞=2!Ejֻwym댋3UUU|@ZyMDea8+N^@LtB$,8::VX/ V$ǜԔB>8_'aB¿o{ C/>}:<|Гỗ5_͊WJRcIY_vEX44vóg^#ѣaxx8yƓ`WU4r>~RI#߿QxӧܹWPH/Ez=@p|hii`MMM7oxu-ĉvGOX/u$hzz:wuB _P. _B'eRݝ`:!KԐB&e=X 2|# _K}q+~dQB _P}zzr`|i$tP(8K qk||<| ,$"eԔ`Bl6+e,&FFF _>!$-.. `|joo _`/VTr×tkooQB:;; _>Z[[B%eR`B\.g `: `BHŢ7`/N$'VtQB?_ _{,UfggCj _se+j_JLLL`/*`%:֚.e'T&'']G _q4??t,×?I 0| $`GG _I:upp`B 畿 `/X/?! ` `/(O _h! _~ˋ`BgcccA _,%hffaX/[jkk _Q _Eu+QM0 -U, _Hny`%( 999ʳη7Rre2huuAB(,×Fmmm9`BFe٨P(`B)Jg|v  _0|݆DFq MJ LCDYa` BL {%AD$,H.I$`dHڛh A!y`ugG{V32gy!"DDDDDD%ǏLl< Ç244d۪ӧnyX߿ӧO؈/ev}~~lڴIn޼)O<}jjjSڤH4P,ѧUVzj[ζmNMM2e?~Զw>},Z1%""l7nnÆ .ohh9s3 #/____Ç=^~=o׮]޷n2mC;44T6n8^~]3eݼ/MӧOKffKYYO4Y~,[L.]&e2uTY|K [m۶?~]\p$^p|Ff̵kƝǏ%V>| ӦMфyxxxHzziϵY YG;m\p$%%Y@+Wܡtʒ={,X`2c 9yi۷o?EOO V Q*jy8kŋ興/M,whϟ'9994///OT(ŋ̙3޽{Ulի'Tس/Fx=={֥)))N1%d͚5۷07 ǎӉzJ\7o&=`TB|ikuDvvEcf_PmZt_xQZZZl:::jIz{{5X10N޽{sݽ{׶޺uw϶*bq,h{ѿR%+Vx^tDD&n9bZ9Y-))1mC0'e4"9uO@qۆHnyi{9sFV\KIHHi}XX̛7Og|6ɳg4\__Qw099YvZ322t_[K.>.//Y(anjj2;wJ^^h{]Vyd:{!""bKD+z [V :@xMƍ˗/-ag:cc1C9=dc=2T|쏀?รYhZv00cc ḁN^?x@3ǰd ]2dTa#vd? sllQƣag[ݭA+X{1)#s]JLL~XDDD |7*X>xf/oL o>ٳg-uš'N?;W(O (&L,dc#0Š>7xt^uܟu=]zϹ~* fytt$nu"{8<kgM&/s>>>2Dux<FL㝕{AAo߆*xzCh-Tl^ORyrQZ yTޱB``{rrR8S̾K\ M0H>?%OJAd[d;寠미pJ/*7L>IAA-h~occc4w/5&e`C1kAV9Tmu%TPcAmr=R]8Jv_ Q>[b&YYYɭ~L:=+3U[nii),,,dQ'j~/B16} O P/_B~yy)R]B8=9g>]sss^TQ  7o57y4w/WwނI!!4Je_|J \)bRN`%X L"]rkTc枃 m[-&<>88uk-lS4;0i@ځVSƍPWWW2D[]^^K%ߛE8mtGrkjj2yU(O :zU ?oɉ jEB&~SMZh^g"hr^^ixzVmW}@.TqŲoid}Z"^Ngy `zEC^}ӹO] 4__HVx޿Z;՟cj_VEG!T+++v2(vvvVc=?UmIW'QF9~W Ϊ<}V9߷aWETRYFvQ Q+' R l* 9ӱ) +i\=窶l) D,'/!EäTך2HzЦV;gW ^֑_| @Ѳ4W###Mzz0 9spp`9P M&''DŽ-<<Ǜ$EDD2Cmllp 9;;3iii6:w1(͍IHH0Aݏ+jvww]__ۛI|TEzsssz{{y}2v6333U_OMMyf0_p![Ϸdffy{{ onnڰ;11}Š'_xޟ퍎6ŦA.4t,ņ[UxCq/ӓ)))#**6g^M~.--W3pu{{컩Y/ɉIMM-&99.}—Іe\ k‚9>>S@7ZZZ 89WMMM&..444}..;7kiiq>z^~zB m/"A֚D@AҌOJIInu|޿G% @7EEEvV__K ƴ?::}UWks٪n/ !FawdddeeXzBOO6UUUrz?wwwZ*3 @,K;V"_B4h*̛$fٝiu“R ÷/@loo `a6N ÷, _, fXUXOOO[C  j+ oXXĄoXXޞ`H o6p GQW0|m'EVa o7Qz+ k6+d HzXX/``t` `4N, _ம _``tίT ``V `:K , _)522/@p)S`=>>:K/@`X/0|: q,×>0|+2|' K;XZZ]]2|]0|JCX/,zҒX/lnn.r×X/}~~fXgggbR#NNN _2|i]0|:`  `QVz @0),e2 @pKX/ `#`K;///ё @T_q(/ `4HߋX/UXbR#}{{+`M2|~~~ wCCCyQ _j`'eҬz}}uhRkee%2|C  "5==-e2 @p驣0|N,nnn _`tK3,lccX?%78u,llK,NRFX rBDXH)Y 2\VBJLp "|OS&Ä37ޯ0Oc>{~O-"⿢ iX__``p??A|`qqѣ `2(@'`|7Q_,ud2yLX@,upK2@|j~~)l_ hVRR^ HX_ X@x,Ka|(/tV@@.R?_= 08`|(/ԑ,w."P XZZd{H; SG%""Bbccb|'^`y `'͒EyVGU͍XV |^ @y]π 3,u/_| ~?[/l6 /OggJuuTUUIqqUP˥Vo/--C }266&OOOL'ǥB |RVV&^^^2==744HjjU ?a>Wt%44TiooAkJJZ]%**J||| Ɔkkkc@_ٟhtww\\\0HpӁfxx۫%ѾݕLoooX,s||,:88p9;;s^`ׯHtt4fY pojZ񰶶&VUc) /cjjJǘrddD/ UOCBBrGܟ ʒ;8?X~~z!3===Ζ-Չdr:«c ~൭-fB|DpS\e9??Gё>A?Q] nܜަB+I|| )L@TU BPQU`D|6i KEI&h"ڈ61?^,x>w{3;gϟq`:~k .lllK4 _[]gº$Q;˗/ՕgaU$檆: d{ST?õ.NA/_\;> "ZaE,炮u~9ߤZwÇt(MuxxV'{s6%Vj@ W 4O DuPcQ;勋5}SS6᜜m >סڕ/..TcczzgRz``@BXAj}"KuuujddD (pؾTvJط߾}mE_~ϵC-//k+M\s]^Jӧ~qvvn n1`[y^]]]ZU#]sXYY훷.Tδ#U[[=!O ^a{Atd&Ř 6 o_4)@@pU^^\ϔ/޽%S`ebE=ޞ;=!NBi,JAvvvOU\\ <(Jui 娖.R=>>rSb]fz&HjLL&(Ysiqgg[:nc}}]xi7.VrPQQј* @d8gcfeeFMBWs\ ElH~ok3d57tm~/Y.pe\ 1#4آǫz=AJ Аjkk QoS]]xjZcgʖ+e‚VPPCpDb犡<@J*D`HȐ߁gg+6&Jk8Bv3 (&RI1xV(0=l%333"!3Ϟ=sG19'歵I=*1R/OHH}?[z!(?d؊Q399_gddhk9_[llzԳAg~p< w:DM؞$Xw7M::)cH6`Ǒ6 \R YJwCٿe|O\9ec@ W D9 I$sb= "̨CFccc$I@@109ŠW߿ 0lRȐ i򹖖}`mm-d= L͛kBzҜP# - i (]l@ӞQi6h-&FQEU ƩV 7}@Dه&<پ`fZ%3PF gggUeecf˳c൚c7n6 ;33#( D]mџlR ˾iږ}8A+[ȵQ!ԺZ- < HxB۠] 0555B?`l1 U(Ov~KafdDCTȆߠY\C }QkEXw\Xlb%ƧO4!W lF`hhb;$fF &o,OtfsN6.Ljw z6=:pd eΉ  `RJN٬~RG Glp`r#HʶU{ql/<#:_A >\|{s@Niݧkֲ~hh4(߫???_ӑUtwwkǏ ,()uIlYcig-h:E [g.҃sfl*4 I F888X ̠foQU!#+3ktRHG .//A{@R%E6Ȏ@؜)hEV1oQU@^™anmp#`P>!z͊|l!sO9*,6>_ϖ@,:w`/K1Yؐ]ch4M|ƆA>o %Z(5J<U7%䂕2@ r-q[4EQ ,ۭ4k0_v]Ϧ(1xbyΉf|/R1W)R1@6 c "ߛ-#:^YGlްg4{wQj]u &]![6'Gl9֓.9ߋvh"A ezfn\.rj],`J_ xvFSn4M|B9[J$g`s`93JL1e*_lUoP 4Uܝ{?].v_~z1QHgggַ<h݋t~þ6#u} qTF|5f]T+~xxx7(/+i@(ҳ e3پj;[y0ѥSc^影>Q65}|Wq3v4M|B]k.3(YD#UR[짧w_]]-~W\aԄg{ql yGc.VJ:pȡF~nDw}Jb>rHl(|/B' 9eW6T)qz΍ع,T۷s]?<<\M3XݗqOVR ; dm:99ygeuSʳs{"vr((m1E@ ,ϜCes̮{]q ۿeyeXFķhlRo߾NJK*KX Gs"'>rao{uz5'[(e԰9(3`aRePk^nu`{:wzz`93uũSDm6<-P5b҅|DIz9w*<QGE>7DIsWȣӶق 9^NEq_I̲&Y\aL#ѰnAud~g1er,K)6mBU耜rЙ1.H7 ; `:l.'eLdݯy^ϓ [XG }~=˚5&FcMV56 i㡯T l-@V `ꑪ|"Ȋo#Ꙭ(bXsO.vͼ(b@1&OpQ76a69kzxgfeev# <%Ѝ !>CGFm]۫}BIN|i|wh1Rڵ+|0c$:ISSݻ\΋Fرc 482,nߠ ϧ($_I %Х9>>7+ӧOǀ!ׯ}ԩ8J.UÍ7Bssshllo2DmX;11 .>`~&/W WW-6BMI{cX ` ѥU/]W WmooR?pX`B4)\e2M*p%&/Z'"M WLBpp*5,0|u2|M᪗J:^ w,0|^__[2| ejnn||,\2VwZFjkeB#G<M _h̅|U/RVWWuHy3lŻ`~&/RWU/?C*ߙXR_;ek0|` Spwiox `a&*×\ejyyW "H)X.~._O 2|!\O `a]` c#\e' W1^, 4,0|DŽ _҄MX'NJ H,0|!pKZ~bR _` IU/ipΎp%e&/ %\e'U5*J{7qc_ _:* Wő*jE%O5C8ޝ _:"ށ)U3*@%O4L&tK?U _F W=>>P=,×/@0|I꯬WA `g'LJjN%pKZNNN^xW G% /0|;&I WA`)X` {||MhSqKrK|R*lC't4*U(|Jy78 Eqй~I߿@AlmUҬ[_Aiח K-8 =}}},>Z__O?~h# b["/  // &ёnɉ,7gggxMinn.3==糋GX dvǏS\N10x4yJwRgg{"Ϳ|f=KGۻw5>o~?ОvwwyHʾdCD677X6s̙gEpVdoE"g ccc?q~kkqo[lvvv. g$^OO>]z[e Yy: ]m͛춵oo{7-zeܗ/_9ܔ/sϷ.U8+`Z\\Bﭬd֔"\7]3RpKhWQ7[Qtʝ("> n֕OܩEE](>vhbiҙd$q466͘w͙޹fL<f{ǹssPp7 J'r/&7CCѹk<[@#:891!W+V]ۇ/3r l---RTL8xr[a'y/T&Ĺ^&64UW7|>wwwy(N.i.~]3a+!_,[&/Wg :l0 C= 0Ni06# LKi#kAV Y\/9YD.L'.qN22XI1ro e<=w}:`0v QĠaJ׍2 )E4bp;W=1ѯ+Wu)aΜ]}>'O7DKIwTD}/2JWG$`0$2)c t9@&q]wB3 6Poo#wf6Lgp.F,.26w`3Sfx:PC}`q"?WV(?VgXmڂmAn<1畇8诿s4rxnpK(P~V퉍k DJb.t&)\tF2Qutt( CwrcwI(u2(`p(61АvxۺK6SH:ALJ30(\V~/R>CnȖtL}x!7cdd}Q@ݎGt 2ܲh#g-w|MvFGNsC}d,ѵŋΝ~葼ڶSoGoKU8ܳG*_/ӧU2}&[tt>z`0 fߋ̈́]ߘ[[wvlBP؇E1[I2)#-4cڬb?I%EBQ|o.smQw x#_XR+ PQ֢XGJPND!?$/}D$!6Y1;oΞ/Aݳ9wZN_̰ x x37a̟lԅ1[yuza'sSRRRRK*l/r!0#B+86[fLK^]`@ȓ>Y+Tēpm,C7!a/7v-yze zN>tL~/ 4ՋR[!>>Cq=((z{ȴշ.~zV cO@߫ &:3KŰ<mWTtܢH&WEmC߬o]+Ԇ[<'dzBn,QBlm~sglsmhn?ܲja̭n <=wvh]`R&S>l&,]/y  C'f`Kd@_2-{YKNe>1A,*@B{%//fs 8ԎW`cDNE 8b`l~/wh!͞8϶bfJ1gl?_yYfnQx*ӕ9̬<$xuǘbSJJ?vˋI[v9͜E(p[FϗܩSa-g?okڵ¥Kݳ^ +~zJJJJl^l>!ٔCD8(T*LpOtDmTHv}CfJv@:=TwX,1q++e]y"jFlkŦAE,v!p(DVeFlIټV;&_ͯleˆ_xXEM|&. Ob#{*զ \_)o}1){*Ϛh4?9A<>8Bۼ] >99D+͛ 쬕$jxx!cnܸQDD%ѳf/_GE. MmS0Nn۫(|_tzsl333hAxtjpp(~}DD3~磻3RB^5J[VeWb(ѻU _>Y&5ːӂj}U.` n'8::*UwDhSO]M oFk<`r*GHN:60g`h{ߗS|NOO}_Fy/\Dhs&mbgg 0DYOs0'6YԴ(~|a2,C/ʱ絵X`T᪬yfeRi,Kn`CDT6m 0st~~ KV~ `%UYQ*W\x4X$6 `}RsN>:ugVD$eXo.p"Jz|ɢ V"1$\ŢQZ*yʛ*N:aɢ-X@*(|Y,!#V `E!J_HLdeȝu&ݻXWQ*0L"Yf+6W1Q*0BkI=$G3$CϟX@+RE/,D$y4X_|s4p~|-K plTdX$g `6U4իW^ԣT9a|ae,&fGGuL t}VyF$k&*D ^r\I$k͛7cП?Wפ(ё`aB 9W(|*`R9dG{{{ō7}oSW]^^PF7Tggg`$IeիWǺ]R5OqHxds͛޽{ǏOU֌RUݎ-O|/b+5Lֳg/U*<0RX!ak , TpURI,Atx@Uz5T @6c"Y;,r]ߝr/CHQժ4k%1!J_O `K*WW5X>hpUx0sf+OŇzǏ>k`uQnIÇŝ;w`U/t9&:)X=*|(0'nҥ 5X?~9+\(UޯΩ#7Y/ry2w鄫~R_H6.y,8ZXA+'SrYjkD=JurrR_&~7?OWDVCZ Q* H7 `ݿ_Ѹ,3UgZ0/{ Ip8V!(܉*6 B-")ɈT FlQ_ofNdɮ3u>H T,@:T`N"Y ɊVXR^'E+1?c=NR_"Y;;;kC*'J|j6) ~yn2X. %\U;qQ 04pEb,k_~X*F #%T !㑬ʞo#V@]~(J|Z(ɺ .М{`g`ܰNĈR_aW$"5\YYUF IɊa,#YX1 `QMR3n|.E^XMk(Uk `{# YkD 4)G;;|*v4HT_ "Y];XX]|o|J*SN||j$+]ˇbwR|t>~}}m:j.YnXR| G&p( t!%PضpU>JM @F[#Y,;jԶp(*HV X͔YTUT_6kAZ$k><>>kPWj0v qxQ* ZWR`1Q H\E$UGT|`HVXUD0@ C}භI_^7eZ*vyF(_(HfJ}DzŢT|gGn 0+JC0|fuER^(Ucv]/ pUGR J_:0j|Z ڻw0 Jll,T/`"hx-BBA @Hx)*":Y7='sYkmp5 9T IoHhmm ===ɱH]]]uaaM/G6@WWW%_PcWSM}oo/b_P[[k2@۷oŋaxxd O{{{| Niiix c/+{ /'{߾}|>|:;;̓VWWC]]]L&_ȬTo]|ҽYS}ɣs)""""/١jmmcdz }1#G wwwUժ=bccmw/| j\ Y>߿SR$De?V%&{"S(| gggE|7yܖQ[rvUv>>~Xvt>q~iAKDDDD _.'''hS*%l#G z* ʟ~3Odn;,h￐эf;@оW7"o߾U_ _~K4lmm՟ ^1K%tB<7??_]^^ώH'~KGi'?L[Ζ6!G'ץF˳rGЍgyIWM0B8T1ǥ&/,0ouvGDDDD doGFF~ `62yXlD&5?cF4~g {3[VOJExt׮q8t|)5i#+eMA{`Az @VWzȻ"Nxn Otq(? ".UN R;M#afTjM'sM\]HxifmqBA~yܺQiLk#{aSp\' [Efo{c.xì5?|@_|@k )noof*T0β7v; D199YcffX^^.677xzzѸ룺^投bww8>>.... 2N?oݑ ^,?W4y/7(qvzFiGGG3M1{|im7u2___G<< o@w ͌)IWWW_<&d{y;zGres>ZK#VWWkg#4%ըoBxʭ«Λ 222emF>̨KݺЦTeW]mV s #m/c*[~/S9ʑk/.blդr~ijD1/c݌ne}eFM7ej2|~?]+v)K2*kL In5S!A1Ց-Z&3;"WKKK _Hn[`_Z&XiU=X/,`,(|i9Xɞę% @`![R@e`!CF,Tk {)/ (|iX-t:K(B,S;XVub,`UVu*B @`!GK)B,{||T%z!P (|LKe0X/-Ke8 _ZNp`\i/S TX֙ __GLJ,:_)$q+H.LxY7Ll鼧Ybec%Xg5%|9% _kⴄ—"xc0X— T%9X—~ `_X/e/T/e/c ,K? I{X ` _b+=E |!#X—V21%|gZ/$eKO `M&f4,K,@B55%|,@B ` _ `kX,aٙ,@BF//$: ` _ |/e 0%|)3_Hn+ _ `3%| |!9X—2X t~۱NK_ cW ` _ |!V|~~ XXgDayK `뼹nKXӓ_Ȧ,w2_@mX—?n]@B&Xk*|I |!/`/dyKr, 8%|96X d,@BrY/f /C/# uK2$xh42_jhX—!ꞔf. |! ` _,\@BVqvw7_ ~\<rPK | |@ fw"z;ɗa?叏zj{~>7bhVxvcǿQ|ww|w&=@}_"$N,**dO^ 6~h^Oh}}}0kciiif1ci:*(WVV:W $Gcooo?|GGGݽiw{ooS{c1fގ.//UV'n|Ӌt"G7ݥE"(ͤcOU'wc13UH\\\阼!zFu>gONN5CݑiҒ8@Ԩ{ss3<+0Ӧ,#8郉k c135pp;muu___o89d13L0P{奚6_5MdgL ^`c13U H"ΰSJq5!HOeB&5H%;qq"ř9\$!'}øˈUrQY \;c-L-~2V}/#CBϲ^c1ƘB0Ò!gɩ5D滑-kù5N8NJ0D [q"ʸ,uxxXl"l+I7 R}/Ҵڴ[\7ij1!^c1ƘK:)9D9N \ $.'Ltx.}˫spj{؏q85rmmd)8:LSg-ĕ99T߫v9IQ.!S@{Xb|Z}/myXbRc,|1?BWbg'H$qlxӣI_d%Xf ` Id[C]r8^*c Ʃ5ckT[s,t#tx E 9QX":yO}Ix\bA]8nL ZmYA;*mvsBVKrbNz%>1 K\TMm1cf]mc 4-:U%b)PCm<ޜ*הz_Y\>_6I$XϤ1"b}/q+c5}*)Z4g.->m/SJߔ0ޝDa~:C,N8< jRREo:AhbCwU;wb,U{RoYյRNa c~oށAHcARpe:_T48FWL'  )X*~|מ-IWҿk~on^lʔVK9.UӪZJVWEl*LCGښmxqN|~o8- eż/c;2Ǜpc[ql!m0^ç(p2g.!8ڗٿ^q!̓J3xO\hs1: $|%}^{SѶEƉ},4IyZe[yצ#Z iUި ُ4vyQюX+*\ _\BMWo+?e@l M#``1JuT|هR?<K>/2zǶ.uu B "6Q*̵hNKUgr5!>nߍ_0J$Fp$ƃ LyRCH7!M(*:E'H%q嵥 a8CE:#*O~ZBnJU:*k~?[ 5.p*-2ѱ𕊪$I2J(ܺj.m,:sș/":xoI $ %>+K $I_I$I $I$|%I$I2J$Id$I$+i+I$|%[[[TnWf=::\^^v>*I$|% %*Xg||z9xaaFK$$}[U%8 4pׁKsuuy||IdTjNOO1I;uuI10,IW⢫.F" rfffŠ*xш$+I 5vi۝5PTN a~D54M}'I2JRP"r"MkBg#M1R&B0$+I <,CsxVNLLT-OOOx _nggg;K DVeDhWO;>> |~ppИ}۫л^}]ܜmϒ$$ #Z<9gN `P9--EgBSRW%E!$|%i֩s{{[ tCp =_U777픐$|%iv pXNܻnW*ϯQM&///a$|%iȸ~z||CyF)!I2JҐr,|&jZ.%I;HQ# 0}) Ł*8 AI$m>YB[=U2| `a `` @ ÷M  o, _Ƌo/@8, >X0|0| & N ÷vz<. _#6tI _0X}*z5a0|io_O0|B `osn`2|i` ` ``2|# NM `X/m/@8,×6, _puYM  K, _pX/mXV+e9, _` ``2|s\0|Uk>YO+× `{` _P5l6X/_0|ZO _~w _Ub>s˱N×Uk `2|#`Nm`-D=  L껦X/0|K @8,×>X/ _N锄 @(,×fޛ Ko{8EX/ _*W @,×>8`D @8,×_X K/`rV+,×/`2|#`N @*e `0,×kD  c2|%`]X/J  ܻ _ @w ` ,2|9U70|3j; `O=(,×W0|J+:-!`oVN×W0|c-޽at44\D*6 5H\A4 )ADȉcHB@BΚOHa$ ]^?I_IRcҫdZ)4ڜK uX_'$$X_4'$$}, $|%I:WEX $[[[NJ< E I2JTCguu5LMMLO4X*0==X $Iݒ Ɔ "+I'=d$IҭDY $I$|%I$I2J$Id$I$+I*_~c%I [ϟ?G[Y__ayy9,--??eaaa!|9勋g˫4looW|1mx?߿{I B( ˗ݻ߿x@Kpf;2;͛7all,ZO9^۷o}n󉉉so߿_ƶ$I_I>'쫸{NНlTo0>= uBT}d.CaH2J!>6ݿ߆ҵWd`RJp9$1Uz+F*y,O=۠Ƿ^|YeJclYSyJ׭+9zҠUK 8gE8 -dP__Y&F &цҵukk,q!KOQzz)&~=}m9.]FOa?ᙋܒ١`3z&Wb<%W"o|oyHRm}}W{>{{7M鷜SFgq2Z +++E[lmmP8jYaff&pwwWT4#Egynnm v]__TP K8C* a1G~#,S _1 czيJQUm$#SnK c)'9Z$t?\;&.[-Id!/K{\& $|pܒoΉrc{+<ӱk&0Buym 11 {&g$e C s: ӿe>AxO?(Kdqp _YprrmR5s(GGG2#3559ҮB9VfTc ] yodJ}Ghl&tX5'{ X-|2cP&) JƱ%EmC!ْL01R*M.D&؈]K{S9yX4#2Ř *1υ?U_;444d/a`` &wB3eqT[5/*S6 Eozhjj*Rp 88/n?>>섖"mQS&ZǔsJaT*% l*;qQpq]'/W9E"@$[GኅfY;2$E\{H eE:%SN9I+Z&c=S3o45A6nƃX % E y񔗱{_Qe4 Ƃcpvv&'' D*sHQ EuҌ!fmZ:[yZ2==eq_\\dj&Iy .fbImA3B9¨?14*pRBbeqEda0߫ E3$G>OS=ATN8f!՞{ )B8wG^ ,߆Kʊd4BZX-H/v)ƳIG9۫9'h2ᴢvvvfğ6Pu!6qll, •Y?ѥ¢!ch188Nj,;0Ԫ88 f{ U߆k=w.3Yx,J]hȖj# tr^8$sC@G`r2zZWD"A"6kol|wԩ͇>eGlqw6$ ~fX`D}rrrCt9D}ra08 ՙ3gҹs6pu  VtxzZsCޠ0j]8`sj1=̺p톽7? J t1Qצ.\#x$*# QfKqJtF$@2S׿濃s++}tw{t4::AЛ7ofIB42/2;Sɓ'9Vx._E*={:xuȱ[Fi$LNvp0q Ts%lӔ//oeHYA c;Odw@⽧O"Dy2571–u,NzȾ새:1Q 9/l_fa .)3L0G0.0D H*F0IA F< DS';~wΊC$bH<7>K" _ˋ'CƆJca!t1BEDDD""//o %A"""" _(|EDDDDDD""""""" _v%DDDrGd(477fffҽ{ҕ+W˗^䌈z<\Ç9|z*-.."""#KKKyϟ?L{^S_|yy9bQHtrȑtϋPgKfcc#G%V%o߾A,Sk|1ׯP" _I&&&wGMW^vuuusD1>gZ[[K>}J޽2xgb@&5 WzCC͛|WHЇ]9pܖdID"+"z w>}tz$!,($$U@-aXWb kP-Xz bm$AEA"QTEʕw8g&<“fdg{wr&?' ky:888{0d\s_`ÇgΟ?_໲RmnCVg3HjSٚQژl3}ooEb0w2Y6ZYRv5e ӧK. ._ԩS>~וZ =yŶ]c}n/ŶyyI;~`sssg Gӧ|Q/tދ/JeIC1;,|Jz #N _>4W omJ|S/,pqUW/x X Hqŋ{Q\%yfݙNo3 @J_MDo3 @sqKS+>#} _W 4x)BLp_,j}}U/(8)BmFpdի_P\,)|fS"g` eWe@yQ%Ҍ,|aU\%2*ڤKe:X B-U/͔'0z _:p _7gE C3, _rO 7*(/,×l0|xZ\\2| 6]* `d#K.u* U@;X/UUm$8,2|K$pogœi[X/"0/\u{{`$\K67UsssՕ񱋂,×l\UT\ __v@I 2|$ _ [ ÷[q (" _kO/9cC 7PvE `_* l</u^]]:e2lX/9 \;;%Bi AUONN\ rϗ@E<[%o߫[0|Sԇl.y/y)×>i Wy÷YXQL}+ח ×^ݭj!+0|Qe-6|YJNà bSJݗ?s/MtaǕF]BAĝ w*Rwv½ׅ x/[Qiz/mmkնiKjo&yH$=+Vm$3ɓ3g3s$~vuH$\Ԯb1ww$޿c@)4"w@ /_H| ߵ,h8Ki[ 0YScmGX޾cܣ!8qb[&*rVUeYƍ.np:Oaq|Ijnp***&؏ڬњltttUI&633C/5==+V]]ª:VWW5꿨Oe---V__˒a*mzO$ ߿fu9c6T/XhgR)jYul*r1m;z@,]D ֝ w޹)qFL誎~ wҥ d2VUUe_|)zRA1-,}HK΃ZK|v͛Wv.^t ԰ w[>pqCYl-Yw5jJ\uvT0|`(PNtǏÕ|{˕|rr[ \BWUNCq}z/\p a9F>uqkg?&X( $ Fidi;=Jm PpJg'pY࣫*UJGX鄔"HȔU#׵2\$'O\6x횷aW9ݶ[a՛6YhV[5V: y*_+CPFxK0PNu,y˳sYV|]%J5'Gɮba?^N?=ۤ'p3A@+%j:$,=;W86fC7nXVD:Lg6p%޼YPF޵GKso6y6r ^K1 Wv7-znVl~tCiS?|}ȝ;+ ] ^jA]i.Fw>|7[ ٹlXpPwϨ3KiZ^%߾}sn_b]mM,w"h>WӧSW2v_m}n;XAO54sFǘ_.g8v9 \[㫲"܌SorSQ,nQhԭ}sdk{k鵾}d6wkz̮׾>o~O]-vBJEq>\~}s)nZ^l:w)qao;<ߵķ~.wup~lЩL]sgdk5;)((7ʍҝ"BAEčD|(Е v>((.G2Ā3>2:Iq$WsVՌr]]]}_u}dNUF'o$W +s|wd1G 77n8y2ʊ7׽yrX?:nZ d\@|߱cyMٳkR7iH6V|V{u׵d0ne˲g2Ek<0>=;X D7/_.ȟ_t4V|/-MX@, RY2;fDYbLZl`xc;Xr(QD_%ߋ n!h#`ɚYpD.ȝz]]AUڇBx*AF(Sr%ok6)' s:N|'Ƶ {yFy?:VDjZs>Xwl3vi@d؂א(:QIۨ,&GxW|/qK(ilOʠ_(Hd7In0w5~<.B)[`>S+~ZU&Tԩp]\y*$`Tիy=o0¬^ sF 9og΄[xMX?OV  ǵk}Ǐk9ӽ5nLrϞDmnڴPO6&~=/3  3wݺώ~>>w a3w@72&Mֻ67n^J7H=aZ0{0# 4f\RlA1B BDȜ3Ej, BȑIP>u(cJh(QDd3"ha=Pqe;ńr/)ggX֭/?haPD3N~ŋ1 n;c!RR& zQISÂypL`f-^=DE 9BA~s+.""(QDj%[@di^`즑Ki[5+Q{QY|/e-q dY?B|17 0#2,bd0Hט,w3[ܧvΔm]9XiƧ, 3'zRBMݱg avZ{5VS@vnLďޛ4lVaw ĽJo#{wւ-?m4*suӮ{˖z{a 1PKn aaݤ7 `wd_XV+VcG,x񽊧&9A+q+WܫC,h9VE p{uLLʍv"#Q 4hHnD-fۗX,`]`e+ڔ(QD 2S[`br-X{bBqUY 6*t ZtX7& 9g-#e Q"1ګK%Nʣ\x+)(LIJyZceY O?TY?D?`%16X]IVŝhdwqTG{^u 8}[NU_}jl+?deeD܊zAsΦ}yܫy6$}iӄTadY^B)i9h=2f=wf]ҨmZ$5]Emْ˟ صkb=ᑢ~OC_iy3y3L;i7n !Pjxqt9+/iQ7sT?6H-T~CZBıő$a]=*****6CtIr%He9DJ*|v`02g <TZi FB^F2y?.-}x§,۩KeMRA!zpI%y_ J}VVr92 ()]1Α>PuEo/e i\>x{\z|L (bZcRcNJE˵޽۪e!Fd8[XQ,JQ*S1=hkH4la4[DgWOmɼf1,d8.l6}/ej*6L4~Q;JS_LhsAq&}dz`*R6ZbG+2[P`G2e'&m7ҳɜ>1 {!VLUlΧ^_ӼIrb:7_ ]@cĸy(0G]^]J_VTTTT|_t{1-)H (udD {|X_hkͨeDF?Og[\UDŽQ@tƱd]QfßSW+_)~o"k)Col Sv"cGV޿ɾQlUƁ#/sѩqKKt5_x2Fߞ??2_>߱c٧СF#Z=ݸ=4* eبN F N4TdTѰ/$ mJ6?l0;~|Dff2A/xX ^ O+&w༚oIQ}[ '.qC^2& Rx*k(m@_̈́H-oo5^yXEvYZEEEźQ:%Lkߏtx#6%}71E 0ndHE D !栵%OL/y;c.С^fUFĞJǮn+mZZ}{KkȪ?6}oŶi8֢6wɓ[϶nͤ M_z5kP(߿<*B"GY]H(ŏg J<ŜHgW( s\JMU퓈Vs>""H 2Sk)=xEZ+n)GpBso*^dV~!D9O#Zދ@+*W4O "܉*7X X0!,,.,}S{Y pŔg!|-,T4Hߋ{9^|H2$zZU }g Jq$=[-c( p@ztҵrB yg[[# c& !Hv"J>>^ƙ{Q(a#!G Xgx6֛B ?]FsdA,Ќq&% 0QD,$4I,-i,,i-#467Bg $V"ȏZh \#"1;:z]]}`pf3vPa$ hK!% ͛kh>MpZ k1ҿ_ w+g:#|S mX[BR.cW2 #dYl ٞݻߟPgq#ft7 ;\$9Ҟl!R]-Pռoc{-2…ev#IRc1UiS(&@ە 4ϣMC}A'I.#e>;Jy`t `0rD9KG6pζ59* cx=Ly<I/ߟתԱry8R58Ok:FH?佳|{qM)yt~gS+I$IW$Id+I$I$I$I$I$J$IdૃEs6$I-ت&+jClrr2.]Ξ=CSSS<=Yj(c6cQ,I)U:fi>z(ɓ'ŋ۷qfe_MO |Uc`{رpĉb[zp;^~]lX\\y;%1Kv Ps\^^o޼Ϲu^ϟc=_Z6Kt/_F" SdYKGM^yyTgW̅ ɓ'AS@ |;;;ϗ/_k~={ISC0e/f+>x$)Z Nn#ؐiLNO5u9 |UիYt֭#\v-ܻw/|Z޼ܫWb%*I-VA!yhS2NkSycc8}[k2U͍upx3;TFB4Kb1_' kXYYJFMKEkTo2˗~i,{ Tj/SVydૺ!۷wx +WĄX{n[]]~yZZ3̔)*KֶIҟv}d($I HZTe39ꁎgZ[ړtR'eZ=Q(_j0S'N>w\1I֖'I5\YfYLbg4X\BʨZr[#nZII]Fi)߿hzLvuudoʘ7oC~'Krj]\ *D$0` toooLU$A֘@CV&;IX;96Tzt7I$_ d D`I:Hi*;TkJ2viw܉LU&tUJ\%GT+_Jd&?%. 0BZ/ԩn\pcA ?_AI$XIݞgMM|Uv:, %L///G7FE+/Ra,K? `ϑ'@&\RaɢHX@WQw[i*/ 0B1bPְ"\ŬDK#Yn;_0A X$*f!J_H#YdŶ跷7V,&yk(|a*"Y̲^^^\ULC gHv-:J???@|"\O76~6WTD$.XOzɆNzB}Y P|$kmm-y3,ElȊi*~.Q~ P"Y=Bx<∕(|6}qq {{{"Y4X*D Fb[tlj4 ,h'vT^/^3 8"Y`A;v/>99vC["P XǂVGh W E</jl+΀Cs>U͖RSW /#Y+++"Y ^<8} `A W5[>Jov(+` dd5P6]~lo3͹/R(HV_,bA7>U'J_FEb[HV `A4\%J_DG 'o)"}U @d#Y_NX$f|pU tl*Rh|$kkk+{ TqXxٽ2eQ* -g&E<.,?GbFb0|$kuu;q%G 3DeUqdIT6>R_b .R`A14)J|?7T$`vU$J|RdUL/ WUR긏R_tP!K$Z`}K|Tp* ZM64 WcT*0d-//dD*{@ 0MHHւ `F W-и(Cr  J61ɊE!EW-"J| xX4^"\5_T "Y-:P,2 WO6J)E/@DC}W 0hT$+Ed@*V7U\ 0TH>)GG*F K 0L>utt$U| WN 4T6;ɺv$EplaUlUϯ(hXd@?MbQ~G 0$d6EOyި(UݽNmaP`@Atr z T =Oz1 | ($͛YVv!\W }3 pOHAq(Uܾ0|%~؎8}(u{{E `GUuRUpS _ӕl$Vdb(Q'\(U>kQ* 7"YųfSGJU0|Z6ס߾}+ `1#T/@ae#Yd"o+kЫuxQ*#Yo޼IEV*%UmURd܋d@.;jCQ*5xD*J/%W$kdTFC _:I>>d}!Htymm-mrT(G:t#Juppj)b)Y__'10zz%o]@ܟ?חc/y2<<>K P:[[[P/P>b2`@,,,$Z ߞ>w +/_{k| fLL&׏`d,Jɬ(JJl 6,8s~wϽ׫>}ypw [[[a`` 섥011>??;;; ===nnn,0BowB⧅xАN.Ocooo_Oln||< g硭-<==ec/:<" )~||͍055...*nqMMMes).//[d| [R=gx ߭| -xGGGapp,䮯ݲBUUUIP_*p_2 d+++ےCmmm @~+nnn@{||\2듓t_<Ȫl_G %-v}}N{.El,hZ]]pwwg@?/X{qq`c?| O~~||L[dzb@__RJ)Ru5IENDB`optics-core-0.4.1.1/diagrams/ReversedPrism.png0000644000000000000000000007004307346545000017366 0ustar0000000000000000PNG  IHDR'dsBIT|d pHYs&:4tEXtSoftwarewww.inkscape.org<oIDATxYHmql *,$ h!ZD l9Ƞ #@J:h:0Rʴlմ}6,}\==.=3 (^odTWW{JS__o̫Wxw7ܹcrrr̋/Ǐ盫W+ %%%ჹyyy.ЌիWcǚheƍge̙]vժc/Z 27++}Ϝ9cf̘aǴixc@UETTT4Mlݻ}|U^|{uaa!1|bbbbLBBϟ?7 0>mpkj.]>*j8p:|5t7o|oאꂂ>9c;wVe.]v盋/ӧO7'NlѾϟσK wMpVUU0jI4YԩSa7oϟ?M>}Ljjj~{:||um߾}R(ڵkj۷o1~xөS'SUUV[[kG78WP ԪĤIl Zٳg-iXׯWO<C^eeer|fUt]z\c]sS14񖂸Ӷ5߫ÇmW?oZZZٳgmx͚5V±c̪U̖-[l|n̎;xS@7.R…`Ujoܸaê [mS=o߶_oLa@Wð'_WU)-- L٨{,Yئ0#F'xB)&&&e˖Ϯ>P{Nj/_8yS@uTՏduQ6t8°BBf}'ڞ4 V@póU (D8M$ .wԨQv8l OAKq {gϞm5{ 0\TQũ+MGeT!mbWEWicɁ` RnohΝ;Mrrr}W\i.~4ZAСCm… A=znPi & os\0N#j`Kn8BNqëI}\ECCʥYAr\\1cF9rĆ}[wȑiK/[6f{VfadRiIv=vKh+=+ٍTp4ݳgO㤤tQVÙT)6six OWUq^alQ GQì5ܳ%TUŷKoĉuְK : 4(u~6m ڵk*~@"`]K*So}c;z傭_7Wq! v*𖔔U& n b-WXP﷡ӧAuG>ئTW'\W"A=zt`+lo<!mpP Z;Kլ.]E Ov(WC8Ak+W׻ MaÆhv ZrKV/ɓ6@nz=Lfff`_Mn:{]K%6*j :0Iq+Q/5k~+)uUn\ʲêVt€:Fh%L/"E'x6olU88pYC-l۶ɓf/ٳ Z"{BJ^ϻwÞ.\h&Nt~`뇴~Xt}}}U0U01 cPxnPVX74 Wڊ>DJܦ޽{MFFF`\R[Z}Z2-B&:t @ ///|ܹs<ܮWB5]YY揫u7ol ׯy#@PȽx6999..]2!!VxCC… y@m޽~.tQu@o TPQQazeW<;v7 LhR+x͗/_M2z}EEE"%+++P޽Y~IKK37SL_SYY)ܸqÆ/^0mF'_{Z+R6nh'ׯ-z>)))6 '%%'O|UWWަ!W^᪪*^,v,+ kɭHɟYfFg~&..aM /ڙ*JUo޼ijjjx[hh}smiHѨ '}]vzT/M4~Uc,:.{ 8γbd-fVFˆٰ 6J,H(JBJ&Q.3CȭjР\F::qy3sF>;ץ3gd3f`H}a_{EQ~+^3Kbb+l0|'`R0| 0|Ioq _'[PUU%`*, X-ʮ%1XKvؑ]XO>?%51u , ߈0jԨuV,×`a1,[, `ٳǵ/-K0| v;Kj0| 0|)VCCo? _'[,× `a'>}Kzzz _\kܸqZ %EX/ `,×u;(/)2|)NSSS cǎX?vP _R"eR5kK~. _ `]z5{(/0|IL^X1 _Ƨ=g _'`VӧO/XӦMX.0|IL,eҿ _#eRK 2|)L %qX/ʼn˗ `*^(eRX `͞=[ %UX/XǏ . W\qP! 5X/uuu `N/^`C@ _,2,×`/$No߾G `/L{.++ k׮  `Bj _ `Y _HKqk֬ _HKqbkΜ9aʔ)ٵ. _HKa `/#ܾ}[7JKaX ]&eXX )2|)`BY,,×?//$F\kX 2|)L 0|!q}Xlkr<`Bb _#8,×r &`/*?֖E `8( y]y*e2P:y,Ǐ _,f0^X,×W `͝;W 0|!U1i,˟?~`BbJ5e' `/R `^~/oÇ/B|xW 0|!Q2| ɓRre`/X/[ 0|!u) _,ĥ2|rr, P:|p[l>dzg۰aC/\PSS3{޺uO:5lܸ“'O~yꕃ֏/ )_~ ׯÇUUUEO<[z^wΝ̙3C]]/GgYYYɓ'|7ھ}{ x͛7~1/k5q}6.]^~:;;~zx׏֗/_f.LiKg|nj&NXaȑa?-B$ϟ?Ͼ3vǎ.q\ǯ#y/?{*Doyea&^zE֏Q8a5lذcxvp; x+9G1}ڴiSvM~~Y^m۶??'''ܹn:!B:@ű|I/^0ΰHMH,^؄'ŗDE铉5aDS.87i$a;˽{DݻM{ٳ'*((i U O73f0u69rdlǏod*\ݻ70U ۷o4etB!$|U`Go(G17Ӓ%n/|,Z(m\yyyp"%6o8|]FzJ>dȐM6&2yd4_|8ϟ??=zte˖b_ ݻ1 cǎ!>M3:/Ǝmذ!aT!3>g߻o>xB!$|Us~-a; 7jQ|γɠH Ay1Oh!`{~sEG***;P]b+'s8-8ɜG˗/O>th̘1Cn݌(FZ_~³}ET*.1fdd~!'Mdrjg͚5?iaEtЇPޱ'}hsBׯ +q]HgĉIE-o˖-I$6Æ KN.,B/L+3GD?l'|O#FtӧO}q}pj7v_v{yi>y 5!BWO,~ʶ;|WMer!WlCM"tqri@s-@t߹sǴ˂<5aٮMU K|VXS@LՙU[̌,X3ZAB˔A.|&jbڵ3o>l'2Ν;g !.̙3w7^Q͛Ej !B*^K*7ʬ~~s7W֊MŸT/31wvWu~#! M=̱[kv΍05kV;O;Fʕ+c!<-[4/]Ԅ${sРA*0"M#?K4ٳvr7ons ܬY3!B*#U~uSCf2J8 ˤ0R'a8_ʛ d4 ӱ~Ņ8a{q ٬]IE-Z!&l7}t#(*E(_N2… ;nmԨɡ]jU\5P~/L83m!h]5jTEE1̽z Kvi*6'l\#Bf^q; y6kf(D/ B !BF^Tn [v"ֵҖ_(}"S i#*v]{=܅~ݶNdm:mv^]k.j8r3)֭[*rV !BW!UPL&Li_6_k#B!BQHO9B _!B!BW!B!B!B!$|B!B _!W!B _!Dɓ'ѵkע7oF<ʢׯ_G>||}]U{B![RR]z5FEEEfaa|] `Q#~!BW!?~ `W{N?v~e^TTTTk?nܸk.ׯ_E۷o%B _!!pC—&P^^nIѣGG3KzzzԴiS/iiiQFFF4h Q!BH !D /O>U,Q#% eqqqgbQc_233??N!B$={[ZZݺuKlL)6~"}eVbcE,m-, qI[T-V~4'uW2yLh=sg̤z3qvФߧߧŋx… 8/@S#v#0ӧkqp|Ͻ{F7>޹s&W,O6]pa |jP xO|XH= Կޟ7>驙xP3%Ξ=,Y֬Y.^@&N{nqMǏ `5-Ǚ 8666S^O 8q"͜93ٳ'uttx@z>z͸[~f@:y?Ǒ#G8P/_DFwWIזG춵|/+۷/͘1aX_OI-[@·իW{_/@ `!|ˍ%@d·,/@ `!|c Pb [ g ` |,o9X_:` [ syIw-p `!|֭[Ӝ9sS ` |2c [ϧKX1 3≢xۣsXmmm  7-7zk߾} |2cKR.7< ` _5770w X—TVZe #X—rvm #X—~O ` |2gKR sq,Kjll4ȕ,Ku ` |2gKRnVkkM ĵ/==OȌ,K9X_T gq]GNq%|@ `-[ W"#h֮] `_r1޾} `_@e+op@/-O^۷o @NbodÇeѶmٳ `_rdKRʕ+ `_rdKR25o޼b+@5[X—X—r/3%|, @ ` _sҥvZX\=yzy/1%|)=z7zzz @n ` _SCCC:t, @n ` _sʹ}bرcs @n ` _SZb, @ ` _ʍ~ |ȍ,K9X:XMMM/` @9X—d:1n:X\}DekiӦM/92%|)g @P*XZq!@uKߺuVڱcG5kV1W@mK;彲/W/߿0u5@zc"/,d @W}tz /=E8*X˗/7 |Qo,?WbG `_@e+B8o, @b2cX~f @x7,d}vڹs, @rLZ~,@@j}KR *X ,H7nLW^uP ,K-;rիb%  _dzgFc_pM~_x%:jM\w^XU-ZΜ9c ԟ:uT?~:~_ӧO /_jַo߼= |O)ׯ_O>|yEL?N===+}˗/ӃңGғ'Owww|oszuշ~?86x޿x@˗/O4<<\|A 񵈦5ݸqO}}}}/@~ 4@HݻwǏ˗a4yAYBÇ+H0ccݏ? Ο[dɒlرĉiӦe׮] Yb_$p|)(eZ YGB1+ YʜT_1cca(JPMQxcDٳgA%:^z"}G58~*rJׯ֭[CeGΖ-[֠~|G߿p8:M]Hûw >Hp9͛ӧل3F,e^x="΍qѯ rH/|eG\ׯ_PtСCpd>óf͚e/_~p(n:jjjj!Éє@0}Vo ;u86pxC%ɓ'U 㸉9]~V _ .8O˘??ScW|J}.܊[tEDHTզMlƌȑ#W/wpɬyهu떭Zopp4e@ 1#2Q#PT^1\!|=*1K(0ykK}(:yF=$C]CCJ)eC5A"H(T~GΑqqSQkqlc,:vli2zYym/}hkL-R­KiKإvגc蛹 E=]Fw a yD1P%p8:MXa8BA1<: *g0J帊s&'ajޒMŤF,&m:`ܐbv3_DL8rB:!>89_k|v|Ϣ6kkseIu TU iXyO\}M!6ѧ[>G[$͐cǎ<_߾}KF1-Zp8N|& !1q޽@b<6j t2Vo :Li!*|5#8 hRdC#e$DWͥ}UHH?$bf3lJ?̣ bY0'O:wv`[{2v:cĖ׌-j%_9wkJ[z\;&.Z1c8_5{E"kvKԳ8v==2kٲeֱczΊcܹs1ްaC(%kŋ2ɓ:thx0O/k۶mx6[)ڵkg7oS<&ÉpH~+C)Ji0h5 uJ$`K^~$4 f Btl"m`@)DCF03=?M|1\VGTr߹ok@*WØYE߫',9D.d][/v?-ڣ|q,QcvSU{x9? :Xe]Y6{+Æ ٳuCHo޼Yg#ׯ_^zefͪG.-^v_>4$Y-kp8u8· $FA >bJ*/DBPlM^6҅4yM !(Z|wBzdBuB{ɘzRY;:wk_lE0H%(aDExZa6*B=K.l!cgРA8ΰ&w͙ؑ3zӧORubt*wƍaDM5jTmҭ[p𸤝;w v8:Ɔ^Q?c`@Z,Q`ǔ kiCy͸ Z)@mKUi/Ն@϶frSB +0b*N!KmD#%F_zr_!t2"\ÆאkjMG /Bp|rM càYKM\-)m I.iqH] g_][ I֏ⵐd/RI&R !9{ԩ"T`*X~? E0rl„ ~s'A*ƔQh/3S!' k#I8a܊R+Bk` kJeIU 6^߁0B?ȭD@Z111G`AlS>iJdc# I7 $6Q X.`a~g[@HSUUU ީSqQy߾}^\2_g*mwĈA5޻wohѢ@g}0bZ1*h6 6<:mv46ʨ@lGA > wg9KvK.ٳg}|&L,~9W_}SwHO>dYjo;w,vڵ^+\;@fTe)[~Cu$> M:C>ʀުLzZfV&mrX}ԩ;x۶m?\<[oUSk- #m]N8Qozw-{ׇ*ٳgG>=dUV亖ר+ŲeתU5k˗//-sO#oWm+!oտ/A11?35k*!U?(GK. &oV^OʊQ{+W^ M_`>O?ˌW_}UP^F)WCdӧ?|7$9rHCr>8x(>_|\Gb +{ _`2;S }s~G%5_`0n;fy 2`VXmܸ 7pCy|! ~Uu.Y{ %E0J}9ꇦ,2$q<:|g~C&Ü_7|Л{os=Wt@ s>*rjb?xxӀ6Rq Źsocnj<]_}Uo˛|Stu…bŃ>Xq믿^o@ 4y.~ 3gț̹[iVTK$ӂN<߻r#|Ja1k׮2KWݻwwygQ@)3*2˾ s{3P [>(gAβݏ?Jp#B[7U#. ՍX0Ű;v39y~ر_|Xvm裏_ t3s{M`$GiÒ-N2HN@K\x],)}&::87lWư$TFKu V^q8v-O W%Lj)ɓ'04g{~ BY<1;]aJT6> @zWM+ag5D;h^K3rgF=Rl,X=P~zX |KqU7W  Z~#Boz͛gF=W ̻*&Oy^o/_]T\%2NURoq3S۟,|aU0*QNwYzvXެW b|FF0~*|v@<{@mW`u] @1U/ד=a%` Sa֋_%H?v2` i^_ʶ7Tߙ |۝:uJ0橸JZ՟fIf2|i)b)|i/'N8(0Uil=/ )b? _S S.wo+|Oq^uŋK<5k(BiJ*,nҁuVX0W t WX|Y^u+BIJ@Fq _Z(B JUHVV )|i DqK7,nz r**f`` t-`!(|6pW\KK]o޽{_X(|iԋrXG`Uֺu`!µP\%ҍ*9V`Yq$… s7tSYuyQ\%ҍ*Xʳ _S T U/) .]rP_dl wU@? _UX7n, k| U.Թ!%͖] _ޙUa\qkEFZ\ŭESpGQQQDETQ_DWPP uA6Kٗi4IoMs=;w:L~0;s3gysL8(Ҫ+҆GBW33ӀM U `!|!9~,GQ 8h\$@&n5U*`!|aaH`i @B079Wb3h0)xBۭ$vn`\f9`!|xشiX |q0>#|!pX+W '`)YNX_H`_*@. X_HŸ`0 |7Bb]Zk׮7b,2 or0\!_ӕ85k`|*@&*`GB7Z~=X_ȷq |q_t; yBw \@‰,/0 1or0|' ' c`\h?UŴ'/,2*(( UMU@;ҡ Y01or08+++z@ *@.<ø  R^^n'`%*@.|W$F۝51m_64An: i0orUrlf?@n_Vի1Bbq |\ CBXU_X֪ULaa!X_Hh4jg^ |#b``/`P:Ҫl)R hG ƍ)/3h F&]]]lXdԯ ƥD͛)/ @ Mi N(sfỐLyy)++3>MCCs <-7Ֆ-[lٽ{4veGALz`II[UYuN7댎1 `222bǕ;vboMMo( H_5uwiv^m.T^sSw]M) 夓L 7Ċ pml4<-۪o4 g;{2H_޽{m}Сo6F#gϞc*K LnXWWWܱ{3sΚm۶F `o>;0;̖O6mmGп2{|B ܜ): 6Ya⋱b߷:>(uj;wFaⶵ5:_Lg"!ڼKA&ьXجڲfSE[@;ضnj'E2!J=ה_zi񦧟"(,ն\+~3N>S 8Dfjm#ULLLJSX4YI0ffflӃ*X-+=LO88h+ UiRヲC͎ZQ\SXz|[gm _m&,DohhȊn377s\5TGJ$F*|ź[kZ'% m5ˤ́\ *7Ze*AYW}v" YP}•QwU{:sSUꂫC?;+['2.9|= (x}Gϻ-j+j[zNH:z^ENoǓDQW_5.(&أŅ%o&8v70v䏀S~THr|% EEfpsN{u9KKc8'~9ڦ-2wqNw|C3D(o[=ͦ\9=ƍUZ_{-7ߌ;*wHlw^Owg*S,t"-頞o1mom'~ٖT>?CwL*?}) _ 8NE:qӡNJα$pQƈ^/bu^;, >P)X5չՁ<'uz ZmQ9XWaĠ)V3=+tf`߫|*7\wϠϪ*Ve&0k ΫaT+WuAV 6mK_[Uc2:ڕUQݗڑΧzھV_tR)Ṳ1 X.[b)1CޣPCEaqb%7v gvY{ /46Jyu⪫`ꃄg2^l!S, 4 X3_}ut"gͨWkoŮTyq+%垬nGuҋe{$d'DduY!k͟WWMەZ\~Q+\w^vysLC 7]fzsExÔ]r|Hxw}xMŔUkfƋ"F\F8[@׭դ>sYA*WsI~S _+1GGL$EEEqbKu!T%\DVW^ϙUVZ琬T[5NJKKcD`=<F(_^Q|[}\u^4p d;{TwjC|R ]=ڞ)QSpmHb8ϥk^Z)q[pWu@ 8^!qVu5θq-WLp{b҄;/.^}@uvR n3?o v~.x[O9Ŋ9Gw6!rUiI?(anDQtgPJ.E@T.\8Fppa b\E_'VH/ ɴ3$m;9ϩn[Չ&]p[{s_3Z,vIO?yN$,?<]:_…wD"r7\B0!~ErL\_}5O qܺdIs|ojA>WyCe=zuN" a(3/; {"5'j⮻5g: \ロ/bR=&V}u_-larU$}ϥY8bG.Z&?0ac c1jm0д qA*@=0X14c~ id0ėһs͠m灁c0OZSB8Ľ W{l1l&\)/"6 (,U390c^bs!A}d9+dWa" qa1%-=I6mz@9.˹7^3~MS՘kGF%E F68re&n?Z`${H#>(ɨ%mO:ob{>o|Y(Ǹ/zvݺj=wmVu/6bB.K*F0+wmŕBV||,X0ım03z1k%]|6k3JvtTv{] ^kxO:J*p4RgcEJq3ˆM޹dh6ey7`쌇d6#KA`P|/8 ig,%`c60_0,)Ո[؁{~˜H {:s!7OLkDp $Lįz *&Uq&xqK& 3Y=d_TOfڴWw 5myJ-x;{޽k;r#9N#.ױ$\qs#/k"TlQ C_Rf̒`k CD!ČD;ɪ>sQg)fc g\zkfׯHfl}\Nj/{镹R|%3iD^& O20 ݊IyX*@q,Xl5fxW]A?SO>gɬق^h(`rNцcވINCMdgl';\p)=/)kfT'2}6)WyKYs X|Kcۤ~s);k1["|Ŗ^s\Gܾ=Q8r~7WP6W qEE7{)%y_F=|{7mωة ܜRj!B s YV%DSL0.i(xaO+|ln2= ~edp.3(giI{(&)^cs>cev)cr2@f-85{iuՎ͹r:ʵCh+,?п0#~Oﰮwx,>W\Y_@i M 'ىV6x>"H"ٔ"Hp{clџ7e=lA캦3a~Er3١ ]ߜN,,eLueY\g#j#Dt+J5h#8'b-4qø!S_߉OmFZ2/6ӆ Y_HxE"4kXjggLH>us##(ॶ. Jx?mN-> Ś֖ +M(w:_-d=RL:;絠[/ OYy$| ٘VA 7cQ'ǃĕ4A1\IE&Hf fgFedqKĸv*a(WVg O,"ʰ A@^"մkڶs[L}϶1DA|sLV+ O8]rs9|-V Azو .0ٗTӏXyotH`KYDH!ӐX曬r<L?FV#lyՖcr> 鉉 m]ۧhBq?d3']iJq!=.]C /4*~=H.ݗf|^3TR/ܕq͍b< h   f   "    +   "    +   "  JNLLK pQv*5L V{vUmݺ5g3A.#~xk `Jc߾}=rǎyEN83gtA3eڶ]^޽[)?(4WŻ! .N[Vl3͓[PN3L[^oݺU\c)U0MJpiii~jj3ܾ{={Coܭ˗x0lGQ&׮]b겪ը΃]G{V }ivu7H]sSnhϝ;Wl[*mVum@0ҫ$/e$+[QE8 wԪ@4ÛWkvqIRs1_:-lvT,BιB0g.)Uy=}Qf"Lj/'J,q(Y=\VRرcE* 09T,fI hU0jѣ+TyK0 _HVg5X$ipUnpT 6zWmپ,JH$Yr`h`5(ջ+JN$iFIUT}`nVysM 2"YBS *&!J_zdH?bMXVb3Q_] Bb\$+/+f\#\z "YlX=S 0UG5J[oRe`5de[t;EՔQT%`d | XzJw#T`Gʕ>,ٳgXWQo TGY3_EH`k=GWQ(|52?dP'\(|sHVEgKHV?~jĉEeQ*0Bd!#\բT$0Bdɹ*M$?*wVGzʰmT/^,/0j+V;UVRGQ*0 vsapUգTF>|/0)r#1y~p$\ (E l%nˍ_27Ux}/P"YY1|檆|J{=~X @/DE %< WSng(|G2ߺuK$e`q=Q7|S @׍dsr7lrD=իWˢTznH3%'\ծ׳j^[ 0C"Y#WWe)T}`߾}7xcw0[-e_`tW5ZQ*i|lilj&,FEΜ9Sl_ @k/2d͇}'\59#J|^ɚ,fyyx:(UVt(Օ+WO<__Ę4Xtp֩F;&J|zXtpR_)JeML] \5[y2J;R_Y\Њd͞m%\5}T`FE.MN2Jܜ Rd"X$k2,ES WMGVʳ}R޽[ 0A=7 _.IX4pd֊R9 |Zj$* `1OU(U*gr=JA/@eڼgH"\1T_HVN梺2ԍ'Ŭ W_=Jum}9q|D6FYZ[5JR|6|d.['P,&9Zھ}0JuU`z"Y2b"\5Z=JT_-#5^f޼yS5ED Vde;Hˡ&<&92\#T_z)gS-XvxQ*/@'dek۷{귾~E E2 wVqΝ;儨~Q0O_#Yxv_5\3޹Z|ʿ:9 `uOnjwŋ;wR|جDm0J'J)C$K)QӧOm&J``FW#YXеzQ*/ mBHVͶ=%\egE X5md `5GoFԣT }o0B$Kkںڳg(+#Y9 E<ޫZ\\,/w 6md `VVF80R жH5LjQ ]xk/ l6EPva @)GuIƋTJ|(JbYt̸VTV='TD*dE$+++ňKN 2$yV,XXJ5o|GKwgϞ{ӿ@R^TD%Y~_,0aBC)U_(A[}M%%YXJ5cƌR'Ox@PJZRce̱Y)/KZR*|hced&Rs+@đE>|H/^HyYt___zeˈyΝ;sܾ}{~ e)~K;{m۶G6Z` bX<|iڴiiҤIyV9ʞMUV. M}6DE2 @9w\3fLڿ/-[g /hN|87-7;NڵkiŊ=ONK,Iw@jQBC=x -X ޿-Z8q"uvvW^կ]p!_sP[n uִaÆׯ ?֯ž8w sy{/]! թ{6mJ'NLvJ7nhyi֬Yݼy3#Gx @5~74wtt#=gz㡺XJ PH===iݺuBgիӸq2 @6otϟݻӧOƍ믏=?O>)S{ @u̙tɓ's|re˖/__r%/ݛOn_FݫW3EwmE,zʕ۷okQhVǎ_e3gL?@~#Z׬Y}СE]]]iϞ=M߽{L۷/ر#{  //|0 0 0 0u B IENDB`optics-core-0.4.1.1/diagrams/Review.png0000644000000000000000000006474407346545000016050 0ustar0000000000000000PNG  IHDR'dsBIT|d pHYs&:4tEXtSoftwarewww.inkscape.org<iaIDATx읇NKE?łI&G9g&{ˠH#I;nnWݚQ(|_˗/\^V]WǏUuzzZ]|ҽYS}ɣs)""""/١jmmcdz }1#G wwwUժ=bccmw/| j\ Y>߿SR$De?V%&{"S(| gggE|7yܖQ[rvUv>>~Xvt>q~iAKDDDD _.'''hS*%l#G z* ʟ~3Odn;,h￐эf;@оW7"o߾U_ _~K4lmm՟ ^1K%tB<7??_]^^ώH'~KGi'?L[Ζ6!G'ץF˳rGЍgyIWM0B8T1ǥ&/,0ouvGDDDD doGFF~ `62yXlD&5?cF4~g {3[VOJExt׮q8t|)5i#+eMA{`Az @VWzȻ"Nxn Otq(? ".UN R;M#afTjM'sM\]HxifmqBA~yܺQiLk#{aSp\' [Efo{c.xì5?|@_|@k )noof*T0β7v; D199YcffX^^.677xzzѸ룺^投bww8>>.... 2N?oݑ ^,?W4y/7(qvzFiGGG3M1{|im7u2___G<< o@w ͌)IWWW_<&d{y;zGres>ZK#VWWkg#4%ըoBxʭ«Λ 222emF>̨KݺЦTeW]mV s #m/c*[~/S9ʑk/.blդr~ijD1/c݌ne}eFM7ej2|~?]+v)K2*kL In5S!A1Ց-Z&3;"WKKK _Hn[`_Z&XiU=X/,`,(|i9Xɞę% @`![R@e`!CF,Tk {)/ (|iX-t:K(B,S;XVub,`UVu*B @`!GK)B,{||T%z!P (|LKe0X/-Ke8 _ZNp`\i/S TX֙ __GLJ,:_)$q+H.LxY7Ll鼧Ybec%Xg5%|9% _kⴄ—"xc0X— T%9X—~ `_X/e/T/e/c ,K? I{X ` _b+=E |!#X—V21%|gZ/$eKO `M&f4,K,@B55%|,@B ` _ `kX,aٙ,@BF//$: ` _ |/e 0%|)3_Hn+ _ `3%| |!9X—2X t~۱NK_ cW ` _ |!V|~~ XXgDayK `뼹nKXӓ_Ȧ,w2_@mX—?n]@B&Xk*|I |!/`/dyKr, 8%|96X d,@BrY/f /C/# uK2$xh42_jhX—!ꞔf. |! ` _,\@BVqvw7_ ~\<rPK | |@ fw"z;ɗa?叏zj{~>7bhVxvcǿQ|ww|w&=@}_"$N,**dO^ 6~h^Oh}}}0kciiif1ci:*(WVV:W $Gcooo?|GGGݽiw{ooS{c1fގ.//UV'n|Ӌt"G7ݥE"(ͤcOU'wc13UH\\\阼!zFu>gONN5CݑiҒ8@Ԩ{ss3<+0Ӧ,#8郉k c135pp;muu___o89d13L0P{奚6_5MdgL ^`c13U H"ΰSJq5!HOeB&5H%;qq"ř9\$!'}øˈUrQY \;c-L-~2V}/#CBϲ^c1ƘB0Ò!gɩ5D滑-kù5N8NJ0D [q"ʸ,uxxXl"l+I7 R}/Ҵڴ[\7ij1!^c1ƘK:)9D9N \ $.'Ltx.}˫spj{؏q85rmmd)8:LSg-ĕ99T߫v9IQ.!S@{Xb|Z}/myXbRc,|1?BWbg'H$qlxӣI_d%Xf ` Id[C]r8^*c Ʃ5ckT[s,t#tx E 9QX":yO}Ix\bA]8nL ZmYA;*mvsBVKrbNz%>1 K\TMm1cf]mc 4-:U%b)PCm<ޜ*הz_Y\>_6I$XϤ1"b}/q+c5}*)Z4g.->m/SJߔ0ޝDa~:C,N8< jRREo:AhbCwU;wb,U{RoYյRNa c~oށAHcARpe:_T48FWL'  )X*~|מ-IWҿk~on^lʔVK9.UӪZJVWEl*LCGښmxqN|~o8- eż/c;2Ǜpc[ql!m0^ç(p2g.!8ڗٿ^q!̓J3xO\hs1: $|%}^{SѶEƉ},4IyZe[yצ#Z iUި ُ4vyQюX+*\ _\BMWo+?e@l M#``1JuT|هR?<K>/2zǶ.uu B "6Q*̵hNKUgr5!>nߍ_0J$Fp$ƃ LyRCH7!M(*:E'H%q嵥 a8CE:#*O~ZBnJU:*k~?[ 5.p*-2ѱ𕊪$I2J(ܺj.m,:sș/":xoI $ %>+K $I_I$I $I$|%I$I2J$Id$I$+i+I$|%[[[TnWf=::\^^v>*I$|% %*Xg||z9xaaFK$$}[U%8 4pׁKsuuy||IdTjNOO1I;uuI10,IW⢫.F" rfffŠ*xш$+I 5vi۝5PTN a~D54M}'I2JRP"r"MkBg#M1R&B0$+I <,CsxVNLLT-OOOx _nggg;K DVeDhWO;>> |~ppИ}۫л^}]ܜmϒ$$ #Z<9gN `P9--EgBSRW%E!$|%i֩s{{[ tCp =_U777픐$|%iv pXNܻnW*ϯQM&///a$|%iȸ~z||CyF)!I2JҐr,|&jZ.%I;HQ# 0}) Ł*8 AI$m>YB[=U2| `a `` @ ÷M  o, _Ƌo/@8, >X0|0| & N ÷vz<. _#6tI _0X}*z5a0|io_O0|B `osn`2|i` ` ``2|# NM `X/m/@8,×6, _puYM  K, _pX/mXV+e9, _` ``2|s\0|Uk>YO+× `{` _P5l6X/_0|ZO _~w _Ub>s˱N×Uk `2|#`Nm`-D=  L껦X/0|K @8,×>X/ _N锄 @(,×fޛ Ko{8EX/ _*W @,×>8`D @8,×_X K/`rV+,×/`2|#`N @*e `0,×kD  c2|%`]X/J  ܻ _ @w ` ,2|9U70|3j; `O=(,×W0|J+:-!`oVN×W0|c-޽4цq7~ݹqppĕkMn7.tx9 Rx-ydPfh_@;t{ϣ$$1U2Vu|hN%I_IRK:e,Ί`IWe,Κ`IW>WEX $E"q,I_I΁Ik'-_Xd$|%Ij"LS.CT:}L%,Ft,I_I$oXRx@$|%It'cB $I:h˷5_W$I$$I$I_I$I $I$|%I8c$IWtϟuǏaxx8|-LNN_lvv6|||F u_ 986###$+Ij*Җ\SSSa`` Z3!߹H?~ q>\u.󮮮{o_~x)IWRÿOT= +ޅEh[[[ 4T=k%к[[[ahh(Vz4ioooh0vvvNf>oT}CcƱ#bFT ӧOtx%$|%oԣGҥ}F2,zf_k`o1'oބ;wТ hRYKRf-S9%jJ7+h.'_ }_Bt{zza |;T~xdTP _[~Ȳ?aeFrnu+TUtqƶ${=AJjN0Q}uBoooR gD?to0>= >+XYYKadtF݋v=rI ڮ^@Q=0\ $&B5mܳ *Ֆj$4p~|qj=Z;ջnXPKzx6!~1qkI||QF¸z[%| vJ8h[=P:u }R)CV`lVeT mDŽ(3'r9dvhNik䤞ɕ.zM#ϑb=1o3}"O7qؗ԰rnʖW5k6y\#RE*ǘq1Sa8=u;+ %ؼ"6V1UZ>'*o<cd.M/ۙ'>wcN'NVkq]__:2N|kƘLh$C'Ym7@jq^OU3o|/;'ϑjx: '!d[E ܇[u}6oXY ޹FDaDBA[p#*@|ą("ՅԍnEtqƙ8щ$$0GjҧsLMO&-s>t߮[u=_}b|pCZ,K 'XyOSy)MBKunrԒA}i1`@W)DŽ|K*cOmLüf]sQ먹c9w !3I07x)f-k֥y<̠=)z3Ow8N|$ $$B {O ˖crya0(8Q%΍4ѢErdd>8'{J+OW/҈ T9RQ_0E|wX{n[P,M v @Ŵcv<H\p<@l\ YM rAk`Cl.$}Tk ]eo~#D4u\FNK3 ]¢0Ch&$lRHs!J\-)o ϖx|oclhRI$7#\KݬL=.P \Zp8u8~\8Μ_:v,/_/YݠS Z%  0~R| A 2@) ž}5g WqՆB2% \6֯Cùskdjir4DM 6l\so(-3QP4 V١nQ^o^ `ceVHtk6~#WSu2+-t8)MqKsZU~YeWHM dgp\c:JYY|/'qb-/Y+S^@|69N|Gc- KFrr;~rex0kV$?0=s&tnP%/\`$ɽ'OԁK3*ۂ ~^fMܓ57kҹiS$H/ c!}E5WgꤼgsVcB;ZqOA>S*d!ROs2Jv'A/P_*Y3J^M(R$ 1eJE"m j7v5 o#3%YYֿuV YрTײ^H^ e^|Y@룞_`xsf6W\G*£ c-j**w$@Յ\4k֐ԩUweGc?ѥܢ!CC+BǺu_ Êz:ݵm[r!Zar+7b; aTH}'?`F;^|%~)! l.ƹrif K)2f)\6trzMtyͽ sb+ zcG5uGY<R Xe kYczR0kp8u8 17b%9L.]۷\#exX4udM!暤WθZ19e}%>lN?z")]{qgB&Z]g^FNMWdA5bl~8̇$a%.4.L\_;62qθWlܸЍ5 1n4HK)ئE`jДyNy3G~O2:3gwޯP<xCyR9x.F548r9+L0Y>f\?u͵Ş89Ňrm1.wL^W<Ͽp὇|횛:}:yhb*J>U\~H䉉@h"b 1Ć9FI?>A!:D4ax$F:^8/ք+e$ccS՜*->k̩Z+ģ_,!l<'srm<pz!$|BO.!ƚJcrA S$tBB!$|BKKXbG]!B _!B!BW!B!B!B!+B!BH ! R8BH톄Bm^+Juvvmeesu===QB|4[-Ah̸isSn^Oa!bt]]]õ:Z[[]KK |nٯ ! }VkȈFGGs_|vvVNBH !vVMܦ&WyMNNz膆C=^5ˮ\.~\%-x" F* fO` J"ȹ|qʶԮfԭ;W<==qoBYъ%M4sz]{=>>F_aW}}}2k J\^^;Y;[CY]]t#}]{u>u^u~(vXA_ H#; ͑ͤUUU}|ppȼTp^w""J///>$@V_!ydZ[[ vtX{211H+++.A$r|K:3 ' g; ϡ8h{,]V蘴r@ ---vaj^]]ǾXK_i]v،#ښox9)|ïB8D}.wE^7vO4}fcc\__vl@ڲv짛Ѕ2b;eƚ D$$QQ˝5q ou˜͗Aw-v\zED®T=<<_ߥ/ױ1 }#u?99kY@ޖiPaҍnΎN4X䂛nH mhM΅;Pѕf5NMw7Yir%@Z>[SSczBFwTkZM¯Y^cJt'ZZX{5A%uhQKZnPK/cS8Z Wi5ߘ1㼙fS(|}l\^F:Sр!X@.W\i0q&Eq)f~xV:nuS{? /t444|)"fv4K*ށ @G@RM7*y+?_1 GV (@$-Bg`XhJǃ,"" db`(@ũ*/*?e XH͊*""DCpa@(@"Ujq㙰v| [\uqqs@EkZIiQ|WiEE!<BP|⪶TW|S}H~wGP|ؤRP\B(7 /4W|U WbƒOXM6M}qAP\R|(0 /P/W\544*/ DP|_sU]]]W|UX_o0Z)`_ 0-(ҍH(BT("" /PR\EEaW!N`|QXEq*=΋*Y´2"ؕ`_T\%W|U(G`|KA-\)YRY՟?w7q]V8K| %HIBuӣuuBez~_/\ _'\H _Z U[[[޿ziR<$w2|IӕgvwpU3*@e]}^^^\ _|*.K*gZ/\\/\o31|N&/ `aB r _M _DB , W Uc/0|7F*×rUW2|)' !\eF 6": _ `a„W _`aNpJwE1|) \2|I# H%] ~F%/P\upppU~ _`a(pK9*h,×4Y+>v _;2|L ×2| ߊp`XTpo*h/,×4XT&VWW _÷nW X/i0|KhccC ÷pЏK|Am/\5==-\G#B@,U _*$ WMMMu0|K~+L2|,r ×GE-}$\+,×4᪥ZEu@%Qo... Wa!\6 _3# _Wňc`~&[X/\%v:^E[F6 _Y|#\7D@!eS| W Wai5˨xyRpo Ǥhje|U cuմWa8y~~^ˤ `TpoÝove ٻ8ZW0ҋDC7S A حCб#-SEʙ,rVs8ô&x`tz>@}>O/3A Wl6r( tb9`k ̷7XL|>_\u!wWl! ~|>EE\|ӥXpd', x Hv b;\x\uYs@MF5#P'A$kҏ @:JTWJ~ BEN{@!p8v~@ ^f{5 ƿpB| @ @ I~!_|v#?0>>.rZijj2oGV4EoO>:)..6uK ]EFGG)ӧO5ZUU%EEERVV&f^v]>,[)bٳgyF(ׯxB&''իWksY9H'^|)N\a}z^SSToq8c|po©S&\dqzY 'Ol05=vBNtvv>ۛv vͬodϞ=rq wޙ lV!W4j[]]p{$1.sss)Nd|Aij~‚icZbߚٻw [aIltuCN 탁@ MGJJJfe>|E@<\.&APu۷oMHcweSP(dٮWۣѨeNipg1T]\\4ϺM;w=,ɽ{L]>|`ٮKN 9#o>lR}]ڵ˄`StevoZt'O2nYk,Wޑ;44dڵk,ۏ=jGFFaI:::dmKKKB!'tI.O>mcӮȖыcO1}LWSZIe]ZZXIu3e ź'ߊ].#?̙3٪pZݻwk5 Ңih $AEx2LAZG}߿/W\Ñ$vww˝;w˗/˃F< {!gD3}>z(㋲Ki. Қ8q⏟06@d^gJtXիWMjgH{P_nݻػר M 1؛`EV("Q0 GB-,Ĕe}ql{~9~3syŋ1~ׯ_>|[^^ٳg庮jײbaaڰ޻w^ wana1kmm$I&M6|ml8eX߿K֞ """ q3Ǐ{GǺ6`Q8nҩ?:Cp_J狈Uf;:V0;#p}aps荒.+c; ->^6ï_J}3G7GeǢ/OhO}c❬ sbX ‘#G 4O:?ř.+eaÇ X>z ?~ػtR׷n*ڵ2'߽{7oJenn~ ʸ$~qqqޱcJr*ظd#{]8zh!!?~Od>/c }5x(B.o{Pl}9|ѱ Ym۶r`9fޚ?˼#׮]+F %Ν*ۼ:{l'#}… h#˗/a:x'G-II&Ml>^@U› 0bNLdpMfµh'QM=Iܶ.5 k0s&tRG3]jA虲<>kg~]?.z#hЇ iv R;+G @5CpI/_:^8pi[J2x/F)#9Yk1wcermԥ/ ߍ~__qM|#A2A[2u9cǎޫW8pXݾ}4ڵk{-O>- ,-6lsh+B!Կ{XL}́jΝ;t$4k&{Xrĉᕷ#5&9U6e߫ 0,2>D3g %pbٞ| 6̾vC7iҤI%ߋ ٻo /An=da$u^OIj[7֒`+Nd$ _,k2AF]0A&t]-E;~g/tear'Br["[6RٷyuWkm t _^]@vUcB%^:H%e 7 ۼ LB)/\8/ ^$ut Yv4ސEc*##ހ#&{UTc=zmDauf4ٻ8|fUc,WHWvr G^￾eYn:I޾}J<ŦJ`f zI„i)Es>|Rj(BEl\?>}t.X#+bU퟾>mW{߾}Ɨ/_n +wׯ_Њȋ~ZԻFzeQ9 #(F~ChXzJW^MAsֈ0>֋/C)j!;,f#}aaaaf(9lB*6 2÷G)Qf{&Q[5KސQqڐA61.b̤g@ C'+X 1dt]4?M y^9aGX=RIi?΀8WZ0?\;(GiDv$/).SCa2{ >~84GB,bZyA^E?vr?v{^~/e5ҍ@4FÄ{y!9+T][EFzisTS̳X̃Y.¿uy/wc{;h =+3R=bVg|;{2)ja/fwr̮C'rìhq ɟSe}({mTDRGFuGBX pu׬F*(LZb3ZUob؈"k3LׅKm/4\TW2WB(5b,DB4yôM >v]IP܋z]c H2mܺu?5Kr}A,׽?{Goj"*s2j<>"qcA!q^~}a^{_Vw;g9<(4hC/ԕ+W AOOUaw ~իch)Oz`vj# !ryC#.-aRl> !ߓ24y0.f-B H&ft7>ÂDXtv˰zʲ )>pI o˃rߓ;3DDD6)gR4'$3ڵ+k׮YYRU}0::ss^ȯA˕M>LRm:55txQxEx]L.Z~l /(lwjkkKB7[XFڜ>}dѣGÙ3gŋ͛7Xx%"{A͛r{L?~Xa𕍡gϞBKinnT?(zv 766ϗ/_DD2%K޳œ'O|ˎÇv/ګ(|eLLLDPmjj .\1J|5_ʾ}:""/t潻Yq}SJA2"{V!YD+ #Gػwo'gϞYiR޾}NSa\$"RB y12ĆH5 y~~>߻w/vk5훕& _0ܹs%QWmqqݸq#_DƁHXZZe۸sN+ޚhN >|DD2(Lh%]0ySѦ$/.N_zk8feEdtR8vX\|g9,ICG`N`6""S^4i/"[ ^Z" ggg}q=ڋblmEe0[*^H={6N?VlI3zz?^Z>77N<ZZZbXcEoᣌ|y%^|Y99lG"niOɂEn&h# E+;^BEt H&mmmI*w(Nq ){xW ^ZbPPBAP"U~'&{JC|? Hꨟkfdc_AiVHsvK626Re<ݻw1q502s|\2;{H~ɇm<~Ν3@eMārlPpf]TM+ [Yw^@=VC_O5\5N][x0%aI7VnxxAQ7uE C=X~ʗܸz֭[ŗ'nʉ/`TdmoodP52tCzkޯ=T`$o`Ad͠xpURh"Y91|HVyF Z< HNK @dӧOE~Z WuSC,J_GēFݻ"Y&ͪr;QRz$ŋſO>@-'^UmSN泾,J|aҲHU`9o`ʠ[Re0z$ܹsH]?DUUyd)T9(`-ϔ.dMSEyXv.-Ry0kˉG֟^+/e++Ϟ=sQ`EU$J|FdW=+JpU{ԣTy:ˢTh\(d,j(`:XͰ#0,sʚlVqT˗z$̙3"Y b脫 cj hn8 `1wQaZ( 1),;;<OcX)t B((h!b Eٗ'&7uUj:~g|RAGE>}4 |a)#Y141X pUsD/D'E_W͗(`"YTfzJ^ cUSFR 0̘HV3lm  4)cVd\2ZUUEQqQ* "HEfp ˗[C[WFlE/@#YgΜdRl~`U'J`zd-//d@Sbpa_XA(wN֝;wF7oU(*ckkkErV`,AjzT t3"Y>|p&l `1kU'+TϞ=0NnwR$ϟ.9Ç80'\5qQ|9`lWHŋEjVa"ꄫVRעT_ƈd-G/޽+ʼn@I7Q*/@>w#YU֭[۷o677}p W!I6CD UF~r$+5?~|2`rZ W 4(ꑬgώE?zhP,a+UhR|d3e$+r?K. ` @3 %\T/OR|d--- &c2\f_kW >1gsԷce+^~B*U&;[lQ*/ɺvA$+7}!՟a*Q*/ HVw¾(U;;;T_F,v[J @eU$+"Y_~X-U^xp(+#Y9HV=Sou=\URJNR|2uʕNFV^V0z*_ @U|d}ep8Go.Ryf||Y /DK_ Ժg4^^^ umk((_וHVʑmksJ /xHիW"Y߿_2$q6D0pGEr,ɓ'?~, `M?\%\%J֫G2t.:k  @#Y7no_3gפl~[dR @oʟ7'*XkkkA W}m||R!(_zoWR`2ADj*\UE޽{7~E0 *:HVXMD0 ek#݃dمqO ]lp&ADw ɩ( ] B% ZD B\|4Is39M6lߚdEkhhH_%_5UGTDbq&YO˥Z)/>~V7.kfT@+UjT93kJ +bMTM@`[&YM^x)߾}KK'OLB!7ڹsg]GOOO^]>uTnu|Sꎎׯ_MMA_X"(jpsssjoo߈yE9:!Go޼ۗ#/,O>||`չqFZn]6 sȑ|c2 uTYYOxâ|fXe|0}q%]v-]x1;v,}}s>LMMMk׮s /B۶m+~N(>-cǎ<>Sڼys2=֭[ylrr$ 3}ӧs=z4=zoߞNjcq."ݼysֻ޽˿{ /ީ9:֯_N>?~<e˖9IͦMroҵի%.~}3LT{ޖً\A5|m~o֪=XKDDDD PT m/L&c*׮Uz--^آlX [Qӫ+:kW;Pߋu]R³T!\YYiN0۟vM{~/FGv^""޽6qo(]t!B] .*skq Aэ ]ƅS/A62㥷)۴c;mgL~/}$USsN9L ?y^ Qx|B\SHΝ{rH>5ۊ۷َw5)o_\ԈJǎ:FOS^h2ףGmij*rjycee6A{O ׯoxn_G{^-x1xϮfuDkڳΡsÏkd9 4# 04_SNߪ=,- l V๦)'|wÇo_.-٧'c;v5 :G޴N5Rjآ{ע:6\;33kk~tb?6*HRjuz& 7.|js8p~T)\\s?̻N`*UѝM$ܵKF]ׯqV4+W:hfhɡX,V0/{SUuKa-s𪥄ΞuZZ(`ӯ^E`wkNx:;47[Ә{ra@ >G#WV̟w6es<)8uV}o.HŐdTcLx|pDžYz<]%ua|c+ F #5+)6RpV+HkoꄵOwߋwEL1| | @h_۷on޼i[\\Nmxxx˯uu]?wߟ‚XIIۮ]jkkh.]7n%laD۷_~,[*ql6@v222b.F=lnn7 E8<5ՆڮǏ@ݎ޽{F|={Ν;I( xj L *++W2oJӇ4!siiiC罽|P nwN YEE>}5errڂflEߋtvv544iϻw޽4qnFBo \kpnK1D /jb E9@CrL?< z<[^^:ˏT*-CsooǾw}cG6^UU×,QȍZ12l}}=p_4bWƳX@<,0/nzFGGX||HŤ @Ht a _~vQ{{ֲlii#\6ɂ#'v.wLg$!?A,,C %LO=;R^K⣨O>.|Hؠ K, 6 _W `ţ0| `$N ÷;X/k`ݹ(%GGGX/:>>o:Kja, /"qW %AXvQ0|KD+>-諫+,×4XXmX777×<>>~0|0|Iogg?/oX/+-÷KXjE1|]X/K.// _,×ppp eҁK _#`8,×`$N;X/k`uK\688ZUsE0|If6>>"K+,׼=/ _W `9kD#G _7X/_0|8b˹F×VX/=2|KlqqQ X/Kw,×ŝ,,× _z@ _0|X/ `$9UT\×X 2|"0,×"u/2,×",VV _HQ&&& _(8;`{i8%q@ y06XY{BN,( r[az,5Ϗ2 |!Qb!|yweff& \` )`UVV| |!%] ` _~ |!X/0_H\q6tvv|8599i "X—W `b˰-X(`UWW| |! ` _ |!qv _[ ;==5%|),@B ` _ |!` [ /hhll/e X---ajjJ; `wqqw/$.`uuuݝaWx>5;;-_HLD=wX—d \ ` _XR: |!^`?Օ,@B0%|n / |!R|7XXMMMI ` _~,@BX~ e;%|i +,Kx> |!!/eGRNbB` PUU `/{3`9 }8544jjjB[[[/YxN%_ |@@@ ?}޻prr-ǧVU.[J~|<. |,--q̾^XXɾ_ x_ݰ"5>k.%̊ioll066xɴP(x |eW구cPNNNfŐ{{{o׳縹ouu5{_t=E9n%=~zz:y |500z{{K8h ! ; 9{0%]-$PPɖBZB @E q!-ˢ`B^@i"EA7Wm9~9̧_y~07w9yX^A pwϟcE"(OrI> ߾}"?.Ύ}t !BC“'Onb]\Rs 3==m733crssMkk\}v>|9&(EԨǏmVܑBw?{Cp5q0 !BCѣGfhh(AhΞ=kRI_DyζG}HG& =Eů_ӆ*9-fʽW} !BCիߑu848---)?~,//ڵkV d> F(g*{ُ/8Rg `>#C*0^t V9G:ӧO6^rpnі=^|QB!$| tuuwbb"ebiE8s8 vӹG\S% 1uz:xD Sq "G)I؈W+\OqEr8rnKNW9( & !B:L6B}}~߱hi, U{d4pLJn*qQqܧRErp/x%Nlq}qAxt:Ig8ɹ@ $}!`u ”ww~I~};BTxowWb>IQCO M%/`, !Bh(;wb$߿oⶶ68~y{s^2fvvtS.E(":R4"p%#I3 w+BWWpͱۛlis Lqqsrr""Btan%%%Eܜw{\E'% !B3<-UtqW1HPj˕ą](*Dw*"V;Uz@J3sgCZ\nޙ{a&w? ko0!@nɢɖJF3Rq@Xrggg555UV)EcB>lR=9ufgg8,#XD3ϟGfq_T~fBUӿ9f^j!%yuuX—e8u_RT q ȱ-9"1pGni5R~/[C'?#tD2w^5r7y4s1'liN|'D.שQȥC)^:11Q܆EBSccc-..k^(j~~P"FPW# "H)G(#'m!/0::Z#ɾ,9r5J7)BACo˵ZMelx|]6PzE0۹v\xycle|ݔN4'or<qt{EDD+"N k" Eıh-φ8&z3n.߿eaKzksz NTqN߸o. `юNS`xhwquiD.y1by敧۷om8=T\2=yP=}r[Hb-B G'՞={v&GѺ^?-ArTKOR>J-Ah)}M- V D2oN5L577u${bW\}R{X',#(@(,(@(,(@(\}ʊۀ,_`6O|R pD֍7ҥK`!6 pX===9{X Z/A|JR_533 6P-zE 0 |[W(0 |8( | K|V[d $ZQuUX/ p _Z p _Z p?V%rX'G`EXBxW/@ ` .;Gsև` .J}j *"䵢 ` _ 7o/*|iB/@j "+|iL/@` Ǐ |J>W_^+ _޽Da@l#7$+0kfj!PQd gfILVGU CX3, MX/]` `鴵P _:x}}0|,bA` `D%eߊ @`gggekppP'2`L` `t!`\kkjjJ' _2| @pX/y||LX/Q} _>k `( @4z]|W  C1| }qq!`M3544$eEk:}||8H~C1|@  8,×_k`===9hrk~~> `t _kjKX/C1|@  8,×`w~~.e X/ e5"`Xkkrr2mllЁ @p_5eO `X/ @p_%e; _*`oo,×?u^^^ @$U`IX/qW&e7`_]]A3_0|(\~n0| @Y ## _kM  411Qr  _{{{+X###e+~ _L  (,× @pNV? _`@~y`/jZfff < _^^NKKK}1ƏB}_s:== _΁/q @5=` / )"Fאַo߾wfpa'ԍ"…$QBD*B/,ARUՒ!% nT$ QP"X&4hiEkM3g~%39}yy?TPP@y/_R||vs헷7 VQQAբ 諯xGqq1999Ç1v< 0 _aA(: nBXXX KKK!h*...Rhh(x񂌍K=kkktUzkyyׯ*!׶6޽#gggZhiic6@MNNmnn}HiAb/0g}޼yCccc 9>>>z=v^rbbb_x?uQ__/ [~YYY߿/_"[///255@O>۷yBh!##lll ;>>./gXb+R0Oz!`/0 _)Rx}"kh¾QT$+p;w&&&R{{#TY"D/ugp}Qp !RSS«Jhϟ?B^yyyh2?~[nG%n',^8s b7B>t0#ޞI 0,|vB`b?,A/ĎbE5ئ 8&O=wI߃VrJڵka׿~7nA(y1'W^K9Q]VV&rG.R Rͅ'NW"00PqttT Bb{SE;Loo/Y[[+Ħ$E(9 wTA׸(h$F*D{--xp~f;NߋYr ðeK+'ln-L 0n`l@ ۣlC gccC>ywQmA!h+ -4& "M+bmZmhS "ZRsaٳfn9{;ߙ9!f̫̪ }q/m)C洯]'_ +=W7+6HCi-W^ ա[T& Pnݺ5(-ϟ?g-T6dz33k. mzGiu1YzyBoPX"D^~OH,"Fm(a:H vQ籽'=ꎹWD$ܫe͜WH~/X80$CsusoQB2h{1{)tmmm;{uɁsg9zE"̙+Cy(R(ҽb_ǏxgN;ަ&p\\t{Ɵez#^SHDR_t힣3dLu5,"<7qH~okKջ( !Ftk(f0cF5J8!vk[*IUe 3mD:ҟ>ڱ>H%u0߳gΌO[5߾}5ҽ{w>hՋàt޹sg+2JCB3ڵks6redW!(E dÇS)q4l/BHm߄P8/;J÷CmVA]s*PB͍yq^p.xlۿBPķP(,9{{ gLȓrͱ##J)-1+x-T1 ιӁP#Gw-UmQ!BtG 4h MM@5p4$'B MȑIJ" Rmޖn}Q{\}9g^kE.bOܿ?֡ YX'.vM¦^5bNbH2/zvvq쌍bVKa!J t1P˗dl1oRRG/O;NׯDcHy~Pߛ41. "m0 o%^E}*M&*kIv]-rn )2Z &pQ9NGh ϝyS WK9#:X2WGJL e>wjrphxe!Hvu188K)7n8\l 5hSI,T۹#6iy[`hSXIjV?~mZ8oF+"z9 sNWG>OMZ0uCCCݻ*E75˷oߎybbF@ v=z( aV. Ԏ))m,wG8vL&&,ʬ}Νxj}i̠TS%lQ.d^ӄmN|ڂl>{x(|E䌒RjI$Lwr6eZ)5_ SFyҙqtE1G3¢\0 &R㠓r/C=X*E')7OMp~$XsVݔ. Җ68,Y`,em}9iLDc-Tq۲r,pM†+ܯV@'\C21slm&Ze,{s^CiaAsұiI!GTpI=`FvKk e?-rWYϋ'B8-1#[']&Lpr_t) N΋|a'O>Ԇ{u=kߙ>llB0ss~:l@ig'6*KX76}`J;,qqL "? %hMQ!"QDpt!li_)B׍a/wRpd:E|V>ζח6܇" _ KH.QjcᐲgbĆzYmEDDD""r.!řHiDfff eWDDDDDDD+"""""" _WDph;M$ݑDD+"zo|޿^~[oK˙5lllw޵핕hCѾbgz WDNZ}6=]\\ aaa!Ǐ[?W^c_k#5mC[M|>}>}&BD5ٷS9޷&~uuL"_Df ո^=wŅ %ŋQd}aY0G fU4֖KI'h5ֺDWj5 QD4DFB!7ϛ;1c治${Ͻ͜9;?twwEVa7h4]]]_4&e_j[V|4Vr{xxi&Zmqyb!jeeņߠ 01KKK Ju qjE7cCפI_uN3P[WΆx IDmyy]]6ee M νMtvhBRG ^__ٙ]tsUnqn(͆ahm^\缪zy(`aa3vv%RgMuX5+zŽ_+,u[ gR}ꦫC H?j:nL\bц?!W#Ҋ=aN;LL__X%EA-zG}\fґJH@h+_nzG[2Z ӭ|H]S*LPיV+uOc=66f+hwɹ>ί(pJצpz.@.R7TA@Y333&B͙Mvvv렼4ѵf\@#]__]k /oqUR|HfqqўC?O=qVUdݡ| د kWr N`, νW|v*mUq Z^R(@$89eJjvWf`, 5J[Z\EE3hBHU& FC@NW|H⪧'%8 o4`_ ^^^ڪF$;V „(@"kq-v|Q|<ȷsqB RR J@ @@ZRZ-^{q`eVA @@ZF)qwyV*ί h(@lX\EOMZ5LW(-b_`_i\\EETNqU>U \\\\.Vx|h3XhM((B= Qos XF[(Bx _|E@~*/Q\Fr ,X_|CX Q\EE8~ BP|PW|]\511AqJX [ + /*/QPX4###W!?`|F`_fD)""MNNR\Wo ?>>J%V +,_|S /* -cPNc&AMVc!t]\upp qaUX0ךUD!_4ux^Kj6"&b6*M!iú:TݙwvKxU X^\ ;WAMOLL`N×r'𥘭˗/Iooo똋v.X=/w `aB2|WBi ` 1|KA*`9(/ `aB 2|W]W9aB ] 2p4lDkppP/w _b,×|XpwN _;>>G\ `T_ _g×|Yj`` W "iVOOK^?gR0|ɗFGG>cY+n0Ņ>/0|I94|)F ^7 _I= _("/m/FSWWW^cr6 /r4|ydii)HUqq~~x2|Ɓ a _ W}5qPEĻq#iQ].aR y×|?~HFFFEkrrR/gRT<4\\__;(,ӧd}}A1|i߿𥼄 _EIggg>p,×b4^0|[1UP2S, _ڏpKpU$% _u8 _B^%pTJH _ڕ;ud᪾>*R%/-I 7ѭpUTS}ׯ_KZ1̗Ύ/# {W`S×W!\/ W W`c?-^/cm" W WEkjjJht _Mx,\uuu`6`-,,WO: dff&Y[[3|Q~Ξ@tIpvryy`6޽{'\< ,×bV<aDs× O]* ?'CgUC_pU_Hm۷oUb0|)t!pp0|pǏ7 _+* bVjU!eTX0| W* `uww=lmm Wa|NvQ2 _^"[UUmߥ `, -F (`MOO1|oĉN 7_<4??/\Fm+F `N 7pPvs _^K*RX'''/4`0* |C {y8"5ЕRC!W](@H(B"-rx,MJ{s1g|FMf?~1w9X_D ҁ<@Ӹ4pie5QHQU ^+n\M9 Lnny5pA,/"!E*|/7`r>WZLfggnaF*|/vq:6///%?KnEE4VhEEи ߋ93)))vB[t,H5!"9 hEMПYцz@=K:7oD &##ü} ~_S/J{x5 }ђM{}>iYcc]u16Ob`Eb /_/_| F߿# &\2ꏉ>ߛA366f6fuu<Mn&''АߧOlM)miiL,ZpVSQMU[Tuׯ_f?v϶p?~}ggǼ{{N)cjJp@<}_wX}}=pキgLII [~Q 7wc )uwwT_cA 1|u%5.,,,//srxxh/_JW]A]KNN6ݻU cL7vLo][M :n4|Me 1|Y]7,g)kkk.+W?XˇDjjq=+ 6pT볤b nff2UC4Ǯǵl.}v eXr=L###83?J,CWRpЅ-;+++s=aQ,z~TTTP -)k(qoɼn(쪦+2*w>󊦀%+++g .cZ;yZ*Hl O:XδkO@r1C-RS!" WKTS5ZUcuZ-S#D\۞?nNsS[[{rίgϞZƯ󾺺^w:*++͋/:ZZZcYj8"1 v b@,T "EA+QAb臰>[d7OHd.s9󟙝3ܹs\ŋ/_ȓN:uիy˗5_^/gJ(Bzp޽C"[n5yV=|<;ώћ[IF7NkW֕ ~3^ўqB}V.Vu]1N[-|eE?~X?7g7eab,5kW;Ӛ?_WZ.t ݠt"Lh?̳8\-;E&iM }2@;f(릙7oG8Wj`k~C("oUV&c0VeύCe%sIzN>]Û7o.8͛7ׯCpŋ .Y{pԩud^ѻwǏmvvفW^ Ν~ZSdٳEޝ}R;ui3e5BgϞ | vAXKo9nb:<=p' ,~"3dMpR A~$6!GG?p}i`*h;rMF$5ƁƥL[`g Nる VikNe,ƭƬj'[P> 0R~%1pflaTd35̱vcr*HP۬ldH&8~_vmToK+@`qɉV10]"`@N vdBWg_8C"pk|5@spVո# 8XkxASLb~"kjQ76ӗ_&^ ~͘1B=WVO+;ڌ o֗(/Yb- \[y\7a9軧 {c)BB9]fϟ?օm!hOOOsk{ _/^ ›F" ">pnqa{: 3===u"'6H$F ͭ^UYbHȱx]=;;+JO+ 5D|:tmߋFdd`V>Ik`܌c 'J!lX"ڴGe ?1-ˬ^˜3vV?#cO{)$Fn up?1ܨ]H8`b-Xs1tGś6W)UWc[ 9kx -M\J`Jbc c2{ Z =aXK&>8EqrlW|OC cR SlsuJt$ nmA)4b,.?kMҏCe}d0Z 6~;rS#EVVˈb [*䯋֠ؼ%jY_hcw1esDb@ -6 do>== g%<  ȃ& 安*j,R7 zYclNŦ֬M]aaIV戇Mżڸce|+B) o˰ɱ; \{m ފܫ&;uo;c!Čl &m^s0bL5=$X=r}Ymr=91qM/Z`,vjj^EZ/%tgxC6+s__Km _oBȱ*|~~\]ZZzY7罽ND"H(c;\pyy9Dfkle{vsF+ (I777sdS}'b .COd1DGr5{WjȴzQlJX.Њ^X>I/*p. ng5~[+A+W_⁐U=i)uYρԋ Ȝ_!P2[B@P RlOв]EiS –qˏLT!6YD+j&6EY\M0i2&זED(H]5A5窱z8iûdD+:}յ+}Ř{g1+=YdRWpIei^__f6gjj󧧧ظM {4cq`Ζ["H$> ǔ#M)+狋i;Qd/)Rrރ%Yl }yyy) dIC6=%taxk͈̎ /n@.>2kN܁<= QdO|/|@}~i˥eME*C<e6-Ud.nƘ`PƸ!Û2*rQ3eZjgF*vP'+Fv*)BS|~'mNh͗/p/*$F[,P}eۓk'SX΂j~… eGʲU/_[ AHFR9c~f$1X.c*mEuRHZ%YCQLC,ĥ-xc aG)Վej^Ľ)."3ı$7)II`#"4͋3_nzr6O"ALqx'%~'k) KIG;ҞkjZ+ijq)̟5}(N"OQU5$I$i0$I$J$Id+I$I$I$I&$I$jyQRK$IĞ.(*e,bbfqkfUօes!x5þzڵpΝkI7Y޽{ի1u[S J}Tsa{葍YƤ7ii#p۴iS}9K2FFFbH?MtӶvڰ{OKMӧecSVeCWtJޜ)qD/Ic@+ٲI/5)L8BLi2qe6L|UTӣ#U-V~R;}t/g{oܸ;_IZ8;6<<6nhipÆ appFҲL'N={V;qB\"2Ւ:IZ1Uh U1rxСCpe˖py?I~p]/E9&'ǎ]'UKv}%.)iez*֥=d؟(v~y{ ]]]B*ٳ'ڵ+ܺu믾Pwl,5,%ch'_?X$KL~`Kһcǎp8,I+ Ǒ#G֭[voJ(Wʙ~2 :K X$Kˁ7oN8(Z(|aFēa,B|>K G>\u}*5FU=T0B%DE qm*tK{L 1o#mX@pT`V_bHV7etwϟ? WuYQׯ_)_h',{G @NRlsc|tAU׮]KUxM/FU`!MY\\LX@1ߎp͛7Z|G A$;bq dyy9]<5އ WT1Ju;`J؊dS>@3ddssS%D TH$q:莍Ai0Q*05vV$KP޼y#5W%^rP~ / "Y,dnnN.5 _,'5w&ʇl{m^ Q*0.Ԑ^?~\tI! {5W1WJAf`&<V<S WœB\/B=n[Dkii)W՗O_`bX,,޿}/ ݻw]^*\U#L=ͻWAP1Jٳtב\l/ʩHV`AoU~R_H,\IH_Yjrr2Y__R;\#/HŻmM$Xt]upR_sD_ƂXt^ՁK tvqS_~9@C"EW(`H `FpէO!E/@ zEbO,)۷oh<ќ#J;tD/@DFӧXqpUD/@Ίdł,}o2X;;; %\UOr(𛽻煥 8nGMEF|=w֖JJDBC"AZϜ9;;/_wNqN%s}1f-dŻ!E~M#566 `ō0p`0) d+{ݮHE5~ 5dz~~vHQʇNNN\oVQ* 1d\I, fff@ 47G ~,!XaR*Y>Q*^;ӛG_/,- WRQ*/X/X1D+,~A>RϟG_ȯd-EK?[q^<47(Uv("YKKKXz#J`(l$+Cd?LMM%sssIA]hQ*/@ofE޶kF7 `4Eo;|jZI PKEbQ,fˆ{{ۨQ*/@d5a'슟V+]0HV X5񞞞vmQ*/߸FϏfggj"ެ:\onnXR|uL `CUT_ ЄHV51\RR|(P#Yr[J @T>_VdUq6{gg_( wC_HV>U!.aDUu|@ZbUuyߛ >T%Uǐ !ꊘpUi) *Ӳ™:a [Z+exP֊(_ QE)qQ* gTG>ujZtwwWϓ(_J#BQGBwqq!te|lll*Q* TZL^r~~>3r(wgόw]Q* GHV}O6533F}b~ު$/JZe$i|i(_Fb@""Yu`JWWWU|Q* EG*"\%J0d 5bV뵾'7?R*o<( fɪe:R` yqvՖ! 0bdUzeT9]=w0@ɪQ*0Ѐoؑ2FE @S@wͦqo |yyѿlll$[[["mnn|ttT}}oW6v 8VG"VPcOZVoU敺-8Q1x(? Ĉdd )))ׁD ab]<ǽܫϧ~e)kmZqU 𯹻 d ?f SSS&_ywL_qCqq c+{ /'{[ZZ:;;z CCC=빣ښ<Ņ r+5]lyy9'loo'c///&_ȝTYֽӓ>>>uuu!= Vƻ&_ȝT[ֽPTTFFFɗKBeeeֽ$͙d| 74&6V\|?`^\J ߛBWWWV]ZZJ666kooA|[FGGMx2ۛO޿x1n /NUU՗+++Iojj ;;;냃乸g㡬^| 7b=<==h|@RJ)RJ)S/qQ{IENDB`optics-core-0.4.1.1/diagrams/Traversal.png0000644000000000000000000007143007346545000016540 0ustar0000000000000000PNG  IHDR'dsBIT|d pHYs&:4tEXtSoftwarewww.inkscape.org<rIDATx[HT]p-0 {B!AH1HTDA3SITBJI^k%$!BJFDCA)!J>YR>QVZƹx/?s=""""""̎""""""bKDDDDDDw{<~X$%%Enܸ!?_~ɽ{xt쬌errrͺKKK;>󈈈/,,,HTTܜpΖK.D^$((He{ѲM)>{lͺ̙3<0DDDD#R]]mQv}hwttl{2ǎC;Ʒodr?~赵Y7oyqqqݺࠟ!""""ߦ&9t,//[}Avڥ,bjjJf婩3vO9g΅ gmGGGɓ'7TKNj/xP/:ΝZ633#[n/:߶rŋ=xDFFZ-k׮mm%zzzZ-h2v9c,O>}UFGG-nDHH1rlQb;_|g0CёWʏ?lllL*^^^Z^__EG>##C_|i=XQQQ!W\@9.\ OLOېߋZU{ʪO<ёRikk6ru6V)..GGGA!""""G! 눈 1m_՟?>,^7|]޾}+۷u0}Y9ztx1 {zzZaj(F Fmy!,,LxF_e5uK_ԩSre=<ƶ9[O>7{3~  15x?~0R FUbѣGn1Iuvv^:x!0F=X! >>JDC~NgF<[Pa(7LG$3ڀUzxxhaU94cWAJ߼y.0#xfsB^UUe܇Qdb4 ?t$h:0u$%%Y-,,70mnF{Mo@KKTiS'N`~/1]Siii}Qcݫ\ZcaQ+,ne XUeeeig1…@~/N#'ػP03faXHbVlB$- EaLןtkf )5}Oc~-\ηs<}T^^IMM5eeeQϟ. e/..=^///~vvyw_)]z}6*@pTuannξ`AU+5s?}uGFjzԇGQG}/|͛k[2T˛hOʊ۸^ V,^wymNu̙kejp.@To~$Ͳ BQ;%TO{n]uM;),,֓J8*hvH+Q 꺺k) .//7cUW5.zo׵V<]]]1A7449?Ak@ujΦׇF~jG 㺟f}=W |k |jPMMV=f9??t.m&ռ{.*oGLMMzލ {А})\RRbڟ?{kS @T#jsQu֬7p8l;DPNkO#:Z;kǏg5ϠY |Er3>.P5&.&W366fh,9 X̗/_*ſasb?]tpp`?Mڟɽj;;;M__=V@Pnj'B[[[ ?jCPTw~~/{wVqxRJAE}> :;998 } Gk[u|@P-ChC))d.pq 9O;, ׬T*eݴ7od?~̎Ғ '_,$w}q8Bs`򚝟#7N>>blfv_D59ޏJ*#!Ɏ1|tt~wֲ677],b̋Æ~x$:s/P+[YYɺi_³J|}}b/|h?pN `o;;0|IM%-Du*7KJso߾mB %qX1 _R , & _W666\  _W* .B4 `8, `$Tu!Z0|?2|iA %qX/0|IK{ _'e,×ŢbRC Dkrr22|W*J. Kj׳<1, _ `$\._{w# _ `$:///]×*82 `Q~2|yKs`9hRO TXX/O0|I\%ۛMMM `b Jd˰%Xh`utt |! ` _>f XO;%Xĝ|,@B ` _>f &''͍g `r`ff&WX—2_H$| ʢ0vww/ |!qqkll, _XR)[Np/,@B4z{{s1%|`OK\x>SKF |!ey|V\I7_HPX—b )` _,@B$/? |!q088زX—f VXZ-;'@BBVGGGX,/*c~dd$+9 _x*`eX@BZeK8555:;;CPȞ |!w...DXYY Ӿ _ |@@@|pvvexxxs.gǎCO>>. |O߾Rpzzzjvl?x1xŵZ-'q(ST?KY[[[_;;;aii)Άjm%}χb $ ^:boS ɅpppXo$4, Â;]ʅ ʕ E  6nqE%P$VŪݦ֤T*[ƪD m.)9wxx_SS~6v; D["@@G!—R\:.\bwp|=*WK%uHN/\UUոȅkneeaOg Q6#{/hmm"<.v:cB/!hH9vLz% HۤIs$ܿ/ȏ8?&ݷnV^) Q BF)cTJ;8_ÌB `)C\#8̄B/!hDOK-3ܹΜqO촟;'oM8H=-D__o0Jg#:::\n=D0 LM0!BK)*+%L%jkcaNNɗ/9py߰A6n@HD'4_@PT]4Bz/Cfߺ!)؜uH}>9H;Z(}2*E B:^42Vfq៯uwwޥB(| !%QW'qrE O7oA wvr|fti?Q@,B>juk!BĿ\c ;#%ܑ%p D$QM<=〈FZB4| P^Z< iċŽWt^  XK!—Rt޿#eC ! wuI?Mf3jB%ISa8\!5NlVkd2z{w&XŇgb㺾W=@x4~ΰsY6 J@HZ,k"e>F\cwSk†DWr[[ǚ^ή_}/b,h^B!9S7SڻWqk #vʝԭY#IիRnM8Vx>ݽ;!TO>u4n!vԭ]&#afo9xPz>2&-sOʻylOms i6mga5_U.6ոHabӯՈL*che8>D1~V"{kRzx-a=b\?wZA{ɤv!B(| !?Sۼc%&eShk\wKҥl\1kM֬XX\!ΌhIS[.eDMk-UG…6'"QacҷIb3>?~<*Drb݉YOUX(]̞=Ex?'-@JLµ4cp=ıYvqZdNw RT;F5[_ĉd8q ^8N0&^ͧ7au{ZA,D!PB&Lˣ7n!miMlZ-BS;/{gZq\ ѝ;QPAu A7~.Jv\"X[Zۦ!iڦĪ1mJ{;95\3s ё5M=={t}ڵO˖},qXxr]3N66vp[,Lݼg>~<7渶_MRaFZC} Uݼ|y:pw/;yr{dI־aCYLlFd0^ΉRuw'{|No,6>2Pe'7 NةE2v06ľx̛>!޿sB!$|Fߛ(jI, Y>9b8>a>Or^" etiMX3} 1vp]Y {g9Ä'oXjds{!YG*!,IYMvT3׳f?DuϥKs=_X&4z*QN7F jYk, I &38tCvh,{oc; @uX+{_EB _!ĸS.\X_iم 5dž͹m^@EݼYs`gg)A$nq9+~`npE!Çsnrӓ=XE@!G[-eq²ͻΜYb⁋ZUZWbmD,9Xh(޸1|z!v=7U9Eu<6s1&d:^ƾ&m_p3J.BH !)J7 eQ(f%EBM+ M^]rwqYBQPb# B{]+i89ȴE afWAw GhYS}]U[| bͱcCPW&yMo+87Rl_0pa#2Zx،{"jM8=c<^!Bqm6oT$&6ߴgM}z\THYn.EB]rmGF7}~J͸Twp1|Ngsͷ9ҳg'i@"Tm/H X펼3ͳ ӈ\zm1=f>_g\yZ|V0jnB!Cu;ף};# /"u$/?ڿD(>x`՞;v%ri 5&ᛂVG]Gdq_"1xd:zԄ3VJH~.ky|9ոοmݚ=ܳtͳ?v6IӋ]ы]w/=y,B!$|B ZL)Bwqv&gP`XUB!BB*)Օإ3q;"!BH !ޱw7+Q~qLUQet -ۉAж.]"^|)Md2A*{E[;0buQ<00@_|@u78^;Μ9.__n߾h>fssӍ@۷o-9r$_GMMMM%?RwwwFՕ_{}:}tjhhHwu4<<߰#brr2-,,窯 _=̤Bov^jRzAzMR*ZzQ>|T Ԉ<ݭ ===icc &&&r|Iٳv߿w^9|jȵk׶?{ٙ.\Ξ=jbruuukny?~ Pk.]Co}}}zE7 zfnDU.#~&Ç_kǏe;%|jxzݞ/oܸN8z{{9S<_~]3k|e^SBKO>b+WRsssy,VG 451==$:>*2, н{ŋs֝;w}ӧ]Coj潾ի<7 P0vӹsr9VLO{gggqtk1M-: ``7EH{q/ _j`gg'2|B  fkll,666K,ZYYy`8×)utt$`K{E  /`:×X/ `|5P _IlddD/`X35>>.e҅ @pcbRB  8,×j _2| @ `TF _+&''5J`]X/J  2|]X/}˟0|Z _:* @$u`|%,8LO}j2| _+w׆/h'X/V0| @ Y +鿀# _&`j611R vX/<?/0|.J0|.=K/ _lqq=+5,S?~w7!QuaǓrƍ (JH.hPB .̔)r5"HFP-MJ E؇FGEiY9RiYs`dgzC;w9s{{sl7͛j.8O?u<5-l۶'qO &_~&@ 1Vggv*/V X4-|@ /6::*?~"/`HWWׯ9}dgg˱cǤB gʥKd߾}RZZ*UUUf}IIyfY'---^?\"?pU$77W/raYfܸqëO<)255e~׀vÆ f?GNs]劋PIcc9-kBB]'NiN>}*N:E|o߾]G+^x!&|Wq@@m$%%E.^(~~~bZfddD̙3Vׯ_Kxx{nr W^fɦM8!fN`6ЌnǏˇ:000@% 4իWr-yi|tttȯ_xKj*gϞ_ܹsf[Wiղ~z^MǞ/66V֭[gg CIpp}GMNN@Çޠқ:A?|^_  |c!i x9<\=zD#vwM0=1aaa.رC|lz_|lbb¤3oٲe7oޔǏsR,"&&F222's<{ Ml^/nY- *wٵ1Aӆ ԴasNl NFITTdff\d_o5q[[[`M9u-W7޽u_1᪌zܕU|}ٛٺ=ջUk׮x|f0ܾ}[4x:)t x||\$==],I١=*f",wI$KvJ9p\p2߫4[gujM.((0i.{nsr5[΁kAott^|i> sJ~^EEEuVӫ3Q1dcf࠙Kr9x?U%8(  OP#3& \@L40| (7^~ ]pu/>8lOϞꫪkڇ_N.^~{'΋ c Yuh-0ǏE>qP(-ag c/P7! bEHm 4q/^}}϶#N{y#GqlYDc>#2mXg"$/G"Ogmñ4 BB F˗750 addR; Ƈ2QI:m}`L0m"H cCFH'Pr(f/_EP*2/}8Bk"a3Ll 򜟓_Hz ,._<9uԊ?jݻ~M{ƍɦ0[޽kO ж^ q=}ti ^ar9(D+7oܹsgeϞ=krRJJBoݺ^)#OU[(QСC3CH} T~+-T>ǽ33#(\@zH#7ȭc BBDͣ^ XD4/PxX9d3<픣7TZO\aGpΗɳ6s^! }`π! vj`mڴi{xEzA; e18RO){]q3gZ~{>ydH<G0g EbN0Hj@>=epB7F}9pr>5bǎ߻0-{?B1Ad)uOw9:C橮{ED085.I:cmzBBĢllfhR#0?$qam>~! *|n!nNk Mj>HϼGph؟Do߾mٌ!Ø WU)R@ /_>K> "7\jh rrFxf@m۶F/jDa=D[%;8(A" si6-Kea#! %H BV@+u?#Ǔ]緮y@\8vԌF\ߋ8S?1J4GR3|b5];#s4f]Dm3~ݭqJ81^B㞂H7!(xZ QvʳsCj.4N߂ȻD|CUe/>8J©: \ǽ"B2&ƪFG#J$-FՏ0^ISϱ Q1ε0:ԨkGwCF}}y/_ԏh8kP""ǰ5m~uޝҺa7DBEPRjT$:HJDHD! ! B0$ur^w{~7s }YY՘6hZ֖ "}@v{48{ޮuuΚ^JK;Z}}}fzz':QƎ'z굓n@IKKKtDˏWMqM/]\\I322bMss4yyy&))ɤ_sss x455.3<<544do7??O'XYY `e$xJu~x~~oN I&|"w`nj%zyy}Rpyy[W^ Wx ]b688H}btt]~~>;[𔂤3>= ':Mtxcc Ђ4E/zxx0vWઊ< (k2xAGuW!׹ޖ&a]jj 1tumm2SSS#" 'g 5=3? 8KmS8:@$p¤_~B>4:܅lkk3333t7,,,ABؘ)))1 v sttsֻõpM, HpXEE$N{U~wEOlq nO߿Q Ctحp/hig7//D8.DP _w@Bӽׯ W| Wh %@/Pbp~r)p`*DgF,|C@SJGcp^Ђ W{إ7<@܉U_DRpk:%q/P 1> W|ɀwǪB0)(|M;a98(|s*/~ E3eee-7 `_ *%J*/~@ `׳o@HU_|;<{zzX XM"";f``U  .""(|$r*/*))@|eww*,,(<!3/1*4腫Q ߯%{W8\{ 1 D((hP;6kA$Ia/fO3Uwwtvٙ`BW W)x×FX`“ Wd9,×6"7 ܄ _U,×|LU/jUkkkU`[0|i$/4%\eOD>W꿋X/oƾT2|mmm WuX/mb?<<8(`RL//4IT×#\oZ}A9]%[:;;sMRKx6\#e-^z׽0|. _Շ~ _\'Kr'%dss3~;梇~,HX?~^cH zpKp߿K>Z(d(b҄/t!*×lO> WQh.c|+eҚ0|. _Eg~~^ mDkrrR/tw _|)X/0|*O*z,×l*$kJ N%, _ dKU޽4ikttTaB. _Y*x47Bm$#\/7 _/]×lUq͛7n×F,hOrrpp TUqׯ',×7 _H<cGmj{{;)J tx1nD WX/ƆK/ _%333U"$e3|+ ب{z3. `&KJ/*×lO WA2|G'5 ߂>SqP _HX_~/G%[}*n%ΉX/y×.0|&\r||\ `^u$/ʝ: |p۷oX/0|JU~W*>uyy4KלJoU@+X/g0|yUppV}+oK|ga1tc^]] `愫",ez4XER:/~b珃D<.\<37nMOO'+++ɉ Ms\ _$ W]\\$rm" W W!eOG?h`(䉱+\6\w@G9eE0|ɭ6\#a6S]X/%K oc^^Ry8WD-+UQ"pQmѲ]QҢU;7ڴh"nTV݌_tQŢ;=?Cm<}pNuqt<3EWW9NB`|+ߗ,|*|CqUr(""_` *|Q\Xuuu+ |`[S\*v >XEE!^+`[(\zqU ` P ( @-aW) ":@5'_XYkee,/~|̊P/oRd|P.KD|G(K |=3 _J_$=*ars{؂`c/_/_| Zחzg *|nHW>L< 677Ύ&cW[[[cz}}!ojhhH9NUQQUWn533#?ʓeP UF F5Z93cE d oEd%I11ozm^LJzyyOMBzRjuuU;ٙ XʘP(:z==m xWw{Xw!p;DG(5ݓqƵ:kch(A'I}%$bKfdՇr!2=ƫwFnM#cqeڡ?y0 ;_JAI 8!<S/"i609ChH;\zjŦM&zS'BR.>k}/R?CnȖdNcD!36^>/0E⺰Q@}}5D|:NMMXmomm2KNmY{{)--[[[-,,/Ύ[CCճaŅ-xYljjqv  QXXh) `sKKK+;F033cI2v']ZZ];"fܘ0A?BD_\݋ @s! 6;60mh/3]nx ~/8N7 Ơ3h:yHzh>w=mDQ]sI9pU4RCJ p J]4F~X7u f̴w8O &daFߨM 8bhl!(! B]NZ$i "fΕQ"-`Jx jƶv~05:msK{ Zߋ\I ԋLؒ C^ LK.$lq Y⢢"iiÔ'x@srrZKvϑQ=??dddjN]UUe^088h |3w}/8'=Y3Gߤ:m֐Jszz7B/@@ Fr\b3 L. aDX-m~lg&>uJC+|  r\ m³]O_D"Ɵl}l9ob؈./gk'a~qp3".NIƙ9|Ɲ_٠I?-B$&9(D|9GK&xXQWh!zieėGsKI?:J g\Ƃu~j y\_Z5s3*%"'+#D`sss^E)6}}}q^^^Ǝ޹Q8A@@33AQ31 E͍D8R[[3,===SƂx3s<#{~~ng}X6'Db9wDKw}?1,`ccQZE>Gu?<<|G2Zb2ȷw!opY*[%!Ϡ%bD^9ޖp?;y.C+\bgA9Cۣz/.7ګC ,>Xwn#Sg߆[^})ZD&^R2,7`QPQkhB[ZJg6n\INKjnLfcQPO,weo>ek*}2&WEe9/6;tTc.V{# >-E0u Z_a9ͳ~ ëZn~ $́M$!Z|/,1$[,^J"Wv"x 1RI1=T T =aXK&>85#rl[|!ڄt@)P O{9%WPڶj%tniB)4bL6?kMҏCe}3j<δce;i%wi)3]aeV lNI5+mm(<`41&)#ڃ/Bb" %a{tt&"y~k?>>|֞{aL<%H$ ;rSU|o"+eDFiliɄ-`ĎA5(M6oj(O!ϥ5iZ\YDR/VfD-I\OIp ¢ce!iq * wyyZ!3YdYt4660R|r_=9H$FAͧc[Ba2":"ѐyD6;1PhgY-#~ժ Ƚ^֦MԩԒU׉oݤ=H f˟dexWw _Qη,ޛ Ѱ ++ΚhަQI Ƚz~@WQ2Fpc݉ %f Odk2 rn'{}l^⼦'"d"k]GꗥL/׃S d/&UP\Y-;|GYZlk888Z__o9& !yUpB Ϻ9 %DwޏPf7 WWW}d<==5{[޻rn_777Z%f҈ClD %c,V|J Ŗkj {g<[ qȥ[px_l+.@ȪG\M@D|idNHQ2[D@PR?J]ǭ{ࠢA/ YPA tDq E]ATJJHSp`R߆u>=~xz>׳~Upt*I]o Bea)Ì֩":`]\'BU9CR80,z28&ǎe pX9(bqLPl9S2rQZ\+#;Ӽr &8"%xH]tfxSiɵ ?|iӃ?[H3#%snwm""AiǼ7zL<*B|ҥ}3`OĎ""K_.Vg52D/= |IG+`;.D@W6ԝϷeDd|v|&* 򪿏L pMU^@\+N34Ahns1C 8Ea^Pc :Pt}/v.*rd:2T5:Y l z'!x|.Z=$NAbAN:Ue1"A3x`OǍխň֨ 8ِ=9͏/Zl_H [1J{\;wR4$Lt{UӹT+K jV\דʋՙ!""HYV.N NY21||!T!)C~D}v29_\j*?^qC"-l8 ن3o6=I[Ή86/#ĮaN+nl:j}uD7e"S _ _Q(|EDDDDDD""""""" _,D'Tx0""""" R{vQD+m!/9Eb{ܚ\%/,Drҳgr7rȯCMrzx"d!M>((~)ZI[뺽D+maaѰ|,|KPCCC'GϧttΝ499?4HJSSSݻƍʕ+… رcڵkKNK4Aw & _錍 IJ\z5pҢฝ={6X""},n#G˗/]%)~+{{{JSIQ^z@ C|%Պ_JoooFDD~r/ֶ^F~? dYt湹ZTgKqqqqEgK>7HnN:vt} $"RǏӉ'~j;H7`Z3k̗,7oOk}~D+>~hhY+#8X6Ʊn^bGAt}# ""ݷnm%9H_T>}.޽omm5/WÇ~GCDN.{]ȟۍ_F{gggcw=X:sLyfzIixxX#ɁCf ۷onJW8Dw S릪ݷoanZh 2M,#$zA_m__m˶*"rBPHpQFAEh5q 4z<933߲x{RrI;w=v-,//'ON}~v |`}}=[ɢL{U|߯ŋիW .$O> h8$/_N={vBH>`Qo{{{)m]}|i❿"Eo+qٳɭ[һuÇcwuބvR9YF@$Bpxx8YYYj# WEѣGF -9,NJpׯ_ e(| N;unV|( `E ۷oN\ EHVxiHevκrJ299yh eR6lםu_,! `;w.ywb(yA[*8(_[$2X^S(۷o[*75*F$`&\E'DK2'XIWznD GFBۀ\v-zɇu(|H"Y_Vfݻə3g%c D ]L򑬸V!'㇃¾,Jי7oR_H(|m)>~p,Q*0‰*F"OE,,pp#{*~(U0 "Y"wHgD o7޿j6,H Q*0B/n]I$H zssAjâTnI$ ,h/,"ۜD#JP?Yj||< W75OT9ǃHV3Efvv6 `Y;USSSU5nT]\` 8ŋtTSxݻ'\US(U/PV$ TCL?~,\UT`zH$޾~_}=tO:T(|>vX$KP666OU _CE THV|R ϓK. WUqc TP1.᪵5^+U'C ?}H N^VWW᪊p0lbkwwAyP|dUO1OU, qwϽ_"uXS~& -K0 `ݸq#yꕃmUcccU}D0#Ⴣ-ͻW Ab#7Y/sػw_X0íFCҸt:ʟF[   B'8cu\\yF~ˢr*U/XПpU}~R_HܸJH,\5::][[oD>Jurr1o`4?dUCU333U% @dU7XAwuuUD:Uw/ڛ7g`U $U>,RT W]]](~-J|_$+nbŒ9;;yO(U &U7,64EH 0THVܐgq:O Bm W V]x(J|jxE!E~~M#5<< `ō0ԅp`0) RdGt:oRk>+?P᪟?R_#Y{{{o"YOOO.' `QbE{` W-$J`H{XhU$Kܴ_ *Eڰw~O+mيHo?^멋_rɊiiI+Q響^j}}=5_ nCr7ܜV"r8}}J n۰eR+ )D ,fJ1\RR|(QʑbˊZ=0Ps3d U?pUh!J`>oZ$jꐕxpU0M#UV+Un?of`h~ўDR )^|EM]]MZao~``CD@6i4LuJg0`Ұp"Ե-JRsNS\ٲq۸(_*/"]!ωS\uI /Q\UН `#[4\%JF+힞Vr&3V Wmnng;(_Q$+'gUzl;(_Ve$mbW(_(Gb@2"Y We?*(_#YWi]8' F.. єS-孡!H?ŬphE PhIƼ I7hvp@ŊhܛVWx|M|` B״IVcǎgn)˥bjTQ)/6M6e޾ٙӝ;wҥKϟ?W,SGGGP:~x2 @}ƵF* BGƫ=|0۷/ldd$I|wrrrٳt…/_\.*cq.1=}qpؘI|Ǐ˞ ԔzzzҫWV|ںD|޽k@ҼgϞ,FŶN`gb+5 @]|oׯ_ӳgҹs疅dc?^ӧO;we@uյtڵӧXKR{󩹹9?$ s>z( ϟ??qD|~E^4vw^ @}D:t([s}ԩTV޽{G /8ok3g߾}q͛7ٖ7n+Wd &_|@@M|+RJ)R[սZ=JIENDB`optics-core-0.4.1.1/diagrams/reoptics.png0000644000000000000000000005707307346545000016434 0ustar0000000000000000PNG  IHDR%@>sBIT|d pHYs&:4tEXtSoftwarewww.inkscape.org<]IDATx t)EIrJNTR֕SN EIT{.M)h0wk4>716& cwm˞s'}}>`\/_qݛ7[VJlϘa&M8[>p%of}M&mǘf,-l#1-{[U~£ѽt?PߣcwώWw~Yz?==/=oƟosסиh|4N/~.]y#{c8,~Pa,;-;|`Ç8kf7̞qxi4~^yF= _k\4=ʖnȻa{XN Egu (1akwf|3•JuU*Z_vYqSᥗъ}= UqFZM6o?~xeuuǜZkV½{@J;ʡC#f,JSa0k8AkǾEխk=C7hC~KU>};_pum~T>-kfo8JxոP|V >ށZݨu:i&۬y |CX֪U팏>OF% m~]BBVkyi]Wڒi@:6W}+.uzx7͵nu>o;(LST3?RlڵKוdҾڦK5+n- % p*KfrUw-~soGz7q-ko °S]oͯ_}Xʌ |Y;NrJuT 5L[[}i*3Jo礥1P@ Ӂ|_;8GcnmФmTNy  f~>s& 5:]FeM|M{}ͮJ!c4.\H $PW +[׻.MVk{mc g|w睧*_VA^u-UQ3OCȞ-[I=(k+z0RtA\pU큺ܙ~¯+Ʒh36ؠl#tX~qȘflcݺ3o,/DթceZ׀Q϶LiFfB۶Vo)/7pFỦftonZb_Z )[~zr[FZ{n-T2uUe.Y@Iy_}奄 šCv$8g߳=y%ـ:u"Ea}C޲h JרaNxd yctOt@6ys\♑7_^qEߢ_ }X/?z:#{ JlۜdFgS7UuRҨӰaw E _-Uˢֵ /wGf7WMvlA^ލ^5 | $&&Z\\qĉ-55 $_aִiS VZYcAAA`իW0kٲUjTPb^7UQ *رGFR(bj/'yo==Oq9ryRiv?ǎSW_~CDx PEU/Vo޼qqqjj֭s*00,"bKDϞ={$Ep9&ҭ[7᡾|(U Tڵ@ǏZjlڴ駯+'OuqcǎUm۶BD |eFNѣG{˗/_ fzzsʥ\ųpBࠞ>}ڸqU?<_H5h ~(D_Vzujp^|Y: /RJR9sT/_LPKatɒ%-=x@ڱ0~0D_{7nly~̙a3f YDD"Çcܹɾ622Rr; }>>r輘!dб~./:ѡA ggga>3ݩ???A "ՠA.?6fcmfw A-[{?.WjݺqԷ/`vwСI&Qho_x:_"}AD^dWREF PE ÈNfx#o߾dRg,{F ㈥jFXVc;ϟ?_#KW\)Ϟ=#2ػRfi |?c刌0X7o^Y{u[li;a)sb5׬Y#ˠlaX mRխ[9V55іa Q:edl(ݹs8:,@}΅U tqA2F͉Ptr-,1~*\kҤI*&&߄NϟeoWhh0J}YDD oP5̠"_J+̙c;.8X{kl7%p-3ҫW/cSe͚U͘1CxBU'O=a[1%t ^ErIG<(͛k aaY4:K:H&@[.'sLdW{l(!)"V%nݺ}F1Mzxxh3F!UJ O1%?\Zd6fXbN1%{ŊSƍKЩAf:uؖ##qoժUk{a&٘ {""-qqq0Pi7wNJZkߋ:?s^(K'SDrŔ`q51%tIH0fZXFPja?.O &b""J]C* L. LA&C{K $cËҶ1"V/a/,F*#h"پ{C0UHFh{_#,a5ʍJy0.[Xt8K>QF":GMuaARm]2c $eR'0Vnҏ?O[5d%иNb{\Q&"DDDDDDD |1%""""""bKDDDDDD/*HlP7/ E Ũ(f|||ׯ>f̘/6l Nk>pZj:tFa"bKDihΝ*((HnZ)SFȑCeȐAe̘QeΜY~+WWW~ʝ;w_wĈҎ:88([={vUD !1%%22R899Ν;}JQEDD""- ڕ4~@@rvvNݵk?("D;5k̲AF%`GDDڷo/ٻت b5F р"hL4M|( Hqq):um,9 `"lTZ$N@2{}~> )9=oC [8s#8sm8ׅ_`e]> BUUUԔ $ 0)ؼy @ sJлcǎǶmےCp P iٲeg}ʾ& K,):=3̺gg̘accfpN VΝ[uYfM;¹6tkTWW2O Immmr1$sI>]P1o޼'|`$M@w۷/6l#F8gM/4?M!wqȀ Qsssr-wQ'wD~B~g@ @|{N x₭׍7c޽;^ߴi&_ u̙1@N:5illYgmCm'Nw'O.z;.{~s;2ße@~@[[[RWW >9rdAʶ(=~iRSSC…߰d>>ւoC䥗^ 2$q|.dF,\J3;7t @~ɴiJ\>vXX ֮]ۡT Tz BWvʕ+mP|re?[\% N+א):ꨣ` ;U/ﴲx- @) >rI@ںubV?/ХR/||oN _(+R\% r _V\% ?X BIʪJ@8Xv|eI@+X BѪ*7sX Ba*+ w 97_*?_(G o#@)`!Rt6logV\ Ko`!RW! 2`!R0{Q\ K(B%or/_nP||ɛ{O/'S\5rHU|n:zhXU;O/=[\}v KQK)B@mٲE/ ڹ3.oOv66eۇ&[IeEu [C]]st=;Y6}zO~Ͳ讻.3ftXΙ׶,ロEljJǮo@e,l̶N8N> 7ק̦K),xt_[>ڣ}xI{C~c8skם']}]k,_:r |eIcGʼn俖/0'{oS&/^rI6;ѣtR '$sˬOfrHˣG?ﱡC K:%|.(.<9~N>D<N?v['_w]n5%SOM_-q msWWΊ_ /#|׮&KXy*B=l mK@#Kqo 3x?x߷x n57_яvYpq;y 1l.v/2<,OvZ/bܸo2}w}X ˛akX~iʔ_Gy}Odž qK?oވ{~Ҥŋ/믏{g'R"wމۿeÆ/ٱ#|)9,_WQT7)+cpYqz=,7߼?O~9aBpf'55ɓFʼn??@gB[w'y$N A ̻1inNߍrWLj{UE :"hA `A?OB g -Q-P'dyY 1B1+MAAF:̙\oK -}k% sk޻׮/kSAAHؘ1vpia /}%>C<{u5G7oK:x]sq uiiF-19]^n /W~x_>1}&V\O>=-חr(`æSrO/3"h¹sZ/\Ϙ3GgGyI"7ɓ&{dސ!v9u ))':w5ú4(L@U9] y?sD|67֭`m޼YEMȸJ[qSn`kbNV]j8w0.~6ܚ?v/ZyyCNS !Ƃ?pgiؾ݂VY(v?dfrT=I`R磪IB$SiA:ޖOVȅ>}\-q_>&K@H>py\Ej'WjsFh!TsC|!~I8A!̵3۝ܽ[WhuKM"ȸJh(ӯzr5JK5VEP:_Y/] Guۿ,~ε~ ~T"I&yڷ7i+ *iHI䎗۶FN2 89ߩ[uz7y&u:!,A7!*@^+ʌh[m7dpdۤl)V#;qc_AEIJYO0PGrوۧ2jרJ,o~C^H(7 W^1%2sB<17>| 3* O~ @B]iT $ NHP0/ 'wg"za>-8kH*y rH*K>8رF_!̺*6dH4'Qi&|0׳+HA۲^\}*ɘGaXǎFs}}ӥ"eL `jx%Q_D4ыCy{6b柍Z00N;{j5kYb7Vo߾2޸ β2?B[Qar-z0Y7n |Aj{v9>떿^On˃k׶KWhM em#f|-B\ӻv j"/ۖ(@# ȎQ/yBO&>AzL,y,u@X"BTү ӇJ #2_=ȋ}J-PtͻĚ)lɟj5+P'ˌ!l֧`lW$܂kn hы/Z7|ܢLGiFq+569FV=AE~pΫ4 ,_!:udR]V/Oȡ*Q5}G 0*Л NN Jj =_, ?GhMuh-$c<٩Y׽DCcSa'!AoIFe%m(PFBH$їoGp!P#`c<Z~:zPw yFЧ>s)2*T0 :a['YH93Y'(`Po#MqFhЎZ߿redD ?F?6ɷj{L '%%6OhKWЌ?1/zI( eK *HmTNa"I@lB*[g϶졪GKbH#R?7y` uAE i5 T2mհΝ]V~fE!%o'Q̕>>JOZB]88,1 D|6UtшFWqShwsz A7ᅴTVqd=YԐ^ {nWTXE ozT`.2~dvS1KF\"@wֽ?-!#!1FVM|c!#F1FeùecFA[ψߎO5:t+ &AWh!$q!Bk者Cn3 $za]B ]4C7yDu_KPޣb{ʁJXZ)u|bײ4"IoN3҂:~B?퓹s|<3Ʒoo?ߕX bK QeeeZd"Bs!j\ < d^ud#T҂אy$`Gb;*WFTd|+1Z'65|%2K3%/'OZE )5 yj1+Km\} ⛨8aB?OW_Ví0f"H> nУGT,]u  6$;c.;<'t|e|Fu;uɑ|(, aDpNNf}B4PÑ#ݺ5f µB|4f39gOs5{$+fmT9'T`anJn5];SelsnȐ!&^03BT 7z'-O$B9#H1=-N;I*پSOq"77WD"F/~ ɂ%K -_A eEE+} =X3L[TS2eA6I X d䖾t# BdP!=W'=Mj LB`R Wz=wbWY^ % BEi5[.:'N/?H B!wmր7-d#zRcP=(H\%zRf@QZ\[_y+xuS=0XD|*$0"\}C]́ CG?wРYTx0O>2SS-+%J7YȂ_I!ϑ*Wq%6[r9HNcmܟg6w v+>. B3a*dV@Nկ9UF{=X'vL1c,p޻I]X593f[iɾAF2ްMGU ?df9r i,jւ  B P}R41*ϫ]q}EȬho.%y -EmvyVLgrT =OźLӀ$" *0ce|nZ(H;KNӟ}vمrlq2]DA_Aߧcڌ锔w@VYE Z@- Y\*-K]dw헞;Mf_j+ݷs^+ /$[XJ/yaٲ!@A( v`8d LeCW5j$ %B-NǮ !::c4@ :j׮jժƎnܸ!}T T|TB#\~P-[_߂UʕKKJ,/ʕ+unݺr޼y^~nڍublsjBTzO]@ gV/TpGv ͝;ȕWH'OTUVUKs רQC=|P^ ؼy+Ӯ];5qDi(֭[i۷A^۵Ejܸq-ZSU~}Auɒ%;K.iaoE/_USVժUwիWjƍMs̩]T >'LelԨQ~~a|bgϞ ݛA3I$f͚ ͈@ $X e5Nb_Νٗ`3ߠ,.#,#(QBΝ;=\ٳjС*VXj̙X>~ݻbĈڴi˗/… u֭[Wv=uꔪWxKK" *Zh.{1w"#+P#G꧟<@hҤ˗/;̞={5>z4@ |!9p Tdp.\+)LR%O-RHPE\|q;FǏRH5k,X!p; !v9}qEN*)q4iRcxl#F?X@ "2g,!QGxڶmSΝAL2Z|qH/zΝ0& 8x:uq^ל8qB6Xv<;wϵ =ۍC@8[rWz^f:xn.]'D㍬-?me%ŋڎzwlw~$ju>;Njl[@5jTT`!nYdщ܄u:Ewz=wTVԊ+TC@+w6$(6l|kРA: /l֬YO>jӦM:ٳ=ʖ-JwÆ 5(J*]27oz[XX?a7J(^rާe=&i&iQӦMÆ ә"s7M4~d ԩSd9&&"$W~i/1r^%YM#GE ۽YAgcF 2ݻwke'R6h({pl!ELdBNuD[Ca} :sǮ]4Q&b '_E; >RJj: -KClംaݻ1b8 -etmjɂL;wn5;f ٲe[ d^3gZtLndHX2:\6 oV 2D=} s_vkx'Oߨ\o߾:k;< }xN]?DD:hf@iüyixH<mэ`'O>†%K^d 6~xWO)܌3ꇶA"s>$ك䋗AP6/2g@N ~FIm+Ŷ2:v觾(q񓸋{!X9 ݀^'{tn+ Нرc;wEtf/XN;ƍ-D!ǒif##Dg`,rھ}{1NG*{ 䓁Id4VY@6s&17ADNPgY@ (ѣG3O`܇00U֙d-wo);3n5\„|T^]?yz#H4~@ 0czʎZ9@T 2V~~ }%J6 O9 k\t5Թ.b'?@~ 8 Z&-е"D'z.6ljÑA[9 <78qbؘ>};[_OLA$64k9m0u?M(uV]kRJivjU4"eP+a„~&g3^d&XBx@9[lĨs.ޮ?n{&"DNkew<$rzz[ ^:cS.Bio& i=@8v\oU69@g>&M<FAkwﮍ+ebK5@a1`΀ɸٹ)'Gb gD`'M&x^ނ^J.DyxumA` &͛9p*N!n65:N# Fw}'k֬&2]>M6ͣ' a(4C6>:z/ ƹ·Y/:o)Pp-]v>G#$Bm/C#:kXmt8(Db,0< mALtF c;yOV޻>=ߤ}Ꜫڵk{[s[3I<_B;6eH-9Ok3~fN2 E )4߳lrlz]iG=1E;Dr% GѼt$ 3i&A|n2عeSN>=/.W&aK<þw[ڷ}谨RXԇT2×$LιݻG/C/ۦ;Rv9ҫy;1>;΃7M,Ot,~߷me:{ jJ/-61)޵ka)AC<8sa`At>9xEǸ'iGZͩܡOMFR,~nb!.]-JsJ\ݣx!C$`[D-!SYmsg:%<g h1ՏD+{_tLrT3_/:97ieՍi}&)1smTJ>sb;YC5/7/h}?BbT)X:! jDG}(*i7ާ"ʟ><,&*SF BAkR~QT.8E-UdE&\.Uڈsx^IX0Oږ-[YG^ǩ Bj9WsJmE#J!Ԗ ;,Sm!gnmAlP(ilJ*k/l]tg-4=Ҡ͕UtnWZ ۔kUZEH .ҕ QS)bPh=&Uj1=D<U+ڧK=%TLDZEH*K |O[dij RAԼ\ոh#J92ٕLzapmscO՟*6PmsvFyΉQjxS>JÖth%*5lM*uV"d#46e>*,8od7vqUK]#mĆkw[)h5zuB,P} jV$+,L 4rQli|seKobawR~W]5}<ڶ5t#KԂBةCЦIQwD+DDE7[q]H?Z G oBMp+R6u"Ƴ`Dj;9 [*2_7 k[O pT׼ZM1zZ5{d]˽\t|}/Kz hͰIBac8WaXk*rg6Q}fDʩO `?0dښqjOfsg"}NerpMnS5ws1fv.ϩB'nbOM澾@AKA[EJz,דϝk3{n\O4KPtl/穭IJFQA+{Եyõ{zݩqdV^K9Wsʸ !B!`l?CX7B!B!DB!B!B!Bo!B!B!B!D#F!B! aˢ_yq#Gyd[+b8ǽBLBa}?~!lze^~=wqݗ_~yܧ6@ GMw=s1ömۆ?~8SN:i9۷ov,l*6ꪫƹyYg ]wݸO?=|^y{W?368clQs}zꩧ'psw} a9pe w?N<Ĥ ~!64{3X!аq}t5D=:6ks)Q|E q+D}G1\pcj? '|2:cn_~ !o0ۯJB8w}w+g2XBoGkc=EEjqK.dرcp뭷>w-l ꤣ}G3@!0O>9k'Ag¦a}ᮻN;sC5C %J/[wy_|~ [m ЁRB/!uC= ʯ:[þ}K/t x㍇WWb>O? ~ܹso~qz'kf dXW4/h&=?0;W_=D{kQ_4'e4l=%le{-.l)b6={1"|O?k+o38cqcʀu3<^xhqwsθG} !_"tp4h׮]yg~m* R ?lV%s쮧zj!DuxT[zw/ZyS"-l4j. , h d@KHDw!A7ᯈ 7)mUl2䏩Q33|NPuD7>[W\ B}T*9~._Iblh,?N?xZfMھ}P q2۷Ea Rk.{bv)F6n WŢr7~6J_ٳ'X$AnpC>Ju=t/,BHDOD ㇽH ]1\uRa iCP6pU(E0BUdOX@WыG.r0Bd+,`T(|ib$+ddoffEbAXU 8q#T`yo,ѱ1,n0(U(Q*0B"Y$kڵ'c,"y3w@$Rł(|?DQY+nD:x`ڴiS{(|a芑իWm)",*Qnmֱc\ 0pd `mE_"'HMjNQE/&F$<,(ʺj|*^ (թS\ 0B>DUׯO6lH{qQSի.|DXLU$J_hv'O@5o >|EʇbszzE1Q*0md5S>[Ϝ9@MW5(|oE(> `A=W՟(|Ȋd[qBW˗47ktRNvE]v PrUR-[L #YwqHVMd%{*矷oc UՕR(|ɪ,(+F.]*J_7g"Ypk,. Y1\駟(RRŏ/Pdř%c=&CWSAjX(JRh HV5o`>裏 WU(`:q0jvQ*Gz/V>j#!U^X?U|Gi˖-Tw}7~}dtOD/0AP#Y/^tFL npUR_7("Y廙 WG(U HV`*/F 0)%B2<X \UQ* N1eh"ho\ 4(Ɋ3]g;j| nF:v vPUa0ɲEnp,@2 "2X+\ ԂH` `Q%v,_>Je `(M3f'E9?  pAd*2ݳ`|jD$?l' h `u P!~,G.R]p7 @S#YwuW%"YXQpU ϶R`zݳɊv2F |*ܛoY /.uرRY֊+J29t(}irKn=\ T||$[n)e$+X6mjLA_o~uɒҥVWҶ֛nj_~:Mj:wuD002.]*m$ x^J\./io^MNӟ|rSi۲e'H_NGjͥ WR`*9Rkwm=}'{pevxܿm[w[om-`|#z:Eb! J1dɒF^Hw=f_[y$m{ WW /dvQE>Jv?|>; ⋮~O?zf͚kUg?=`km%GVZ%Jzu$Zz_wI Wun(|9gk?.;S*p0HV eu|kƍi߾}FNH]"}{Y*yvC/޽Dyq( 5)%M1`MĦ44V $%1D %.-YUQK+"r=-Df~y7=/=C[oIg_p+R!meO?e_,U[[… M¼j*imm8G999IFFjqqq(h@Ҩ-֮]+zVU!w:]Ѩ1JHH .ȡCdʕrҥaKNNe˖Iff$&&;v̬}o_xAn;ǀX譇>իWɓrʕ궴uyyyzV+̝+=/Q(?[ǃ|丑nj],e@*W%/r0/>+TF|"E2/Ug]VV/Ko;vH%`ohСWkkffng'՗/3/|S֬'Nȿ}Wޓ̠ =-MjLzVFz\֭Hgg%- @޾|PZ`7WW=;ܿX=.;M_0=hk!@| 0}^Fh4Ffj"ĽIENDB`optics-core-0.4.1.1/optics-core.cabal0000644000000000000000000001266307346545000015516 0ustar0000000000000000cabal-version: 2.2 name: optics-core version: 0.4.1.1 license: BSD-3-Clause license-file: LICENSE build-type: Simple maintainer: optics@well-typed.com author: Adam Gundry, Andres Löh, Andrzej Rybczak, Oleg Grenrus tested-with: GHC ==8.2.2 || ==8.4.4 || ==8.6.5 || ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.8 || ==9.4.5 || ==9.6.2, GHCJS ==8.4 synopsis: Optics as an abstract interface: core definitions category: Data, Optics, Lenses description: This package makes it possible to define and use Lenses, Traversals, Prisms and other optics, using an abstract interface. . This variant provides core definitions with a minimal dependency footprint. See the @@ package (and its dependencies) for documentation and the "batteries-included" variant. extra-doc-files: diagrams/*.png CHANGELOG.md bug-reports: https://github.com/well-typed/optics/issues source-repository head type: git location: https://github.com/well-typed/optics.git subdir: optics-core flag explicit-generic-labels default: False manual: True description: Require explicit GenericLabelOptics instances in order to use generics-based labels common language ghc-options: -Wall -Wcompat default-language: Haskell2010 default-extensions: BangPatterns ConstraintKinds DefaultSignatures DeriveFoldable DeriveFunctor DeriveGeneric DeriveTraversable EmptyCase FlexibleContexts FlexibleInstances FunctionalDependencies GADTs GeneralizedNewtypeDeriving InstanceSigs KindSignatures LambdaCase OverloadedLabels PatternSynonyms RankNTypes ScopedTypeVariables TupleSections TypeApplications TypeFamilies TypeOperators ViewPatterns library import: language hs-source-dirs: src if flag(explicit-generic-labels) cpp-options: -DEXPLICIT_GENERIC_LABELS build-depends: base >= 4.10 && <5 , array >= 0.5.2.0 && <0.6 , containers >= 0.5.10.2 && <0.7 , indexed-profunctors >= 0.1 && <0.2 , transformers >= 0.5 && <0.7 , indexed-traversable >= 0.1 && <0.2 exposed-modules: Optics.Core -- main optic type Optics.Optic -- optic kinds Optics.AffineFold Optics.AffineTraversal Optics.Fold Optics.Getter Optics.Iso Optics.IxAffineFold Optics.IxAffineTraversal Optics.IxFold Optics.IxGetter Optics.IxLens Optics.IxSetter Optics.IxTraversal Optics.Lens Optics.Prism Optics.ReversedLens Optics.ReversedPrism Optics.Review Optics.Setter Optics.Traversal -- optic utilities Optics.Arrow Optics.At.Core Optics.Coerce Optics.Cons.Core Optics.Each.Core Optics.Empty.Core Optics.Generic Optics.Indexed.Core Optics.Mapping Optics.Label Optics.Operators Optics.Operators.Unsafe Optics.Re Optics.ReadOnly Optics.Core.Extras -- optics for data types Data.Either.Optics Data.IntMap.Optics Data.IntSet.Optics Data.List.Optics Data.Map.Optics Data.Maybe.Optics Data.Sequence.Optics Data.Set.Optics Data.Tree.Optics Data.Tuple.Optics Data.Typeable.Optics GHC.Generics.Optics Numeric.Optics -- internal modules Optics.Internal.Bi Optics.Internal.Fold Optics.Internal.Generic Optics.Internal.Generic.TypeLevel Optics.Internal.Indexed Optics.Internal.Indexed.Classes Optics.Internal.IxFold Optics.Internal.IxSetter Optics.Internal.IxTraversal Optics.Internal.Magic Optics.Internal.Optic Optics.Internal.Optic.Subtyping Optics.Internal.Optic.TypeLevel Optics.Internal.Optic.Types Optics.Internal.Setter Optics.Internal.Traversal Optics.Internal.Utils optics-core-0.4.1.1/src/Data/Either/0000755000000000000000000000000007346545000015153 5ustar0000000000000000optics-core-0.4.1.1/src/Data/Either/Optics.hs0000644000000000000000000000136607346545000016756 0ustar0000000000000000-- | Module: Data.Either.Optics -- Description: 'Prism's for the 'Either' datatype. -- -- This module defines 'Prism's for the constructors of the 'Either' datatype. module Data.Either.Optics ( _Left , _Right ) where import Optics.Prism -- | A 'Prism' that matches on the 'Left' constructor of 'Either'. _Left :: Prism (Either a b) (Either c b) a c _Left = prism Left (\ x -> case x of Left y -> Right y Right y -> Left (Right y) ) {-# INLINE _Left #-} -- | A 'Prism' that matches on the 'Right' constructor of 'Either'. _Right :: Prism (Either a b) (Either a c) b c _Right = prism Right (\ x -> case x of Left y -> Left (Left y) Right y -> Right y ) {-# INLINE _Right #-} optics-core-0.4.1.1/src/Data/IntMap/0000755000000000000000000000000007346545000015123 5ustar0000000000000000optics-core-0.4.1.1/src/Data/IntMap/Optics.hs0000644000000000000000000001017507346545000016724 0ustar0000000000000000{-# LANGUAGE CPP #-} -- | 'IntMap' is an instance of 'Optics.At.Core.At' and provides -- 'Optics.At.Core.at' as a lens on values at keys: -- -- >>> IntMap.fromList [(1, "world")] ^. at 1 -- Just "world" -- -- >>> IntMap.empty & at 1 .~ Just "world" -- fromList [(1,"world")] -- -- >>> IntMap.empty & at 0 .~ Just "hello" -- fromList [(0,"hello")] -- -- We can traverse, fold over, and map over key-value pairs in an 'IntMap', -- thanks to indexed traversals, folds and setters. -- -- >>> iover imapped const $ IntMap.fromList [(1, "Venus")] -- fromList [(1,1)] -- -- >>> ifoldMapOf ifolded (\i _ -> Sum i) $ IntMap.fromList [(2, "Earth"), (3, "Mars")] -- Sum {getSum = 5} -- -- >>> itraverseOf_ ifolded (curry print) $ IntMap.fromList [(4, "Jupiter")] -- (4,"Jupiter") -- -- >>> itoListOf ifolded $ IntMap.fromList [(5, "Saturn")] -- [(5,"Saturn")] -- -- A related class, 'Optics.At.Core.Ixed', allows us to use 'Optics.At.Core.ix' to -- traverse a value at a particular key. -- -- >>> IntMap.fromList [(2, "Earth")] & ix 2 %~ ("New " ++) -- fromList [(2,"New Earth")] -- -- >>> preview (ix 8) IntMap.empty -- Nothing -- module Data.IntMap.Optics ( toMapOf , lt , gt , le , ge ) where import Data.IntMap (IntMap) import qualified Data.IntMap as IntMap import Optics.IxAffineTraversal import Optics.IxFold import Optics.Optic -- | Construct a map from an 'IxFold'. -- -- The construction is left-biased (see 'IntMap.union'), i.e. the first occurrences of -- keys in the fold or traversal order are preferred. -- -- >>> toMapOf ifolded ["hello", "world"] -- fromList [(0,"hello"),(1,"world")] -- -- >>> toMapOf (folded % ifolded) [(1,"alpha"),(2, "beta")] -- fromList [(1,"alpha"),(2,"beta")] -- -- >>> toMapOf (icompose (\a b -> 10*a+b) $ ifolded % ifolded) ["foo", "bar"] -- fromList [(0,'f'),(1,'o'),(2,'o'),(10,'b'),(11,'a'),(12,'r')] -- -- >>> toMapOf (folded % ifolded) [(1, "hello"), (2, "world"), (1, "dummy")] -- fromList [(1,"hello"),(2,"world")] -- toMapOf :: (Is k A_Fold, is `HasSingleIndex` Int) => Optic' k is s a -> s -> IntMap a toMapOf o = ifoldMapOf o IntMap.singleton {-# INLINE toMapOf #-} -- | Focus on the largest key smaller than the given one and its corresponding -- value. -- -- >>> IntMap.fromList [(1, "hi"), (2, "there")] & over (lt 2) (++ "!") -- fromList [(1,"hi!"),(2,"there")] -- -- >>> ipreview (lt 1) $ IntMap.fromList [(1, 'x'), (2, 'y')] -- Nothing lt :: Int -> IxAffineTraversal' Int (IntMap v) v lt k = iatraversalVL $ \point f s -> case IntMap.lookupLT k s of Nothing -> point s Just (k', v) -> f k' v <&> \v' -> IntMap.insert k' v' s {-# INLINE lt #-} -- | Focus on the smallest key greater than the given one and its corresponding -- value. -- -- >>> IntMap.fromList [(1, "hi"), (2, "there")] & over (gt 2) (++ "!") -- fromList [(1,"hi"),(2,"there")] -- -- >>> ipreview (gt 1) $ IntMap.fromList [(1, 'x'), (2, 'y')] -- Just (2,'y') gt :: Int -> IxAffineTraversal' Int (IntMap v) v gt k = iatraversalVL $ \point f s -> case IntMap.lookupGT k s of Nothing -> point s Just (k', v) -> f k' v <&> \v' -> IntMap.insert k' v' s {-# INLINE gt #-} -- | Focus on the largest key smaller or equal than the given one and its -- corresponding value. -- -- >>> IntMap.fromList [(1, "hi"), (2, "there")] & over (le 2) (++ "!") -- fromList [(1,"hi"),(2,"there!")] -- -- >>> ipreview (le 1) $ IntMap.fromList [(1, 'x'), (2, 'y')] -- Just (1,'x') le :: Int -> IxAffineTraversal' Int (IntMap v) v le k = iatraversalVL $ \point f s -> case IntMap.lookupLE k s of Nothing -> point s Just (k', v) -> f k' v <&> \v' -> IntMap.insert k' v' s {-# INLINE le #-} -- | Focus on the smallest key greater or equal than the given one and its -- corresponding value. -- -- >>> IntMap.fromList [(1, "hi"), (3, "there")] & over (ge 2) (++ "!") -- fromList [(1,"hi"),(3,"there!")] -- -- >>> ipreview (ge 2) $ IntMap.fromList [(1, 'x'), (3, 'y')] -- Just (3,'y') ge :: Int -> IxAffineTraversal' Int (IntMap v) v ge k = iatraversalVL $ \point f s -> case IntMap.lookupGE k s of Nothing -> point s Just (k', v) -> f k' v <&> \v' -> IntMap.insert k' v' s {-# INLINE ge #-} -- $setup -- >>> import Data.Monoid -- >>> import Optics.Core optics-core-0.4.1.1/src/Data/IntSet/0000755000000000000000000000000007346545000015141 5ustar0000000000000000optics-core-0.4.1.1/src/Data/IntSet/Optics.hs0000644000000000000000000000260207346545000016736 0ustar0000000000000000-- | -- Module: Data.IntSet.Optics -- Description: Optics for working with 'IntSet's. -- -- This module defines optics for constructing and manipulating finite 'IntSet's. -- module Data.IntSet.Optics ( members , setmapped , setOf ) where import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet import Optics.Fold import Optics.Optic import Optics.Setter -- | IntSet isn't Foldable, but this 'Fold' can be used to access the members of -- an 'IntSet'. -- -- >>> sumOf members $ setOf folded [1,2,3,4] -- 10 members :: Fold IntSet Int members = folding IntSet.toAscList {-# INLINE members #-} -- | This 'Setter' can be used to change the type of a 'IntSet' by mapping the -- elements to new values. -- -- Sadly, you can't create a valid 'Optics.Traversal.Traversal' for an 'IntSet', -- but you can manipulate it by reading using 'Optics.Fold.folded' and -- reindexing it via 'setmapped'. -- -- >>> over setmapped (+1) (IntSet.fromList [1,2,3,4]) -- fromList [2,3,4,5] setmapped :: Setter' IntSet Int setmapped = sets IntSet.map {-# INLINE setmapped #-} -- | Construct an 'IntSet' from a fold. -- -- >>> setOf folded [1,2,3,4] -- fromList [1,2,3,4] -- -- >>> setOf (folded % _2) [("hello",1),("world",2),("!!!",3)] -- fromList [1,2,3] setOf :: Is k A_Fold => Optic' k is s Int -> s -> IntSet setOf l = foldMapOf l IntSet.singleton {-# INLINE setOf #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Data/List/0000755000000000000000000000000007346545000014646 5ustar0000000000000000optics-core-0.4.1.1/src/Data/List/Optics.hs0000644000000000000000000000562307346545000016451 0ustar0000000000000000-- | -- Module: Data.List.Optics -- Description: Traversals for manipulating parts of a list. -- -- Additional optics for manipulating lists are present more generically in this -- package. -- -- The 'Optics.At.Core.Ixed' class allows traversing the element at a specific -- list index. -- -- >>> [0..10] ^? ix 4 -- Just 4 -- -- >>> [0..5] & ix 4 .~ 2 -- [0,1,2,3,2,5] -- -- >>> [0..10] ^? ix 14 -- Nothing -- -- >>> [0..5] & ix 14 .~ 2 -- [0,1,2,3,4,5] -- -- The 'Optics.Cons.Core.Cons' and 'Optics.Empty.Core.AsEmpty' classes provide -- 'Optics.Prism.Prism's for list constructors. -- -- >>> [1..10] ^? _Cons -- Just (1,[2,3,4,5,6,7,8,9,10]) -- -- >>> [] ^? _Cons -- Nothing -- -- >>> [] ^? _Empty -- Just () -- -- >>> _Cons # (1, _Empty # ()) :: [Int] -- [1] -- -- Additionally, 'Optics.Cons.Core.Snoc' provides a 'Optics.Prism.Prism' for -- accessing the end of a list. Note that this 'Optics.Prism.Prism' always will -- need to traverse the whole list. -- -- >>> [1..5] ^? _Snoc -- Just ([1,2,3,4],5) -- -- >>> _Snoc # ([1,2],5) -- [1,2,5] -- -- Finally, it's possible to traverse, fold over, and map over index-value pairs -- thanks to instances of 'Optics.Indexed.Core.TraversableWithIndex', -- 'Optics.Indexed.Core.FoldableWithIndex', and -- 'Optics.Indexed.Core.FunctorWithIndex'. -- -- >>> imap (,) "Hello" -- [(0,'H'),(1,'e'),(2,'l'),(3,'l'),(4,'o')] -- -- >>> ifoldMap replicate "Hello" -- "ellllloooo" -- -- >>> itraverse_ (curry print) "Hello" -- (0,'H') -- (1,'e') -- (2,'l') -- (3,'l') -- (4,'o') -- ---------------------------------------------------------------------------- module Data.List.Optics ( prefixed , suffixed ) where import Control.Monad (guard) import qualified Data.List as L import Optics.Prism -- | A 'Prism' stripping a prefix from a list when used as a -- 'Optics.Traversal.Traversal', or prepending that prefix when run backwards: -- -- >>> "preview" ^? prefixed "pre" -- Just "view" -- -- >>> "review" ^? prefixed "pre" -- Nothing -- -- >>> prefixed "pre" # "amble" -- "preamble" prefixed :: Eq a => [a] -> Prism' [a] [a] prefixed ps = prism' (ps ++) (L.stripPrefix ps) {-# INLINE prefixed #-} -- | A 'Prism' stripping a suffix from a list when used as a -- 'Optics.Traversal.Traversal', or appending that suffix when run backwards: -- -- >>> "review" ^? suffixed "view" -- Just "re" -- -- >>> "review" ^? suffixed "tire" -- Nothing -- -- >>> suffixed ".o" # "hello" -- "hello.o" suffixed :: Eq a => [a] -> Prism' [a] [a] suffixed qs = prism' (++ qs) (stripSuffix qs) {-# INLINE suffixed #-} ---------------------------------------- -- Internal stripSuffix :: Eq a => [a] -> [a] -> Maybe [a] stripSuffix qs xs0 = go xs0 zs where zs = drp qs xs0 drp (_:ps) (_:xs) = drp ps xs drp [] xs = xs drp _ [] = [] go (_:xs) (_:ys) = go xs ys go xs [] = zipWith const xs0 zs <$ guard (xs == qs) go [] _ = Nothing -- impossible {-# INLINE stripSuffix #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Data/Map/0000755000000000000000000000000007346545000014450 5ustar0000000000000000optics-core-0.4.1.1/src/Data/Map/Optics.hs0000644000000000000000000001054607346545000016253 0ustar0000000000000000{-# LANGUAGE CPP #-} -- | -- Module: Data.Map.Optics -- Description: Optics for working with 'Data.Map.Map's. -- -- This module exists to provide documentation for lenses for working with -- 'Map', which might otherwise be obscured by their genericity. -- -- 'Map' is an instance of 'Optics.At.Core.At' and provides 'Optics.At.Core.at' -- as a lens on values at keys: -- -- >>> Map.fromList [(1, "world")] ^. at 1 -- Just "world" -- -- >>> Map.empty & at 1 .~ Just "world" -- fromList [(1,"world")] -- -- >>> Map.empty & at 0 .~ Just "hello" -- fromList [(0,"hello")] -- -- We can traverse, fold over, and map over key-value pairs in a 'Map', -- thanks to indexed traversals, folds and setters. -- -- >>> iover imapped const $ Map.fromList [(1, "Venus")] -- fromList [(1,1)] -- -- >>> ifoldMapOf ifolded (\i _ -> Sum i) $ Map.fromList [(2, "Earth"), (3, "Mars")] -- Sum {getSum = 5} -- -- >>> itraverseOf_ ifolded (curry print) $ Map.fromList [(4, "Jupiter")] -- (4,"Jupiter") -- -- >>> itoListOf ifolded $ Map.fromList [(5, "Saturn")] -- [(5,"Saturn")] -- -- A related class, 'Optics.At.Core.Ixed', allows us to use 'Optics.At.Core.ix' to -- traverse a value at a particular key. -- -- >>> Map.fromList [(2, "Earth")] & ix 2 %~ ("New " ++) -- fromList [(2,"New Earth")] -- -- >>> preview (ix 8) Map.empty -- Nothing -- module Data.Map.Optics ( toMapOf , lt , gt , le , ge ) where import Data.Map (Map) import qualified Data.Map as Map import Optics.IxAffineTraversal import Optics.IxFold import Optics.Optic -- | Construct a map from an 'IxFold'. -- -- The construction is left-biased (see 'Map.union'), i.e. the first -- occurrences of keys in the fold or traversal order are preferred. -- -- >>> toMapOf ifolded ["hello", "world"] -- fromList [(0,"hello"),(1,"world")] -- -- >>> toMapOf (folded % ifolded) [('a',"alpha"),('b', "beta")] -- fromList [('a',"alpha"),('b',"beta")] -- -- >>> toMapOf (ifolded <%> ifolded) ["foo", "bar"] -- fromList [((0,0),'f'),((0,1),'o'),((0,2),'o'),((1,0),'b'),((1,1),'a'),((1,2),'r')] -- -- >>> toMapOf (folded % ifolded) [('a', "hello"), ('b', "world"), ('a', "dummy")] -- fromList [('a',"hello"),('b',"world")] -- toMapOf :: (Is k A_Fold, is `HasSingleIndex` i, Ord i) => Optic' k is s a -> s -> Map i a toMapOf o = ifoldMapOf o Map.singleton {-# INLINE toMapOf #-} -- | Focus on the largest key smaller than the given one and its corresponding -- value. -- -- >>> Map.fromList [('a', "hi"), ('b', "there")] & over (lt 'b') (++ "!") -- fromList [('a',"hi!"),('b',"there")] -- -- >>> ipreview (lt 'a') $ Map.fromList [('a', 'x'), ('b', 'y')] -- Nothing lt :: Ord k => k -> IxAffineTraversal' k (Map k v) v lt k = iatraversalVL $ \point f s -> case Map.lookupLT k s of Nothing -> point s Just (k', v) -> f k' v <&> \v' -> Map.insert k' v' s {-# INLINE lt #-} -- | Focus on the smallest key greater than the given one and its corresponding -- value. -- -- >>> Map.fromList [('a', "hi"), ('b', "there")] & over (gt 'b') (++ "!") -- fromList [('a',"hi"),('b',"there")] -- -- >>> ipreview (gt 'a') $ Map.fromList [('a', 'x'), ('b', 'y')] -- Just ('b','y') gt :: Ord k => k -> IxAffineTraversal' k (Map k v) v gt k = iatraversalVL $ \point f s -> case Map.lookupGT k s of Nothing -> point s Just (k', v) -> f k' v <&> \v' -> Map.insert k' v' s {-# INLINE gt #-} -- | Focus on the largest key smaller or equal than the given one and its -- corresponding value. -- -- >>> Map.fromList [('a', "hi"), ('b', "there")] & over (le 'b') (++ "!") -- fromList [('a',"hi"),('b',"there!")] -- -- >>> ipreview (le 'a') $ Map.fromList [('a', 'x'), ('b', 'y')] -- Just ('a','x') le :: Ord k => k -> IxAffineTraversal' k (Map k v) v le k = iatraversalVL $ \point f s -> case Map.lookupLE k s of Nothing -> point s Just (k', v) -> f k' v <&> \v' -> Map.insert k' v' s {-# INLINE le #-} -- | Focus on the smallest key greater or equal than the given one and its -- corresponding value. -- -- >>> Map.fromList [('a', "hi"), ('c', "there")] & over (ge 'b') (++ "!") -- fromList [('a',"hi"),('c',"there!")] -- -- >>> ipreview (ge 'b') $ Map.fromList [('a', 'x'), ('c', 'y')] -- Just ('c','y') ge :: Ord k => k -> IxAffineTraversal' k (Map k v) v ge k = iatraversalVL $ \point f s -> case Map.lookupGE k s of Nothing -> point s Just (k', v) -> f k' v <&> \v' -> Map.insert k' v' s {-# INLINE ge #-} -- $setup -- >>> import Data.Monoid -- >>> import Optics.Core optics-core-0.4.1.1/src/Data/Maybe/0000755000000000000000000000000007346545000014770 5ustar0000000000000000optics-core-0.4.1.1/src/Data/Maybe/Optics.hs0000644000000000000000000000214407346545000016566 0ustar0000000000000000-- | -- Module: Data.Maybe.Optics -- Description: 'Prism's for the 'Maybe' datatype. -- -- This module defines 'Prism's for the constructors of the 'Maybe' datatype. module Data.Maybe.Optics ( _Nothing , _Just , (%?) ) where import Optics.Internal.Optic import Optics.Prism -- | A 'Prism' that matches on the 'Nothing' constructor of 'Maybe'. _Nothing :: Prism' (Maybe a) () _Nothing = prism (\ () -> Nothing) (\ x -> case x of Nothing -> Right () Just y -> Left (Just y) ) {-# INLINE _Nothing #-} -- | A 'Prism' that matches on the 'Just' constructor of 'Maybe'. _Just :: Prism (Maybe a) (Maybe b) a b _Just = prism Just (\ x -> case x of Nothing -> Left Nothing Just y -> Right y ) {-# INLINE _Just #-} -- | Shortcut for @'%' '_Just' '%'@. -- -- Useful for composing lenses of 'Maybe' type. -- -- @since 0.4.1 infixl 9 %? (%?) :: (AppendIndices is js ks, JoinKinds k A_Prism k', JoinKinds k' l m) => Optic k is s t (Maybe u) (Maybe v) -> Optic l js u v a b -> Optic m ks s t a b o1 %? o2 = o1 % _Just % o2 {-# INLINE (%?) #-} optics-core-0.4.1.1/src/Data/Sequence/0000755000000000000000000000000007346545000015503 5ustar0000000000000000optics-core-0.4.1.1/src/Data/Sequence/Optics.hs0000644000000000000000000000722307346545000017304 0ustar0000000000000000-- | -- Module: Data.Sequence.Optics -- Description: Optics for working with 'Seq's. -- -- This module defines optics for constructing and manipulating finite 'Seq's. -- module Data.Sequence.Optics ( viewL, viewR , sliced, slicedTo, slicedFrom , seqOf ) where import Data.Sequence (Seq, ViewL (..), ViewR (..), (><)) import qualified Data.Sequence as Seq import Optics.Internal.Indexed import Optics.Fold import Optics.Iso import Optics.IxTraversal import Optics.Optic import Optics.Traversal -- * Sequence isomorphisms -- | A 'Seq' is isomorphic to a 'ViewL' -- -- @'viewl' m ≡ m 'Optics.Operators.^.' 'viewL'@ -- -- >>> Seq.fromList [1,2,3] ^. viewL -- 1 :< fromList [2,3] -- -- >>> Seq.empty ^. viewL -- EmptyL -- -- >>> EmptyL ^. re viewL -- fromList [] -- -- >>> review viewL $ 1 Seq.:< Seq.fromList [2,3] -- fromList [1,2,3] viewL :: Iso (Seq a) (Seq b) (ViewL a) (ViewL b) viewL = iso Seq.viewl $ \xs -> case xs of EmptyL -> mempty a Seq.:< as -> a Seq.<| as {-# INLINE viewL #-} -- | A 'Seq' is isomorphic to a 'ViewR' -- -- @'viewr' m ≡ m 'Optics.Operators.^.' 'viewR'@ -- -- >>> Seq.fromList [1,2,3] ^. viewR -- fromList [1,2] :> 3 -- -- >>> Seq.empty ^. viewR -- EmptyR -- -- >>> EmptyR ^. re viewR -- fromList [] -- -- >>> review viewR $ Seq.fromList [1,2] Seq.:> 3 -- fromList [1,2,3] viewR :: Iso (Seq a) (Seq b) (ViewR a) (ViewR b) viewR = iso Seq.viewr $ \xs -> case xs of EmptyR -> mempty as Seq.:> a -> as Seq.|> a {-# INLINE viewR #-} -- | Traverse the first @n@ elements of a 'Seq' -- -- >>> Seq.fromList [1,2,3,4,5] ^.. slicedTo 2 -- [1,2] -- -- >>> Seq.fromList [1,2,3,4,5] & slicedTo 2 %~ (*10) -- fromList [10,20,3,4,5] -- -- >>> Seq.fromList [1,2,4,5,6] & slicedTo 10 .~ 0 -- fromList [0,0,0,0,0] slicedTo :: Int -> IxTraversal' Int (Seq a) a slicedTo n = conjoined noix ix where noix = traversalVL $ \f m -> case Seq.splitAt n m of (l, r) -> (>< r) <$> traverse f l ix = itraversalVL $ \f m -> case Seq.splitAt n m of (l, r) -> (>< r) <$> itraverse f l {-# INLINE slicedTo #-} -- | Traverse all but the first @n@ elements of a 'Seq' -- -- >>> Seq.fromList [1,2,3,4,5] ^.. slicedFrom 2 -- [3,4,5] -- -- >>> Seq.fromList [1,2,3,4,5] & slicedFrom 2 %~ (*10) -- fromList [1,2,30,40,50] -- -- >>> Seq.fromList [1,2,3,4,5] & slicedFrom 10 .~ 0 -- fromList [1,2,3,4,5] slicedFrom :: Int -> IxTraversal' Int (Seq a) a slicedFrom n = conjoined noix ix where noix = traversalVL $ \f m -> case Seq.splitAt n m of (l, r) -> (l ><) <$> traverse f r ix = itraversalVL $ \f m -> case Seq.splitAt n m of (l, r) -> (l ><) <$> itraverse (f . (+n)) r {-# INLINE slicedFrom #-} -- | Traverse all the elements numbered from @i@ to @j@ of a 'Seq' -- -- >>> Seq.fromList [1,2,3,4,5] & sliced 1 3 %~ (*10) -- fromList [1,20,30,4,5] -- -- >>> Seq.fromList [1,2,3,4,5] ^.. sliced 1 3 -- [2,3] -- -- >>> Seq.fromList [1,2,3,4,5] & sliced 1 3 .~ 0 -- fromList [1,0,0,4,5] sliced :: Int -> Int -> IxTraversal' Int (Seq a) a sliced i j = conjoined noix ix where noix = traversalVL $ \f s -> case Seq.splitAt i s of (l, mr) -> case Seq.splitAt (j-i) mr of (m, r) -> traverse f m <&> \n -> l >< n >< r ix = itraversalVL $ \f s -> case Seq.splitAt i s of (l, mr) -> case Seq.splitAt (j-i) mr of (m, r) -> itraverse (f . (+i)) m <&> \n -> l >< n >< r {-# INLINE sliced #-} -- | Construct a 'Seq' from a fold. -- -- >>> seqOf folded ["hello","world"] -- fromList ["hello","world"] -- -- >>> seqOf (folded % _2) [("hello",1),("world",2),("!!!",3)] -- fromList [1,2,3] seqOf :: Is k A_Fold => Optic' k is s a -> s -> Seq a seqOf l = foldMapOf l Seq.singleton {-# INLINE seqOf #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Data/Set/0000755000000000000000000000000007346545000014466 5ustar0000000000000000optics-core-0.4.1.1/src/Data/Set/Optics.hs0000644000000000000000000000220107346545000016256 0ustar0000000000000000-- | -- Module: Data.Set.Optics -- Description: Optics for working with 'Set's. -- -- This module defines optics for constructing and manipulating finite 'Set's. -- module Data.Set.Optics ( setmapped , setOf ) where import Data.Set (Set) import qualified Data.Set as Set import Optics.Fold import Optics.Optic import Optics.Setter -- | This 'Setter' can be used to change the type of a 'Set' by mapping the -- elements to new values. -- -- Sadly, you can't create a valid 'Optics.Traversal.Traversal' for a 'Set', but -- you can manipulate it by reading using 'Optics.Fold.folded' and reindexing it -- via 'setmapped'. -- -- >>> over setmapped (+1) (Set.fromList [1,2,3,4]) -- fromList [2,3,4,5] setmapped :: Ord b => Setter (Set a) (Set b) a b setmapped = sets Set.map {-# INLINE setmapped #-} -- | Construct a set from a fold. -- -- >>> setOf folded ["hello","world"] -- fromList ["hello","world"] -- -- >>> setOf (folded % _2) [("hello",1),("world",2),("!!!",3)] -- fromList [1,2,3] setOf :: (Is k A_Fold, Ord a) => Optic' k is s a -> s -> Set a setOf l = foldMapOf l Set.singleton {-# INLINE setOf #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Data/Tree/0000755000000000000000000000000007346545000014632 5ustar0000000000000000optics-core-0.4.1.1/src/Data/Tree/Optics.hs0000644000000000000000000000132007346545000016423 0ustar0000000000000000-- | -- Module: Data.Tree.Optics -- Description: Optics for working with 'Tree's. -- -- This module defines optics for manipulating 'Tree's. -- module Data.Tree.Optics ( root , branches ) where import Data.Tree (Tree (..)) import Optics.Lens -- | A 'Lens' that focuses on the root of a 'Tree'. -- -- >>> view root $ Node 42 [] -- 42 root :: Lens' (Tree a) a root = lensVL $ \f (Node a as) -> (`Node` as) <$> f a {-# INLINE root #-} -- | A 'Lens' returning the direct descendants of the root of a 'Tree' -- -- @'Optics.Getter.view' 'branches' ≡ 'subForest'@ branches :: Lens' (Tree a) [Tree a] branches = lensVL $ \f (Node a as) -> Node a <$> f as {-# INLINE branches #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Data/Tuple/0000755000000000000000000000000007346545000015024 5ustar0000000000000000optics-core-0.4.1.1/src/Data/Tuple/Optics.hs0000644000000000000000000003065607346545000016633 0ustar0000000000000000{-# LANGUAGE DataKinds #-} -- | -- Module: Data.Tuple.Optics -- Description: 'Lens'es for tuple types. -- -- This module defines 'Lens'es for the fields of tuple types. These are -- overloaded using the 'Field1' to 'Field9' typeclasses, so that '_1' can be -- used as a 'Lens' for the first field of a tuple with any number of fields (up -- to the maximum supported tuple size, which is currently 9). For example: -- -- >>> view _1 ('a','b','c') -- 'a' -- -- >>> set _3 True ('a','b','c') -- ('a','b',True) -- -- If a datatype has a 'Generic' instance, the corresponding @FieldN@ instances -- can be defined using their default methods: -- -- >>> :set -XDeriveGeneric -- >>> import GHC.Generics (Generic) -- >>> data T a b = MkT a Int b deriving (Generic, Show) -- >>> instance Field1 (T a c) (T b c) a b -- >>> instance Field2 (T a b) (T a b) Int Int -- >>> instance Field3 (T c a) (T c b) a b -- -- >>> set _3 'x' (MkT False 1 ()) -- MkT False 1 'x' -- -- For a generalization of this pattern see 'GPosition'. -- module Data.Tuple.Optics ( -- * Tuples Field1(..) , Field2(..) , Field3(..) , Field4(..) , Field5(..) , Field6(..) , Field7(..) , Field8(..) , Field9(..) -- * Strict variations , _1', _2', _3', _4', _5', _6', _7', _8', _9' ) where import Data.Functor.Identity import Data.Functor.Product import GHC.Generics ((:*:)(..)) import Optics.Generic import Optics.Lens import Optics.Optic -- | Provides access to 1st field of a tuple. class Field1 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 1st field of a tuple (and possibly change its type). -- -- >>> (1,2) ^. _1 -- 1 -- -- >>> (1,2) & _1 .~ "hello" -- ("hello",2) -- -- >>> traverseOf _1 putStrLn ("hello","world") -- hello -- ((),"world") -- -- This can also be used on larger tuples as well: -- -- >>> (1,2,3,4,5) & _1 %~ (+41) -- (42,2,3,4,5) _1 :: Lens s t a b default _1 :: GPosition 1 s t a b => Lens s t a b _1 = gposition @1 {-# INLINE[1] _1 #-} instance Field1 (Identity a) (Identity b) a b where _1 = lensVL $ \f (Identity a) -> Identity <$> f a {-# INLINE[1] _1 #-} instance Field1 (Product f g a) (Product f' g a) (f a) (f' a) where _1 = lensVL $ \f ~(Pair a b) -> flip Pair b <$> f a {-# INLINE[1] _1 #-} instance Field1 ((f :*: g) p) ((f' :*: g) p) (f p) (f' p) where _1 = lensVL $ \f ~(l :*: r) -> (:*: r) <$> f l {-# INLINE[1] _1 #-} instance Field1 (a,b) (a',b) a a' where _1 = lensVL $ \k ~(a,b) -> k a <&> \a' -> (a',b) {-# INLINE[1] _1 #-} instance Field1 (a,b,c) (a',b,c) a a' where _1 = lensVL $ \k ~(a,b,c) -> k a <&> \a' -> (a',b,c) {-# INLINE[1] _1 #-} instance Field1 (a,b,c,d) (a',b,c,d) a a' where _1 = lensVL $ \k ~(a,b,c,d) -> k a <&> \a' -> (a',b,c,d) {-# INLINE[1] _1 #-} instance Field1 (a,b,c,d,e) (a',b,c,d,e) a a' where _1 = lensVL $ \k ~(a,b,c,d,e) -> k a <&> \a' -> (a',b,c,d,e) {-# INLINE[1] _1 #-} instance Field1 (a,b,c,d,e,f) (a',b,c,d,e,f) a a' where _1 = lensVL $ \k ~(a,b,c,d,e,f) -> k a <&> \a' -> (a',b,c,d,e,f) {-# INLINE[1] _1 #-} instance Field1 (a,b,c,d,e,f,g) (a',b,c,d,e,f,g) a a' where _1 = lensVL $ \k ~(a,b,c,d,e,f,g) -> k a <&> \a' -> (a',b,c,d,e,f,g) {-# INLINE[1] _1 #-} instance Field1 (a,b,c,d,e,f,g,h) (a',b,c,d,e,f,g,h) a a' where _1 = lensVL $ \k ~(a,b,c,d,e,f,g,h) -> k a <&> \a' -> (a',b,c,d,e,f,g,h) {-# INLINE[1] _1 #-} instance Field1 (a,b,c,d,e,f,g,h,i) (a',b,c,d,e,f,g,h,i) a a' where _1 = lensVL $ \k ~(a,b,c,d,e,f,g,h,i) -> k a <&> \a' -> (a',b,c,d,e,f,g,h,i) {-# INLINE[1] _1 #-} -- | Provides access to the 2nd field of a tuple. class Field2 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 2nd field of a tuple. -- -- >>> _2 .~ "hello" $ (1,(),3,4) -- (1,"hello",3,4) -- -- >>> (1,2,3,4) & _2 %~ (*3) -- (1,6,3,4) -- -- >>> traverseOf _2 print (1,2) -- 2 -- (1,()) _2 :: Lens s t a b default _2 :: GPosition 2 s t a b => Lens s t a b _2 = gposition @2 {-# INLINE[1] _2 #-} instance Field2 (Product f g a) (Product f g' a) (g a) (g' a) where _2 = lensVL $ \f ~(Pair a b) -> Pair a <$> f b {-# INLINE[1] _2 #-} instance Field2 ((f :*: g) p) ((f :*: g') p) (g p) (g' p) where _2 = lensVL $ \f ~(l :*: r) -> (l :*:) <$> f r {-# INLINE[1] _2 #-} instance Field2 (a,b) (a,b') b b' where _2 = lensVL $ \k ~(a,b) -> k b <&> \b' -> (a,b') {-# INLINE[1] _2 #-} instance Field2 (a,b,c) (a,b',c) b b' where _2 = lensVL $ \k ~(a,b,c) -> k b <&> \b' -> (a,b',c) {-# INLINE[1] _2 #-} instance Field2 (a,b,c,d) (a,b',c,d) b b' where _2 = lensVL $ \k ~(a,b,c,d) -> k b <&> \b' -> (a,b',c,d) {-# INLINE[1] _2 #-} instance Field2 (a,b,c,d,e) (a,b',c,d,e) b b' where _2 = lensVL $ \k ~(a,b,c,d,e) -> k b <&> \b' -> (a,b',c,d,e) {-# INLINE[1] _2 #-} instance Field2 (a,b,c,d,e,f) (a,b',c,d,e,f) b b' where _2 = lensVL $ \k ~(a,b,c,d,e,f) -> k b <&> \b' -> (a,b',c,d,e,f) {-# INLINE[1] _2 #-} instance Field2 (a,b,c,d,e,f,g) (a,b',c,d,e,f,g) b b' where _2 = lensVL $ \k ~(a,b,c,d,e,f,g) -> k b <&> \b' -> (a,b',c,d,e,f,g) {-# INLINE[1] _2 #-} instance Field2 (a,b,c,d,e,f,g,h) (a,b',c,d,e,f,g,h) b b' where _2 = lensVL $ \k ~(a,b,c,d,e,f,g,h) -> k b <&> \b' -> (a,b',c,d,e,f,g,h) {-# INLINE[1] _2 #-} instance Field2 (a,b,c,d,e,f,g,h,i) (a,b',c,d,e,f,g,h,i) b b' where _2 = lensVL $ \k ~(a,b,c,d,e,f,g,h,i) -> k b <&> \b' -> (a,b',c,d,e,f,g,h,i) {-# INLINE[1] _2 #-} -- | Provides access to the 3rd field of a tuple. class Field3 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 3rd field of a tuple. _3 :: Lens s t a b default _3 :: GPosition 3 s t a b => Lens s t a b _3 = gposition @3 {-# INLINE[1] _3 #-} instance Field3 (a,b,c) (a,b,c') c c' where _3 = lensVL $ \k ~(a,b,c) -> k c <&> \c' -> (a,b,c') {-# INLINE[1] _3 #-} instance Field3 (a,b,c,d) (a,b,c',d) c c' where _3 = lensVL $ \k ~(a,b,c,d) -> k c <&> \c' -> (a,b,c',d) {-# INLINE[1] _3 #-} instance Field3 (a,b,c,d,e) (a,b,c',d,e) c c' where _3 = lensVL $ \k ~(a,b,c,d,e) -> k c <&> \c' -> (a,b,c',d,e) {-# INLINE[1] _3 #-} instance Field3 (a,b,c,d,e,f) (a,b,c',d,e,f) c c' where _3 = lensVL $ \k ~(a,b,c,d,e,f) -> k c <&> \c' -> (a,b,c',d,e,f) {-# INLINE[1] _3 #-} instance Field3 (a,b,c,d,e,f,g) (a,b,c',d,e,f,g) c c' where _3 = lensVL $ \k ~(a,b,c,d,e,f,g) -> k c <&> \c' -> (a,b,c',d,e,f,g) {-# INLINE[1] _3 #-} instance Field3 (a,b,c,d,e,f,g,h) (a,b,c',d,e,f,g,h) c c' where _3 = lensVL $ \k ~(a,b,c,d,e,f,g,h) -> k c <&> \c' -> (a,b,c',d,e,f,g,h) {-# INLINE[1] _3 #-} instance Field3 (a,b,c,d,e,f,g,h,i) (a,b,c',d,e,f,g,h,i) c c' where _3 = lensVL $ \k ~(a,b,c,d,e,f,g,h,i) -> k c <&> \c' -> (a,b,c',d,e,f,g,h,i) {-# INLINE[1] _3 #-} -- | Provide access to the 4th field of a tuple. class Field4 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 4th field of a tuple. _4 :: Lens s t a b default _4 :: GPosition 4 s t a b => Lens s t a b _4 = gposition @4 {-# INLINE[1] _4 #-} instance Field4 (a,b,c,d) (a,b,c,d') d d' where _4 = lensVL $ \k ~(a,b,c,d) -> k d <&> \d' -> (a,b,c,d') {-# INLINE[1] _4 #-} instance Field4 (a,b,c,d,e) (a,b,c,d',e) d d' where _4 = lensVL $ \k ~(a,b,c,d,e) -> k d <&> \d' -> (a,b,c,d',e) {-# INLINE[1] _4 #-} instance Field4 (a,b,c,d,e,f) (a,b,c,d',e,f) d d' where _4 = lensVL $ \k ~(a,b,c,d,e,f) -> k d <&> \d' -> (a,b,c,d',e,f) {-# INLINE[1] _4 #-} instance Field4 (a,b,c,d,e,f,g) (a,b,c,d',e,f,g) d d' where _4 = lensVL $ \k ~(a,b,c,d,e,f,g) -> k d <&> \d' -> (a,b,c,d',e,f,g) {-# INLINE[1] _4 #-} instance Field4 (a,b,c,d,e,f,g,h) (a,b,c,d',e,f,g,h) d d' where _4 = lensVL $ \k ~(a,b,c,d,e,f,g,h) -> k d <&> \d' -> (a,b,c,d',e,f,g,h) {-# INLINE[1] _4 #-} instance Field4 (a,b,c,d,e,f,g,h,i) (a,b,c,d',e,f,g,h,i) d d' where _4 = lensVL $ \k ~(a,b,c,d,e,f,g,h,i) -> k d <&> \d' -> (a,b,c,d',e,f,g,h,i) {-# INLINE[1] _4 #-} -- | Provides access to the 5th field of a tuple. class Field5 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 5th field of a tuple. _5 :: Lens s t a b default _5 :: GPosition 5 s t a b => Lens s t a b _5 = gposition @5 {-# INLINE[1] _5 #-} instance Field5 (a,b,c,d,e) (a,b,c,d,e') e e' where _5 = lensVL $ \k ~(a,b,c,d,e) -> k e <&> \e' -> (a,b,c,d,e') {-# INLINE[1] _5 #-} instance Field5 (a,b,c,d,e,f) (a,b,c,d,e',f) e e' where _5 = lensVL $ \k ~(a,b,c,d,e,f) -> k e <&> \e' -> (a,b,c,d,e',f) {-# INLINE[1] _5 #-} instance Field5 (a,b,c,d,e,f,g) (a,b,c,d,e',f,g) e e' where _5 = lensVL $ \k ~(a,b,c,d,e,f,g) -> k e <&> \e' -> (a,b,c,d,e',f,g) {-# INLINE[1] _5 #-} instance Field5 (a,b,c,d,e,f,g,h) (a,b,c,d,e',f,g,h) e e' where _5 = lensVL $ \k ~(a,b,c,d,e,f,g,h) -> k e <&> \e' -> (a,b,c,d,e',f,g,h) {-# INLINE[1] _5 #-} instance Field5 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e',f,g,h,i) e e' where _5 = lensVL $ \k ~(a,b,c,d,e,f,g,h,i) -> k e <&> \e' -> (a,b,c,d,e',f,g,h,i) {-# INLINE[1] _5 #-} -- | Provides access to the 6th element of a tuple. class Field6 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 6th field of a tuple. _6 :: Lens s t a b default _6 :: GPosition 6 s t a b => Lens s t a b _6 = gposition @6 {-# INLINE[1] _6 #-} instance Field6 (a,b,c,d,e,f) (a,b,c,d,e,f') f f' where _6 = lensVL $ \k ~(a,b,c,d,e,f) -> k f <&> \f' -> (a,b,c,d,e,f') {-# INLINE[1] _6 #-} instance Field6 (a,b,c,d,e,f,g) (a,b,c,d,e,f',g) f f' where _6 = lensVL $ \k ~(a,b,c,d,e,f,g) -> k f <&> \f' -> (a,b,c,d,e,f',g) {-# INLINE[1] _6 #-} instance Field6 (a,b,c,d,e,f,g,h) (a,b,c,d,e,f',g,h) f f' where _6 = lensVL $ \k ~(a,b,c,d,e,f,g,h) -> k f <&> \f' -> (a,b,c,d,e,f',g,h) {-# INLINE[1] _6 #-} instance Field6 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f',g,h,i) f f' where _6 = lensVL $ \k ~(a,b,c,d,e,f,g,h,i) -> k f <&> \f' -> (a,b,c,d,e,f',g,h,i) {-# INLINE[1] _6 #-} -- | Provide access to the 7th field of a tuple. class Field7 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 7th field of a tuple. _7 :: Lens s t a b default _7 :: GPosition 7 s t a b => Lens s t a b _7 = gposition @7 {-# INLINE[1] _7 #-} instance Field7 (a,b,c,d,e,f,g) (a,b,c,d,e,f,g') g g' where _7 = lensVL $ \k ~(a,b,c,d,e,f,g) -> k g <&> \g' -> (a,b,c,d,e,f,g') {-# INLINE[1] _7 #-} instance Field7 (a,b,c,d,e,f,g,h) (a,b,c,d,e,f,g',h) g g' where _7 = lensVL $ \k ~(a,b,c,d,e,f,g,h) -> k g <&> \g' -> (a,b,c,d,e,f,g',h) {-# INLINE[1] _7 #-} instance Field7 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f,g',h,i) g g' where _7 = lensVL $ \k ~(a,b,c,d,e,f,g,h,i) -> k g <&> \g' -> (a,b,c,d,e,f,g',h,i) {-# INLINE[1] _7 #-} -- | Provide access to the 8th field of a tuple. class Field8 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 8th field of a tuple. _8 :: Lens s t a b default _8 :: GPosition 8 s t a b => Lens s t a b _8 = gposition @8 {-# INLINE[1] _8 #-} instance Field8 (a,b,c,d,e,f,g,h) (a,b,c,d,e,f,g,h') h h' where _8 = lensVL $ \k ~(a,b,c,d,e,f,g,h) -> k h <&> \h' -> (a,b,c,d,e,f,g,h') {-# INLINE[1] _8 #-} instance Field8 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f,g,h',i) h h' where _8 = lensVL $ \k ~(a,b,c,d,e,f,g,h,i) -> k h <&> \h' -> (a,b,c,d,e,f,g,h',i) {-# INLINE[1] _8 #-} -- | Provides access to the 9th field of a tuple. class Field9 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 9th field of a tuple. _9 :: Lens s t a b default _9 :: GPosition 9 s t a b => Lens s t a b _9 = gposition @9 {-# INLINE[1] _9 #-} instance Field9 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f,g,h,i') i i' where _9 = lensVL $ \k ~(a,b,c,d,e,f,g,h,i) -> k i <&> \i' -> (a,b,c,d,e,f,g,h,i') {-# INLINE[1] _9 #-} -- Strict versions of the _1 .. _9 operations -- | Strict version of '_1' _1' :: Field1 s t a b => Lens s t a b _1' = equality' % _1 {-# INLINE _1' #-} -- | Strict version of '_2' _2' :: Field2 s t a b => Lens s t a b _2' = equality' % _2 {-# INLINE _2' #-} -- | Strict version of '_3' _3' :: Field3 s t a b => Lens s t a b _3' = equality' % _3 {-# INLINE _3' #-} -- | Strict version of '_4' _4' :: Field4 s t a b => Lens s t a b _4' = equality' % _4 {-# INLINE _4' #-} -- | Strict version of '_5' _5' :: Field5 s t a b => Lens s t a b _5' = equality' % _5 {-# INLINE _5' #-} -- | Strict version of '_6' _6' :: Field6 s t a b => Lens s t a b _6' = equality' % _6 {-# INLINE _6' #-} -- | Strict version of '_7' _7' :: Field7 s t a b => Lens s t a b _7' = equality' % _7 {-# INLINE _7' #-} -- | Strict version of '_8' _8' :: Field8 s t a b => Lens s t a b _8' = equality' % _8 {-# INLINE _8' #-} -- | Strict version of '_9' _9' :: Field9 s t a b => Lens s t a b _9' = equality' % _9 {-# INLINE _9' #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Data/Typeable/0000755000000000000000000000000007346545000015500 5ustar0000000000000000optics-core-0.4.1.1/src/Data/Typeable/Optics.hs0000644000000000000000000000150107346545000017272 0ustar0000000000000000-- | -- Module: Data.Typeable.Optics -- Description: Optics for working with 'Typeable'. -- module Data.Typeable.Optics ( _cast , _gcast ) where import Data.Typeable import Data.Maybe import Optics.AffineTraversal -- | An 'AffineTraversal'' for working with a 'cast' of a 'Typeable' value. _cast :: (Typeable s, Typeable a) => AffineTraversal' s a _cast = atraversalVL $ \point f s -> case cast s of Just a -> fromMaybe (error "_cast: recast failed") . cast <$> f a Nothing -> point s {-# INLINE _cast #-} -- | An 'AffineTraversal'' for working with a 'gcast' of a 'Typeable' value. _gcast :: (Typeable s, Typeable a) => AffineTraversal' (c s) (c a) _gcast = atraversalVL $ \point f s -> case gcast s of Just a -> fromMaybe (error "_gcast: recast failed") . gcast <$> f a Nothing -> point s {-# INLINE _gcast #-} optics-core-0.4.1.1/src/GHC/Generics/0000755000000000000000000000000007346545000015222 5ustar0000000000000000optics-core-0.4.1.1/src/GHC/Generics/Optics.hs0000644000000000000000000000131507346545000017017 0ustar0000000000000000-- | -- Module: GHC.Generics.Optics -- Description: Optics for types defined in "GHC.Generics". -- -- /Note:/ "GHC.Generics" exports a number of names that collide with "Optics" -- (at least 'GHC.Generics.to'). -- -- You can use hiding of imports to mitigate this to an extent. The following -- imports represent a fair compromise for user code: -- -- @ -- import "Optics" -- import "GHC.Generics" hiding (to) -- import "GHC.Generics.Optics" -- @ -- -- You can use 'generic' to replace 'GHC.Generics.from' and 'GHC.Generics.to' -- from "GHC.Generics". -- module GHC.Generics.Optics ( generic , generic1 , _V1 , _U1 , _Par1 , _Rec1 , _K1 , _M1 , _L1 , _R1 ) where import Optics.Internal.Generic optics-core-0.4.1.1/src/Numeric/0000755000000000000000000000000007346545000014464 5ustar0000000000000000optics-core-0.4.1.1/src/Numeric/Optics.hs0000644000000000000000000001327507346545000016271 0ustar0000000000000000-- | -- Module: Numeric.Optics -- Description: Optics for working with numeric types. -- module Numeric.Optics ( base , integral -- * Predefined bases , binary , octal , decimal , hex -- * Arithmetic lenses , adding , subtracting , multiplying , dividing , exponentiating , negated , pattern Integral ) where import Data.Char (chr, ord, isAsciiLower, isAsciiUpper, isDigit) import Data.Maybe (fromMaybe) import GHC.Stack import Numeric (readInt, showIntAtBase) import Data.Tuple.Optics import Optics.AffineFold import Optics.Iso import Optics.Optic import Optics.Prism import Optics.Review import Optics.Setter -- | This 'Prism' can be used to model the fact that every 'Prelude.Integral' -- type is a subset of 'Integer'. -- -- Embedding through the 'Prism' only succeeds if the 'Integer' would pass -- through unmodified when re-extracted. integral :: (Integral a, Integral b) => Prism Integer Integer a b integral = prism toInteger $ \i -> let a = fromInteger i in if toInteger a == i then Right a else Left i {-# INLINE integral #-} -- | Pattern synonym that can be used to construct or pattern match on an -- 'Integer' as if it were of any 'Prelude.Integral' type. pattern Integral :: forall a. Integral a => a -> Integer pattern Integral a <- (preview integral -> Just a) where Integral a = review integral a -- | A prism that shows and reads integers in base-2 through base-36 -- -- Note: This is an improper prism, since leading 0s are stripped when reading. -- -- >>> "100" ^? base 16 -- Just 256 -- -- >>> 1767707668033969 ^. re (base 36) -- "helloworld" base :: (HasCallStack, Integral a) => Int -> Prism' String a base b | b < 2 || b > 36 = error ("base: Invalid base " ++ show b) | otherwise = prism intShow intRead where intShow n = showSigned' (showIntAtBase (toInteger b) intToDigit') (toInteger n) "" intRead s = case readSigned' (readInt (fromIntegral b) (isDigit' b) digitToInt') s of [(n,"")] -> Right n _ -> Left s {-# INLINE base #-} -- | Like 'Data.Char.intToDigit', but handles up to base-36 intToDigit' :: HasCallStack => Int -> Char intToDigit' i | i >= 0 && i < 10 = chr (ord '0' + i) | i >= 10 && i < 36 = chr (ord 'a' + i - 10) | otherwise = error ("intToDigit': Invalid int " ++ show i) {-# INLINE intToDigit' #-} -- | Like 'Data.Char.digitToInt', but handles up to base-36 digitToInt' :: HasCallStack => Char -> Int digitToInt' c = fromMaybe (error ("digitToInt': Invalid digit " ++ show c)) (digitToIntMay c) {-# INLINE digitToInt' #-} -- | A safe variant of 'digitToInt'' digitToIntMay :: Char -> Maybe Int digitToIntMay c | isDigit c = Just (ord c - ord '0') | isAsciiLower c = Just (ord c - ord 'a' + 10) | isAsciiUpper c = Just (ord c - ord 'A' + 10) | otherwise = Nothing {-# INLINE digitToIntMay #-} -- | Select digits that fall into the given base isDigit' :: Int -> Char -> Bool isDigit' b c = case digitToIntMay c of Just i -> i < b _ -> False {-# INLINE isDigit' #-} -- | A simpler variant of 'Numeric.showSigned' that only prepends a dash and -- doesn't know about parentheses showSigned' :: Real a => (a -> ShowS) -> a -> ShowS showSigned' f n | n < 0 = showChar '-' . f (negate n) | otherwise = f n {-# INLINE showSigned' #-} -- | A simpler variant of 'Numeric.readSigned' that supports any base, only -- recognizes an initial dash and doesn't know about parentheses readSigned' :: Real a => ReadS a -> ReadS a readSigned' f ('-':xs) = f xs <&> over _1 negate readSigned' f xs = f xs {-# INLINE readSigned' #-} -- | @'binary' = 'base' 2@ binary :: Integral a => Prism' String a binary = base 2 {-# INLINE binary #-} -- | @'octal' = 'base' 8@ octal :: Integral a => Prism' String a octal = base 8 {-# INLINE octal #-} -- | @'decimal' = 'base' 10@ decimal :: Integral a => Prism' String a decimal = base 10 {-# INLINE decimal #-} -- | @'hex' = 'base' 16@ hex :: Integral a => Prism' String a hex = base 16 {-# INLINE hex #-} -- | @'adding' n = 'iso' (+n) (subtract n)@ -- -- >>> [1..3] ^.. traversed % adding 1000 -- [1001,1002,1003] adding :: Num a => a -> Iso' a a adding n = iso (+n) (subtract n) {-# INLINE adding #-} -- | @ -- 'subtracting' n = 'iso' (subtract n) ((+n) -- 'subtracting' n = 'Optics.Re.re' ('adding' n) -- @ subtracting :: Num a => a -> Iso' a a subtracting n = iso (subtract n) (+n) {-# INLINE subtracting #-} -- | @'multiplying' n = iso (*n) (/n)@ -- -- Note: This errors for n = 0 -- -- >>> 5 & multiplying 1000 %~ (+3) -- 5.003 -- -- >>> let fahrenheit = multiplying (9/5) % adding 32 in 230 ^. re fahrenheit -- 110.0 multiplying :: (Fractional a, Eq a) => a -> Iso' a a multiplying 0 = error "Numeric.Optics.multiplying: factor 0" multiplying n = iso (*n) (/n) {-# INLINE multiplying #-} -- | @ -- 'dividing' n = 'iso' (/n) (*n) -- 'dividing' n = 'Optics.Re.re' ('multiplying' n)@ -- -- Note: This errors for n = 0 dividing :: (Fractional a, Eq a) => a -> Iso' a a dividing 0 = error "Numeric.Optics.dividing: divisor 0" dividing n = iso (/n) (*n) {-# INLINE dividing #-} -- | @'exponentiating' n = 'iso' (**n) (**recip n)@ -- -- Note: This errors for n = 0 -- -- >>> au (coerced1 @Sum % re (exponentiating 2)) (foldMapOf each) (3,4) == 5 -- True exponentiating :: (Floating a, Eq a) => a -> Iso' a a exponentiating 0 = error "Numeric.Optics.exponentiating: exponent 0" exponentiating n = iso (**n) (**recip n) {-# INLINE exponentiating #-} -- | @'negated' = 'iso' 'negate' 'negate'@ -- -- >>> au (coerced1 @Sum % negated) (foldMapOf each) (3,4) == 7 -- True -- -- >>> au (coerced1 @Sum) (foldMapOf (each % negated)) (3,4) == -7 -- True negated :: Num a => Iso' a a negated = iso negate negate {-# INLINE negated #-} -- $setup -- >>> import Data.Monoid -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/0000755000000000000000000000000007346545000014323 5ustar0000000000000000optics-core-0.4.1.1/src/Optics/AffineFold.hs0000644000000000000000000001034707346545000016661 0ustar0000000000000000-- | -- Module: Optics.AffineFold -- Description: A 'Optics.Fold.Fold' that contains at most one element. -- -- An 'AffineFold' is a 'Optics.Fold.Fold' that contains at most one -- element, or a 'Optics.Getter.Getter' where the function may be -- partial. -- module Optics.AffineFold ( -- * Formation AffineFold -- * Introduction , afolding -- * Elimination , preview , previews -- * Computation -- | -- -- @ -- 'preview' ('afolding' f) ≡ f -- @ -- * Additional introduction forms , afoldVL , filtered -- * Additional elimination forms , atraverseOf_ , isn't -- * Monoid structure -- | 'AffineFold' admits a monoid structure where 'afailing' combines folds -- (returning a result from the second fold only if the first returns none) -- and the identity element is 'Optics.IxAffineTraversal.ignored' (which -- returns no results). -- -- /Note:/ There is no 'Optics.Fold.summing' equivalent that returns an -- 'AffineFold', because it would not need to return more than one result. -- -- There is no 'Semigroup' or 'Monoid' instance for 'AffineFold', because -- there is not a unique choice of monoid to use that works for all optics, -- and the ('<>') operator could not be used to combine optics of different -- kinds. , afailing -- * Subtyping , An_AffineFold -- | <> ) where import Data.Maybe import Data.Profunctor.Indexed import Optics.Internal.Bi import Optics.Internal.Optic -- | Type synonym for an affine fold. type AffineFold s a = Optic' An_AffineFold NoIx s a -- | Obtain an 'AffineFold' by lifting 'traverse_' like function. -- -- @ -- 'afoldVL' '.' 'atraverseOf_' ≡ 'id' -- 'atraverseOf_' '.' 'afoldVL' ≡ 'id' -- @ -- -- @since 0.3 afoldVL :: (forall f. Functor f => (forall r. r -> f r) -> (a -> f u) -> s -> f v) -> AffineFold s a afoldVL f = Optic (rphantom . visit f . rphantom) {-# INLINE afoldVL #-} -- | Retrieve the value targeted by an 'AffineFold'. -- -- >>> let _Right = prism Right $ either (Left . Left) Right -- -- >>> preview _Right (Right 'x') -- Just 'x' -- -- >>> preview _Right (Left 'y') -- Nothing -- preview :: Is k An_AffineFold => Optic' k is s a -> s -> Maybe a preview o = previews o id {-# INLINE preview #-} -- | Retrieve a function of the value targeted by an 'AffineFold'. previews :: Is k An_AffineFold => Optic' k is s a -> (a -> r) -> s -> Maybe r previews o = \f -> runForgetM $ getOptic (castOptic @An_AffineFold o) $ ForgetM (Just . f) {-# INLINE previews #-} -- | Traverse over the target of an 'AffineFold', computing a 'Functor'-based -- answer, but unlike 'Optics.AffineTraversal.atraverseOf' do not construct a -- new structure. -- -- @since 0.3 atraverseOf_ :: (Is k An_AffineFold, Functor f) => Optic' k is s a -> (forall r. r -> f r) -> (a -> f u) -> s -> f () atraverseOf_ o point f s = case preview o s of Just a -> () <$ f a Nothing -> point () {-# INLINE atraverseOf_ #-} -- | Create an 'AffineFold' from a partial function. -- -- >>> preview (afolding listToMaybe) "foo" -- Just 'f' -- afolding :: (s -> Maybe a) -> AffineFold s a afolding f = Optic (contrabimap (\s -> maybe (Left s) Right (f s)) Left . right') {-# INLINE afolding #-} -- | Filter result(s) of a fold that don't satisfy a predicate. filtered :: (a -> Bool) -> AffineFold a a filtered p = afoldVL (\point f a -> if p a then f a else point a) {-# INLINE filtered #-} -- | Try the first 'AffineFold'. If it returns no entry, try the second one. -- -- >>> preview (ix 1 % re _Left `afailing` ix 2 % re _Right) [0,1,2,3] -- Just (Left 1) -- -- >>> preview (ix 42 % re _Left `afailing` ix 2 % re _Right) [0,1,2,3] -- Just (Right 2) -- afailing :: (Is k An_AffineFold, Is l An_AffineFold) => Optic' k is s a -> Optic' l js s a -> AffineFold s a afailing a b = afolding $ \s -> maybe (preview b s) Just (preview a s) infixl 3 `afailing` -- Same as (<|>) {-# INLINE afailing #-} -- | Check to see if this 'AffineFold' doesn't match. -- -- >>> isn't _Just Nothing -- True -- -- The negation of this operator is 'Optics.Core.Extras.is' from -- "Optics.Core.Extras". isn't :: Is k An_AffineFold => Optic' k is s a -> s -> Bool isn't k s = isNothing (preview k s) {-# INLINE isn't #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/AffineTraversal.hs0000644000000000000000000001406307346545000017737 0ustar0000000000000000-- | -- Module: Optics.AffineTraversal -- Description: A 'Optics.Traversal.Traversal' that applies to at most one element. -- -- An 'AffineTraversal' is a 'Optics.Traversal.Traversal' that -- applies to at most one element. -- -- These arise most frequently as the composition of a -- 'Optics.Lens.Lens' with a 'Optics.Prism.Prism'. -- module Optics.AffineTraversal ( -- * Formation AffineTraversal , AffineTraversal' -- * Introduction , atraversal -- * Elimination -- | An 'AffineTraversal' is in particular an 'Optics.AffineFold.AffineFold' -- and a 'Optics.Setter.Setter', therefore you can specialise types to obtain: -- -- @ -- 'Optics.AffineFold.preview' :: 'AffineTraversal' s t a b -> s -> Maybe a -- @ -- -- @ -- 'Optics.Setter.over' :: 'AffineTraversal' s t a b -> (a -> b) -> s -> t -- 'Optics.Setter.set' :: 'AffineTraversal' s t a b -> b -> s -> t -- @ , matching -- * Computation -- | -- -- @ -- 'matching' ('atraversal' f g) ≡ f -- 'Data.Either.isRight' (f s) => 'Optics.Setter.set' ('atraversal' f g) b s ≡ g s b -- @ -- * Additional introduction forms -- | See 'Optics.Cons.Core._head', 'Optics.Cons.Core._tail', -- 'Optics.Cons.Core._init' and 'Optics.Cons.Core._last' for -- 'AffineTraversal's for container types. , unsafeFiltered -- * Additional elimination forms , withAffineTraversal -- * Subtyping , An_AffineTraversal -- | <> -- * van Laarhoven encoding , AffineTraversalVL , AffineTraversalVL' , atraversalVL , atraverseOf ) where import Data.Profunctor.Indexed import Optics.Internal.Optic -- | Type synonym for a type-modifying affine traversal. type AffineTraversal s t a b = Optic An_AffineTraversal NoIx s t a b -- | Type synonym for a type-preserving affine traversal. type AffineTraversal' s a = Optic' An_AffineTraversal NoIx s a -- | Type synonym for a type-modifying van Laarhoven affine traversal. -- -- Note: this isn't exactly van Laarhoven representation as there is -- no @Pointed@ class (which would be a superclass of 'Applicative' -- that contains 'pure' but not '<*>'). You can interpret the first -- argument as a dictionary of @Pointed@ that supplies the @point@ -- function (i.e. the implementation of 'pure'). -- -- A 'Optics.Traversal.TraversalVL' has 'Applicative' available and -- hence can combine the effects arising from multiple elements using -- '<*>'. In contrast, an 'AffineTraversalVL' has no way to combine -- effects from multiple elements, so it must act on at most one -- element. (It can act on none at all thanks to the availability of -- @point@.) -- type AffineTraversalVL s t a b = forall f. Functor f => (forall r. r -> f r) -> (a -> f b) -> s -> f t -- | Type synonym for a type-preserving van Laarhoven affine traversal. type AffineTraversalVL' s a = AffineTraversalVL s s a a -- | Build an affine traversal from a matcher and an updater. -- -- If you want to build an 'AffineTraversal' from the van Laarhoven -- representation, use 'atraversalVL'. atraversal :: (s -> Either t a) -> (s -> b -> t) -> AffineTraversal s t a b atraversal match update = Optic $ -- Do not define atraversal in terms of atraversalVL, mixing profunctor-style -- definitions with VL style implementation can lead to subpar generated code. dimap (\s -> (match s, update s)) (\(etb, f) -> either id f etb) . first' . right' {-# INLINE atraversal #-} -- | Work with an affine traversal as a matcher and an updater. withAffineTraversal :: Is k An_AffineTraversal => Optic k is s t a b -> ((s -> Either t a) -> (s -> b -> t) -> r) -> r withAffineTraversal o = \k -> case getOptic (castOptic @An_AffineTraversal o) (AffineMarket (\_ b -> b) Right) of AffineMarket update match -> k match update {-# INLINE withAffineTraversal #-} -- | Build an affine traversal from the van Laarhoven representation. -- -- Example: -- -- >>> :{ -- azSnd = atraversalVL $ \point f ab@(a, b) -> -- if a >= 'a' && a <= 'z' -- then (a, ) <$> f b -- else point ab -- :} -- -- >>> preview azSnd ('a', "Hi") -- Just "Hi" -- -- >>> preview azSnd ('@', "Hi") -- Nothing -- -- >>> over azSnd (++ "!!!") ('f', "Hi") -- ('f',"Hi!!!") -- -- >>> set azSnd "Bye" ('Y', "Hi") -- ('Y',"Hi") -- atraversalVL :: AffineTraversalVL s t a b -> AffineTraversal s t a b atraversalVL f = Optic (visit f) {-# INLINE atraversalVL #-} -- | Traverse over the target of an 'AffineTraversal' and compute a -- 'Functor'-based answer. -- -- @since 0.3 atraverseOf :: (Is k An_AffineTraversal, Functor f) => Optic k is s t a b -> (forall r. r -> f r) -> (a -> f b) -> s -> f t atraverseOf o point = runStarA . getOptic (castOptic @An_AffineTraversal o) . StarA point {-# INLINE atraverseOf #-} -- | Retrieve the value targeted by an 'AffineTraversal' or return the original -- value while allowing the type to change if it does not match. -- -- @ -- 'Optics.AffineFold.preview' o ≡ 'either' ('const' 'Nothing') 'id' . 'matching' o -- @ matching :: Is k An_AffineTraversal => Optic k is s t a b -> s -> Either t a matching o = withAffineTraversal o $ \match _ -> match {-# INLINE matching #-} -- | Filter result(s) of a traversal that don't satisfy a predicate. -- -- /Note:/ This is /not/ a legal 'Optics.Traversal.Traversal', unless you are -- very careful not to invalidate the predicate on the target. -- -- As a counter example, consider that given @evens = 'unsafeFiltered' 'even'@ -- the second 'Optics.Traversal.Traversal' law is violated: -- -- @ -- 'Optics.Setter.over' evens 'succ' '.' 'Optics.over' evens 'succ' '/=' 'Optics.Setter.over' evens ('succ' '.' 'succ') -- @ -- -- So, in order for this to qualify as a legal 'Optics.Traversal.Traversal' you -- can only use it for actions that preserve the result of the predicate! -- -- For a safe variant see 'Optics.IxTraversal.indices' (or -- 'Optics.AffineFold.filtered' for read-only optics). -- unsafeFiltered :: (a -> Bool) -> AffineTraversal' a a unsafeFiltered p = atraversalVL (\point f a -> if p a then f a else point a) {-# INLINE unsafeFiltered #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Arrow.hs0000644000000000000000000000650207346545000015754 0ustar0000000000000000-- | -- Module: Optics.Arrow -- Description: Turn optics into arrow transformers. module Optics.Arrow ( ArrowOptic(..) , assignA ) where import Control.Arrow import Data.Coerce import qualified Control.Category as C import Data.Profunctor.Indexed import Optics.AffineTraversal import Optics.Prism import Optics.Setter import Optics.Internal.Optic import Optics.Internal.Utils newtype WrappedArrow p i a b = WrapArrow { unwrapArrow :: p a b } instance C.Category p => C.Category (WrappedArrow p i) where WrapArrow f . WrapArrow g = WrapArrow (f C.. g) id = WrapArrow C.id {-# INLINE (.) #-} {-# INLINE id #-} instance Arrow p => Arrow (WrappedArrow p i) where arr = WrapArrow #. arr first = WrapArrow #. first .# unwrapArrow second = WrapArrow #. second .# unwrapArrow WrapArrow a *** WrapArrow b = WrapArrow (a *** b) WrapArrow a &&& WrapArrow b = WrapArrow (a &&& b) {-# INLINE arr #-} {-# INLINE first #-} {-# INLINE second #-} {-# INLINE (***) #-} {-# INLINE (&&&) #-} instance Arrow p => Profunctor (WrappedArrow p) where dimap f g k = arr f >>> k >>> arr g lmap f k = arr f >>> k rmap g k = k >>> arr g {-# INLINE dimap #-} {-# INLINE lmap #-} {-# INLINE rmap #-} lcoerce' = lmap coerce rcoerce' = rmap coerce {-# INLINE lcoerce' #-} {-# INLINE rcoerce' #-} instance Arrow p => Strong (WrappedArrow p) where first' (WrapArrow k) = WrapArrow (first k) second' (WrapArrow k) = WrapArrow (second k) {-# INLINE first' #-} {-# INLINE second' #-} instance ArrowChoice p => Choice (WrappedArrow p) where left' (WrapArrow k) = WrapArrow (left k) right' (WrapArrow k) = WrapArrow (right k) {-# INLINE left' #-} {-# INLINE right' #-} instance ArrowChoice p => Visiting (WrappedArrow p) class Arrow arr => ArrowOptic k arr where -- | Turn an optic into an arrow transformer. overA :: Optic k is s t a b -> arr a b -> arr s t instance Arrow arr => ArrowOptic An_Iso arr where overA = overA__ {-# INLINE overA #-} instance Arrow arr => ArrowOptic A_Lens arr where overA = overA__ {-# INLINE overA #-} instance ArrowChoice arr => ArrowOptic A_Prism arr where overA = overA__ {-# INLINE overA #-} instance ArrowChoice arr => ArrowOptic An_AffineTraversal arr where overA = overA__ {-# INLINE overA #-} -- | Run an arrow command and use the output to set all the targets of an optic -- to the result. -- -- @ -- runKleisli action ((), (), ()) where -- action = assignA _1 (Kleisli (const getVal1)) -- \>>> assignA _2 (Kleisli (const getVal2)) -- \>>> assignA _3 (Kleisli (const getVal3)) -- getVal1 :: Either String Int -- getVal1 = ... -- getVal2 :: Either String Bool -- getVal2 = ... -- getVal3 :: Either String Char -- getVal3 = ... -- @ -- -- has the type @'Either' 'String' ('Int', 'Bool', 'Char')@ assignA :: (Is k A_Setter, Arrow arr) => Optic k is s t a b -> arr s b -> arr s t assignA o p = arr (flip $ set o) &&& p >>> arr (uncurry' id) {-# INLINE assignA #-} ---------------------------------------- -- | Internal implementation of overA. overA__ :: (p ~ WrappedArrow arr, Profunctor p, Constraints k p) => Optic k is s t a b -> arr a b -> arr s t overA__ o = unwrapArrow #. getOptic o .# WrapArrow {-# INLINE overA__ #-} optics-core-0.4.1.1/src/Optics/At/0000755000000000000000000000000007346545000014667 5ustar0000000000000000optics-core-0.4.1.1/src/Optics/At/Core.hs0000644000000000000000000003542707346545000016126 0ustar0000000000000000{-# LANGUAGE CPP #-} {-# LANGUAGE TypeInType #-} -- | -- Module: Optics.At.Core -- Description: Optics for 'Map' and 'Set'-like containers. -- -- This module provides optics for 'Map' and 'Set'-like containers, including an -- 'AffineTraversal' to traverse a key in a map or an element of a sequence: -- -- >>> preview (ix 1) ['a','b','c'] -- Just 'b' -- -- a 'Lens' to get, set or delete a key in a map: -- -- >>> set (at 0) (Just 'b') (Map.fromList [(0, 'a')]) -- fromList [(0,'b')] -- -- and a 'Lens' to insert or remove an element of a set: -- -- >>> IntSet.fromList [1,2,3,4] & contains 3 .~ False -- fromList [1,2,4] -- -- The @Optics.At@ module from @optics-extra@ provides additional instances of -- the classes defined here. -- module Optics.At.Core ( -- * Type families Index , IxValue -- * Ixed , Ixed(..) , ixAt -- * At , At(..) , at' , sans -- * Contains , Contains(..) ) where import qualified Data.Array.IArray as Array import Data.Array.Unboxed (UArray) import Data.Complex (Complex (..)) import Data.Ix (Ix (..)) import Data.Functor.Identity (Identity (..)) import Data.Kind (Type) import Data.List.NonEmpty (NonEmpty (..)) import Data.Tree (Tree (..)) import Data.IntMap (IntMap) import qualified Data.IntMap as IntMap import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet import Data.Map (Map) import qualified Data.Map as Map import Data.Sequence (Seq) import qualified Data.Sequence as Seq import Data.Set (Set) import qualified Data.Set as Set import Data.Maybe.Optics import Optics.AffineTraversal import Optics.Iso import Optics.Lens import Optics.Optic import Optics.Setter -- | Type family that takes a key-value container type and returns the type of -- keys (indices) into the container, for example @'Index' ('Map' k a) ~ k@. -- This is shared by 'Ixed', 'At' and 'Contains'. type family Index (s :: Type) :: Type type instance Index (e -> a) = e type instance Index IntSet = Int type instance Index (Set a) = a type instance Index [a] = Int type instance Index (NonEmpty a) = Int type instance Index (Seq a) = Int type instance Index (a,b) = Int type instance Index (a,b,c) = Int type instance Index (a,b,c,d) = Int type instance Index (a,b,c,d,e) = Int type instance Index (a,b,c,d,e,f) = Int type instance Index (a,b,c,d,e,f,g) = Int type instance Index (a,b,c,d,e,f,g,h) = Int type instance Index (a,b,c,d,e,f,g,h,i) = Int type instance Index (IntMap a) = Int type instance Index (Map k a) = k type instance Index (Array.Array i e) = i type instance Index (UArray i e) = i type instance Index (Complex a) = Int type instance Index (Identity a) = () type instance Index (Maybe a) = () type instance Index (Tree a) = [Int] -- | This class provides a simple 'Lens' that lets you view (and modify) -- information about whether or not a container contains a given 'Index'. -- Instances are provided for 'Set'-like containers only. class Contains m where -- | -- >>> IntSet.fromList [1,2,3,4] ^. contains 3 -- True -- -- >>> IntSet.fromList [1,2,3,4] ^. contains 5 -- False -- -- >>> IntSet.fromList [1,2,3,4] & contains 3 .~ False -- fromList [1,2,4] contains :: Index m -> Lens' m Bool instance Contains IntSet where contains k = lensVL $ \f s -> f (IntSet.member k s) <&> \b -> if b then IntSet.insert k s else IntSet.delete k s {-# INLINE contains #-} instance Ord a => Contains (Set a) where contains k = lensVL $ \f s -> f (Set.member k s) <&> \b -> if b then Set.insert k s else Set.delete k s {-# INLINE contains #-} -- | Type family that takes a key-value container type and returns the type of -- values stored in the container, for example @'IxValue' ('Map' k a) ~ a@. This -- is shared by both 'Ixed' and 'At'. type family IxValue (m :: Type) :: Type -- | Provides a simple 'AffineTraversal' lets you traverse the value at a given -- key in a 'Map' or element at an ordinal position in a list or 'Seq'. class Ixed m where -- | Type family that takes a key-value container type and returns the kind -- of optic to index into it. For most containers, it's 'An_AffineTraversal', -- @Representable@ (Naperian) containers it is 'A_Lens', and multi-maps would -- have 'A_Traversal'. type IxKind (m :: Type) :: OpticKind type IxKind m = An_AffineTraversal -- | /NB:/ Setting the value of this 'AffineTraversal' will only set the value -- in 'at' if it is already present. -- -- If you want to be able to insert /missing/ values, you want 'at'. -- -- >>> [1,2,3,4] & ix 2 %~ (*10) -- [1,2,30,4] -- -- >>> "abcd" & ix 2 .~ 'e' -- "abed" -- -- >>> "abcd" ^? ix 2 -- Just 'c' -- -- >>> [] ^? ix 2 -- Nothing ix :: Index m -> Optic' (IxKind m) NoIx m (IxValue m) default ix :: (At m, IxKind m ~ An_AffineTraversal) => Index m -> Optic' (IxKind m) NoIx m (IxValue m) ix = ixAt {-# INLINE ix #-} -- | A definition of 'ix' for types with an 'At' instance. This is the default -- if you don't specify a definition for 'ix'. ixAt :: At m => Index m -> AffineTraversal' m (IxValue m) ixAt = \i -> at i % _Just {-# INLINE ixAt #-} type instance IxValue (e -> a) = a instance Eq e => Ixed (e -> a) where type IxKind (e -> a) = A_Lens ix e = lensVL $ \p f -> p (f e) <&> \a e' -> if e == e' then a else f e' {-# INLINE ix #-} type instance IxValue (Maybe a) = a instance Ixed (Maybe a) where ix () = castOptic @An_AffineTraversal _Just {-# INLINE ix #-} type instance IxValue [a] = a instance Ixed [a] where ix k = atraversalVL (ixListVL k) {-# INLINE ix #-} type instance IxValue (NonEmpty a) = a instance Ixed (NonEmpty a) where ix k = atraversalVL $ \point f xs0 -> if k < 0 then point xs0 else let go (a:|as) 0 = f a <&> (:|as) go (a:|as) i = (a:|) <$> ixListVL (i - 1) point f as in go xs0 k {-# INLINE ix #-} type instance IxValue (Identity a) = a instance Ixed (Identity a) where type IxKind (Identity a) = An_Iso ix () = coerced {-# INLINE ix #-} type instance IxValue (Tree a) = a instance Ixed (Tree a) where ix xs0 = atraversalVL $ \point f -> let go [] (Node a as) = f a <&> \a' -> Node a' as go (i:is) t@(Node a as) | i < 0 = point t | otherwise = Node a <$> ixListVL i point (go is) as in go xs0 {-# INLINE ix #-} type instance IxValue (Seq a) = a instance Ixed (Seq a) where ix i = atraversalVL $ \point f m -> if 0 <= i && i < Seq.length m then f (Seq.index m i) <&> \a -> Seq.update i a m else point m {-# INLINE ix #-} type instance IxValue (IntMap a) = a -- Default implementation uses IntMap.alterF instance Ixed (IntMap a) type instance IxValue (Map k a) = a -- Default implementation uses Map.alterF instance Ord k => Ixed (Map k a) type instance IxValue (Set k) = () instance Ord k => Ixed (Set k) where ix k = atraversalVL $ \point f m -> if Set.member k m then f () <&> \() -> Set.insert k m else point m {-# INLINE ix #-} type instance IxValue IntSet = () instance Ixed IntSet where ix k = atraversalVL $ \point f m -> if IntSet.member k m then f () <&> \() -> IntSet.insert k m else point m {-# INLINE ix #-} type instance IxValue (Array.Array i e) = e -- | -- @ -- arr 'Array.!' i ≡ arr 'Optics.Operators.^.' 'ix' i -- arr '//' [(i,e)] ≡ 'ix' i 'Optics.Operators..~' e '$' arr -- @ instance Ix i => Ixed (Array.Array i e) where ix i = atraversalVL $ \point f arr -> if inRange (Array.bounds arr) i then f (arr Array.! i) <&> \e -> arr Array.// [(i,e)] else point arr {-# INLINE ix #-} type instance IxValue (UArray i e) = e -- | -- @ -- arr 'Array.!' i ≡ arr 'Optics.Operators.^.' 'ix' i -- arr '//' [(i,e)] ≡ 'ix' i 'Optics.Operators..~' e '$' arr -- @ instance (Array.IArray UArray e, Ix i) => Ixed (UArray i e) where ix i = atraversalVL $ \point f arr -> if inRange (Array.bounds arr) i then f (arr Array.! i) <&> \e -> arr Array.// [(i,e)] else point arr {-# INLINE ix #-} -- | @'ix' :: 'Int' -> 'AffineTraversal'' (a, a) a@ type instance IxValue (a0, a2) = a0 instance (a0 ~ a1) => Ixed (a0, a1) where ix i = atraversalVL $ \point f ~s@(a0, a1) -> case i of 0 -> (,a1) <$> f a0 1 -> (a0,) <$> f a1 _ -> point s -- | @'ix' :: 'Int' -> 'AffineTraversal'' (a, a, a) a@ type instance IxValue (a0, a1, a2) = a0 instance (a0 ~ a1, a0 ~ a2) => Ixed (a0, a1, a2) where ix i = atraversalVL $ \point f ~s@(a0, a1, a2) -> case i of 0 -> (,a1,a2) <$> f a0 1 -> (a0,,a2) <$> f a1 2 -> (a0,a1,) <$> f a2 _ -> point s -- | @'ix' :: 'Int' -> 'AffineTraversal'' (a, a, a, a) a@ type instance IxValue (a0, a1, a2, a3) = a0 instance (a0 ~ a1, a0 ~ a2, a0 ~ a3) => Ixed (a0, a1, a2, a3) where ix i = atraversalVL $ \point f ~s@(a0, a1, a2, a3) -> case i of 0 -> (,a1,a2,a3) <$> f a0 1 -> (a0,,a2,a3) <$> f a1 2 -> (a0,a1,,a3) <$> f a2 3 -> (a0,a1,a2,) <$> f a3 _ -> point s -- | @'ix' :: 'Int' -> 'AffineTraversal'' (a, a, a, a, a) a@ type instance IxValue (a0, a1, a2, a3, a4) = a0 instance (a0 ~ a1, a0 ~ a2, a0 ~ a3, a0 ~ a4) => Ixed (a0, a1, a2, a3, a4) where ix i = atraversalVL $ \point f ~s@(a0, a1, a2, a3, a4) -> case i of 0 -> (,a1,a2,a3,a4) <$> f a0 1 -> (a0,,a2,a3,a4) <$> f a1 2 -> (a0,a1,,a3,a4) <$> f a2 3 -> (a0,a1,a2,,a4) <$> f a3 4 -> (a0,a1,a2,a3,) <$> f a4 _ -> point s -- | @'ix' :: 'Int' -> 'AffineTraversal'' (a, a, a, a, a, a) a@ type instance IxValue (a0, a1, a2, a3, a4, a5) = a0 instance (a0 ~ a1, a0 ~ a2, a0 ~ a3, a0 ~ a4, a0 ~ a5 ) => Ixed (a0, a1, a2, a3, a4, a5) where ix i = atraversalVL $ \point f ~s@(a0, a1, a2, a3, a4, a5) -> case i of 0 -> (,a1,a2,a3,a4,a5) <$> f a0 1 -> (a0,,a2,a3,a4,a5) <$> f a1 2 -> (a0,a1,,a3,a4,a5) <$> f a2 3 -> (a0,a1,a2,,a4,a5) <$> f a3 4 -> (a0,a1,a2,a3,,a5) <$> f a4 5 -> (a0,a1,a2,a3,a4,) <$> f a5 _ -> point s -- | @'ix' :: 'Int' -> 'AffineTraversal'' (a, a, a, a, a, a, a) a@ type instance IxValue (a0, a1, a2, a3, a4, a5, a6) = a0 instance (a0 ~ a1, a0 ~ a2, a0 ~ a3, a0 ~ a4, a0 ~ a5, a0 ~ a6 ) => Ixed (a0, a1, a2, a3, a4, a5, a6) where ix i = atraversalVL $ \point f ~s@(a0, a1, a2, a3, a4, a5, a6) -> case i of 0 -> (,a1,a2,a3,a4,a5,a6) <$> f a0 1 -> (a0,,a2,a3,a4,a5,a6) <$> f a1 2 -> (a0,a1,,a3,a4,a5,a6) <$> f a2 3 -> (a0,a1,a2,,a4,a5,a6) <$> f a3 4 -> (a0,a1,a2,a3,,a5,a6) <$> f a4 5 -> (a0,a1,a2,a3,a4,,a6) <$> f a5 6 -> (a0,a1,a2,a3,a4,a5,) <$> f a6 _ -> point s -- | @'ix' :: 'Int' -> 'AffineTraversal'' (a, a, a, a, a, a, a, a) a@ type instance IxValue (a0, a1, a2, a3, a4, a5, a6, a7) = a0 instance (a0 ~ a1, a0 ~ a2, a0 ~ a3, a0 ~ a4, a0 ~ a5, a0 ~ a6, a0 ~ a7 ) => Ixed (a0, a1, a2, a3, a4, a5, a6, a7) where ix i = atraversalVL $ \point f ~s@(a0, a1, a2, a3, a4, a5, a6, a7) -> case i of 0 -> (,a1,a2,a3,a4,a5,a6,a7) <$> f a0 1 -> (a0,,a2,a3,a4,a5,a6,a7) <$> f a1 2 -> (a0,a1,,a3,a4,a5,a6,a7) <$> f a2 3 -> (a0,a1,a2,,a4,a5,a6,a7) <$> f a3 4 -> (a0,a1,a2,a3,,a5,a6,a7) <$> f a4 5 -> (a0,a1,a2,a3,a4,,a6,a7) <$> f a5 6 -> (a0,a1,a2,a3,a4,a5,,a7) <$> f a6 7 -> (a0,a1,a2,a3,a4,a5,a6,) <$> f a7 _ -> point s -- | @'ix' :: 'Int' -> 'AffineTraversal'' (a, a, a, a, a, a, a, a, a) a@ type instance IxValue (a0, a1, a2, a3, a4, a5, a6, a7, a8) = a0 instance (a0 ~ a1, a0 ~ a2, a0 ~ a3, a0 ~ a4, a0 ~ a5, a0 ~ a6, a0 ~ a7, a0 ~ a8 ) => Ixed (a0, a1, a2, a3, a4, a5, a6, a7, a8) where ix i = atraversalVL $ \point f ~s@(a0, a1, a2, a3, a4, a5, a6, a7, a8) -> case i of 0 -> (,a1,a2,a3,a4,a5,a6,a7,a8) <$> f a0 1 -> (a0,,a2,a3,a4,a5,a6,a7,a8) <$> f a1 2 -> (a0,a1,,a3,a4,a5,a6,a7,a8) <$> f a2 3 -> (a0,a1,a2,,a4,a5,a6,a7,a8) <$> f a3 4 -> (a0,a1,a2,a3,,a5,a6,a7,a8) <$> f a4 5 -> (a0,a1,a2,a3,a4,,a6,a7,a8) <$> f a5 6 -> (a0,a1,a2,a3,a4,a5,,a7,a8) <$> f a6 7 -> (a0,a1,a2,a3,a4,a5,a6,,a8) <$> f a7 8 -> (a0,a1,a2,a3,a4,a5,a6,a7,) <$> f a8 _ -> point s -- | 'At' provides a 'Lens' that can be used to read, write or delete the value -- associated with a key in a 'Map'-like container on an ad hoc basis. -- -- An instance of 'At' should satisfy: -- -- @ -- 'ix' k ≡ 'at' k '%' '_Just' -- @ class (Ixed m, IxKind m ~ An_AffineTraversal) => At m where -- | -- >>> Map.fromList [(1,"world")] ^. at 1 -- Just "world" -- -- >>> at 1 ?~ "hello" $ Map.empty -- fromList [(1,"hello")] -- -- /Note:/ Usage of this function might introduce space leaks if you're not -- careful to make sure that values put inside the 'Just' constructor are -- evaluated. To force the values and avoid such leaks, use 'at'' instead. -- -- /Note:/ 'Map'-like containers form a reasonable instance, but not -- 'Array'-like ones, where you cannot satisfy the 'Lens' laws. at :: Index m -> Lens' m (Maybe (IxValue m)) -- | Version of 'at' strict in the value inside the `Just` constructor. -- -- Example: -- -- >>> (at () .~ Just (error "oops") $ Nothing) `seq` () -- () -- -- >>> (at' () .~ Just (error "oops") $ Nothing) `seq` () -- *** Exception: oops -- ... -- -- >>> view (at ()) (Just $ error "oops") `seq` () -- () -- -- >>> view (at' ()) (Just $ error "oops") `seq` () -- *** Exception: oops -- ... -- -- It also works as expected for other data structures: -- -- >>> (at 1 .~ Just (error "oops") $ Map.empty) `seq` () -- () -- -- >>> (at' 1 .~ Just (error "oops") $ Map.empty) `seq` () -- *** Exception: oops -- ... at' :: At m => Index m -> Lens' m (Maybe (IxValue m)) at' k = at k % iso f f where f = \case Just !x -> Just x Nothing -> Nothing {-# INLINE at' #-} -- | Delete the value associated with a key in a 'Map'-like container -- -- @ -- 'sans' k = 'at' k 'Optics.Operators..~' Nothing -- @ sans :: At m => Index m -> m -> m sans k = set (at k) Nothing {-# INLINE sans #-} instance At (Maybe a) where at () = lensVL id {-# INLINE at #-} instance At (IntMap a) where at k = lensVL $ \f -> IntMap.alterF f k {-# INLINE at #-} instance Ord k => At (Map k a) where at k = lensVL $ \f -> Map.alterF f k {-# INLINE at #-} instance At IntSet where at k = lensVL $ \f m -> let mv = if IntSet.member k m then Just () else Nothing in f mv <&> \r -> case r of Nothing -> maybe m (const (IntSet.delete k m)) mv Just () -> IntSet.insert k m {-# INLINE at #-} instance Ord k => At (Set k) where at k = lensVL $ \f m -> let mv = if Set.member k m then Just () else Nothing in f mv <&> \r -> case r of Nothing -> maybe m (const (Set.delete k m)) mv Just () -> Set.insert k m {-# INLINE at #-} ---------------------------------------- -- Internal ixListVL :: Int -> AffineTraversalVL' [a] a ixListVL k point f xs0 = if k < 0 then point xs0 else let go [] _ = point [] go (a:as) 0 = f a <&> (:as) go (a:as) i = (a:) <$> (go as $! i - 1) in go xs0 k {-# INLINE ixListVL #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Coerce.hs0000644000000000000000000000246107346545000016062 0ustar0000000000000000-- | -- Module: Optics.Coerce -- Description: Operators to 'coerce' the type parameters of 'Optic'. -- -- This module defines operations to 'coerce' the type parameters of optics to -- a representationally equal type. For example, if we have -- -- > newtype MkInt = MkInt Int -- -- and -- -- > l :: Lens' S Int -- -- then -- -- > coerceA @Int @MkInt l :: Lens' S MkInt -- module Optics.Coerce ( coerceS , coerceT , coerceA , coerceB ) where import Data.Coerce import Data.Profunctor.Indexed import Optics.Internal.Optic -- | Lift 'coerce' to the @s@ parameter of an optic. coerceS :: Coercible s s' => Optic k is s t a b -> Optic k is s' t a b coerceS = \(Optic o) -> Optic (lcoerce . o) {-# INLINE coerceS #-} -- | Lift 'coerce' to the @t@ parameter of an optic. coerceT :: Coercible t t' => Optic k is s t a b -> Optic k is s t' a b coerceT = \(Optic o) -> Optic (rcoerce . o) {-# INLINE coerceT #-} -- | Lift 'coerce' to the @a@ parameter of an optic. coerceA :: Coercible a a' => Optic k is s t a b -> Optic k is s t a' b coerceA = \(Optic o) -> Optic (o . lcoerce) {-# INLINE coerceA #-} -- | Lift 'coerce' to the @b@ parameter of an optic. coerceB :: Coercible b b' => Optic k is s t a b -> Optic k is s t a b' coerceB = \(Optic o) -> Optic (o . rcoerce) {-# INLINE coerceB #-} optics-core-0.4.1.1/src/Optics/Cons/0000755000000000000000000000000007346545000015225 5ustar0000000000000000optics-core-0.4.1.1/src/Optics/Cons/Core.hs0000644000000000000000000001662307346545000016461 0ustar0000000000000000-- | -- Module: Optics.Cons.Core -- Description: Optics to access the left or right element of a container. -- -- This module defines the 'Cons' and 'Snoc' classes, which provide 'Prism's for -- the leftmost and rightmost elements of a container, respectively. -- -- Note that orphan instances for these classes are defined in the @Optics.Cons@ -- module from @optics-extra@, so if you are not simply depending on @optics@ -- you may wish to import that module instead. -- module Optics.Cons.Core ( -- * Cons Cons(..) , (<|) , cons , uncons , _head, _tail , pattern (:<) -- * Snoc , Snoc(..) , (|>) , snoc , unsnoc , _init, _last , pattern (:>) ) where import Control.Applicative (ZipList(..)) import Data.Coerce import Data.Sequence hiding ((<|), (|>), (:<), (:>)) import qualified Data.Sequence as Seq import Data.Tuple.Optics import Optics.AffineFold import Optics.AffineTraversal import Optics.Coerce import Optics.Internal.Utils import Optics.Optic import Optics.Prism import Optics.Review infixr 5 <|, `cons` infixl 5 |>, `snoc` -- | Pattern synonym for matching on the leftmost element of a structure. -- -- >>> case ['a','b','c'] of (x :< _) -> x -- 'a' -- pattern (:<) :: forall s a. Cons s s a a => a -> s -> s pattern (:<) a s <- (preview _Cons -> Just (a, s)) where (:<) a s = review _Cons (a, s) infixr 5 :< infixl 5 :> -- | Pattern synonym for matching on the rightmost element of a structure. -- -- >>> case ['a','b','c'] of (_ :> x) -> x -- 'c' -- pattern (:>) :: forall s a. Snoc s s a a => s -> a -> s pattern (:>) s a <- (preview _Snoc -> Just (s, a)) where (:>) a s = review _Snoc (a, s) ------------------------------------------------------------------------------ -- Cons ------------------------------------------------------------------------------ -- | This class provides a way to attach or detach elements on the left -- side of a structure in a flexible manner. class Cons s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | -- -- @ -- '_Cons' :: 'Prism' [a] [b] (a, [a]) (b, [b]) -- '_Cons' :: 'Prism' ('Seq' a) ('Seq' b) (a, 'Seq' a) (b, 'Seq' b) -- '_Cons' :: 'Prism' (Vector a) (Vector b) (a, Vector a) (b, Vector b) -- '_Cons' :: 'Prism'' 'String' ('Char', 'String') -- '_Cons' :: 'Prism'' Text ('Char', Text) -- '_Cons' :: 'Prism'' ByteString ('Data.Word.Word8', ByteString) -- @ _Cons :: Prism s t (a, s) (b, t) instance Cons [a] [b] a b where _Cons = prism (uncurry' (:)) $ \aas -> case aas of (a:as) -> Right (a, as) [] -> Left [] {-# INLINE _Cons #-} instance Cons (ZipList a) (ZipList b) a b where _Cons = coerceS . coerceT . coerceA . coerceB $ listCons where listCons :: Prism [a] [b] (a, [a]) (b, [b]) listCons = _Cons {-# INLINE _Cons #-} instance Cons (Seq a) (Seq b) a b where _Cons = prism (uncurry' (Seq.<|)) $ \aas -> case viewl aas of a Seq.:< as -> Right (a, as) EmptyL -> Left mempty {-# INLINE _Cons #-} -- | 'cons' an element onto a container. -- -- This is an infix alias for 'cons'. -- -- >>> 1 <| [] -- [1] -- -- >>> 'a' <| "bc" -- "abc" -- -- >>> 1 <| [] -- [1] -- -- >>> 1 <| [2, 3] -- [1,2,3] (<|) :: Cons s s a a => a -> s -> s (<|) = curry (review _Cons) {-# INLINE (<|) #-} -- | 'cons' an element onto a container. -- -- >>> cons 'a' "" -- "a" -- -- >>> cons 'a' "bc" -- "abc" cons :: Cons s s a a => a -> s -> s cons = curry (review _Cons) {-# INLINE cons #-} -- | Attempt to extract the left-most element from a container, and a version of -- the container without that element. -- -- >>> uncons [] -- Nothing -- -- >>> uncons [1, 2, 3] -- Just (1,[2,3]) uncons :: Cons s s a a => s -> Maybe (a, s) uncons = preview _Cons {-# INLINE uncons #-} -- | An 'AffineTraversal' reading and writing to the 'head' of a /non-empty/ -- container. -- -- >>> "abc" ^? _head -- Just 'a' -- -- >>> "abc" & _head .~ 'd' -- "dbc" -- -- >>> [1,2,3] & _head %~ (*10) -- [10,2,3] -- -- >>> [] & _head %~ absurd -- [] -- -- >>> [1,2,3] ^? _head -- Just 1 -- -- >>> [] ^? _head -- Nothing -- -- >>> [1,2] ^? _head -- Just 1 -- -- >>> [] & _head .~ 1 -- [] -- -- >>> [0] & _head .~ 2 -- [2] -- -- >>> [0,1] & _head .~ 2 -- [2,1] _head :: Cons s s a a => AffineTraversal' s a _head = _Cons % _1 {-# INLINE _head #-} -- | An 'AffineTraversal' reading and writing to the 'tail' of a /non-empty/ -- container. -- -- >>> "ab" & _tail .~ "cde" -- "acde" -- -- >>> [] & _tail .~ [1,2] -- [] -- -- >>> [1,2,3,4,5] & _tail % traversed %~ (*10) -- [1,20,30,40,50] -- -- >>> [1,2] & _tail .~ [3,4,5] -- [1,3,4,5] -- -- >>> [] & _tail .~ [1,2] -- [] -- -- >>> "abc" ^? _tail -- Just "bc" -- -- >>> "hello" ^? _tail -- Just "ello" -- -- >>> "" ^? _tail -- Nothing _tail :: Cons s s a a => AffineTraversal' s s _tail = _Cons % _2 {-# INLINE _tail #-} ------------------------------------------------------------------------------ -- Snoc ------------------------------------------------------------------------------ -- | This class provides a way to attach or detach elements on the right side of -- a structure in a flexible manner. class Snoc s t a b | s -> a, t -> b, s b -> t, t a -> s where _Snoc :: Prism s t (s, a) (t, b) instance Snoc [a] [b] a b where _Snoc = prism (\(as,a) -> as Prelude.++ [a]) $ \aas -> if Prelude.null aas then Left [] else Right (Prelude.init aas, Prelude.last aas) {-# INLINE _Snoc #-} instance Snoc (ZipList a) (ZipList b) a b where _Snoc = withPrism listSnoc $ \listReview listPreview -> prism (coerce listReview) (coerce listPreview) where listSnoc :: Prism [a] [b] ([a], a) ([b], b) listSnoc = _Snoc {-# INLINE _Snoc #-} instance Snoc (Seq a) (Seq b) a b where _Snoc = prism (uncurry' (Seq.|>)) $ \aas -> case viewr aas of as Seq.:> a -> Right (as, a) EmptyR -> Left mempty {-# INLINE _Snoc #-} -- | An 'AffineTraversal' reading and replacing all but the a last element of a -- /non-empty/ container. -- -- >>> "abcd" ^? _init -- Just "abc" -- -- >>> "" ^? _init -- Nothing -- -- >>> "ab" & _init .~ "cde" -- "cdeb" -- -- >>> [] & _init .~ [1,2] -- [] -- -- >>> [1,2,3,4] & _init % traversed %~ (*10) -- [10,20,30,4] -- -- >>> [1,2,3] ^? _init -- Just [1,2] -- -- >>> "hello" ^? _init -- Just "hell" -- -- >>> [] ^? _init -- Nothing _init :: Snoc s s a a => AffineTraversal' s s _init = _Snoc % _1 {-# INLINE _init #-} -- | An 'AffineTraversal' reading and writing to the last element of a -- /non-empty/ container. -- -- >>> "abc" ^? _last -- Just 'c' -- -- >>> "" ^? _last -- Nothing -- -- >>> [1,2,3] & _last %~ (+1) -- [1,2,4] -- -- >>> [1,2] ^? _last -- Just 2 -- -- >>> [] & _last .~ 1 -- [] -- -- >>> [0] & _last .~ 2 -- [2] -- -- >>> [0,1] & _last .~ 2 -- [0,2] _last :: Snoc s s a a => AffineTraversal' s a _last = _Snoc % _2 {-# INLINE _last #-} -- | 'snoc' an element onto the end of a container. -- -- This is an infix alias for 'snoc'. -- -- >>> "" |> 'a' -- "a" -- -- >>> "bc" |> 'a' -- "bca" (|>) :: Snoc s s a a => s -> a -> s (|>) = curry (review _Snoc) {-# INLINE (|>) #-} -- | 'snoc' an element onto the end of a container. -- -- >>> snoc "hello" '!' -- "hello!" snoc :: Snoc s s a a => s -> a -> s snoc = curry (review _Snoc) {-# INLINE snoc #-} -- | Attempt to extract the right-most element from a container, and a version -- of the container without that element. -- -- >>> unsnoc "hello!" -- Just ("hello",'!') -- -- >>> unsnoc "" -- Nothing unsnoc :: Snoc s s a a => s -> Maybe (s, a) unsnoc s = preview _Snoc s {-# INLINE unsnoc #-} -- $setup -- >>> import Data.Void -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Core.hs0000644000000000000000000000435407346545000015555 0ustar0000000000000000-- | -- -- Module: Optics.Core -- Description: The core optics functionality re-exported. -- -- See the @Optics@ module in the main @optics@ package for overview -- documentation. -- module Optics.Core ( -- * Basic definitions module Optics.Optic -- * Kinds of optic , module O -- * Indexed optics , module I -- * Overloaded labels , module Optics.Label -- * Combinators , module P -- * Optics for basic data types , module D ) where import Optics.AffineFold as O import Optics.AffineTraversal as O import Optics.Fold as O import Optics.Getter as O import Optics.Iso as O import Optics.IxAffineFold as O import Optics.IxAffineTraversal as O import Optics.IxFold as O import Optics.IxGetter as O import Optics.IxLens as O import Optics.IxSetter as O import Optics.IxTraversal as O import Optics.Lens as O import Optics.ReversedLens as O import Optics.Prism as O import Optics.ReversedPrism as O import Optics.Review as O import Optics.Setter as O import Optics.Traversal as O import Optics.Indexed.Core as I import Optics.Arrow as P import Optics.At.Core as P import Optics.Coerce as P import Optics.Cons.Core as P import Optics.Each.Core as P import Optics.Empty.Core as P import Optics.Generic as P import Optics.Mapping as P import Optics.Operators as P import Optics.Re as P import Optics.ReadOnly as P import Optics.Label import Optics.Optic import Data.Either.Optics as D import Data.Maybe.Optics as D import Data.Tuple.Optics as D optics-core-0.4.1.1/src/Optics/Core/0000755000000000000000000000000007346545000015213 5ustar0000000000000000optics-core-0.4.1.1/src/Optics/Core/Extras.hs0000644000000000000000000000055007346545000017015 0ustar0000000000000000module Optics.Core.Extras ( is ) where import Data.Maybe import Optics.Optic import Optics.AffineFold -- | Check to see if this 'AffineFold' matches. -- -- >>> is _Just Nothing -- False -- -- @since 0.4.1 is :: Is k An_AffineFold => Optic' k is s a -> s -> Bool is k s = isJust (preview k s) {-# INLINE is #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Each/0000755000000000000000000000000007346545000015163 5ustar0000000000000000optics-core-0.4.1.1/src/Optics/Each/Core.hs0000644000000000000000000001575407346545000016423 0ustar0000000000000000-- | -- Module: Optics.Each.Core -- Description: An 'IxTraversal' for each element of a (potentially monomorphic) container. -- -- This module defines the 'Each' class, which provides an 'IxTraversal' that -- extracts 'each' element of a (potentially monomorphic) container. -- -- Note that orphan instances for this class are defined in the @Optics.Each@ -- module from @optics-extra@, so if you are not simply depending on @optics@ -- you may wish to import that module instead. -- {-# LANGUAGE UndecidableInstances #-} module Optics.Each.Core ( -- * Each Each(..) ) where import Data.Complex (Complex (..)) import Data.Functor.Identity (Identity (..)) import Data.List.NonEmpty (NonEmpty (..)) import Data.Tree (Tree (..)) import Data.Ix (Ix) import Data.Array (Array) import Data.IntMap (IntMap) import qualified Data.IntMap as IntMap import Data.Map (Map) import qualified Data.Map as Map import Data.Sequence (Seq) import Optics.IxLens import Optics.IxTraversal import Optics.Optic -- | Extract 'each' element of a (potentially monomorphic) container. -- -- >>> over each (*10) (1,2,3) -- (10,20,30) -- -- >>> iover each (\i a -> a*10 + succ i) (1,2,3) -- (11,22,33) -- class Each i s t a b | s -> i a, t -> i b, s b -> t, t a -> s where each :: IxTraversal i s t a b default each :: (TraversableWithIndex i g, s ~ g a, t ~ g b) => IxTraversal i s t a b each = itraversed {-# INLINE[1] each #-} -- | @'each' :: 'IxTraversal' 'Int' (a, a) (b, b) a b@ instance (a ~ a1, b ~ b1 ) => Each Int (a, a1) (b, b1) a b where each = itraversalVL $ \f (a0, a1) -> (,) <$> f 0 a0 <*> f 1 a1 {-# INLINE[1] each #-} -- | @'each' :: 'IxTraversal' 'Int' (a, a, a) (b, b, b) a b@ instance (a ~ a1, a ~ a2, b ~ b1, b ~ b2 ) => Each Int (a, a1, a2) (b, b1, b2) a b where each = itraversalVL $ \f (a0, a1, a2) -> (,,) <$> f 0 a0 <*> f 1 a1 <*> f 2 a2 {-# INLINE[1] each #-} -- | @'each' :: 'IxTraversal' 'Int' (a, a, a, a) (b, b, b, b) a b@ instance (a ~ a1, a ~ a2, a ~ a3, b ~ b1, b ~ b2, b ~ b3 ) => Each Int (a, a1, a2, a3) (b, b1, b2, b3) a b where each = itraversalVL $ \f (a0, a1, a2, a3) -> (,,,) <$> f 0 a0 <*> f 1 a1 <*> f 2 a2 <*> f 3 a3 {-# INLINE[1] each #-} -- | @'each' :: 'IxTraversal' 'Int' (a, a, a, a, a) (b, b, b, b, b) a b@ instance (a ~ a1, a ~ a2, a ~ a3, a ~ a4, b ~ b1, b ~ b2, b ~ b3, b ~ b4 ) => Each Int (a, a1, a2, a3, a4) (b, b1, b2, b3, b4) a b where each = itraversalVL $ \f (a0, a1, a2, a3, a4) -> (,,,,) <$> f 0 a0 <*> f 1 a1 <*> f 2 a2 <*> f 3 a3 <*> f 4 a4 {-# INLINE[1] each #-} -- | @'each' :: 'IxTraversal' 'Int' (a, a, a, a, a, a) (b, b, b, b, b, b) a b@ instance (a ~ a1, a ~ a2, a ~ a3, a ~ a4, a ~ a5, b ~ b1, b ~ b2, b ~ b3, b ~ b4, b ~ b5 ) => Each Int (a, a1, a2, a3, a4, a5) (b, b1, b2, b3, b4, b5) a b where each = itraversalVL $ \f (a0, a1, a2, a3, a4, a5) -> (,,,,,) <$> f 0 a0 <*> f 1 a1 <*> f 2 a2 <*> f 3 a3 <*> f 4 a4 <*> f 5 a5 {-# INLINE[1] each #-} -- | @'each' :: 'IxTraversal' 'Int' (a, a, a, a, a, a, a) (b, b, b, b, b, b, b) -- a b@ instance (a ~ a1, a ~ a2, a ~ a3, a ~ a4, a ~ a5, a ~ a6, b ~ b1, b ~ b2, b ~ b3, b ~ b4, b ~ b5, b ~ b6 ) => Each Int (a, a1, a2, a3, a4, a5, a6) (b, b1, b2, b3, b4, b5, b6) a b where each = itraversalVL $ \f (a0, a1, a2, a3, a4, a5, a6) -> (,,,,,,) <$> f 0 a0 <*> f 1 a1 <*> f 2 a2 <*> f 3 a3 <*> f 4 a4 <*> f 5 a5 <*> f 6 a6 {-# INLINE[1] each #-} -- | @'each' :: 'IxTraversal' 'Int' (a, a, a, a, a, a, a, a) (b, b, b, b, b, b, -- b, b) a b@ instance (a ~ a1, a ~ a2, a ~ a3, a ~ a4, a ~ a5, a ~ a6, a ~ a7, b ~ b1, b ~ b2, b ~ b3, b ~ b4, b ~ b5, b ~ b6, b ~ b7 ) => Each Int (a, a1, a2, a3, a4, a5, a6, a7) (b, b1, b2, b3, b4, b5, b6, b7) a b where each = itraversalVL $ \f (a0, a1, a2, a3, a4, a5, a6, a7) -> (,,,,,,,) <$> f 0 a0 <*> f 1 a1 <*> f 2 a2 <*> f 3 a3 <*> f 4 a4 <*> f 5 a5 <*> f 6 a6 <*> f 7 a7 {-# INLINE[1] each #-} -- | @'each' :: 'IxTraversal' 'Int' (a, a, a, a, a, a, a, a, a) (b, b, b, b, b, -- b, b, b, b) a b@ instance (a ~ a1, a ~ a2, a ~ a3, a ~ a4, a ~ a5, a ~ a6, a ~ a7, a ~ a8, b ~ b1, b ~ b2, b ~ b3, b ~ b4, b ~ b5, b ~ b6, b ~ b7, b ~ b8 ) => Each Int (a, a1, a2, a3, a4, a5, a6, a7, a8) (b, b1, b2, b3, b4, b5, b6, b7, b8) a b where each = itraversalVL $ \f (a0, a1, a2, a3, a4, a5, a6, a7, a8) -> (,,,,,,,,) <$> f 0 a0 <*> f 1 a1 <*> f 2 a2 <*> f 3 a3 <*> f 4 a4 <*> f 5 a5 <*> f 6 a6 <*> f 7 a7 <*> f 8 a8 {-# INLINE[1] each #-} -- | @'each' :: 'IxTraversal' 'Int' (a, a, a, a, a, a, a, a, a, a) (b, b, b, b, -- b, b, b, b, b, b) a b@ instance (a ~ a1, a ~ a2, a ~ a3, a ~ a4, a ~ a5, a ~ a6, a ~ a7, a ~ a8, a ~ a9, b ~ b1, b ~ b2, b ~ b3, b ~ b4, b ~ b5, b ~ b6, b ~ b7, b ~ b8, b ~ b9 ) => Each Int (a, a1, a2, a3, a4, a5, a6, a7, a8, a9) (b, b1, b2, b3, b4, b5, b6, b7, b8, b9) a b where each = itraversalVL $ \f (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) -> (,,,,,,,,,) <$> f 0 a0 <*> f 1 a1 <*> f 2 a2 <*> f 3 a3 <*> f 4 a4 <*> f 5 a5 <*> f 6 a6 <*> f 7 a7 <*> f 8 a8 <*> f 9 a9 {-# INLINE[1] each #-} -- | @'each' :: 'IxTraversal' ('Either' () ()) ('Either' a a) ('Either' b b) a -- b@ instance (a ~ a', b ~ b' ) => Each (Either () ()) (Either a a') (Either b b') a b where each = castOptic chosen {-# INLINE[1] each #-} -- | @'each' :: ('RealFloat' a, 'RealFloat' b) => 'IxTraversal' (Either () ()) -- ('Complex' a) ('Complex' b) a b@ instance Each (Either () ()) (Complex a) (Complex b) a b where each = itraversalVL $ \f (a :+ b) -> (:+) <$> f (Left ()) a <*> f (Right ()) b {-# INLINE[1] each #-} -- | @'each' :: 'IxTraversal' k ('Map' k a) ('Map' k b) a b@ instance k ~ k' => Each k (Map k a) (Map k' b) a b where -- traverseWithKey has best performance for all flavours for some reason. each = itraversalVL Map.traverseWithKey {-# INLINE[1] each #-} -- | @'each' :: 'IxTraversal' 'Int' ('IntMap' a) ('IntMap' b) a b@ instance Each Int (IntMap a) (IntMap b) a b where -- traverseWithKey has best performance for all flavours for some reason. each = itraversalVL IntMap.traverseWithKey {-# INLINE[1] each #-} -- | @'each' :: 'IxTraversal' 'Int' [a] [b] a b@ instance Each Int [a] [b] a b -- | @'each' :: 'IxTraversal' 'Int' (NonEmpty a) (NonEmpty b) a b@ instance Each Int (NonEmpty a) (NonEmpty b) a b -- | @'each' :: 'IxTraversal' () ('Identity' a) ('Identity' b) a b@ instance Each () (Identity a) (Identity b) a b -- | @'each' :: 'IxTraversal' () ('Maybe' a) ('Maybe' b) a b@ instance Each () (Maybe a) (Maybe b) a b -- | @'each' :: 'IxTraversal' 'Int' ('Seq' a) ('Seq' b) a b@ instance Each Int (Seq a) (Seq b) a b -- | @'each' :: 'IxTraversal' [Int] ('Tree' a) ('Tree' b) a b@ instance Each [Int] (Tree a) (Tree b) a b -- | @'each' :: 'Ix' i => 'IxTraversal' i ('Array' i a) ('Array' i b) a b@ instance (Ix i, i ~ j) => Each i (Array i a) (Array j b) a b -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Empty/0000755000000000000000000000000007346545000015421 5ustar0000000000000000optics-core-0.4.1.1/src/Optics/Empty/Core.hs0000644000000000000000000000771507346545000016657 0ustar0000000000000000-- | -- Module: Optics.Empty.Core -- Description: A 'Prism' for a type that may be '_Empty'. -- -- This module defines the 'AsEmpty' class, which provides a 'Prism' for a type -- that may be '_Empty'. -- -- Note that orphan instances for this class are defined in the @Optics.Empty@ -- module from @optics-extra@, so if you are not simply depending on @optics@ -- you may wish to import that module instead. -- -- >>> isn't _Empty [1,2,3] -- True -- -- >>> case Nothing of { Empty -> True; _ -> False } -- True -- {-# LANGUAGE CPP #-} module Optics.Empty.Core ( AsEmpty(..) , pattern Empty ) where import Control.Applicative (ZipList(..)) import Data.Maybe (isNothing) import Data.Monoid (Any (..), All (..), Product (..), Sum (..), Last (..), First (..), Dual (..)) import Data.Set (Set) import qualified Data.Set as Set import Data.IntMap (IntMap) import qualified Data.IntMap as IntMap import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet import Data.Map (Map) import qualified Data.Map as Map import qualified Data.Sequence as Seq import Data.Profunctor.Indexed import Data.Maybe.Optics import Optics.AffineTraversal import Optics.Fold import Optics.Iso import Optics.Optic import Optics.Prism import Optics.Review #if !defined(mingw32_HOST_OS) && !defined(ghcjs_HOST_OS) import GHC.Event (Event) #endif -- | Class for types that may be '_Empty'. -- class AsEmpty a where -- | -- -- >>> isn't _Empty [1,2,3] -- True _Empty :: Prism' a () default _Empty :: (Monoid a, Eq a) => Prism' a () _Empty = only mempty {-# INLINE _Empty #-} -- | Pattern synonym for matching on any type with an 'AsEmpty' instance. -- -- >>> case Nothing of { Empty -> True; _ -> False } -- True -- pattern Empty :: forall a. AsEmpty a => a pattern Empty <- (has _Empty -> True) where Empty = review _Empty () {- Default Monoid instances -} instance AsEmpty Ordering instance AsEmpty () instance AsEmpty Any instance AsEmpty All #if !defined(mingw32_HOST_OS) && !defined(ghcjs_HOST_OS) instance AsEmpty Event #endif instance (Eq a, Num a) => AsEmpty (Product a) instance (Eq a, Num a) => AsEmpty (Sum a) instance AsEmpty (Maybe a) where _Empty = _Nothing {-# INLINE _Empty #-} instance AsEmpty (Last a) where _Empty = nearly (Last Nothing) (isNothing .# getLast) {-# INLINE _Empty #-} instance AsEmpty (First a) where _Empty = nearly (First Nothing) (isNothing .# getFirst) {-# INLINE _Empty #-} instance AsEmpty a => AsEmpty (Dual a) where _Empty = iso getDual Dual % _Empty {-# INLINE _Empty #-} instance (AsEmpty a, AsEmpty b) => AsEmpty (a, b) where _Empty = prism' (\() -> (review _Empty (), review _Empty ())) (\(s, s') -> case matching _Empty s of Right () -> case matching _Empty s' of Right () -> Just () Left _ -> Nothing Left _ -> Nothing) {-# INLINE _Empty #-} instance (AsEmpty a, AsEmpty b, AsEmpty c) => AsEmpty (a, b, c) where _Empty = prism' (\() -> (review _Empty (), review _Empty (), review _Empty ())) (\(s, s', s'') -> case matching _Empty s of Right () -> case matching _Empty s' of Right () -> case matching _Empty s'' of Right () -> Just () Left _ -> Nothing Left _ -> Nothing Left _ -> Nothing) {-# INLINE _Empty #-} instance AsEmpty [a] where _Empty = nearly [] Prelude.null {-# INLINE _Empty #-} instance AsEmpty (ZipList a) where _Empty = nearly (ZipList []) (Prelude.null . getZipList) {-# INLINE _Empty #-} instance AsEmpty (Map k a) where _Empty = nearly Map.empty Map.null {-# INLINE _Empty #-} instance AsEmpty (IntMap a) where _Empty = nearly IntMap.empty IntMap.null {-# INLINE _Empty #-} instance AsEmpty (Set a) where _Empty = nearly Set.empty Set.null {-# INLINE _Empty #-} instance AsEmpty IntSet where _Empty = nearly IntSet.empty IntSet.null {-# INLINE _Empty #-} instance AsEmpty (Seq.Seq a) where _Empty = nearly Seq.empty Seq.null {-# INLINE _Empty #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Fold.hs0000644000000000000000000004615507346545000015556 0ustar0000000000000000-- | -- Module: Optics.Fold -- Description: Extracts elements from a container. -- -- A @'Fold' S A@ has the ability to extract some number of elements of type @A@ -- from a container of type @S@. For example, 'toListOf' can be used to obtain -- the contained elements as a list. Unlike a 'Optics.Traversal.Traversal', -- there is no way to set or update elements. -- -- This can be seen as a generalisation of 'traverse_', where the type @S@ does -- not need to be a type constructor with @A@ as the last parameter. -- -- A close relative is the 'Optics.AffineFold.AffineFold', which is a 'Fold' -- that contains at most one element. -- module Optics.Fold ( -- * Formation Fold -- * Introduction , foldVL -- * Elimination , foldOf , foldMapOf , foldrOf , foldlOf' , toListOf , sequenceOf_ , traverseOf_ , forOf_ -- * Computation -- -- | -- -- @ -- 'traverseOf_' ('foldVL' f) ≡ f -- @ -- * Additional introduction forms , folded , folding , foldring , unfolded -- * Additional elimination forms -- | See also 'Data.Set.Optics.setOf', which constructs a 'Data.Set.Set' from a 'Fold'. , has , hasn't , headOf , lastOf , andOf , orOf , allOf , anyOf , noneOf , productOf , sumOf , asumOf , msumOf , elemOf , notElemOf , lengthOf , maximumOf , minimumOf , maximumByOf , minimumByOf , findOf , findMOf , lookupOf , universeOf , cosmosOf , paraOf -- * Combinators , pre , backwards_ -- * Monoid structures #monoids# -- | 'Fold' admits (at least) two monoid structures: -- -- * 'summing' concatenates results from both folds. -- -- * 'failing' returns results from the second fold only if the first returns -- no results. -- -- In both cases, the identity element of the monoid is -- `Optics.IxAffineTraversal.ignored`, which returns no results. -- -- There is no 'Semigroup' or 'Monoid' instance for 'Fold', because there is -- not a unique choice of monoid to use, and the ('<>') operator could not be -- used to combine optics of different kinds. When porting code from @lens@ -- that uses '<>' to combine folds, use 'summing' instead. , summing , failing -- * Subtyping , A_Fold -- | <> ) where import Control.Applicative import Control.Applicative.Backwards import Control.Monad import Data.Foldable import Data.Function import Data.Monoid import Data.Profunctor.Indexed import Optics.AffineFold import Optics.Internal.Bi import Optics.Internal.Fold import Optics.Internal.Optic import Optics.Internal.Utils -- | Type synonym for a fold. type Fold s a = Optic' A_Fold NoIx s a -- | Obtain a 'Fold' by lifting 'traverse_' like function. -- -- @ -- 'foldVL' '.' 'traverseOf_' ≡ 'id' -- 'traverseOf_' '.' 'foldVL' ≡ 'id' -- @ foldVL :: (forall f. Applicative f => (a -> f u) -> s -> f v) -> Fold s a foldVL f = Optic (foldVL__ f) {-# INLINE foldVL #-} -- | Combine the results of a fold using a monoid. foldOf :: (Is k A_Fold, Monoid a) => Optic' k is s a -> s -> a foldOf o = foldMapOf o id {-# INLINE foldOf #-} -- | Fold via embedding into a monoid. foldMapOf :: (Is k A_Fold, Monoid m) => Optic' k is s a -> (a -> m) -> s -> m foldMapOf o = runForget #. getOptic (castOptic @A_Fold o) .# Forget {-# INLINE foldMapOf #-} -- | Fold right-associatively. foldrOf :: Is k A_Fold => Optic' k is s a -> (a -> r -> r) -> r -> s -> r foldrOf o = \arr r s -> (\e -> appEndo e r) $ foldMapOf o (Endo #. arr) s {-# INLINE foldrOf #-} -- | Fold left-associatively, and strictly. foldlOf' :: Is k A_Fold => Optic' k is s a -> (r -> a -> r) -> r -> s -> r foldlOf' o = \rar r0 s -> foldrOf o (\a rr r -> rr $! rar r a) id s r0 {-# INLINE foldlOf' #-} -- | Fold to a list. -- -- >>> toListOf (_1 % folded % _Right) ([Right 'h', Left 5, Right 'i'], "bye") -- "hi" toListOf :: Is k A_Fold => Optic' k is s a -> s -> [a] toListOf o = foldrOf o (:) [] {-# INLINE toListOf #-} ---------------------------------------- -- | Traverse over all of the targets of a 'Fold', computing an -- 'Applicative'-based answer, but unlike 'Optics.Traversal.traverseOf' do not -- construct a new structure. 'traverseOf_' generalizes -- 'Data.Foldable.traverse_' to work over any 'Fold'. -- -- >>> traverseOf_ each putStrLn ("hello","world") -- hello -- world -- -- @ -- 'Data.Foldable.traverse_' ≡ 'traverseOf_' 'folded' -- @ traverseOf_ :: (Is k A_Fold, Applicative f) => Optic' k is s a -> (a -> f r) -> s -> f () traverseOf_ o = \f -> runTraversed . foldMapOf o (Traversed #. f) {-# INLINE traverseOf_ #-} -- | A version of 'traverseOf_' with the arguments flipped. forOf_ :: (Is k A_Fold, Applicative f) => Optic' k is s a -> s -> (a -> f r) -> f () forOf_ = flip . traverseOf_ {-# INLINE forOf_ #-} -- | Evaluate each action in a structure observed by a 'Fold' from left to -- right, ignoring the results. -- -- @ -- 'sequenceA_' ≡ 'sequenceOf_' 'folded' -- @ -- -- >>> sequenceOf_ each (putStrLn "hello",putStrLn "world") -- hello -- world sequenceOf_ :: (Is k A_Fold, Applicative f) => Optic' k is s (f a) -> s -> f () sequenceOf_ o = runTraversed . foldMapOf o Traversed {-# INLINE sequenceOf_ #-} ---------------------------------------- -- | Fold via the 'Foldable' class. folded :: Foldable f => Fold (f a) a folded = Optic folded__ {-# INLINE folded #-} -- | Obtain a 'Fold' by lifting an operation that returns a 'Foldable' result. -- -- This can be useful to lift operations from @Data.List@ and elsewhere into a -- 'Fold'. -- -- >>> toListOf (folding tail) [1,2,3,4] -- [2,3,4] folding :: Foldable f => (s -> f a) -> Fold s a folding f = Optic (contrafirst f . foldVL__ traverse_) {-# INLINE folding #-} -- | Obtain a 'Fold' by lifting 'foldr' like function. -- -- >>> toListOf (foldring foldr) [1,2,3,4] -- [1,2,3,4] foldring :: (forall f. Applicative f => (a -> f u -> f u) -> f v -> s -> f w) -> Fold s a foldring fr = Optic (foldring__ fr) {-# INLINE foldring #-} -- | Build a 'Fold' that unfolds its values from a seed. -- -- @ -- 'Prelude.unfoldr' ≡ 'toListOf' '.' 'unfolded' -- @ -- -- >>> toListOf (unfolded $ \b -> if b == 0 then Nothing else Just (b, b - 1)) 10 -- [10,9,8,7,6,5,4,3,2,1] unfolded :: (s -> Maybe (a, s)) -> Fold s a unfolded step = foldVL $ \f -> fix $ \loop b -> case step b of Just (a, b') -> f a *> loop b' Nothing -> pure () {-# INLINE unfolded #-} -- | Convert a fold to an 'AffineFold' that visits the first element of the -- original fold. -- -- For the traversal version see 'Optics.Traversal.singular'. pre :: Is k A_Fold => Optic' k is s a -> AffineFold s a pre = afolding . headOf {-# INLINE pre #-} -- | This allows you to traverse the elements of a 'Fold' in the opposite order. backwards_ :: Is k A_Fold => Optic' k is s a -> Fold s a backwards_ o = foldVL $ \f -> forwards #. traverseOf_ o (Backwards #. f) {-# INLINE backwards_ #-} -- | Return entries of the first 'Fold', then the second one. -- -- >>> toListOf (_1 % ix 0 `summing` _2 % ix 1) ([1,2], [4,7,1]) -- [1,7] -- -- For the traversal version see 'Optics.Traversal.adjoin'. summing :: (Is k A_Fold, Is l A_Fold) => Optic' k is s a -> Optic' l js s a -> Fold s a summing a b = foldVL $ \f s -> traverseOf_ a f s *> traverseOf_ b f s infixr 6 `summing` -- Same as (<>) {-# INLINE summing #-} -- | Try the first 'Fold'. If it returns no entries, try the second one. -- -- >>> toListOf (ix 1 `failing` ix 0) [4,7] -- [7] -- >>> toListOf (ix 1 `failing` ix 0) [4] -- [4] -- failing :: (Is k A_Fold, Is l A_Fold) => Optic' k is s a -> Optic' l js s a -> Fold s a failing a b = foldVL $ \f s -> let OrT visited fu = traverseOf_ a (wrapOrT . f) s in if visited then fu else traverseOf_ b f s infixl 3 `failing` -- Same as (<|>) {-# INLINE failing #-} ---------------------------------------- -- Special folds -- | Check to see if this optic matches 1 or more entries. -- -- >>> has _Left (Left 12) -- True -- -- >>> has _Right (Left 12) -- False -- -- This will always return 'True' for a 'Optics.Lens.Lens' or -- 'Optics.Getter.Getter'. -- -- >>> has _1 ("hello","world") -- True has :: Is k A_Fold => Optic' k is s a -> s -> Bool has o = getAny #. foldMapOf o (\_ -> Any True) {-# INLINE has #-} -- | Check to see if this 'Fold' or 'Optics.Traversal.Traversal' has -- no matches. -- -- >>> hasn't _Left (Right 12) -- True -- -- >>> hasn't _Left (Left 12) -- False hasn't :: Is k A_Fold => Optic' k is s a -> s -> Bool hasn't o = getAll #. foldMapOf o (\_ -> All False) {-# INLINE hasn't #-} -- | Retrieve the first entry of a 'Fold'. -- -- >>> headOf folded [1..10] -- Just 1 -- -- >>> headOf each (1,2) -- Just 1 headOf :: Is k A_Fold => Optic' k is s a -> s -> Maybe a headOf o = getLeftmost . foldMapOf o LLeaf {-# INLINE headOf #-} -- | Retrieve the last entry of a 'Fold'. -- -- >>> lastOf folded [1..10] -- Just 10 -- -- >>> lastOf each (1,2) -- Just 2 lastOf :: Is k A_Fold => Optic' k is s a -> s -> Maybe a lastOf o = getRightmost . foldMapOf o RLeaf {-# INLINE lastOf #-} -- | Returns 'True' if every target of a 'Fold' is 'True'. -- -- >>> andOf each (True, False) -- False -- >>> andOf each (True, True) -- True -- -- @ -- 'Data.Foldable.and' ≡ 'andOf' 'folded' -- @ andOf :: Is k A_Fold => Optic' k is s Bool -> s -> Bool andOf o = getAll #. foldMapOf o All {-# INLINE andOf #-} -- | Returns 'True' if any target of a 'Fold' is 'True'. -- -- >>> orOf each (True, False) -- True -- >>> orOf each (False, False) -- False -- -- @ -- 'Data.Foldable.or' ≡ 'orOf' 'folded' -- @ orOf :: Is k A_Fold => Optic' k is s Bool -> s -> Bool orOf o = getAny #. foldMapOf o Any {-# INLINE orOf #-} -- | Returns 'True' if any target of a 'Fold' satisfies a predicate. -- -- >>> anyOf each (=='x') ('x','y') -- True anyOf :: Is k A_Fold => Optic' k is s a -> (a -> Bool) -> s -> Bool anyOf o = \f -> getAny #. foldMapOf o (Any #. f) {-# INLINE anyOf #-} -- | Returns 'True' if every target of a 'Fold' satisfies a predicate. -- -- >>> allOf each (>=3) (4,5) -- True -- >>> allOf folded (>=2) [1..10] -- False -- -- @ -- 'Data.Foldable.all' ≡ 'allOf' 'folded' -- @ allOf :: Is k A_Fold => Optic' k is s a -> (a -> Bool) -> s -> Bool allOf o = \f -> getAll #. foldMapOf o (All #. f) {-# INLINE allOf #-} -- | Returns 'True' only if no targets of a 'Fold' satisfy a predicate. -- -- >>> noneOf each (not . isn't _Nothing) (Just 3, Just 4, Just 5) -- True -- >>> noneOf (folded % folded) (<10) [[13,99,20],[3,71,42]] -- False noneOf :: Is k A_Fold => Optic' k is s a -> (a -> Bool) -> s -> Bool noneOf o = \f -> not . anyOf o f {-# INLINE noneOf #-} -- | Calculate the 'Product' of every number targeted by a 'Fold'. -- -- >>> productOf each (4,5) -- 20 -- >>> productOf folded [1,2,3,4,5] -- 120 -- -- @ -- 'Data.Foldable.product' ≡ 'productOf' 'folded' -- @ -- -- This operation may be more strict than you would expect. If you want a lazier -- version use @\\o -> 'getProduct' '.' 'foldMapOf' o 'Product'@. productOf :: (Is k A_Fold, Num a) => Optic' k is s a -> s -> a productOf o = foldlOf' o (*) 1 {-# INLINE productOf #-} -- | Calculate the 'Sum' of every number targeted by a 'Fold'. -- -- >>> sumOf each (5,6) -- 11 -- >>> sumOf folded [1,2,3,4] -- 10 -- >>> sumOf (folded % each) [(1,2),(3,4)] -- 10 -- -- @ -- 'Data.Foldable.sum' ≡ 'sumOf' 'folded' -- @ -- -- This operation may be more strict than you would expect. If you want a lazier -- version use @\\o -> 'getSum' '.' 'foldMapOf' o 'Sum'@ sumOf :: (Is k A_Fold, Num a) => Optic' k is s a -> s -> a sumOf o = foldlOf' o (+) 0 {-# INLINE sumOf #-} -- | The sum of a collection of actions. -- -- >>> asumOf each ("hello","world") -- "helloworld" -- -- >>> asumOf each (Nothing, Just "hello", Nothing) -- Just "hello" -- -- @ -- 'asum' ≡ 'asumOf' 'folded' -- @ asumOf :: (Is k A_Fold, Alternative f) => Optic' k is s (f a) -> s -> f a asumOf o = foldrOf o (<|>) empty {-# INLINE asumOf #-} -- | The sum of a collection of actions. -- -- >>> msumOf each ("hello","world") -- "helloworld" -- -- >>> msumOf each (Nothing, Just "hello", Nothing) -- Just "hello" -- -- @ -- 'msum' ≡ 'msumOf' 'folded' -- @ msumOf :: (Is k A_Fold, MonadPlus m) => Optic' k is s (m a) -> s -> m a msumOf o = foldrOf o mplus mzero {-# INLINE msumOf #-} -- | Does the element occur anywhere within a given 'Fold' of the structure? -- -- >>> elemOf each "hello" ("hello","world") -- True -- -- @ -- 'elem' ≡ 'elemOf' 'folded' -- @ elemOf :: (Is k A_Fold, Eq a) => Optic' k is s a -> a -> s -> Bool elemOf o = anyOf o . (==) {-# INLINE elemOf #-} -- | Does the element not occur anywhere within a given 'Fold' of the structure? -- -- >>> notElemOf each 'd' ('a','b','c') -- True -- -- >>> notElemOf each 'a' ('a','b','c') -- False -- -- @ -- 'notElem' ≡ 'notElemOf' 'folded' -- @ notElemOf :: (Is k A_Fold, Eq a) => Optic' k is s a -> a -> s -> Bool notElemOf o = allOf o . (/=) {-# INLINE notElemOf #-} -- | Calculate the number of targets there are for a 'Fold' in a given -- container. -- -- /Note:/ This can be rather inefficient for large containers and just like -- 'length', this will not terminate for infinite folds. -- -- @ -- 'length' ≡ 'lengthOf' 'folded' -- @ -- -- >>> lengthOf _1 ("hello",()) -- 1 -- -- >>> lengthOf folded [1..10] -- 10 -- -- >>> lengthOf (folded % folded) [[1,2],[3,4],[5,6]] -- 6 lengthOf :: Is k A_Fold => Optic' k is s a -> s -> Int lengthOf o = foldlOf' o (\ n _ -> 1 + n) 0 {-# INLINE lengthOf #-} -- | Obtain the maximum element (if any) targeted by a 'Fold' safely. -- -- Note: 'maximumOf' on a valid 'Optics.Iso.Iso', 'Optics.Lens.Lens' -- or 'Optics.Getter.Getter' will always return 'Just' a value. -- -- >>> maximumOf folded [1..10] -- Just 10 -- -- >>> maximumOf folded [] -- Nothing -- -- >>> maximumOf (folded % filtered even) [1,4,3,6,7,9,2] -- Just 6 -- -- @ -- 'maximum' ≡ 'Data.Maybe.fromMaybe' ('error' \"empty\") '.' 'maximumOf' 'folded' -- @ -- -- In the interest of efficiency, This operation has semantics more strict than -- strictly necessary. @\\o -> 'Data.Semigroup.getMax' . 'foldMapOf' o 'Data.Semigroup.Max'@ has lazier -- semantics but could leak memory. maximumOf :: (Is k A_Fold, Ord a) => Optic' k is s a -> s -> Maybe a maximumOf o = foldlOf' o mf Nothing where mf Nothing y = Just $! y mf (Just x) y = Just $! max x y {-# INLINE maximumOf #-} -- | Obtain the minimum element (if any) targeted by a 'Fold' safely. -- -- Note: 'minimumOf' on a valid 'Optics.Iso.Iso', 'Optics.Lens.Lens' -- or 'Optics.Getter.Getter' will always return 'Just' a value. -- -- >>> minimumOf folded [1..10] -- Just 1 -- -- >>> minimumOf folded [] -- Nothing -- -- >>> minimumOf (folded % filtered even) [1,4,3,6,7,9,2] -- Just 2 -- -- @ -- 'minimum' ≡ 'Data.Maybe.fromMaybe' ('error' \"empty\") '.' 'minimumOf' 'folded' -- @ -- -- In the interest of efficiency, This operation has semantics more strict than -- strictly necessary. @\\o -> 'Data.Semigroup.getMin' . 'foldMapOf' o 'Data.Semigroup.Min'@ has lazier -- semantics but could leak memory. minimumOf :: (Is k A_Fold, Ord a) => Optic' k is s a -> s -> Maybe a minimumOf o = foldlOf' o mf Nothing where mf Nothing y = Just $! y mf (Just x) y = Just $! min x y {-# INLINE minimumOf #-} -- | Obtain the maximum element (if any) targeted by a 'Fold' according to a -- user supplied 'Ordering'. -- -- >>> maximumByOf folded (compare `on` length) ["mustard","relish","ham"] -- Just "mustard" -- -- In the interest of efficiency, This operation has semantics more strict than -- strictly necessary. -- -- @ -- 'Data.Foldable.maximumBy' cmp ≡ 'Data.Maybe.fromMaybe' ('error' \"empty\") '.' 'maximumByOf' 'folded' cmp -- @ maximumByOf :: Is k A_Fold => Optic' k is s a -> (a -> a -> Ordering) -> s -> Maybe a maximumByOf o = \cmp -> let mf Nothing y = Just $! y mf (Just x) y = Just $! if cmp x y == GT then x else y in foldlOf' o mf Nothing {-# INLINE maximumByOf #-} -- | Obtain the minimum element (if any) targeted by a 'Fold' according to a -- user supplied 'Ordering'. -- -- In the interest of efficiency, This operation has semantics more strict than -- strictly necessary. -- -- >>> minimumByOf folded (compare `on` length) ["mustard","relish","ham"] -- Just "ham" -- -- @ -- 'minimumBy' cmp ≡ 'Data.Maybe.fromMaybe' ('error' \"empty\") '.' 'minimumByOf' 'folded' cmp -- @ minimumByOf :: Is k A_Fold => Optic' k is s a -> (a -> a -> Ordering) -> s -> Maybe a minimumByOf o = \cmp -> let mf Nothing y = Just $! y mf (Just x) y = Just $! if cmp x y == GT then y else x in foldlOf' o mf Nothing {-# INLINE minimumByOf #-} -- | The 'findOf' function takes a 'Fold', a predicate and a structure and -- returns the leftmost element of the structure matching the predicate, or -- 'Nothing' if there is no such element. -- -- >>> findOf each even (1,3,4,6) -- Just 4 -- -- >>> findOf folded even [1,3,5,7] -- Nothing -- -- @ -- 'Data.Foldable.find' ≡ 'findOf' 'folded' -- @ findOf :: Is k A_Fold => Optic' k is s a -> (a -> Bool) -> s -> Maybe a findOf o = \f -> foldrOf o (\a y -> if f a then Just a else y) Nothing {-# INLINE findOf #-} -- | The 'findMOf' function takes a 'Fold', a monadic predicate and a structure -- and returns in the monad the leftmost element of the structure matching the -- predicate, or 'Nothing' if there is no such element. -- -- >>> findMOf each (\x -> print ("Checking " ++ show x) >> return (even x)) (1,3,4,6) -- "Checking 1" -- "Checking 3" -- "Checking 4" -- Just 4 -- -- >>> findMOf each (\x -> print ("Checking " ++ show x) >> return (even x)) (1,3,5,7) -- "Checking 1" -- "Checking 3" -- "Checking 5" -- "Checking 7" -- Nothing -- -- @ -- 'findMOf' 'folded' :: (Monad m, Foldable f) => (a -> m Bool) -> f a -> m (Maybe a) -- @ findMOf :: (Is k A_Fold, Monad m) => Optic' k is s a -> (a -> m Bool) -> s -> m (Maybe a) findMOf o = \f -> foldrOf o (\a y -> f a >>= \r -> if r then pure (Just a) else y) (pure Nothing) {-# INLINE findMOf #-} -- | The 'lookupOf' function takes a 'Fold', a key, and a structure containing -- key/value pairs. It returns the first value corresponding to the given -- key. This function generalizes 'lookup' to work on an arbitrary 'Fold' -- instead of lists. -- -- >>> lookupOf folded 4 [(2, 'a'), (4, 'b'), (4, 'c')] -- Just 'b' -- -- >>> lookupOf folded 2 [(2, 'a'), (4, 'b'), (4, 'c')] -- Just 'a' lookupOf :: (Is k A_Fold, Eq a) => Optic' k is s (a, v) -> a -> s -> Maybe v lookupOf o a = foldrOf o (\(a', v) next -> if a == a' then Just v else next) Nothing {-# INLINE lookupOf #-} -- | Given a 'Fold' that knows how to locate immediate children, retrieve all of -- the transitive descendants of a node, including itself. -- -- @since 0.4.1 universeOf :: Is k A_Fold => Optic' k is a a -> a -> [a] universeOf o = (`appEndo` []) . go where go a = Endo (a :) <> foldMapOf o go a {-# INLINE universeOf #-} -- | Given a 'Fold' that knows how to locate immediate children, fold all of the -- transitive descendants of a node, including itself. -- -- @since 0.4.1 cosmosOf :: forall k is a. Is k A_Fold => Optic' k is a a -> Fold a a cosmosOf o = foldVL go where go :: Applicative f => (a -> f ()) -> a -> f () go f a = f a *> traverseOf_ o (go f) a {-# INLINE cosmosOf #-} -- | Perform a fold-like computation on each value, technically a paramorphism. -- -- @since 0.4.1 paraOf :: Is k A_Fold => Optic' k is a a -> (a -> [r] -> r) -> a -> r paraOf o f = go where go a = f a (go <$> toListOf o a) {-# INLINE paraOf #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Generic.hs0000644000000000000000000002333007346545000016234 0ustar0000000000000000{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE UndecidableInstances #-} -- | -- Module: Optics.Generic -- Description: Data access via the 'Generic' type class. -- -- This module provides, for data types having a 'Generic' instance, a way to -- focus on: -- -- - their named total fields via 'gfield', -- -- - their named partial fields via 'gafield', -- -- - their constructors via 'gconstructor', -- -- - their fields at a specific position via 'gposition', -- -- - their fields of a specific type via 'gplate'. -- -- /Note:/ 'gfield' and 'gconstructor' are supported by -- 'Optics.Label.labelOptic' and can be used with a consise syntax via -- @OverloadedLabels@. -- -- If you're looking for optics for working with a generic representation of a -- data type, there's "GHC.Generics.Optics". -- module Optics.Generic ( -- * Fields GField(..) , GAffineField(..) -- * Positions , GPosition(..) -- * Constructors , GConstructor(..) -- * Types , GPlate(..) ) where import Data.Type.Bool import GHC.Generics (Generic, Rep) import GHC.TypeLits import Optics.AffineTraversal import Optics.Internal.Generic import Optics.Internal.Magic import Optics.Internal.Optic import Optics.Lens import Optics.Prism import Optics.Traversal -- | Hidden type for preventing GHC from solving constraints too early. data Void0 -- | Focus on a field @name@ of type @a@ within a type @s@ using its 'Generic' -- instance. -- -- >>> :{ -- data User a -- = User { name :: String -- , age :: a -- } -- | LazyUser { name :: String -- , age :: a -- , lazy :: Bool -- } -- deriving (Show, Generic) -- :} -- -- >>> let user = User "Tom" 32 :: User Int -- -- >>> user ^. gfield @"name" -- "Tom" -- -- >>> user ^. gfield @"age" -- 32 -- -- >>> user ^. gfield @"salary" -- ... -- ...Data constructor ‘User’ doesn't have a field named ‘salary’ -- ...In the... -- ... -- -- Only total fields are accessible (for partial ones see 'gafield'): -- -- >>> user ^. gfield @"lazy" -- ... -- ...Data constructor ‘User’ doesn't have a field named ‘lazy’ -- ...In the... -- ... -- -- Type changing updates are supported: -- -- >>> user & gfield @"age" .~ () -- User {name = "Tom", age = ()} -- -- Types without a 'Generic' instance are not supported: -- -- >>> NoG 'x' ^. gfield @"any" -- ... -- ...Type ‘NoG’ doesn't have a Generic instance -- ...In the... -- ... -- -- /Note:/ 'gfield' is supported by 'Optics.Label.labelOptic' and can be used -- with a concise syntax via @OverloadedLabels@. -- -- >>> user ^. #name -- "Tom" -- -- >>> user & #age %~ (+1) -- User {name = "Tom", age = 33} -- -- @since 0.4 -- class GField (name :: Symbol) s t a b | name s -> t a b , name t -> s a b where gfield :: Lens s t a b instance GFieldContext name s t a b => GField name s t a b where gfield = gfieldImpl @name -- | Hide implementation from haddock. type GFieldContext name s t a b = ( s `HasShapeOf` t , t `HasShapeOf` s , Unless (Defined (Rep s)) (NoGenericError s) , Unless (Defined (Rep t)) (NoGenericError t) , GFieldImpl name s t a b , Dysfunctional name () s t a b ) -- | Hidden instance. instance (a ~ Void0, b ~ Void0) => GField name Void0 Void0 a b where gfield = lensVL id -- | Focus on a possibly partial field @name@ of type @a@ within a type @s@ -- using its 'Generic' instance. -- -- >>> :{ -- data Fish = Herring { name :: String } -- | Tuna { name :: String, sleeping :: Bool } -- deriving Generic -- :} -- -- >>> let herring = Herring { name = "Henry" } -- >>> let tuna = Tuna { name = "Tony", sleeping = True } -- -- >>> herring ^? gafield @"name" -- Just "Henry" -- -- >>> herring ^? gafield @"sleeping" -- Nothing -- -- >>> tuna ^? gafield @"sleeping" -- Just True -- -- Types without a 'Generic' instance are not supported: -- -- >>> NoG 'x' ^? gafield @"any" -- ... -- ...Type ‘NoG’ doesn't have a Generic instance -- ...In the... -- ... -- -- /Note:/ trying to access a field that doesn't exist in any data constructor -- results in an error: -- -- >>> tuna ^? gafield @"salary" -- ... -- ...Type ‘Fish’ doesn't have a field named ‘salary’ -- ...In the... -- ... -- -- @since 0.4 -- class GAffineField (name :: Symbol) s t a b | name s -> t a b , name t -> s a b where gafield :: AffineTraversal s t a b instance GAFieldContext repDefined name s t a b => GAffineField name s t a b where gafield = gafieldImpl @repDefined @name -- | Hide implementation from haddock. type GAFieldContext repDefined name s t a b = ( s `HasShapeOf` t , t `HasShapeOf` s , repDefined ~ (Defined (Rep s) && Defined (Rep t)) , Unless (Defined (Rep s)) (NoGenericError s) , Unless (Defined (Rep t)) (NoGenericError t) , GAffineFieldImpl repDefined name s t a b , Dysfunctional name () s t a b ) -- | Hidden instance. instance (a ~ Void0, b ~ Void0) => GAffineField name Void0 Void0 a b where gafield = atraversalVL (\_ _ -> \case {}) -- | Focus on a field at position @n@ of type @a@ within a type @s@ using its -- 'Generic' instance. -- -- >>> ('a', 'b', 'c') ^. gposition @2 -- 'b' -- -- >>> ('a', 'b') & gposition @1 .~ "hi" & gposition @2 .~ "there" -- ("hi","there") -- -- >>> ('a', 'b', 'c') ^. gposition @4 -- ... -- ...Data constructor ‘(,,)’ has 3 fields, 4th requested -- ...In the... -- ... -- -- >>> () ^. gposition @1 -- ... -- ...Data constructor ‘()’ has no fields, 1st requested -- ...In the... -- ... -- -- Types without a 'Generic' instance are not supported: -- -- >>> NoG 'x' ^. gposition @1 -- ... -- ...Type ‘NoG’ doesn't have a Generic instance -- ...In the... -- ... -- -- /Note:/ Positions start from @1@: -- -- >>> ('a', 'b') ^. gposition @0 -- ... -- ...There is no 0th position -- ...In the... -- ... -- -- @since 0.4 -- class GPosition (n :: Nat) s t a b | n s -> t a b , n t -> s a b where gposition :: Lens s t a b instance GPositionContext repDefined n s t a b => GPosition n s t a b where gposition = gpositionImpl @repDefined @n -- | Hide implementation from haddock. type GPositionContext repDefined n s t a b = ( s `HasShapeOf` t , t `HasShapeOf` s , repDefined ~ (Defined (Rep s) && Defined (Rep t)) , Unless (Defined (Rep s)) (NoGenericError s) , Unless (Defined (Rep t)) (NoGenericError t) , GPositionImpl repDefined n s t a b , Dysfunctional n () s t a b ) -- | Hidden instance. instance (a ~ Void0, b ~ Void0) => GPosition name Void0 Void0 a b where gposition = lensVL id -- | Focus on a constructor @name@ of a type @s@ using its 'Generic' instance. -- -- >>> :{ -- data Animal = Dog { name :: String, age :: Int } -- | Cat { name :: String, purrs :: Bool } -- deriving (Show, Generic) -- :} -- -- >>> let dog = Dog "Sparky" 2 -- >>> let cat = Cat "Cuddly" True -- -- >>> dog ^? gconstructor @"Dog" -- Just ("Sparky",2) -- -- >>> dog ^? gconstructor @"Cat" -- Nothing -- -- >>> cat & gconstructor @"Cat" % _2 %~ not -- Cat {name = "Cuddly", purrs = False} -- -- >>> dog & gconstructor @"Cat" % _1 .~ "Merry" -- Dog {name = "Sparky", age = 2} -- -- >>> cat ^? gconstructor @"Parrot" -- ... -- ...Type ‘Animal’ doesn't have a constructor named ‘Parrot’ -- ...In the... -- ... -- -- Types without a 'Generic' instance are not supported: -- -- >>> NoG 'x' ^. gconstructor @"NoG" -- ... -- ...Type ‘NoG’ doesn't have a Generic instance -- ...In the... -- ... -- -- /Note:/ 'gconstructor' is supported by 'Optics.Label.labelOptic' and can be -- used with a concise syntax via @OverloadedLabels@. -- -- >>> dog ^? #_Dog -- Just ("Sparky",2) -- -- >>> cat & #_Cat % _1 .~ "Merry" -- Cat {name = "Merry", purrs = True} -- -- @since 0.4 -- class GConstructor (name :: Symbol) s t a b | name s -> t a b , name t -> s a b where gconstructor :: Prism s t a b instance GConstructorContext repDefined name s t a b => GConstructor name s t a b where gconstructor = gconstructorImpl @repDefined @name -- | Hide implementation from haddock. type GConstructorContext repDefined name s t a b = ( s `HasShapeOf` t , t `HasShapeOf` s , repDefined ~ (Defined (Rep s) && Defined (Rep t)) , Unless (Defined (Rep s)) (NoGenericError s) , Unless (Defined (Rep t)) (NoGenericError t) , GConstructorImpl repDefined name s t a b , Dysfunctional name () s t a b ) -- | Hidden instance. instance (a ~ Void0, b ~ Void0) => GConstructor name Void0 Void0 a b where gconstructor = prism id (\case {}) -- | Traverse occurrences of a type @a@ within a type @s@ using its 'Generic' -- instance. -- -- >>> toListOf (gplate @Char) ('h', ((), 'e', Just 'l'), "lo") -- "hello" -- -- If @a@ occurs recursively in its own definition, only outermost occurrences -- of @a@ within @s@ will be traversed: -- -- >>> toListOf (gplate @String) ("one","two") -- ["one","two"] -- -- /Note:/ types without a 'Generic' instance in scope when 'GPlate' class -- constraint is resolved will not be entered during the traversal. -- -- >>> let noG = (NoG 'n', (Just 'i', "c"), 'e') -- -- >>> toListOf (gplate @Char) noG -- "ice" -- -- >>> deriving instance Generic NoG -- -- >>> toListOf (gplate @Char) noG -- "nice" -- -- @since 0.4 -- class GPlate a s where gplate :: Traversal' s a instance GPlateContext a s => GPlate a s where gplate = traversalVL (gplateInner @'True) {-# INLINE gplate #-} -- | Hide implementation from haddock. type GPlateContext a s = ( Generic s , GPlateImpl (Rep s) a ) -- | Hidden instance. instance GPlate a Void0 where gplate = error "unreachable" -- | Hidden instance. instance GPlate Void0 a where gplate = error "unreachable" -- $setup -- >>> :set -XDataKinds -XDeriveGeneric -XStandaloneDeriving -XOverloadedLabels -- >>> import Optics.Core -- >>> newtype NoG = NoG { fromNoG :: Char } optics-core-0.4.1.1/src/Optics/Getter.hs0000644000000000000000000000306307346545000016113 0ustar0000000000000000-- | -- Module: Optics.Getter -- Description: A function considered as an 'Optic'. -- -- A 'Getter' is simply a function considered as an 'Optic'. -- -- Given a function @f :: S -> A@, we can convert it into a -- @'Getter' S A@ using 'to', and convert back to a function using 'view'. -- -- This is typically useful not when you have functions/'Getter's -- alone, but when you are composing multiple 'Optic's to produce a -- 'Getter'. -- module Optics.Getter ( -- * Formation Getter -- * Introduction , to -- * Elimination , view , views -- * Computation -- | -- -- @ -- 'view' ('to' f) ≡ f -- @ -- * Well-formedness -- | A 'Getter' is not subject to any laws. -- * Subtyping , A_Getter -- | <> ) where import Data.Profunctor.Indexed import Optics.Internal.Bi import Optics.Internal.Optic -- | Type synonym for a getter. type Getter s a = Optic' A_Getter NoIx s a -- | View the value pointed to by a getter. -- -- If you want to 'view' a type-modifying optic that is insufficiently -- polymorphic to be type-preserving, use 'Optics.ReadOnly.getting'. -- view :: Is k A_Getter => Optic' k is s a -> s -> a view o = views o id {-# INLINE view #-} -- | View the function of the value pointed to by a getter. views :: Is k A_Getter => Optic' k is s a -> (a -> r) -> s -> r views o = \f -> runForget $ getOptic (castOptic @A_Getter o) (Forget f) {-# INLINE views #-} -- | Build a getter from a function. to :: (s -> a) -> Getter s a to f = Optic (lmap f . rphantom) {-# INLINE to #-} optics-core-0.4.1.1/src/Optics/Indexed/0000755000000000000000000000000007346545000015703 5ustar0000000000000000optics-core-0.4.1.1/src/Optics/Indexed/Core.hs0000644000000000000000000001342207346545000017131 0ustar0000000000000000{-# LANGUAGE DataKinds #-} -- | -- Module: Optics.Indexed.Core -- Description: Core definitions for indexed optics. -- -- This module defines basic functionality for indexed optics. See the "Indexed -- optics" section of the overview documentation in the @Optics@ module of the -- main @optics@ package for more details. -- module Optics.Indexed.Core ( -- * Class for optic kinds that can be indexed IxOptic(..) , conjoined -- * Composition of indexed optics , (%) , (<%>) , (%>) , (<%) , reindexed , icompose , icompose3 , icompose4 , icompose5 , icomposeN -- * Indexed optic flavours , module Optics.IxAffineFold , module Optics.IxAffineTraversal , module Optics.IxFold , module Optics.IxGetter , module Optics.IxLens , module Optics.IxSetter , module Optics.IxTraversal -- * Functors with index , FunctorWithIndex (..) -- ** Foldable with index , FoldableWithIndex (..) , itraverse_ , ifor_ , itoList -- ** Traversable with index , TraversableWithIndex (..) , ifor ) where import Data.Profunctor.Indexed import Optics.Internal.Indexed import Optics.Internal.Indexed.Classes import Optics.Internal.Optic import Optics.AffineFold import Optics.AffineTraversal import Optics.Fold import Optics.Getter import Optics.IxAffineFold import Optics.IxAffineTraversal import Optics.IxFold import Optics.IxGetter import Optics.IxLens import Optics.IxSetter import Optics.IxTraversal import Optics.Lens import Optics.Setter import Optics.Traversal -- | Compose two indexed optics. Their indices are composed as a pair. -- -- >>> itoListOf (ifolded <%> ifolded) ["foo", "bar"] -- [((0,0),'f'),((0,1),'o'),((0,2),'o'),((1,0),'b'),((1,1),'a'),((1,2),'r')] -- infixl 9 <%> (<%>) :: (JoinKinds k l m, IxOptic m s t a b, is `HasSingleIndex` i, js `HasSingleIndex` j) => Optic k is s t u v -> Optic l js u v a b -> Optic m (WithIx (i, j)) s t a b o <%> o' = icompose (,) (o % o') {-# INLINE (<%>) #-} -- | Compose two indexed optics and drop indices of the left one. (If you want -- to compose a non-indexed and an indexed optic, you can just use ('%').) -- -- >>> itoListOf (ifolded %> ifolded) ["foo", "bar"] -- [(0,'f'),(1,'o'),(2,'o'),(0,'b'),(1,'a'),(2,'r')] -- infixl 9 %> (%>) :: (JoinKinds k l m, IxOptic k s t u v, NonEmptyIndices is) => Optic k is s t u v -> Optic l js u v a b -> Optic m js s t a b o %> o' = noIx o % o' {-# INLINE (%>) #-} -- | Compose two indexed optics and drop indices of the right one. (If you want -- to compose an indexed and a non-indexed optic, you can just use ('%').) -- -- >>> itoListOf (ifolded <% ifolded) ["foo", "bar"] -- [(0,'f'),(0,'o'),(0,'o'),(1,'b'),(1,'a'),(1,'r')] -- infixl 9 <% (<%) :: (JoinKinds k l m, IxOptic l u v a b, NonEmptyIndices js) => Optic k is s t u v -> Optic l js u v a b -> Optic m is s t a b o <% o' = o % noIx o' {-# INLINE (<%) #-} -- | Remap the index. -- -- >>> itoListOf (reindexed succ ifolded) "foo" -- [(1,'f'),(2,'o'),(3,'o')] -- -- >>> itoListOf (ifolded %& reindexed succ) "foo" -- [(1,'f'),(2,'o'),(3,'o')] -- reindexed :: is `HasSingleIndex` i => (i -> j) -> Optic k is s t a b -> Optic k (WithIx j) s t a b reindexed = icomposeN {-# INLINE reindexed #-} -- | Flatten indices obtained from two indexed optics. -- -- >>> itoListOf (ifolded % ifolded %& icompose (,)) ["foo","bar"] -- [((0,0),'f'),((0,1),'o'),((0,2),'o'),((1,0),'b'),((1,1),'a'),((1,2),'r')] -- icompose :: (i -> j -> ix) -> Optic k '[i, j] s t a b -> Optic k (WithIx ix) s t a b icompose = icomposeN {-# INLINE icompose #-} -- | Flatten indices obtained from three indexed optics. -- -- >>> itoListOf (ifolded % ifolded % ifolded %& icompose3 (,,)) [["foo","bar"],["xyz"]] -- [((0,0,0),'f'),((0,0,1),'o'),((0,0,2),'o'),((0,1,0),'b'),((0,1,1),'a'),((0,1,2),'r'),((1,0,0),'x'),((1,0,1),'y'),((1,0,2),'z')] -- icompose3 :: (i1 -> i2 -> i3 -> ix) -> Optic k '[i1, i2, i3] s t a b -> Optic k (WithIx ix) s t a b icompose3 = icomposeN {-# INLINE icompose3 #-} -- | Flatten indices obtained from four indexed optics. icompose4 :: (i1 -> i2 -> i3 -> i4 -> ix) -> Optic k '[i1, i2, i3, i4] s t a b -> Optic k (WithIx ix) s t a b icompose4 = icomposeN {-# INLINE icompose4 #-} -- | Flatten indices obtained from five indexed optics. icompose5 :: (i1 -> i2 -> i3 -> i4 -> i5 -> ix) -> Optic k '[i1, i2, i3, i4, i5] s t a b -> Optic k (WithIx ix) s t a b icompose5 = icomposeN {-# INLINE icompose5 #-} -- | Flatten indices obtained from arbitrary number of indexed optics. icomposeN :: forall k i is s t a b . (CurryCompose is, NonEmptyIndices is) => Curry is i -> Optic k is s t a b -> Optic k (WithIx i) s t a b icomposeN f (Optic o) = Optic (ixcontramap (\ij -> composeN @is ij f) . o) {-# INLINE icomposeN #-} ---------------------------------------- -- IxOptic -- | Class for optic kinds that can have indices. class IxOptic k s t a b where -- | Convert an indexed optic to its unindexed equivalent. noIx :: NonEmptyIndices is => Optic k is s t a b -> Optic k NoIx s t a b instance (s ~ t, a ~ b) => IxOptic A_Getter s t a b where noIx o = to (view o) {-# INLINE noIx #-} instance IxOptic A_Lens s t a b where noIx o = lensVL (toLensVL o) {-# INLINE noIx #-} instance IxOptic An_AffineTraversal s t a b where noIx o = atraversalVL (atraverseOf o) {-# INLINE noIx #-} instance (s ~ t, a ~ b) => IxOptic An_AffineFold s t a b where noIx o = afolding (preview o) {-# INLINE noIx #-} instance IxOptic A_Traversal s t a b where noIx o = traversalVL (traverseOf o) {-# INLINE noIx #-} instance (s ~ t, a ~ b) => IxOptic A_Fold s t a b where noIx o = foldVL (traverseOf_ o) {-# INLINE noIx #-} instance IxOptic A_Setter s t a b where noIx o = sets (over o) {-# INLINE noIx #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Internal/0000755000000000000000000000000007346545000016077 5ustar0000000000000000optics-core-0.4.1.1/src/Optics/Internal/Bi.hs0000644000000000000000000000416107346545000016767 0ustar0000000000000000{-# OPTIONS_HADDOCK not-home #-} -- | Classes for co- and contravariant bifunctors. -- -- This module is intended for internal use only, and may change without warning -- in subsequent releases. module Optics.Internal.Bi where import Data.Coerce import Data.Void import Data.Profunctor.Indexed -- | Class for (covariant) bifunctors. class Bifunctor p where bimap :: (a -> b) -> (c -> d) -> p i a c -> p i b d first :: (a -> b) -> p i a c -> p i b c second :: (c -> d) -> p i a c -> p i a d instance Bifunctor Tagged where bimap _f g = Tagged #. g .# unTagged first _f = coerce second g = Tagged #. g .# unTagged -- | Class for contravariant bifunctors. class Bicontravariant p where contrabimap :: (b -> a) -> (d -> c) -> p i a c -> p i b d contrafirst :: (b -> a) -> p i a c -> p i b c contrasecond :: (c -> b) -> p i a b -> p i a c instance Bicontravariant (Forget r) where contrabimap f _g (Forget k) = Forget (k . f) contrafirst f (Forget k) = Forget (k . f) contrasecond _g (Forget k) = Forget k instance Bicontravariant (ForgetM r) where contrabimap f _g (ForgetM k) = ForgetM (k . f) contrafirst f (ForgetM k) = ForgetM (k . f) contrasecond _g (ForgetM k) = ForgetM k instance Bicontravariant (IxForget r) where contrabimap f _g (IxForget k) = IxForget (\i -> k i . f) contrafirst f (IxForget k) = IxForget (\i -> k i . f) contrasecond _g (IxForget k) = IxForget k instance Bicontravariant (IxForgetM r) where contrabimap f _g (IxForgetM k) = IxForgetM (\i -> k i . f) contrafirst f (IxForgetM k) = IxForgetM (\i -> k i . f) contrasecond _g (IxForgetM k) = IxForgetM k ---------------------------------------- -- | If @p@ is a 'Profunctor' and a 'Bifunctor' then its left parameter must be -- phantom. lphantom :: (Profunctor p, Bifunctor p) => p i a c -> p i b c lphantom = first absurd . lmap absurd -- | If @p@ is a 'Profunctor' and 'Bicontravariant' then its right parameter -- must be phantom. rphantom :: (Profunctor p, Bicontravariant p) => p i c a -> p i c b rphantom = rmap absurd . contrasecond absurd optics-core-0.4.1.1/src/Optics/Internal/Fold.hs0000644000000000000000000000725607346545000017331 0ustar0000000000000000{-# OPTIONS_HADDOCK not-home #-} -- | Internal implementation details of folds. -- -- This module is intended for internal use only, and may change without warning -- in subsequent releases. module Optics.Internal.Fold where import Data.Functor import Data.Foldable import Data.Maybe import qualified Data.Semigroup as SG import Data.Profunctor.Indexed import Optics.Internal.Bi import Optics.Internal.Optic -- | Internal implementation of 'Optics.Fold.foldVL'. foldVL__ :: (Bicontravariant p, Traversing p) => (forall f. Applicative f => (a -> f u) -> s -> f v) -> Optic__ p i i s t a b foldVL__ f = rphantom . wander f . rphantom {-# INLINE foldVL__ #-} -- | Internal implementation of 'Optics.Fold.folded'. folded__ :: (Bicontravariant p, Traversing p, Foldable f) => Optic__ p i i (f a) (f b) a b folded__ = foldVL__ traverse_ {-# INLINE folded__ #-} -- | Internal implementation of 'Optics.Fold.foldring'. foldring__ :: (Bicontravariant p, Traversing p) => (forall f. Applicative f => (a -> f u -> f u) -> f v -> s -> f w) -> Optic__ p i i s t a b foldring__ fr = foldVL__ $ \f -> void . fr (\a -> (f a *>)) (pure v) where v = error "foldring__: value used" {-# INLINE foldring__ #-} ------------------------------------------------------------------------------ -- Leftmost and Rightmost ------------------------------------------------------------------------------ -- | Used for 'Optics.Fold.headOf' and 'Optics.IxFold.iheadOf'. data Leftmost a = LPure | LLeaf a | LStep (Leftmost a) instance SG.Semigroup (Leftmost a) where x <> y = LStep $ case x of LPure -> y LLeaf _ -> x LStep x' -> case y of -- The last two cases make headOf produce a Just as soon as any element is -- encountered, and possibly serve as a micro-optimisation; this behaviour -- can be disabled by replacing them with _ -> mappend x y'. Note that -- this means that firstOf (backwards folded) [1..] is Just _|_. LPure -> x' LLeaf a -> LLeaf $ fromMaybe a (getLeftmost x') LStep y' -> x' SG.<> y' instance Monoid (Leftmost a) where mempty = LPure mappend = (SG.<>) -- | Extract the 'Leftmost' element. This will fairly eagerly determine that it -- can return 'Just' the moment it sees any element at all. getLeftmost :: Leftmost a -> Maybe a getLeftmost LPure = Nothing getLeftmost (LLeaf a) = Just a getLeftmost (LStep x) = go x where -- Make getLeftmost non-recursive so it might be inlined for LPure/LLeaf. go LPure = Nothing go (LLeaf a) = Just a go (LStep a) = go a -- | Used for 'Optics.Fold.lastOf' and 'Optics.IxFold.ilastOf'. data Rightmost a = RPure | RLeaf a | RStep (Rightmost a) instance SG.Semigroup (Rightmost a) where x <> y = RStep $ case y of RPure -> x RLeaf _ -> y RStep y' -> case x of -- The last two cases make lastOf produce a Just as soon as any element is -- encountered, and possibly serve as a micro-optimisation; this behaviour -- can be disabled by replacing them with _ -> mappend x y'. Note that -- this means that lastOf folded [1..] is Just _|_. RPure -> y' RLeaf a -> RLeaf $ fromMaybe a (getRightmost y') RStep x' -> mappend x' y' instance Monoid (Rightmost a) where mempty = RPure mappend = (SG.<>) -- | Extract the 'Rightmost' element. This will fairly eagerly determine that it -- can return 'Just' the moment it sees any element at all. getRightmost :: Rightmost a -> Maybe a getRightmost RPure = Nothing getRightmost (RLeaf a) = Just a getRightmost (RStep x) = go x where -- Make getRightmost non-recursive so it might be inlined for RPure/RLeaf. go RPure = Nothing go (RLeaf a) = Just a go (RStep a) = go a optics-core-0.4.1.1/src/Optics/Internal/Generic.hs0000644000000000000000000004306207346545000020014 0ustar0000000000000000{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_HADDOCK not-home #-} -- This module is intended for internal use only, and may change without warning -- in subsequent releases. module Optics.Internal.Generic ( generic , generic1 , _V1 , _U1 , _Par1 , _Rec1 , _K1 , _M1 , _L1 , _R1 -- * Fields , GFieldImpl(..) , GSetFieldSum(..) , GSetFieldProd(..) , GAffineFieldImpl(..) , GAffineFieldSum(..) , GFieldProd(..) -- * Positions , GPositionImpl(..) , GPositionSum(..) -- * Constructors , GConstructorImpl(..) , GConstructorSum(..) , GConstructorTuple(..) -- * Types , GPlateImpl(..) , GPlateInner(..) -- * Re-export , module Optics.Internal.Generic.TypeLevel ) where import Data.Type.Bool import GHC.Generics import GHC.Records import GHC.TypeLits import Optics.AffineTraversal import Optics.Internal.Generic.TypeLevel import Optics.Internal.Magic import Optics.Internal.Optic import Optics.Iso import Optics.Lens import Optics.Prism import Optics.Traversal ---------------------------------------- -- GHC.Generics -- | Convert from the data type to its representation (or back) -- -- >>> view (generic % re generic) "hello" :: String -- "hello" -- generic :: (Generic a, Generic b) => Iso a b (Rep a x) (Rep b y) generic = iso from to -- | Convert from the data type to its representation (or back) generic1 :: (Generic1 f, Generic1 g) => Iso (f x) (g y) (Rep1 f x) (Rep1 g y) generic1 = iso from1 to1 _V1 :: Lens (V1 s) (V1 t) a b _V1 = lensVL (\_ -> \case {}) _U1 :: Iso (U1 p) (U1 q) () () _U1 = iso (const ()) (const U1) _Par1 :: Iso (Par1 p) (Par1 q) p q _Par1 = coerced _Rec1 :: Iso (Rec1 f p) (Rec1 g q) (f p) (g q) _Rec1 = coerced _K1 :: Iso (K1 i c p) (K1 j d q) c d _K1 = coerced _M1 :: Iso (M1 i c f p) (M1 j d g q) (f p) (g q) _M1 = coerced _L1 :: Prism ((a :+: c) t) ((b :+: c) t) (a t) (b t) _L1 = prism L1 reviewer where reviewer (L1 v) = Right v reviewer (R1 v) = Left (R1 v) _R1 :: Prism ((c :+: a) t) ((c :+: b) t) (a t) (b t) _R1 = prism R1 reviewer where reviewer (R1 v) = Right v reviewer (L1 v) = Left (L1 v) ---------------------------------------- -- Field class GFieldImpl (name :: Symbol) s t a b | name s -> a {- These hold morally, but we can't prove it. , name t -> b , name s b -> t , name t a -> s -} where gfieldImpl :: Lens s t a b instance ( Generic s , Generic t , path ~ GetFieldPaths s name (Rep s) , HasField name s a , GSetFieldSum path (Rep s) (Rep t) b ) => GFieldImpl name s t a b where gfieldImpl = lens (getField @name) (\s -> to . gsetFieldSum @path (from s)) {-# INLINE gfieldImpl #-} ---------------------------------------- class GSetFieldSum (path :: PathTree Symbol) g h b | path h -> b , path g b -> h where gsetFieldSum :: g x -> b -> h x instance ( GSetFieldSum path g h b ) => GSetFieldSum path (M1 D m g) (M1 D m h) b where gsetFieldSum (M1 x) = M1 . gsetFieldSum @path x instance ( GSetFieldSum path1 g1 h1 b , GSetFieldSum path2 g2 h2 b ) => GSetFieldSum ('PathTree path1 path2) (g1 :+: g2) (h1 :+: h2) b where gsetFieldSum (L1 x) = L1 . gsetFieldSum @path1 x gsetFieldSum (R1 y) = R1 . gsetFieldSum @path2 y {-# INLINE gsetFieldSum #-} instance ( path ~ GSetFieldPath con epath , When (IsLeft epath) (HideReps g h) , GSetFieldProd path g h b ) => GSetFieldSum ('PathLeaf epath) (M1 C ('MetaCons con fix hs) g) (M1 C ('MetaCons con fix hs) h) b where gsetFieldSum (M1 x) = M1 . gsetFieldProd @path x type family GSetFieldPath (con :: Symbol) (e :: Either Symbol [Path]) :: [Path] where GSetFieldPath _ ('Right path) = path GSetFieldPath con ('Left name) = TypeError ('Text "Data constructor " ':<>: QuoteSymbol con ':<>: 'Text " doesn't have a field named " ':<>: QuoteSymbol name) class GSetFieldProd (path :: [Path]) g h b | path h -> b , path g b -> h where gsetFieldProd :: g x -> b -> h x -- fast path left instance {-# OVERLAPPING #-} ( GSetFieldProd path g1 h1 b ) => GSetFieldProd ('PathLeft : path) (g1 :*: g2) (h1 :*: g2) b where gsetFieldProd (x :*: y) = (:*: y) . gsetFieldProd @path x -- slow path left instance ( GSetFieldProd path g1 h1 b , g2 ~ h2 ) => GSetFieldProd ('PathLeft : path) (g1 :*: g2) (h1 :*: h2) b where gsetFieldProd (x :*: y) = (:*: y) . gsetFieldProd @path x -- fast path right instance {-# OVERLAPPING #-} ( GSetFieldProd path g2 h2 b ) => GSetFieldProd ('PathRight : path) (g1 :*: g2) (g1 :*: h2) b where gsetFieldProd (x :*: y) = (x :*:) . gsetFieldProd @path y -- slow path right instance ( GSetFieldProd path g2 h2 b , g1 ~ h1 ) => GSetFieldProd ('PathRight : path) (g1 :*: g2) (h1 :*: h2) b where gsetFieldProd (x :*: y) = (x :*:) . gsetFieldProd @path y instance ( r ~ b ) => GSetFieldProd '[] (M1 S m (Rec0 a)) (M1 S m (Rec0 b)) r where gsetFieldProd _ = M1 . K1 ---------------------------------------- -- Affine field class GAffineFieldImpl (repDefined :: Bool) (name :: Symbol) s t a b | name s -> a {- These hold morally, but we can't prove it. , name t -> b , name s b -> t , name t a -> s -} where gafieldImpl :: AffineTraversal s t a b instance ( Generic s , Generic t , path ~ GetFieldPaths s name (Rep s) , HasField name s a -- require the field to be in scope , Unless (AnyHasPath path) (TypeError ('Text "Type " ':<>: QuoteType s ':<>: 'Text " doesn't have a field named " ':<>: QuoteSymbol name)) , GAffineFieldSum path (Rep s) (Rep t) a b ) => GAffineFieldImpl 'True name s t a b where gafieldImpl = withAffineTraversal (atraversalVL (\point f s -> to <$> gafieldSum @path point f (from s))) (\match update -> atraversalVL $ \point f s -> either point (fmap (update s) . f) (match s)) {-# INLINE gafieldImpl #-} ---------------------------------------- class GAffineFieldSum (path :: PathTree Symbol) g h a b where gafieldSum :: AffineTraversalVL (g x) (h x) a b instance ( GAffineFieldSum path g h a b ) => GAffineFieldSum path (M1 D m g) (M1 D m h) a b where gafieldSum point f (M1 x) = M1 <$> gafieldSum @path point f x instance ( GAffineFieldSum path1 g1 h1 a b , GAffineFieldSum path2 g2 h2 a b ) => GAffineFieldSum ('PathTree path1 path2) (g1 :+: g2) (h1 :+: h2) a b where gafieldSum point f (L1 x) = L1 <$> gafieldSum @path1 point f x gafieldSum point f (R1 y) = R1 <$> gafieldSum @path2 point f y {-# INLINE gafieldSum #-} instance ( GAffineFieldMaybe epath g h a b ) => GAffineFieldSum ('PathLeaf epath) (M1 C m g) (M1 C m h) a b where gafieldSum point f (M1 x) = M1 <$> gafieldMaybe @epath point f x class GAffineFieldMaybe (epath :: Either Symbol [Path]) g h a b where gafieldMaybe :: AffineTraversalVL (g x) (h x) a b instance ( g ~ h ) => GAffineFieldMaybe ('Left name) g h a b where gafieldMaybe point _ g = point g instance ( GFieldProd prodPath g h a b ) => GAffineFieldMaybe ('Right prodPath) g h a b where gafieldMaybe _ f g = gfieldProd @prodPath f g ---------------------------------------- class GFieldProd (path :: [Path]) g h a b | path g -> a , path h -> b , path g b -> h , path h a -> g where gfieldProd :: LensVL (g x) (h x) a b -- fast path left instance {-# OVERLAPPING #-} ( GFieldProd path g1 h1 a b ) => GFieldProd ('PathLeft : path) (g1 :*: g2) (h1 :*: g2) a b where gfieldProd f (x :*: y) = (:*: y) <$> gfieldProd @path f x -- slow path left instance ( GFieldProd path g1 h1 a b , g2 ~ h2 ) => GFieldProd ('PathLeft : path) (g1 :*: g2) (h1 :*: h2) a b where gfieldProd f (x :*: y) = (:*: y) <$> gfieldProd @path f x -- fast path right instance {-# OVERLAPPING #-} ( GFieldProd path g2 h2 a b ) => GFieldProd ('PathRight : path) (g1 :*: g2) (g1 :*: h2) a b where gfieldProd f (x :*: y) = (x :*:) <$> gfieldProd @path f y -- slow path right instance ( GFieldProd path g2 h2 a b , g1 ~ h1 ) => GFieldProd ('PathRight : path) (g1 :*: g2) (h1 :*: h2) a b where gfieldProd f (x :*: y) = (x :*:) <$> gfieldProd @path f y instance ( r ~ a , s ~ b ) => GFieldProd '[] (M1 S m (Rec0 a)) (M1 S m (Rec0 b)) r s where gfieldProd f (M1 (K1 x)) = M1 . K1 <$> f x ---------------------------------------- -- Position class GPositionImpl (repDefined :: Bool) (n :: Nat) s t a b | n s -> a {- These hold morally, but we can't prove it. , n t -> b , n s b -> t , n t a -> s -} where gpositionImpl :: Lens s t a b instance ( Generic s , Generic t , path ~ If (n <=? 0) (TypeError ('Text "There is no 0th position")) (GetPositionPaths s n (Rep s)) , When (n <=? 0) (HideReps (Rep s) (Rep t)) , GPositionSum path (Rep s) (Rep t) a b ) => GPositionImpl 'True n s t a b where gpositionImpl = withLens (lensVL (\f s -> to <$> gpositionSum @path f (from s))) (\get set -> lensVL $ \f s -> set s <$> f (get s)) {-# INLINE gpositionImpl #-} ---------------------------------------- class GPositionSum (path :: PathTree (Nat, Nat)) g h a b | path g -> a , path h -> b , path g b -> h , path h a -> g where gpositionSum :: LensVL (g x) (h x) a b instance ( GPositionSum path g h a b ) => GPositionSum path (M1 D m g) (M1 D m h) a b where gpositionSum f (M1 x) = M1 <$> gpositionSum @path f x instance ( GPositionSum path1 g1 h1 a b , GPositionSum path2 g2 h2 a b ) => GPositionSum ('PathTree path1 path2) (g1 :+: g2) (h1 :+: h2) a b where gpositionSum f (L1 x) = L1 <$> gpositionSum @path1 f x gpositionSum f (R1 y) = R1 <$> gpositionSum @path2 f y {-# INLINE gpositionSum #-} instance ( path ~ GPositionPath con epath , When (IsLeft epath) (HideReps g h) , GFieldProd path g h a b ) => GPositionSum ('PathLeaf epath) (M1 C ('MetaCons con fix hs) g) (M1 C ('MetaCons con fix hs) h) a b where gpositionSum f (M1 x) = M1 <$> gfieldProd @path f x type family GPositionPath con (e :: Either (Nat, Nat) [Path]) :: [Path] where GPositionPath _ ('Right path) = path GPositionPath con ('Left '(n, k)) = TypeError ('Text "Data constructor " ':<>: QuoteSymbol con ':<>: 'Text " has " ':<>: ShowFieldNumber k ':<>: 'Text ", " ':<>: ToOrdinal n ':<>: 'Text " requested") type family ShowFieldNumber (k :: Nat) :: ErrorMessage where ShowFieldNumber 0 = 'Text "no fields" ShowFieldNumber 1 = 'Text "1 field" ShowFieldNumber k = 'ShowType k ':<>: 'Text " fields" ---------------------------------------- -- Constructor class GConstructorImpl (repDefined :: Bool) (name :: Symbol) s t a b | name s -> a {- These hold morally, but we can't prove it. , name t -> b , name s b -> t , name t a -> s -} where gconstructorImpl :: Prism s t a b instance ( Generic s , Generic t , epath ~ GetNamePath name (Rep s) '[] , path ~ FromRight (TypeError ('Text "Type " ':<>: QuoteType s ':<>: 'Text " doesn't have a constructor named " ':<>: QuoteSymbol name)) epath , When (IsLeft epath) (HideReps (Rep s) (Rep t)) , GConstructorSum path (Rep s) (Rep t) a b ) => GConstructorImpl 'True name s t a b where gconstructorImpl = withPrism (generic % gconstructorSum @path) prism {-# INLINE gconstructorImpl #-} ---------------------------------------- class GConstructorSum (path :: [Path]) g h a b | path g -> a , path h -> b , path g b -> h , path h a -> g where gconstructorSum :: Prism (g x) (h x) a b instance ( GConstructorSum path g h a b ) => GConstructorSum path (M1 D m g) (M1 D m h) a b where gconstructorSum = _M1 % gconstructorSum @path -- fast path left instance {-# OVERLAPPING #-} ( GConstructorSum path g1 h1 a b ) => GConstructorSum ('PathLeft : path) (g1 :+: g2) (h1 :+: g2) a b where gconstructorSum = _L1 % gconstructorSum @path -- slow path left instance ( GConstructorSum path g1 h1 a b , g2 ~ h2 ) => GConstructorSum ('PathLeft : path) (g1 :+: g2) (h1 :+: h2) a b where gconstructorSum = _L1 % gconstructorSum @path -- fast path right instance {-# OVERLAPPING #-} ( GConstructorSum path g2 h2 a b ) => GConstructorSum ('PathRight : path) (g1 :+: g2) (g1 :+: h2) a b where gconstructorSum = _R1 % gconstructorSum @path -- slow path right instance ( GConstructorSum path g2 h2 a b , g1 ~ h1 ) => GConstructorSum ('PathRight : path) (g1 :+: g2) (h1 :+: h2) a b where gconstructorSum = _R1 % gconstructorSum @path instance ( GConstructorTuple g h a b ) => GConstructorSum '[] (M1 C m g) (M1 C m h) a b where gconstructorSum = castOptic (_M1 % gconstructorTuple) class GConstructorTuple g h a b | g -> a , h -> b , g b -> h , h a -> g where gconstructorTuple :: Iso (g x) (h x) a b -- Fon uncluttering types in below instances a bit. type F m a = M1 S m (Rec0 a) instance {-# OVERLAPPABLE #-} ( Dysfunctional () () g h a b , TypeError ('Text "Generic based access supports constructors" ':$$: 'Text "containing up to 5 fields. Please generate" ':$$: 'Text "PrismS with Template Haskell if you need more.") ) => GConstructorTuple g h a b where gconstructorTuple = error "unreachable" instance ( a ~ () , b ~ () ) => GConstructorTuple U1 U1 a b where gconstructorTuple = _U1 {-# INLINE gconstructorTuple #-} instance ( r ~ a , s ~ b ) => GConstructorTuple (F m a) (F m b) r s where gconstructorTuple = coerced {-# INLINE gconstructorTuple #-} instance ( r ~ (a1, a2) , s ~ (b1, b2) ) => GConstructorTuple (F m1 a1 :*: F m2 a2) (F m1 b1 :*: F m2 b2) r s where gconstructorTuple = iso (\(M1 (K1 a1) :*: M1 (K1 a2)) -> (a1, a2)) (\(b1, b2) -> M1 (K1 b1) :*: M1 (K1 b2)) {-# INLINE gconstructorTuple #-} -- | Only for a derived balanced representation. instance ( r ~ (a1, a2, a3) , s ~ (b1, b2, b3) ) => GConstructorTuple (F m1 a1 :*: F m2 a2 :*: F m3 a3) (F m1 b1 :*: F m2 b2 :*: F m3 b3) r s where gconstructorTuple = iso (\(M1 (K1 a1) :*: M1 (K1 a2) :*: M1 (K1 a3)) -> (a1, a2, a3)) (\(b1, b2, b3) -> M1 (K1 b1) :*: M1 (K1 b2) :*: M1 (K1 b3)) {-# INLINE gconstructorTuple #-} -- | Only for a derived balanced representation. instance ( r ~ (a1, a2, a3, a4) , s ~ (b1, b2, b3, b4) ) => GConstructorTuple ((F m1 a1 :*: F m2 a2) :*: (F m3 a3 :*: F m4 a4)) ((F m1 b1 :*: F m2 b2) :*: (F m3 b3 :*: F m4 b4)) r s where gconstructorTuple = iso (\((M1 (K1 a1) :*: M1 (K1 a2)) :*: (M1 (K1 a3) :*: M1 (K1 a4))) -> (a1, a2, a3, a4)) (\(b1, b2, b3, b4) -> (M1 (K1 b1) :*: M1 (K1 b2)) :*: (M1 (K1 b3) :*: M1 (K1 b4))) {-# INLINE gconstructorTuple #-} -- | Only for a derived balanced representation. instance ( r ~ (a1, a2, a3, a4, a5) , s ~ (b1, b2, b3, b4, b5) ) => GConstructorTuple ((F m1 a1 :*: F m2 a2) :*: (F m3 a3 :*: F m4 a4 :*: F m5 a5)) ((F m1 b1 :*: F m2 b2) :*: (F m3 b3 :*: F m4 b4 :*: F m5 b5)) r s where gconstructorTuple = iso (\((M1 (K1 a1) :*: M1 (K1 a2)) :*: (M1 (K1 a3) :*: M1 (K1 a4) :*: M1 (K1 a5))) -> (a1, a2, a3, a4, a5)) (\(b1, b2, b3, b4, b5) -> (M1 (K1 b1) :*: M1 (K1 b2)) :*: (M1 (K1 b3) :*: M1 (K1 b4) :*: M1 (K1 b5))) {-# INLINE gconstructorTuple #-} ---------------------------------------- -- Types class GPlateImpl g a where gplateImpl :: TraversalVL' (g x) a instance GPlateImpl f a => GPlateImpl (M1 i c f) a where gplateImpl f (M1 x) = M1 <$> gplateImpl f x instance (GPlateImpl f a, GPlateImpl g a) => GPlateImpl (f :+: g) a where gplateImpl f (L1 x) = L1 <$> gplateImpl f x gplateImpl f (R1 x) = R1 <$> gplateImpl f x instance (GPlateImpl f a, GPlateImpl g a) => GPlateImpl (f :*: g) a where gplateImpl f (x :*: y) = (:*:) <$> gplateImpl f x <*> gplateImpl f y {-# INLINE gplateImpl #-} -- | Matching type. instance {-# OVERLAPPING #-} GPlateImpl (K1 i a) a where gplateImpl f (K1 a) = K1 <$> f a -- | Recurse into the inner type if it has a 'Generic' instance. instance GPlateInner (Defined (Rep b)) b a => GPlateImpl (K1 i b) a where gplateImpl f (K1 b) = K1 <$> gplateInner @(Defined (Rep b)) f b instance GPlateImpl U1 a where gplateImpl _ = pure instance GPlateImpl V1 a where gplateImpl _ = \case {} instance GPlateImpl (URec b) a where gplateImpl _ = pure class GPlateInner (repDefined :: Bool) s a where gplateInner :: TraversalVL' s a instance (Generic s, GPlateImpl (Rep s) a) => GPlateInner 'True s a where gplateInner f = fmap to . gplateImpl f . from instance {-# INCOHERENT #-} GPlateInner repNotDefined s a where gplateInner _ = pure -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Internal/Generic/0000755000000000000000000000000007346545000017453 5ustar0000000000000000optics-core-0.4.1.1/src/Optics/Internal/Generic/TypeLevel.hs0000644000000000000000000001222207346545000021717 0ustar0000000000000000{-# LANGUAGE DataKinds #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_HADDOCK not-home #-} -- | This module is intended for internal use only, and may change without -- warning in subsequent releases. module Optics.Internal.Generic.TypeLevel ( -- * Pathing PathTree(..) , Path(..) -- ** Names , GetFieldPaths , GetNamePath -- ** Positions , GetPositionPaths , GetPositionPath -- * Misc , HideReps , AnyHasPath , NoGenericError ) where import Data.Kind import Data.Type.Bool import Data.Type.Equality import GHC.Generics import GHC.TypeLits import Optics.Internal.Optic.TypeLevel -- | A map that allows reaching a specific field in a generic representation of -- a data type. Computed up front by generic optics for early error reporting -- and efficient data traversal. data PathTree e = PathTree (PathTree e) (PathTree e) | PathLeaf (Either e [Path]) data Path = PathLeft | PathRight ---------------------------------------- -- Paths to a field -- | Compute paths to a field with a specific name. type family GetFieldPaths s (name :: Symbol) g :: PathTree Symbol where GetFieldPaths s name (M1 D _ g) = GetFieldPaths s name g GetFieldPaths s name (g1 :+: g2) = 'PathTree (GetFieldPaths s name g1) (GetFieldPaths s name g2) GetFieldPaths s name (M1 C _ g) = 'PathLeaf (GetNamePath name g '[]) GetFieldPaths s name V1 = TypeError ('Text "Type " ':<>: QuoteType s ':<>: 'Text " has no data constructors") -- | Compute path to a constructor in a sum or a field in a product with a -- specific name. type family GetNamePath (name :: Symbol) g (acc :: [Path]) :: Either Symbol [Path] where GetNamePath name (M1 D _ g) acc = GetNamePath name g acc -- Find path to a constructor in a sum type. GetNamePath name (M1 C ('MetaCons name _ _) _) acc = 'Right (Reverse acc '[]) GetNamePath name (g1 :+: g2) acc = FirstRight (GetNamePath name g1 ('PathLeft : acc)) (GetNamePath name g2 ('PathRight : acc)) -- Find path to a field in a product type. GetNamePath name (M1 S ('MetaSel ('Just name) _ _ _) _) acc = 'Right (Reverse acc '[]) GetNamePath name (g1 :*: g2) acc = FirstRight (GetNamePath name g1 ('PathLeft : acc)) (GetNamePath name g2 ('PathRight : acc)) GetNamePath name _ _ = 'Left name ---------------------------------------- -- Paths to a position -- | Compute paths to a field at a specific position. type family GetPositionPaths s (pos :: Nat) g :: PathTree (Nat, Nat) where GetPositionPaths s pos (M1 D _ g) = GetPositionPaths s pos g GetPositionPaths s pos (g1 :+: g2) = 'PathTree (GetPositionPaths s pos g1) (GetPositionPaths s pos g2) GetPositionPaths s pos (M1 C _ g) = 'PathLeaf (GetPositionPath pos g 0 '[]) GetPositionPaths s pos V1 = TypeError ('Text "Type " ':<>: QuoteType s ':<>: 'Text " has no data constructors") -- | Compute path to a constructor in a sum or a field in a product at a -- specific position. type family GetPositionPath (pos :: Nat) g (k :: Nat) (acc :: [Path]) :: Either (Nat, Nat) [Path] where GetPositionPath pos (M1 D _ g) k acc = GetPositionPath pos g k acc -- Find field at a position in a sum type. GetPositionPath pos (M1 C _ _) k acc = If (pos == k + 1) ('Right (Reverse acc '[])) ('Left '(pos, k + 1)) GetPositionPath pos (g1 :+: g2) k acc = ContinueWhenLeft (GetPositionPath pos g1 k ('PathLeft : acc)) g2 acc -- Find field at a position in a product type. GetPositionPath pos (M1 S _ _) k acc = If (pos == k + 1) ('Right (Reverse acc '[])) ('Left '(pos, k + 1)) GetPositionPath pos (g1 :*: g2) k acc = ContinueWhenLeft (GetPositionPath pos g1 k ('PathLeft : acc)) g2 acc -- The second element is the number of fields in the data constructor. GetPositionPath pos _ k _ = 'Left '(pos, k) -- | If the left branch had the position we're looking for, return it. Otherwise -- continue with the right branch. type family ContinueWhenLeft (r :: Either (Nat, Nat) [Path]) g acc :: Either (Nat, Nat) [Path] where ContinueWhenLeft ('Right path) _ _ = 'Right path ContinueWhenLeft ('Left '(pos, k)) g acc = GetPositionPath pos g k ('PathRight : acc) ---------------------------------------- -- Misc data Void1 a -- | Generate bogus equality constraints that attempt to unify generic -- representations with this type in case there is an error such as missing -- field, constructor etc. so these huge types don't leak into error messages. type family HideReps (g :: Type -> Type) (h :: Type -> Type) :: Constraint where HideReps g h = (g ~ Void1, h ~ Void1) -- | Check if any leaf in the tree has a '[Path]'. type family AnyHasPath (path :: PathTree e) :: Bool where AnyHasPath ('PathTree path1 path2) = AnyHasPath path1 || AnyHasPath path2 AnyHasPath ('PathLeaf ('Right _)) = 'True AnyHasPath ('PathLeaf ('Left _ )) = 'False type family NoGenericError t where NoGenericError t = TypeError ('Text "Type " ':<>: QuoteType t ':<>: 'Text " doesn't have a Generic instance") optics-core-0.4.1.1/src/Optics/Internal/Indexed.hs0000644000000000000000000001002307346545000020007 0ustar0000000000000000{-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeInType #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_HADDOCK not-home #-} -- | Internal implementation details of indexed optics. -- -- This module is intended for internal use only, and may change without warning -- in subsequent releases. module Optics.Internal.Indexed where import Data.Kind (Type) import GHC.TypeLits import Data.Profunctor.Indexed import Optics.Internal.Optic -- | Show useful error message when a function expects optics without indices. class is ~ NoIx => AcceptsEmptyIndices (f :: Symbol) (is :: IxList) instance ( TypeError ('Text "‘" ':<>: 'Text f ':<>: 'Text "’ accepts only optics with no indices") , (x ': xs) ~ NoIx ) => AcceptsEmptyIndices f (x ': xs) instance AcceptsEmptyIndices f '[] -- | Check whether a list of indices is not empty and generate sensible error -- message if it's not. class NonEmptyIndices (is :: IxList) instance ( TypeError ('Text "Indexed optic is expected") ) => NonEmptyIndices '[] instance NonEmptyIndices (x ': xs) -- | Generate sensible error messages in case a user tries to pass either an -- unindexed optic or indexed optic with unflattened indices where indexed optic -- with a single index is expected. class is ~ '[i] => HasSingleIndex (is :: IxList) (i :: Type) instance HasSingleIndex '[i] i instance ( TypeError ('Text "Indexed optic is expected") , '[] ~ '[i] ) => HasSingleIndex '[] i instance ( TypeError ('Text "Use (<%>) or icompose to combine indices of type " ':<>: ShowTypes is) , is ~ '[i1, i2] , is ~ '[i] ) => HasSingleIndex '[i1, i2] i instance ( TypeError ('Text "Use icompose3 to combine indices of type " ':<>: ShowTypes is) , is ~ '[i1, i2, i3] , is ~ '[i] ) => HasSingleIndex [i1, i2, i3] i instance ( TypeError ('Text "Use icompose4 to combine indices of type " ':<>: ShowTypes is) , is ~ '[i1, i2, i3, i4] , is ~ '[i] ) => HasSingleIndex '[i1, i2, i3, i4] i instance ( TypeError ('Text "Use icompose5 to flatten indices of type " ':<>: ShowTypes is) , is ~ '[i1, i2, i3, i4, i5] , is ~ '[i] ) => HasSingleIndex '[i1, i2, i3, i4, i5] i instance ( TypeError ('Text "Use icomposeN to flatten indices of type " ':<>: ShowTypes is) , is ~ (i1 ': i2 ': i3 ': i4 ': i5 ': i6 : is') , is ~ '[i] ) => HasSingleIndex (i1 ': i2 ': i3 ': i4 ': i5 ': i6 ': is') i ---------------------------------------- -- Helpers for HasSingleIndex type family ShowTypes (types :: [Type]) :: ErrorMessage where ShowTypes '[i] = QuoteType i ShowTypes '[i, j] = QuoteType i ':<>: 'Text " and " ':<>: QuoteType j ShowTypes (i ': is) = QuoteType i ':<>: 'Text ", " ':<>: ShowTypes is ---------------------------------------- data IntT f a = IntT {-# UNPACK #-} !Int (f a) unIntT :: IntT f a -> f a unIntT (IntT _ fa) = fa newtype Indexing f a = Indexing { runIndexing :: Int -> IntT f a } instance Functor f => Functor (Indexing f) where fmap f (Indexing m) = Indexing $ \i -> case m i of IntT j x -> IntT j (fmap f x) instance Applicative f => Applicative (Indexing f) where pure x = Indexing $ \i -> IntT i (pure x) Indexing mf <*> Indexing ma = Indexing $ \i -> case mf i of IntT j ff -> case ma j of IntT k fa -> IntT k (ff <*> fa) -- | Index a traversal by position of visited elements. indexing :: ((a -> Indexing f b) -> s -> Indexing f t) -> ((Int -> a -> f b) -> s -> f t) indexing l iafb s = unIntT $ runIndexing (l (\a -> Indexing (\i -> IntT (i + 1) (iafb i a))) s) 0 ---------------------------------------- -- | Construct a conjoined indexed optic that provides a separate code path when -- used without indices. Useful for defining indexed optics that are as -- efficient as their unindexed equivalents when used without indices. -- -- /Note:/ @'conjoined' f g@ is well-defined if and only if @f ≡ -- 'Optics.Indexed.Core.noIx' g@. conjoined :: is `HasSingleIndex` i => Optic k NoIx s t a b -> Optic k is s t a b -> Optic k is s t a b conjoined (Optic f) (Optic g) = Optic (conjoined__ f g) optics-core-0.4.1.1/src/Optics/Internal/Indexed/0000755000000000000000000000000007346545000017457 5ustar0000000000000000optics-core-0.4.1.1/src/Optics/Internal/Indexed/Classes.hs0000644000000000000000000000100007346545000021377 0ustar0000000000000000{-# LANGUAGE CPP #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_HADDOCK not-home #-} -- | Internal implementation details of indexed optics. -- -- This module is intended for internal use only, and may change without warning -- in subsequent releases. module Optics.Internal.Indexed.Classes ( module Data.Functor.WithIndex, module Data.Foldable.WithIndex, module Data.Traversable.WithIndex, ) where import Data.Functor.WithIndex import Data.Foldable.WithIndex import Data.Traversable.WithIndex optics-core-0.4.1.1/src/Optics/Internal/IxFold.hs0000644000000000000000000000247307346545000017626 0ustar0000000000000000{-# OPTIONS_HADDOCK not-home #-} -- | Internal implementation details of indexed folds. -- -- This module is intended for internal use only, and may change without warning -- in subsequent releases. module Optics.Internal.IxFold where import Data.Functor import Data.Foldable import Data.Profunctor.Indexed import Optics.Internal.Bi import Optics.Internal.Indexed.Classes import Optics.Internal.Optic import Optics.Internal.Fold -- | Internal implementation of 'Optics.IxFold.ifoldVL'. ifoldVL__ :: (Bicontravariant p, Traversing p) => (forall f. Applicative f => (i -> a -> f u) -> s -> f v) -> Optic__ p j (i -> j) s t a b ifoldVL__ f = rphantom . iwander f . rphantom {-# INLINE ifoldVL__ #-} -- | Internal implementation of 'Optics.IxFold.ifolded'. ifolded__ :: (Bicontravariant p, Traversing p, FoldableWithIndex i f) => Optic__ p j (i -> j) (f a) t a b ifolded__ = conjoined__ (foldVL__ traverse_) (ifoldVL__ itraverse_) {-# INLINE ifolded__ #-} -- | Internal implementation of 'Optics.IxFold.ifoldring'. ifoldring__ :: (Bicontravariant p, Traversing p) => (forall f. Applicative f => (i -> a -> f u -> f u) -> f v -> s -> f w) -> Optic__ p j (i -> j) s t a b ifoldring__ fr = ifoldVL__ $ \f -> void . fr (\i a -> (f i a *>)) (pure v) where v = error "ifoldring__: value used" {-# INLINE ifoldring__ #-} optics-core-0.4.1.1/src/Optics/Internal/IxSetter.hs0000644000000000000000000000106607346545000020205 0ustar0000000000000000{-# OPTIONS_HADDOCK not-home #-} -- | Internal implementation details of indexed setters. -- -- This module is intended for internal use only, and may change without warning -- in subsequent releases. module Optics.Internal.IxSetter where import Data.Profunctor.Indexed import Optics.Internal.Indexed.Classes import Optics.Internal.Optic -- | Internal implementation of 'Optics.IxSetter.imapped'. imapped__ :: (Mapping p, FunctorWithIndex i f) => Optic__ p j (i -> j) (f a) (f b) a b imapped__ = conjoined__ (roam fmap) (iroam imap) {-# INLINE imapped__ #-} optics-core-0.4.1.1/src/Optics/Internal/IxTraversal.hs0000644000000000000000000000361307346545000020702 0ustar0000000000000000{-# OPTIONS_HADDOCK not-home #-} -- | Internal implementation details of indexed traversals. -- -- This module is intended for internal use only, and may change without warning -- in subsequent releases. module Optics.Internal.IxTraversal where import Data.Profunctor.Indexed import Optics.Internal.Fold import Optics.Internal.Indexed.Classes import Optics.Internal.IxFold import Optics.Internal.IxSetter import Optics.Internal.Optic import Optics.Internal.Setter -- | Internal implementation of 'Optics.IxTraversal.itraversed'. itraversed__ :: (Traversing p, TraversableWithIndex i f) => Optic__ p j (i -> j) (f a) (f b) a b itraversed__ = conjoined__ (wander traverse) (iwander itraverse) {-# INLINE [0] itraversed__ #-} -- Because itraversed__ inlines late, GHC needs rewrite rules for all cases in -- order to generate optimal code for each of them. The ones that rewrite -- traversal into a traversal correspond to an early inline. {-# RULES "itraversed__ -> wander traverse" forall (o :: Star g j a b). itraversed__ o = wander traverse (reStar o) :: TraversableWithIndex i f => Star g (i -> j) (f a) (f b) "itraversed__ -> folded__" forall (o :: Forget r j a b). itraversed__ o = folded__ (reForget o) :: FoldableWithIndex i f => Forget r (i -> j) (f a) (f b) "itraversed__ -> mapped__" forall (o :: FunArrow j a b). itraversed__ o = mapped__ (reFunArrow o) :: FunctorWithIndex i f => FunArrow (i -> j) (f a) (f b) "itraversed__ -> itraverse" forall (o :: IxStar g j a b). itraversed__ o = iwander itraverse o :: TraversableWithIndex i f => IxStar g (i -> j) (f a) (f b) "itraversed__ -> ifolded__" forall (o :: IxForget r j a b). itraversed__ o = ifolded__ o :: FoldableWithIndex i f => IxForget r (i -> j) (f a) (f b) "itraversed__ -> imapped__" forall (o :: IxFunArrow j a b). itraversed__ o = imapped__ o :: FunctorWithIndex i f => IxFunArrow (i -> j) (f a) (f b) #-} optics-core-0.4.1.1/src/Optics/Internal/Magic.hs0000644000000000000000000000271507346545000017460 0ustar0000000000000000{-# LANGUAGE DataKinds #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_HADDOCK not-home #-} -- | This module is intended for internal use only, and may change without -- warning in subsequent releases. module Optics.Internal.Magic where -- | How about a magic trick? I'm gonna make the coverage condition disappear. class Dysfunctional field k s t a b | field s -> k t a b , field t -> k s a b -- | Show something useful when type inference goes into a loop and stops with -- "reduction stack overflow" message (sometimes happens when trying to infer -- types of local bindings when monomorphism restriction is enabled). instance ( TypeInferenceLoop "Type inference for the local binding failed. Write the type" "signature yourself or disable monomorphism restriction with" "NoMonomorphismRestriction LANGUAGE pragma so GHC infers it." field k s t a b ) => Dysfunctional field k s t a b class TypeInferenceLoop msg1 msg2 msg3 field k s t a b | field s -> k t a b , field t -> k s a b -- | Including the instance head in the context lifts the coverage condition for -- all type variables in the instance. A dirty trick until we have -- https://github.com/ghc-proposals/ghc-proposals/pull/374 and can do it -- properly. instance ( TypeInferenceLoop msg1 msg2 msg3 field k s t a b ) => TypeInferenceLoop msg1 msg2 msg3 field k s t a b optics-core-0.4.1.1/src/Optics/Internal/Optic.hs0000644000000000000000000001207407346545000017515 0ustar0000000000000000{-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeInType #-} {-# OPTIONS_HADDOCK not-home #-} -- | Core optic types and subtyping machinery. -- -- This module contains the core 'Optic' types, and the underlying -- machinery that we need in order to implement the subtyping between -- various different flavours of optics. -- -- The composition operator for optics is also defined here. -- -- This module is intended for internal use only, and may change without -- warning in subsequent releases. -- module Optics.Internal.Optic ( Optic(..) , Optic' , Optic_ , Optic__ , getOptic , castOptic , (%) , (%%) , (%&) -- * Re-exports , module Optics.Internal.Optic.Subtyping , module Optics.Internal.Optic.Types , module Optics.Internal.Optic.TypeLevel ) where import Data.Function ((&)) import Data.Profunctor.Indexed import Optics.Internal.Optic.Subtyping import Optics.Internal.Optic.TypeLevel import Optics.Internal.Optic.Types -- | Wrapper newtype for the whole family of optics. -- -- The first parameter @k@ identifies the particular optic kind (e.g. 'A_Lens' -- or 'A_Traversal'). -- -- The parameter @is@ is a list of types available as indices. This will -- typically be 'NoIx' for unindexed optics, or 'WithIx' for optics with a -- single index. See the "Indexed optics" section of the overview documentation -- in the @Optics@ module of the main @optics@ package for more details. -- -- The parameters @s@ and @t@ represent the "big" structure, -- whereas @a@ and @b@ represent the "small" structure. -- newtype Optic (k :: OpticKind) (is :: IxList) s t a b = Optic (forall p i. Profunctor p => Optic_ k p i (Curry is i) s t a b) -- | Strip the newtype wrapper off. getOptic :: Profunctor p => Optic k is s t a b -> Optic_ k p i (Curry is i) s t a b -- Note: This is not part of the definition of 'Optic' because it needs to be -- marked INLINE for GHC to optimize away profunctor classes when profiling. -- See https://github.com/well-typed/optics/issues/324 for more details. getOptic (Optic o) = o {-# INLINE getOptic #-} -- | Common special case of 'Optic' where source and target types are equal. -- -- Here, we need only one "big" and one "small" type. For lenses, this -- means that in the restricted form we cannot do type-changing updates. -- type Optic' k is s a = Optic k is s s a a -- | Type representing the various kinds of optics. -- -- The tag parameter @k@ is translated into constraints on @p@ -- via the type family 'Constraints'. -- type Optic_ k p i j s t a b = Constraints k p => Optic__ p i j s t a b -- | Optic internally as a profunctor transformation. type Optic__ p i j s t a b = p i a b -> p j s t -- | Explicit cast from one optic flavour to another. -- -- The resulting optic kind is given in the first type argument, so you can use -- TypeApplications to set it. For example -- -- @ -- 'castOptic' @'A_Lens' o -- @ -- -- turns @o@ into a 'Optics.Lens.Lens'. -- -- This is the identity function, modulo some constraint jiggery-pokery. -- castOptic :: forall destKind srcKind is s t a b . Is srcKind destKind => Optic srcKind is s t a b -> Optic destKind is s t a b castOptic (Optic o) = Optic (cast o) where cast :: forall p i . Optic_ srcKind p i (Curry is i) s t a b -> Optic_ destKind p i (Curry is i) s t a b cast x = implies @srcKind @destKind @p x {-# INLINE castOptic #-} -- | Compose two optics of compatible flavours. -- -- Returns an optic of the appropriate supertype. If either or both optics are -- indexed, the composition preserves all the indices. -- infixl 9 % (%) :: forall k l m is js ks s t u v a b. (JoinKinds k l m, AppendIndices is js ks) => Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b Optic k % Optic l = Optic m where km :: forall p i. Profunctor p => Optic_ m p i (Curry is i) s t u v km = joinKinds @k @l @m @p k lm :: forall p i. Profunctor p => Optic_ m p i (Curry js i) u v a b lm = joinKinds @k @l @m @p l m :: forall p i. (Profunctor p, Constraints m p) => Optic__ p i (Curry ks i) s t a b m | IxEq <- appendIndices @is @js @ks @i = km . lm {-# INLINE (%) #-} -- | Compose two optics of the same flavour. -- -- Normally you can simply use ('%') instead, but this may be useful to help -- type inference if the type of one of the optics is otherwise -- under-constrained. infixl 9 %% (%%) :: forall k is js ks s t u v a b. AppendIndices is js ks => Optic k is s t u v -> Optic k js u v a b -> Optic k ks s t a b Optic o %% Optic o' = Optic oo where oo :: forall p i. (Profunctor p, Constraints k p) => Optic__ p i (Curry ks i) s t a b oo | IxEq <- appendIndices @is @js @ks @i = o . o' {-# INLINE (%%) #-} -- | Flipped function application, specialised to optics and binding tightly. -- -- Useful for post-composing optics transformations: -- -- >>> toListOf (ifolded %& ifiltered (\i s -> length s <= i)) ["", "a","abc"] -- ["","a"] -- infixl 9 %& (%&) :: Optic k is s t a b -> (Optic k is s t a b -> Optic l js s' t' a' b') -> Optic l js s' t' a' b' (%&) = (&) {-# INLINE (%&) #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Internal/Optic/0000755000000000000000000000000007346545000017155 5ustar0000000000000000optics-core-0.4.1.1/src/Optics/Internal/Optic/Subtyping.hs0000644000000000000000000005234207346545000021503 0ustar0000000000000000{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeInType #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_HADDOCK not-home #-} -- | Instances to implement the subtyping hierarchy between optics. -- -- This module is intended for internal use only, and may change without warning -- in subsequent releases. module Optics.Internal.Optic.Subtyping where import GHC.TypeLits (ErrorMessage(..), TypeError) import Optics.Internal.Optic.TypeLevel import Optics.Internal.Optic.Types -- | Subtyping relationship between kinds of optics. -- -- An instance of @'Is' k l@ means that any @'Optics.Optic.Optic' k@ can be used -- as an @'Optics.Optic.Optic' l@. For example, we have an @'Is' 'A_Lens' -- 'A_Traversal'@ instance, but not @'Is' 'A_Traversal' 'A_Lens'@. -- -- This class needs instances for all possible combinations of tags. -- class Is k l where -- | Witness of the subtyping relationship. implies :: (Constraints k p => r) -> (Constraints l p => r) -- | Every kind of optic can be used as itself. instance Is k k where implies r = r -- | Overlappable instance for a custom type error. instance {-# OVERLAPPABLE #-} TypeError ('ShowType k ':<>: 'Text " cannot be used as " ':<>: 'ShowType l ':$$: 'Text "Perhaps you meant one of these:" ':$$: ShowEliminations (EliminationForms k) ) => Is k l where implies _ = error "unreachable" type family EliminationForms (k :: OpticKind) where EliminationForms An_AffineFold = AffineFoldEliminations EliminationForms An_AffineTraversal = AffineTraversalEliminations EliminationForms A_Fold = FoldEliminations EliminationForms A_Getter = GetterEliminations EliminationForms An_Iso = IsoEliminations EliminationForms A_Lens = LensEliminations EliminationForms A_Prism = PrismEliminations EliminationForms A_ReversedLens = ReviewEliminations EliminationForms A_ReversedPrism = GetterEliminations EliminationForms A_Review = ReviewEliminations EliminationForms A_Setter = SetterEliminations EliminationForms A_Traversal = TraversalEliminations type AffineFoldEliminations = '( '[ '("preview", "Optics.AffineFold") ] , '[ "(^?)" ]) type AffineTraversalEliminations = AffineFoldEliminations `AppendEliminations` SetterEliminations type FoldEliminations = '( '[ '("traverseOf_", "Optics.Fold") , '("foldMapOf", "Optics.Fold") , '("toListOf", "Optics.Fold") ] , '[ "(^..)" ]) type GetterEliminations = '( '[ '("view", "Optics.Getter") ] , '[ "(^.)" ]) type IsoEliminations = GetterEliminations `AppendEliminations` ReviewEliminations `AppendEliminations` SetterEliminations type LensEliminations = GetterEliminations `AppendEliminations` SetterEliminations type PrismEliminations = AffineFoldEliminations `AppendEliminations` ReviewEliminations `AppendEliminations` SetterEliminations type ReviewEliminations = '( '[ '("review", "Optics.Review") ] , '[ "(#)" ]) type SetterEliminations = '( '[ '("over", "Optics.Setter") , '("set", "Optics.Setter") ] , '[ "(%~)", "(.~)" ]) type TraversalEliminations = '( '[ '("traverseOf", "Optics.Traversal") ] , '[]) `AppendEliminations` FoldEliminations `AppendEliminations` SetterEliminations ---------------------------------------- -- BEGIN GENERATED CONTENT -- An_Iso instance Is An_Iso A_ReversedLens where implies r = r instance Is An_Iso A_ReversedPrism where implies r = r instance Is An_Iso A_Prism where implies r = r instance Is An_Iso A_Review where implies r = r instance Is An_Iso A_Lens where implies r = r instance Is An_Iso A_Getter where implies r = r instance Is An_Iso An_AffineTraversal where implies r = r instance Is An_Iso An_AffineFold where implies r = r instance Is An_Iso A_Traversal where implies r = r instance Is An_Iso A_Fold where implies r = r instance Is An_Iso A_Setter where implies r = r -- A_ReversedLens instance Is A_ReversedLens A_Review where implies r = r -- A_ReversedPrism instance Is A_ReversedPrism A_Getter where implies r = r instance Is A_ReversedPrism An_AffineFold where implies r = r instance Is A_ReversedPrism A_Fold where implies r = r -- A_Prism instance Is A_Prism A_Review where implies r = r instance Is A_Prism An_AffineTraversal where implies r = r instance Is A_Prism An_AffineFold where implies r = r instance Is A_Prism A_Traversal where implies r = r instance Is A_Prism A_Fold where implies r = r instance Is A_Prism A_Setter where implies r = r -- A_Lens instance Is A_Lens A_Getter where implies r = r instance Is A_Lens An_AffineTraversal where implies r = r instance Is A_Lens An_AffineFold where implies r = r instance Is A_Lens A_Traversal where implies r = r instance Is A_Lens A_Fold where implies r = r instance Is A_Lens A_Setter where implies r = r -- A_Getter instance Is A_Getter An_AffineFold where implies r = r instance Is A_Getter A_Fold where implies r = r -- An_AffineTraversal instance Is An_AffineTraversal An_AffineFold where implies r = r instance Is An_AffineTraversal A_Traversal where implies r = r instance Is An_AffineTraversal A_Fold where implies r = r instance Is An_AffineTraversal A_Setter where implies r = r -- An_AffineFold instance Is An_AffineFold A_Fold where implies r = r -- A_Traversal instance Is A_Traversal A_Fold where implies r = r instance Is A_Traversal A_Setter where implies r = r -- END GENERATED CONTENT ---------------------------------------- -- | Computes the least upper bound of two optics kinds. -- -- In presence of a @JoinKinds k l m@ constraint @Optic m@ represents the least -- upper bound of an @Optic k@ and an @Optic l@. This means in particular that -- composition of an @Optic k@ and an @Optic k@ will yield an @Optic m@. -- -- @since 0.4 -- class JoinKinds k l m | k l -> m where joinKinds :: ((Constraints k p, Constraints l p) => r) -> (Constraints m p => r) -- BEGIN GENERATED CONTENT -- An_Iso ----- instance k ~ An_Iso => JoinKinds An_Iso An_Iso k where joinKinds r = r instance k ~ A_ReversedLens => JoinKinds An_Iso A_ReversedLens k where joinKinds r = r instance k ~ A_ReversedPrism => JoinKinds An_Iso A_ReversedPrism k where joinKinds r = r instance k ~ A_Prism => JoinKinds An_Iso A_Prism k where joinKinds r = r instance k ~ A_Review => JoinKinds An_Iso A_Review k where joinKinds r = r instance k ~ A_Lens => JoinKinds An_Iso A_Lens k where joinKinds r = r instance k ~ A_Getter => JoinKinds An_Iso A_Getter k where joinKinds r = r instance k ~ An_AffineTraversal => JoinKinds An_Iso An_AffineTraversal k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds An_Iso An_AffineFold k where joinKinds r = r instance k ~ A_Traversal => JoinKinds An_Iso A_Traversal k where joinKinds r = r instance k ~ A_Fold => JoinKinds An_Iso A_Fold k where joinKinds r = r instance k ~ A_Setter => JoinKinds An_Iso A_Setter k where joinKinds r = r -- A_ReversedLens ----- instance k ~ A_ReversedLens => JoinKinds A_ReversedLens A_ReversedLens k where joinKinds r = r instance k ~ A_ReversedLens => JoinKinds A_ReversedLens An_Iso k where joinKinds r = r -- no JoinKinds A_ReversedLens A_ReversedPrism instance k ~ A_Review => JoinKinds A_ReversedLens A_Prism k where joinKinds r = r instance k ~ A_Review => JoinKinds A_ReversedLens A_Review k where joinKinds r = r -- no JoinKinds A_ReversedLens A_Lens -- no JoinKinds A_ReversedLens A_Getter -- no JoinKinds A_ReversedLens An_AffineTraversal -- no JoinKinds A_ReversedLens An_AffineFold -- no JoinKinds A_ReversedLens A_Traversal -- no JoinKinds A_ReversedLens A_Fold -- no JoinKinds A_ReversedLens A_Setter -- A_ReversedPrism ----- instance k ~ A_ReversedPrism => JoinKinds A_ReversedPrism A_ReversedPrism k where joinKinds r = r instance k ~ A_ReversedPrism => JoinKinds A_ReversedPrism An_Iso k where joinKinds r = r -- no JoinKinds A_ReversedPrism A_ReversedLens instance k ~ An_AffineFold => JoinKinds A_ReversedPrism A_Prism k where joinKinds r = r -- no JoinKinds A_ReversedPrism A_Review instance k ~ A_Getter => JoinKinds A_ReversedPrism A_Lens k where joinKinds r = r instance k ~ A_Getter => JoinKinds A_ReversedPrism A_Getter k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds A_ReversedPrism An_AffineTraversal k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds A_ReversedPrism An_AffineFold k where joinKinds r = r instance k ~ A_Fold => JoinKinds A_ReversedPrism A_Traversal k where joinKinds r = r instance k ~ A_Fold => JoinKinds A_ReversedPrism A_Fold k where joinKinds r = r -- no JoinKinds A_ReversedPrism A_Setter -- A_Prism ----- instance k ~ A_Prism => JoinKinds A_Prism A_Prism k where joinKinds r = r instance k ~ A_Prism => JoinKinds A_Prism An_Iso k where joinKinds r = r instance k ~ A_Review => JoinKinds A_Prism A_ReversedLens k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds A_Prism A_ReversedPrism k where joinKinds r = r instance k ~ A_Review => JoinKinds A_Prism A_Review k where joinKinds r = r instance k ~ An_AffineTraversal => JoinKinds A_Prism A_Lens k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds A_Prism A_Getter k where joinKinds r = r instance k ~ An_AffineTraversal => JoinKinds A_Prism An_AffineTraversal k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds A_Prism An_AffineFold k where joinKinds r = r instance k ~ A_Traversal => JoinKinds A_Prism A_Traversal k where joinKinds r = r instance k ~ A_Fold => JoinKinds A_Prism A_Fold k where joinKinds r = r instance k ~ A_Setter => JoinKinds A_Prism A_Setter k where joinKinds r = r -- A_Review ----- instance k ~ A_Review => JoinKinds A_Review A_Review k where joinKinds r = r instance k ~ A_Review => JoinKinds A_Review An_Iso k where joinKinds r = r instance k ~ A_Review => JoinKinds A_Review A_ReversedLens k where joinKinds r = r -- no JoinKinds A_Review A_ReversedPrism instance k ~ A_Review => JoinKinds A_Review A_Prism k where joinKinds r = r -- no JoinKinds A_Review A_Lens -- no JoinKinds A_Review A_Getter -- no JoinKinds A_Review An_AffineTraversal -- no JoinKinds A_Review An_AffineFold -- no JoinKinds A_Review A_Traversal -- no JoinKinds A_Review A_Fold -- no JoinKinds A_Review A_Setter -- A_Lens ----- instance k ~ A_Lens => JoinKinds A_Lens A_Lens k where joinKinds r = r instance k ~ A_Lens => JoinKinds A_Lens An_Iso k where joinKinds r = r -- no JoinKinds A_Lens A_ReversedLens instance k ~ A_Getter => JoinKinds A_Lens A_ReversedPrism k where joinKinds r = r instance k ~ An_AffineTraversal => JoinKinds A_Lens A_Prism k where joinKinds r = r -- no JoinKinds A_Lens A_Review instance k ~ A_Getter => JoinKinds A_Lens A_Getter k where joinKinds r = r instance k ~ An_AffineTraversal => JoinKinds A_Lens An_AffineTraversal k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds A_Lens An_AffineFold k where joinKinds r = r instance k ~ A_Traversal => JoinKinds A_Lens A_Traversal k where joinKinds r = r instance k ~ A_Fold => JoinKinds A_Lens A_Fold k where joinKinds r = r instance k ~ A_Setter => JoinKinds A_Lens A_Setter k where joinKinds r = r -- A_Getter ----- instance k ~ A_Getter => JoinKinds A_Getter A_Getter k where joinKinds r = r instance k ~ A_Getter => JoinKinds A_Getter An_Iso k where joinKinds r = r -- no JoinKinds A_Getter A_ReversedLens instance k ~ A_Getter => JoinKinds A_Getter A_ReversedPrism k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds A_Getter A_Prism k where joinKinds r = r -- no JoinKinds A_Getter A_Review instance k ~ A_Getter => JoinKinds A_Getter A_Lens k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds A_Getter An_AffineTraversal k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds A_Getter An_AffineFold k where joinKinds r = r instance k ~ A_Fold => JoinKinds A_Getter A_Traversal k where joinKinds r = r instance k ~ A_Fold => JoinKinds A_Getter A_Fold k where joinKinds r = r -- no JoinKinds A_Getter A_Setter -- An_AffineTraversal ----- instance k ~ An_AffineTraversal => JoinKinds An_AffineTraversal An_AffineTraversal k where joinKinds r = r instance k ~ An_AffineTraversal => JoinKinds An_AffineTraversal An_Iso k where joinKinds r = r -- no JoinKinds An_AffineTraversal A_ReversedLens instance k ~ An_AffineFold => JoinKinds An_AffineTraversal A_ReversedPrism k where joinKinds r = r instance k ~ An_AffineTraversal => JoinKinds An_AffineTraversal A_Prism k where joinKinds r = r -- no JoinKinds An_AffineTraversal A_Review instance k ~ An_AffineTraversal => JoinKinds An_AffineTraversal A_Lens k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds An_AffineTraversal A_Getter k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds An_AffineTraversal An_AffineFold k where joinKinds r = r instance k ~ A_Traversal => JoinKinds An_AffineTraversal A_Traversal k where joinKinds r = r instance k ~ A_Fold => JoinKinds An_AffineTraversal A_Fold k where joinKinds r = r instance k ~ A_Setter => JoinKinds An_AffineTraversal A_Setter k where joinKinds r = r -- An_AffineFold ----- instance k ~ An_AffineFold => JoinKinds An_AffineFold An_AffineFold k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds An_AffineFold An_Iso k where joinKinds r = r -- no JoinKinds An_AffineFold A_ReversedLens instance k ~ An_AffineFold => JoinKinds An_AffineFold A_ReversedPrism k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds An_AffineFold A_Prism k where joinKinds r = r -- no JoinKinds An_AffineFold A_Review instance k ~ An_AffineFold => JoinKinds An_AffineFold A_Lens k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds An_AffineFold A_Getter k where joinKinds r = r instance k ~ An_AffineFold => JoinKinds An_AffineFold An_AffineTraversal k where joinKinds r = r instance k ~ A_Fold => JoinKinds An_AffineFold A_Traversal k where joinKinds r = r instance k ~ A_Fold => JoinKinds An_AffineFold A_Fold k where joinKinds r = r -- no JoinKinds An_AffineFold A_Setter -- A_Traversal ----- instance k ~ A_Traversal => JoinKinds A_Traversal A_Traversal k where joinKinds r = r instance k ~ A_Traversal => JoinKinds A_Traversal An_Iso k where joinKinds r = r -- no JoinKinds A_Traversal A_ReversedLens instance k ~ A_Fold => JoinKinds A_Traversal A_ReversedPrism k where joinKinds r = r instance k ~ A_Traversal => JoinKinds A_Traversal A_Prism k where joinKinds r = r -- no JoinKinds A_Traversal A_Review instance k ~ A_Traversal => JoinKinds A_Traversal A_Lens k where joinKinds r = r instance k ~ A_Fold => JoinKinds A_Traversal A_Getter k where joinKinds r = r instance k ~ A_Traversal => JoinKinds A_Traversal An_AffineTraversal k where joinKinds r = r instance k ~ A_Fold => JoinKinds A_Traversal An_AffineFold k where joinKinds r = r instance k ~ A_Fold => JoinKinds A_Traversal A_Fold k where joinKinds r = r instance k ~ A_Setter => JoinKinds A_Traversal A_Setter k where joinKinds r = r -- A_Fold ----- instance k ~ A_Fold => JoinKinds A_Fold A_Fold k where joinKinds r = r instance k ~ A_Fold => JoinKinds A_Fold An_Iso k where joinKinds r = r -- no JoinKinds A_Fold A_ReversedLens instance k ~ A_Fold => JoinKinds A_Fold A_ReversedPrism k where joinKinds r = r instance k ~ A_Fold => JoinKinds A_Fold A_Prism k where joinKinds r = r -- no JoinKinds A_Fold A_Review instance k ~ A_Fold => JoinKinds A_Fold A_Lens k where joinKinds r = r instance k ~ A_Fold => JoinKinds A_Fold A_Getter k where joinKinds r = r instance k ~ A_Fold => JoinKinds A_Fold An_AffineTraversal k where joinKinds r = r instance k ~ A_Fold => JoinKinds A_Fold An_AffineFold k where joinKinds r = r instance k ~ A_Fold => JoinKinds A_Fold A_Traversal k where joinKinds r = r -- no JoinKinds A_Fold A_Setter -- A_Setter ----- instance k ~ A_Setter => JoinKinds A_Setter A_Setter k where joinKinds r = r instance k ~ A_Setter => JoinKinds A_Setter An_Iso k where joinKinds r = r -- no JoinKinds A_Setter A_ReversedLens -- no JoinKinds A_Setter A_ReversedPrism instance k ~ A_Setter => JoinKinds A_Setter A_Prism k where joinKinds r = r -- no JoinKinds A_Setter A_Review instance k ~ A_Setter => JoinKinds A_Setter A_Lens k where joinKinds r = r -- no JoinKinds A_Setter A_Getter instance k ~ A_Setter => JoinKinds A_Setter An_AffineTraversal k where joinKinds r = r -- no JoinKinds A_Setter An_AffineFold instance k ~ A_Setter => JoinKinds A_Setter A_Traversal k where joinKinds r = r -- no JoinKinds A_Setter A_Fold -- END GENERATED CONTENT instance {-# OVERLAPPABLE #-} ( JoinKinds k l m , TypeError ('ShowType k ':<>: 'Text " cannot be composed with " ':<>: 'ShowType l) ) => JoinKinds k l m where joinKinds _ = error "unreachable" optics-core-0.4.1.1/src/Optics/Internal/Optic/TypeLevel.hs0000644000000000000000000001336007346545000021425 0ustar0000000000000000{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeInType #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_HADDOCK not-home #-} -- | This module is intended for internal use only, and may change without -- warning in subsequent releases. module Optics.Internal.Optic.TypeLevel where import Data.Kind import GHC.TypeLits -- | A list of index types, used for indexed optics. -- -- @since 0.2 type IxList = [Type] -- | An alias for an empty index-list type NoIx = ('[] :: IxList) -- | Singleton index list type WithIx i = ('[i] :: IxList) ---------------------------------------- -- Elimination forms in error messages type family ShowSymbolWithOrigin symbol origin :: ErrorMessage where ShowSymbolWithOrigin symbol origin = 'Text " " ':<>: QuoteSymbol symbol ':<>: 'Text " (from " ':<>: 'Text origin ':<>: 'Text ")" type family ShowSymbolsWithOrigin (fs :: [(Symbol, Symbol)]) :: ErrorMessage where ShowSymbolsWithOrigin '[ '(symbol, origin) ] = ShowSymbolWithOrigin symbol origin ShowSymbolsWithOrigin ('(symbol, origin) ': rest) = ShowSymbolWithOrigin symbol origin ':$$: ShowSymbolsWithOrigin rest type family ShowOperators (ops :: [Symbol]) :: ErrorMessage where ShowOperators '[op] = QuoteSymbol op ':<>: 'Text " (from Optics.Operators)" ShowOperators (op ': rest) = QuoteSymbol op ':<>: 'Text " " ':<>: ShowOperators rest type family AppendEliminations a b where AppendEliminations '(fs1, ops1) '(fs2, ops2) = '(Append fs1 fs2, Append ops1 ops2) type family ShowEliminations forms :: ErrorMessage where ShowEliminations '(fs, ops) = ShowSymbolsWithOrigin fs ':$$: 'Text " " ':<>: ShowOperators ops ---------------------------------------- -- Lists -- | Reverse a type-level list. type family Reverse (xs :: [k]) (acc :: [k]) :: [k] where Reverse '[] acc = acc Reverse (x : xs) acc = Reverse xs (x : acc) -- | Curry a type-level list. -- -- In pseudo (dependent-)Haskell: -- -- @ -- 'Curry' xs y = 'foldr' (->) y xs -- @ type family Curry (xs :: IxList) (y :: Type) :: Type where Curry '[] y = y Curry (x ': xs) y = x -> Curry xs y -- | Append two type-level lists together. type family Append (xs :: [k]) (ys :: [k]) :: [k] where Append '[] ys = ys -- needed for (<%>) and (%>) Append xs '[] = xs -- needed for (<%) Append (x ': xs) ys = x ': Append xs ys -- | Class that is inhabited by all type-level lists @xs@, providing the ability -- to compose a function under @'Curry' xs@. class CurryCompose xs where -- | Compose a function under @'Curry' xs@. This generalises @('.')@ (aka -- 'fmap' for @(->)@) to work for curried functions with one argument for each -- type in the list. composeN :: (i -> j) -> Curry xs i -> Curry xs j instance CurryCompose '[] where composeN = id instance CurryCompose xs => CurryCompose (x ': xs) where composeN ij f = composeN @xs ij . f ---------------------------------------- -- Indices -- | Tagged version of 'Data.Type.Equality.(:~:)' for carrying evidence that two -- index lists in a curried form are equal. data IxEq i is js where IxEq :: IxEq i is is -- | In pseudo (dependent-)Haskell, provide a witness -- -- @ -- foldr f (foldr f init xs) ys = foldr f init (ys ++ xs) -- where f = (->) -- @ -- -- @since 0.4 -- class AppendIndices xs ys ks | xs ys -> ks where appendIndices :: IxEq i (Curry xs (Curry ys i)) (Curry ks i) -- | If the second list is empty, we can pick the first list -- even if nothing is known about it. instance {-# INCOHERENT #-} xs ~ zs => AppendIndices xs '[] zs where appendIndices = IxEq instance ys ~ zs => AppendIndices '[] ys zs where appendIndices = IxEq instance AppendIndices xs ys ks => AppendIndices (x ': xs) ys (x ': ks) where appendIndices :: forall i. IxEq i (Curry (x ': xs) (Curry ys i)) (Curry (x ': ks) i) appendIndices | IxEq <- appendIndices @xs @ys @ks @i = IxEq ---------------------------------------- -- Either -- | If lhs is 'Right', return it. Otherwise check rhs. type family FirstRight (m1 :: Either e a) (m2 :: Either e a) :: Either e a where FirstRight ('Right a) _ = 'Right a FirstRight _ b = b type family FromRight (def :: b) (e :: Either a b) :: b where FromRight _ ('Right b) = b FromRight def ('Left _) = def type family IsLeft (e :: Either a b) :: Bool where IsLeft ('Left _) = 'True IsLeft ('Right _) = 'False ---------------------------------------- -- Errors -- | Show a custom type error if @p@ is true. type family When (p :: Bool) (err :: Constraint) :: Constraint where When 'True err = err When 'False _ = () -- | Show a custom type error if @p@ is false (or stuck). type family Unless (p :: Bool) (err :: Constraint) :: Constraint where Unless 'True _ = () Unless 'False err = err -- | Use with 'Unless' to detect stuck (undefined) type families. type family Defined (f :: k) :: Bool where Defined (f _) = Defined f Defined _ = 'True -- | Show a type surrounded by quote marks. type family QuoteType (x :: t) :: ErrorMessage where QuoteType x = 'Text "‘" ':<>: 'ShowType x ':<>: 'Text "’" -- | Show a symbol surrounded by quote marks. type family QuoteSymbol (x :: Symbol) :: ErrorMessage where QuoteSymbol x = 'Text "‘" ':<>: 'Text x ':<>: 'Text "’" type family ToOrdinal (n :: Nat) :: ErrorMessage where ToOrdinal 1 = 'Text "1st" ToOrdinal 2 = 'Text "2nd" ToOrdinal 3 = 'Text "3rd" ToOrdinal n = 'ShowType n ':<>: 'Text "th" ---------------------------------------- -- Misc -- | Derive the shape of @a@ from the shape of @b@. class HasShapeOf (a :: k) (b :: k) instance {-# OVERLAPPING #-} (fa ~ f a, HasShapeOf f g) => HasShapeOf fa (g b) instance (a ~ b) => HasShapeOf a b optics-core-0.4.1.1/src/Optics/Internal/Optic/Types.hs0000644000000000000000000000400007346545000020607 0ustar0000000000000000{-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeInType #-} {-# OPTIONS_HADDOCK not-home #-} -- | This module is intended for internal use only, and may change without -- warning in subsequent releases. module Optics.Internal.Optic.Types where import Data.Kind (Constraint, Type) import Data.Profunctor.Indexed import Optics.Internal.Bi -- | Kind for types used as optic tags, such as 'A_Lens'. -- -- @since 0.2 type OpticKind = Type -- | Tag for an iso. data An_Iso :: OpticKind -- | Tag for a lens. data A_Lens :: OpticKind -- | Tag for a prism. data A_Prism :: OpticKind -- | Tag for an affine traversal. data An_AffineTraversal :: OpticKind -- | Tag for a traversal. data A_Traversal :: OpticKind -- | Tag for a setter. data A_Setter :: OpticKind -- | Tag for a reversed prism. data A_ReversedPrism :: OpticKind -- | Tag for a getter. data A_Getter :: OpticKind -- | Tag for an affine fold. data An_AffineFold :: OpticKind -- | Tag for a fold. data A_Fold :: OpticKind -- | Tag for a reversed lens. data A_ReversedLens :: OpticKind -- | Tag for a review. data A_Review :: OpticKind -- | Mapping tag types @k@ to constraints on @p@. -- -- Using this type family we define the constraints that the various flavours of -- optics have to fulfill. -- type family Constraints (k :: OpticKind) (p :: Type -> Type -> Type -> Type) :: Constraint where Constraints An_Iso p = Profunctor p Constraints A_Lens p = Strong p Constraints A_ReversedLens p = Costrong p Constraints A_Prism p = Choice p Constraints A_ReversedPrism p = Cochoice p Constraints An_AffineTraversal p = Visiting p Constraints A_Traversal p = Traversing p Constraints A_Setter p = Mapping p Constraints A_Getter p = (Bicontravariant p, Cochoice p, Strong p) Constraints An_AffineFold p = (Bicontravariant p, Cochoice p, Visiting p) Constraints A_Fold p = (Bicontravariant p, Cochoice p, Traversing p) Constraints A_Review p = (Bifunctor p, Choice p, Costrong p) optics-core-0.4.1.1/src/Optics/Internal/Setter.hs0000644000000000000000000000072207346545000017702 0ustar0000000000000000{-# OPTIONS_HADDOCK not-home #-} -- | Internal implementation details of setters. -- -- This module is intended for internal use only, and may change without warning -- in subsequent releases. module Optics.Internal.Setter where import Data.Profunctor.Indexed import Optics.Internal.Optic -- | Internal implementation of 'Optics.Setter.mapped'. mapped__ :: (Mapping p, Functor f) => Optic__ p i i (f a) (f b) a b mapped__ = roam fmap {-# INLINE mapped__ #-} optics-core-0.4.1.1/src/Optics/Internal/Traversal.hs0000644000000000000000000000225207346545000020377 0ustar0000000000000000{-# OPTIONS_HADDOCK not-home #-} -- | Internal implementation details of traversals. -- -- This module is intended for internal use only, and may change without warning -- in subsequent releases. module Optics.Internal.Traversal where import Data.Profunctor.Indexed import Optics.Internal.Optic import Optics.Internal.Fold import Optics.Internal.Setter -- | Internal implementation of 'Optics.Traversal.traversed'. traversed__ :: (Traversing p, Traversable f) => Optic__ p i i (f a) (f b) a b traversed__ = wander traverse {-# INLINE [0] traversed__ #-} -- Because traversed__ inlines late, GHC needs rewrite rules for all cases in -- order to generate optimal code for each of them. The one that rewrites -- traversal into a traversal correspond to an early inline. {-# RULES "traversed__ -> wander traverse" forall (o :: Star g i a b). traversed__ o = wander traverse o :: Traversable f => Star g i (f a) (f b) "traversed__ -> folded__" forall (o :: Forget r i a b). traversed__ o = folded__ o :: Foldable f => Forget r i (f a) (f b) "traversed__ -> mapped__" forall (o :: FunArrow i a b). traversed__ o = mapped__ o :: Functor f => FunArrow i (f a) (f b) #-} optics-core-0.4.1.1/src/Optics/Internal/Utils.hs0000644000000000000000000000541207346545000017535 0ustar0000000000000000{-# OPTIONS_HADDOCK not-home #-} -- | This module is intended for internal use only, and may change without warning -- in subsequent releases. module Optics.Internal.Utils ( Identity'(..) , wrapIdentity' , unwrapIdentity' , Traversed(..) , runTraversed , OrT(..) , wrapOrT , (#.) , (.#) , uncurry' ) where import qualified Data.Semigroup as SG import Data.Profunctor.Indexed -- Needed for strict application of (indexed) setters. -- -- Credit for this goes to Eric Mertens, see -- . data Identity' a = Identity' {-# UNPACK #-} !() a deriving Functor instance Applicative Identity' where pure a = Identity' () a Identity' () f <*> Identity' () x = Identity' () (f x) instance Mapping (Star Identity') where roam f (Star k) = Star $ wrapIdentity' . f (unwrapIdentity' . k) iroam f (Star k) = Star $ wrapIdentity' . f (\_ -> unwrapIdentity' . k) instance Mapping (IxStar Identity') where roam f (IxStar k) = IxStar $ \i -> wrapIdentity' . f (unwrapIdentity' . k i) iroam f (IxStar k) = IxStar $ \ij -> wrapIdentity' . f (\i -> unwrapIdentity' . k (ij i)) -- | Mark a value for evaluation to whnf. -- -- This allows us to, when applying a setter to a structure, evaluate only the -- parts that we modify. If an optic focuses on multiple targets, Applicative -- instance of Identity' makes sure that we force evaluation of all of them, but -- we leave anything else alone. -- wrapIdentity' :: a -> Identity' a wrapIdentity' a = Identity' (a `seq` ()) a unwrapIdentity' :: Identity' a -> a unwrapIdentity' (Identity' () a) = a ---------------------------------------- -- | Helper for 'Optics.Fold.traverseOf_' and the like for better -- efficiency than the foldr-based version. -- -- Note that the argument @a@ of the result should not be used. newtype Traversed f a = Traversed (f a) runTraversed :: Functor f => Traversed f a -> f () runTraversed (Traversed fa) = () <$ fa instance Applicative f => SG.Semigroup (Traversed f a) where Traversed ma <> Traversed mb = Traversed (ma *> mb) instance Applicative f => Monoid (Traversed f a) where mempty = Traversed (pure (error "Traversed: value used")) mappend = (SG.<>) ---------------------------------------- -- | Helper for 'Optics.Fold.failing' family to visit the first fold only once. data OrT f a = OrT !Bool (f a) deriving Functor instance Applicative f => Applicative (OrT f) where pure = OrT False . pure OrT a f <*> OrT b x = OrT (a || b) (f <*> x) -- | Wrap the applicative action in 'OrT' so that we know later that it was -- executed. wrapOrT :: f a -> OrT f a wrapOrT = OrT True -- | 'uncurry' with no lazy pattern matching for more efficient code. -- -- @since 0.3 uncurry' :: (a -> b -> c) -> (a, b) -> c uncurry' f (a, b) = f a b optics-core-0.4.1.1/src/Optics/Iso.hs0000644000000000000000000002321707346545000015416 0ustar0000000000000000-- | -- Module: Optics.Iso -- Description: Translates between types with the same structure. -- -- An 'Iso'morphism expresses the fact that two types have the -- same structure, and hence can be converted from one to the other in -- either direction. -- module Optics.Iso ( -- * Formation Iso , Iso' -- * Introduction , iso -- * Elimination -- | An 'Iso' is in particular a 'Optics.Getter.Getter', a -- 'Optics.Review.Review' and a 'Optics.Setter.Setter', therefore you can -- specialise types to obtain: -- -- @ -- 'Optics.Getter.view' :: 'Iso'' s a -> s -> a -- 'Optics.Review.review' :: 'Iso'' s a -> a -> s -- @ -- -- @ -- 'Optics.Setter.over' :: 'Iso' s t a b -> (a -> b) -> s -> t -- 'Optics.Setter.set' :: 'Iso' s t a b -> b -> s -> t -- @ -- -- If you want to 'Optics.Getter.view' a type-modifying 'Iso' that is -- insufficiently polymorphic to be used as a type-preserving 'Iso'', use -- 'Optics.ReadOnly.getting': -- -- @ -- 'Optics.Getter.view' . 'Optics.ReadOnly.getting' :: 'Iso' s t a b -> s -> a -- @ -- * Computation -- | -- -- @ -- 'Optics.Getter.view' ('iso' f g) ≡ f -- 'Optics.Review.review' ('iso' f g) ≡ g -- @ -- * Well-formedness -- | The functions translating back and forth must be mutually inverse: -- -- @ -- 'Optics.Getter.view' i . 'Optics.Review.review' i ≡ 'id' -- 'Optics.Review.review' i . 'Optics.Getter.view' i ≡ 'id' -- @ -- * Additional introduction forms , equality , simple , coerced , coercedTo , coerced1 , non , non' , anon , curried , uncurried , flipped , involuted , Swapped(..) -- * Additional elimination forms , withIso , au , under -- * Combinators -- | The 'Optics.Re.re' combinator can be used to reverse an 'Iso', and the -- 'Optics.Mapping.mapping' combinator to lift an 'Iso' to an 'Iso' on -- functorial values. -- -- @ -- 'Optics.Re.re' :: 'Iso' s t a b -> 'Iso' b a t s -- 'Optics.Mapping.mapping' :: (Functor f, Functor g) => 'Iso' s t a b -> 'Iso' (f s) (g t) (f a) (g b) -- @ -- * Subtyping , An_Iso -- | <> ) where import Data.Tuple import Data.Bifunctor import Data.Coerce import Data.Maybe import Data.Profunctor.Indexed import Optics.AffineFold import Optics.Prism import Optics.Review import Optics.Internal.Optic -- | Type synonym for a type-modifying iso. type Iso s t a b = Optic An_Iso NoIx s t a b -- | Type synonym for a type-preserving iso. type Iso' s a = Optic' An_Iso NoIx s a -- | Build an iso from a pair of inverse functions. -- -- If you want to build an 'Iso' from the van Laarhoven representation, use -- @isoVL@ from the @optics-vl@ package. iso :: (s -> a) -> (b -> t) -> Iso s t a b iso f g = Optic (dimap f g) {-# INLINE iso #-} -- | Extract the two components of an isomorphism. withIso :: Iso s t a b -> ((s -> a) -> (b -> t) -> r) -> r withIso o k = case getOptic o (Exchange id id) of Exchange sa bt -> k sa bt {-# INLINE withIso #-} -- | Based on @ala@ from Conor McBride's work on Epigram. -- -- This version is generalized to accept any 'Iso', not just a @newtype@. -- -- >>> au (coerced1 @Sum) foldMap [1,2,3,4] -- 10 -- -- You may want to think of this combinator as having the following, simpler -- type: -- -- @ -- au :: 'Iso' s t a b -> ((b -> t) -> e -> s) -> e -> a -- @ au :: Functor f => Iso s t a b -> ((b -> t) -> f s) -> f a au k = withIso k $ \sa bt f -> sa <$> f bt {-# INLINE au #-} -- | The opposite of working 'Optics.Setter.over' a 'Optics.Setter.Setter' is -- working 'under' an isomorphism. -- -- @ -- 'under' ≡ 'Optics.Setter.over' '.' 'Optics.Re.re' -- @ under :: Iso s t a b -> (t -> s) -> b -> a under k = withIso k $ \sa bt ts -> sa . ts . bt {-# INLINE under #-} ---------------------------------------- -- Isomorphisms -- | Capture type constraints as an isomorphism. -- -- /Note:/ This is the identity optic: -- -- >>> :t view equality -- view equality :: a -> a equality :: (s ~ a, t ~ b) => Iso s t a b equality = Optic id {-# INLINE equality #-} -- | Proof of reflexivity. simple :: Iso' a a simple = Optic id {-# INLINE simple #-} -- | Data types that are representationally equal are isomorphic. -- -- >>> view coerced 'x' :: Identity Char -- Identity 'x' -- coerced :: (Coercible s a, Coercible t b) => Iso s t a b coerced = Optic (lcoerce' . rcoerce') {-# INLINE coerced #-} -- | Type-preserving version of 'coerced' with type parameters rearranged for -- TypeApplications. -- -- >>> newtype MkInt = MkInt Int deriving Show -- -- >>> over (coercedTo @Int) (*3) (MkInt 2) -- MkInt 6 -- coercedTo :: forall a s. Coercible s a => Iso' s a coercedTo = Optic (lcoerce' . rcoerce') {-# INLINE coercedTo #-} -- | Special case of 'coerced' for trivial newtype wrappers. -- -- >>> over (coerced1 @Identity) (++ "bar") (Identity "foo") -- Identity "foobar" -- coerced1 :: forall f s a. (Coercible s (f s), Coercible a (f a)) => Iso (f s) (f a) s a coerced1 = Optic (lcoerce' . rcoerce') {-# INLINE coerced1 #-} -- | If @v@ is an element of a type @a@, and @a'@ is @a@ sans the element @v@, -- then @'non' v@ is an isomorphism from @'Maybe' a'@ to @a@. -- -- @ -- 'non' ≡ 'non'' '.' 'only' -- @ -- -- Keep in mind this is only a real isomorphism if you treat the domain as being -- @'Maybe' (a sans v)@. -- -- This is practically quite useful when you want to have a 'Data.Map.Map' where -- all the entries should have non-zero values. -- -- >>> Map.fromList [("hello",1)] & at "hello" % non 0 %~ (+2) -- fromList [("hello",3)] -- -- >>> Map.fromList [("hello",1)] & at "hello" % non 0 %~ (subtract 1) -- fromList [] -- -- >>> Map.fromList [("hello",1)] ^. at "hello" % non 0 -- 1 -- -- >>> Map.fromList [] ^. at "hello" % non 0 -- 0 -- -- This combinator is also particularly useful when working with nested maps. -- -- /e.g./ When you want to create the nested 'Data.Map.Map' when it is missing: -- -- >>> Map.empty & at "hello" % non Map.empty % at "world" ?~ "!!!" -- fromList [("hello",fromList [("world","!!!")])] -- -- and when have deleting the last entry from the nested 'Data.Map.Map' mean -- that we should delete its entry from the surrounding one: -- -- >>> Map.fromList [("hello", Map.fromList [("world","!!!")])] & at "hello" % non Map.empty % at "world" .~ Nothing -- fromList [] -- -- It can also be used in reverse to exclude a given value: -- -- >>> non 0 # rem 10 4 -- Just 2 -- -- >>> non 0 # rem 10 5 -- Nothing -- -- @since 0.2 non :: Eq a => a -> Iso' (Maybe a) a non = non' . only {-# INLINE non #-} -- | @'non'' p@ generalizes @'non' (p # ())@ to take any unit 'Prism' -- -- This function generates an isomorphism between @'Maybe' (a | 'isn't' p a)@ -- and @a@. -- -- >>> Map.singleton "hello" Map.empty & at "hello" % non' _Empty % at "world" ?~ "!!!" -- fromList [("hello",fromList [("world","!!!")])] -- -- >>> Map.fromList [("hello", Map.fromList [("world","!!!")])] & at "hello" % non' _Empty % at "world" .~ Nothing -- fromList [] -- -- @since 0.2 non' :: Prism' a () -> Iso' (Maybe a) a non' p = iso (fromMaybe def) go where def = review p () go b | p `isn't` b = Just b | otherwise = Nothing {-# INLINE non' #-} -- | @'anon' a p@ generalizes @'non' a@ to take any value and a predicate. -- -- @ -- 'anon' a ≡ 'non'' '.' 'nearly' a -- @ -- -- This function assumes that @p a@ holds @'True'@ and generates an isomorphism -- between @'Maybe' (a | 'not' (p a))@ and @a@. -- -- >>> Map.empty & at "hello" % anon Map.empty Map.null % at "world" ?~ "!!!" -- fromList [("hello",fromList [("world","!!!")])] -- -- >>> Map.fromList [("hello", Map.fromList [("world","!!!")])] & at "hello" % anon Map.empty Map.null % at "world" .~ Nothing -- fromList [] -- -- @since 0.2 anon :: a -> (a -> Bool) -> Iso' (Maybe a) a anon a = non' . nearly a {-# INLINE anon #-} -- | The canonical isomorphism for currying and uncurrying a function. -- -- @ -- 'curried' = 'iso' 'curry' 'uncurry' -- @ -- -- >>> view curried fst 3 4 -- 3 -- curried :: Iso ((a, b) -> c) ((d, e) -> f) (a -> b -> c) (d -> e -> f) curried = iso curry uncurry {-# INLINE curried #-} -- | The canonical isomorphism for uncurrying and currying a function. -- -- @ -- 'uncurried' = 'iso' 'uncurry' 'curry' -- @ -- -- @ -- 'uncurried' = 'Optics.Re.re' 'curried' -- @ -- -- >>> (view uncurried (+)) (1,2) -- 3 -- uncurried :: Iso (a -> b -> c) (d -> e -> f) ((a, b) -> c) ((d, e) -> f) uncurried = iso uncurry curry {-# INLINE uncurried #-} -- | The isomorphism for flipping a function. -- -- >>> (view flipped (,)) 1 2 -- (2,1) -- flipped :: Iso (a -> b -> c) (a' -> b' -> c') (b -> a -> c) (b' -> a' -> c') flipped = iso flip flip {-# INLINE flipped #-} -- | Given a function that is its own inverse, this gives you an 'Iso' using it -- in both directions. -- -- @ -- 'involuted' ≡ 'Control.Monad.join' 'iso' -- @ -- -- >>> "live" ^. involuted reverse -- "evil" -- -- >>> "live" & involuted reverse %~ ('d':) -- "lived" involuted :: (a -> a) -> Iso' a a involuted a = iso a a {-# INLINE involuted #-} -- | This class provides for symmetric bifunctors. class Bifunctor p => Swapped p where -- | -- @ -- 'swapped' '.' 'swapped' ≡ 'id' -- 'first' f '.' 'swapped' = 'swapped' '.' 'second' f -- 'second' g '.' 'swapped' = 'swapped' '.' 'first' g -- 'bimap' f g '.' 'swapped' = 'swapped' '.' 'bimap' g f -- @ -- -- >>> view swapped (1,2) -- (2,1) -- swapped :: Iso (p a b) (p c d) (p b a) (p d c) instance Swapped (,) where swapped = iso swap swap {-# INLINE swapped #-} instance Swapped Either where swapped = iso (either Right Left) (either Right Left) {-# INLINE swapped #-} -- $setup -- >>> import qualified Data.Map as Map -- >>> import Data.Functor.Identity -- >>> import Data.Monoid -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/IxAffineFold.hs0000644000000000000000000001012207346545000017151 0ustar0000000000000000-- | -- Module: Optics.IxAffineFold -- Description: An indexed version of an 'Optics.AffineFold.AffineFold'. -- -- An 'IxAffineFold' is an indexed version of an 'Optics.AffineFold.AffineFold'. -- See the "Indexed optics" section of the overview documentation in the -- @Optics@ module of the main @optics@ package for more details on indexed -- optics. -- module Optics.IxAffineFold ( -- * Formation IxAffineFold -- * Introduction , iafolding -- * Elimination , ipreview , ipreviews -- * Computation -- | -- -- @ -- 'ipreview' ('iafolding' f) ≡ f -- @ -- * Additional introduction forms , iafoldVL -- * Additional elimination forms , iatraverseOf_ -- * Combinators , filteredBy -- * Monoid structure -- | 'IxAffineFold' admits a monoid structure where 'iafailing' combines folds -- (returning a result from the second fold only if the first returns none) -- and the identity element is 'Optics.IxAffineTraversal.ignored' (which -- returns no results). -- -- /Note:/ There is no 'Optics.IxFold.isumming' equivalent that returns an -- 'IxAffineFold', because it would not need to return more than one result. -- -- There is no 'Semigroup' or 'Monoid' instance for 'IxAffineFold', because -- there is not a unique choice of monoid to use that works for all optics, -- and the ('<>') operator could not be used to combine optics of different -- kinds. , iafailing -- * Subtyping , An_AffineFold ) where import Data.Profunctor.Indexed import Optics.AffineFold import Optics.Internal.Bi import Optics.Internal.Indexed import Optics.Internal.Optic import Optics.Internal.Utils -- | Type synonym for an indexed affine fold. type IxAffineFold i s a = Optic' An_AffineFold (WithIx i) s a -- | Obtain an 'IxAffineFold' by lifting 'itraverse_' like function. -- -- @ -- 'aifoldVL' '.' 'iatraverseOf_' ≡ 'id' -- 'aitraverseOf_' '.' 'iafoldVL' ≡ 'id' -- @ -- -- @since 0.3 iafoldVL :: (forall f. Functor f => (forall r. r -> f r) -> (i -> a -> f u) -> s -> f v) -> IxAffineFold i s a iafoldVL f = Optic (rphantom . ivisit f . rphantom) {-# INLINE iafoldVL #-} -- | Retrieve the value along with its index targeted by an 'IxAffineFold'. ipreview :: (Is k An_AffineFold, is `HasSingleIndex` i) => Optic' k is s a -> s -> Maybe (i, a) ipreview o = ipreviews o (,) {-# INLINE ipreview #-} -- | Retrieve a function of the value and its index targeted by an -- 'IxAffineFold'. ipreviews :: (Is k An_AffineFold, is `HasSingleIndex` i) => Optic' k is s a -> (i -> a -> r) -> s -> Maybe r ipreviews o = \f -> runIxForgetM (getOptic (castOptic @An_AffineFold o) . IxForgetM $ \i -> Just . f i) id {-# INLINE ipreviews #-} -- | Traverse over the target of an 'IxAffineFold', computing a 'Functor'-based -- answer, but unlike 'Optics.IxAffineTraversal.iatraverseOf' do not construct a -- new structure. -- -- @since 0.3 iatraverseOf_ :: (Is k An_AffineFold, Functor f, is `HasSingleIndex` i) => Optic' k is s a -> (forall r. r -> f r) -> (i -> a -> f u) -> s -> f () iatraverseOf_ o point f s = case ipreview o s of Just (i, a) -> () <$ f i a Nothing -> point () {-# INLINE iatraverseOf_ #-} -- | Create an 'IxAffineFold' from a partial function. iafolding :: (s -> Maybe (i, a)) -> IxAffineFold i s a iafolding g = iafoldVL (\point f s -> maybe (point s) (uncurry' f) $ g s) {-# INLINE iafolding #-} -- | Obtain a potentially empty 'IxAffineFold' by taking the element from -- another 'AffineFold' and using it as an index. -- -- @since 0.3 filteredBy :: Is k An_AffineFold => Optic' k is a i -> IxAffineFold i a a filteredBy p = iafoldVL $ \point f s -> case preview p s of Just i -> f i s Nothing -> point s {-# INLINE filteredBy #-} -- | Try the first 'IxAffineFold'. If it returns no entry, try the second one. -- iafailing :: (Is k An_AffineFold, Is l An_AffineFold, is1 `HasSingleIndex` i, is2 `HasSingleIndex` i) => Optic' k is1 s a -> Optic' l is2 s a -> IxAffineFold i s a iafailing a b = conjoined (afailing a b) $ iafolding $ \s -> maybe (ipreview b s) Just (ipreview a s) infixl 3 `iafailing` -- Same as (<|>) {-# INLINE iafailing #-} optics-core-0.4.1.1/src/Optics/IxAffineTraversal.hs0000644000000000000000000001076207346545000020242 0ustar0000000000000000-- | -- Module: Optics.IxAffineTraversal -- Description: An indexed version of an 'Optics.AffineTraversal.AffineTraversal'. -- -- An 'IxAffineTraversal' is an indexed version of an -- 'Optics.AffineTraversal.AffineTraversal'. See the "Indexed optics" section -- of the overview documentation in the @Optics@ module of the main @optics@ -- package for more details on indexed optics. -- module Optics.IxAffineTraversal ( -- * Formation IxAffineTraversal , IxAffineTraversal' -- * Introduction , iatraversal -- * Elimination -- | An 'IxAffineTraversal' is in particular an -- 'Optics.IxAffineFold.IxAffineFold' and an 'Optics.IxSetter.IxSetter', -- therefore you can specialise types to obtain: -- -- @ -- 'Optics.IxAffineFold.ipreview' :: 'IxAffineTraversal' i s t a b -> s -> Maybe (i, a) -- @ -- -- @ -- 'Optics.IxSetter.iover' :: 'IxAffineTraversal' i s t a b -> (i -> a -> b) -> s -> t -- 'Optics.IxSetter.iset' :: 'IxAffineTraversal' i s t a b -> (i -> b) -> s -> t -- @ -- * Combinators , unsafeFilteredBy -- * Additional introduction forms , ignored -- * Subtyping , An_AffineTraversal -- * van Laarhoven encoding , IxAffineTraversalVL , IxAffineTraversalVL' , iatraversalVL , iatraverseOf ) where import Data.Profunctor.Indexed import Optics.AffineFold import Optics.Internal.Indexed import Optics.Internal.Optic import Optics.Internal.Utils -- | Type synonym for a type-modifying indexed affine traversal. type IxAffineTraversal i s t a b = Optic An_AffineTraversal (WithIx i) s t a b -- | Type synonym for a type-preserving indexed affine traversal. type IxAffineTraversal' i s a = Optic' An_AffineTraversal (WithIx i) s a -- | Type synonym for a type-modifying van Laarhoven indexed affine traversal. -- -- Note: this isn't exactly van Laarhoven representation as there is no -- @Pointed@ class (which would be a superclass of 'Applicative' that contains -- 'pure' but not '<*>'). You can interpret the first argument as a dictionary -- of @Pointed@ that supplies the @point@ function (i.e. the implementation of -- 'pure'). -- type IxAffineTraversalVL i s t a b = forall f. Functor f => (forall r. r -> f r) -> (i -> a -> f b) -> s -> f t -- | Type synonym for a type-preserving van Laarhoven indexed affine traversal. type IxAffineTraversalVL' i s a = IxAffineTraversalVL i s s a a -- | Build an indexed affine traversal from a matcher and an updater. -- -- If you want to build an 'IxAffineTraversal' from the van Laarhoven -- representation, use 'iatraversalVL'. iatraversal :: (s -> Either t (i, a)) -> (s -> b -> t) -> IxAffineTraversal i s t a b iatraversal match update = iatraversalVL $ \point f s -> either point (\a -> update s <$> uncurry' f a) (match s) {-# INLINE iatraversal #-} -- | Build an indexed affine traversal from the van Laarhoven representation. iatraversalVL :: IxAffineTraversalVL i s t a b -> IxAffineTraversal i s t a b iatraversalVL f = Optic (ivisit f) {-# INLINE iatraversalVL #-} -- | Traverse over the target of an 'IxAffineTraversal' and compute a -- 'Functor'-based answer. -- -- @since 0.3 iatraverseOf :: (Is k An_AffineTraversal, Functor f, is `HasSingleIndex` i) => Optic k is s t a b -> (forall r. r -> f r) -> (i -> a -> f b) -> s -> f t iatraverseOf o point = \f -> runIxStarA (getOptic (castOptic @An_AffineTraversal o) (IxStarA point f)) id {-# INLINE iatraverseOf #-} -- | Obtain a potentially empty 'IxAffineTraversal' by taking the element from -- another 'AffineFold' and using it as an index. -- -- -- /Note:/ This is /not/ a legal 'Optics.IxTraversal.IxTraversal', unless you -- are very careful not to invalidate the predicate on the target (see -- 'Optics.AffineTraversal.unsafeFiltered' for more details). -- -- @since 0.3 unsafeFilteredBy :: Is k An_AffineFold => Optic' k is a i -> IxAffineTraversal' i a a unsafeFilteredBy p = iatraversalVL $ \point f s -> case preview p s of Just i -> f i s Nothing -> point s {-# INLINE unsafeFilteredBy #-} -- | This is the trivial empty 'IxAffineTraversal', i.e. the optic that targets -- no substructures. -- -- This is the identity element when a 'Optics.Fold.Fold', -- 'Optics.AffineFold.AffineFold', 'Optics.IxFold.IxFold', -- 'Optics.IxAffineFold.IxAffineFold', 'Optics.Traversal.Traversal' or -- 'Optics.IxTraversal.IxTraversal' is viewed as a monoid. -- -- >>> 6 & ignored %~ absurd -- 6 ignored :: IxAffineTraversal i s s a b ignored = iatraversalVL $ \point _ -> point {-# INLINE ignored #-} -- $setup -- >>> import Optics.Core -- >>> import Data.Void (absurd) optics-core-0.4.1.1/src/Optics/IxFold.hs0000644000000000000000000002560507346545000016054 0ustar0000000000000000{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} -- | -- Module: Optics.IxFold -- Description: An indexed version of a 'Optics.Fold.Fold'. -- -- An 'IxFold' is an indexed version of a 'Optics.Fold.Fold'. See the "Indexed -- optics" section of the overview documentation in the @Optics@ module of the -- main @optics@ package for more details on indexed optics. -- module Optics.IxFold ( -- * Formation IxFold -- * Introduction , ifoldVL -- * Elimination , ifoldMapOf , ifoldrOf , ifoldlOf' , itoListOf , itraverseOf_ , iforOf_ -- * Additional introduction forms , ifolded , ifolding , ifoldring -- * Additional elimination forms -- | See also 'Data.Map.Optics.toMapOf', which constructs a 'Data.Map.Map' from an 'IxFold'. , iheadOf , ilastOf , ianyOf , iallOf , inoneOf , ifindOf , ifindMOf -- * Combinators , ipre , ifiltered , ibackwards_ -- * Monoid structures #monoids# -- | 'IxFold' admits (at least) two monoid structures: -- -- * 'isumming' concatenates results from both folds. -- -- * 'ifailing' returns results from the second fold only if the first returns -- no results. -- -- In both cases, the identity element of the monoid is -- `Optics.IxAffineTraversal.ignored`, which returns no results. -- -- There is no 'Semigroup' or 'Monoid' instance for 'IxFold', because there is -- not a unique choice of monoid to use, and the ('<>') operator could not be -- used to combine optics of different kinds. , isumming , ifailing -- * Subtyping , A_Fold -- * Re-exports , FoldableWithIndex(..) ) where import Control.Applicative.Backwards import Data.Monoid import Data.Profunctor.Indexed import Optics.Internal.Bi import Optics.Internal.Indexed import Optics.Internal.Indexed.Classes import Optics.Internal.Fold import Optics.Internal.IxFold import Optics.Internal.Optic import Optics.Internal.Utils import Optics.IxAffineFold import Optics.Fold -- | Type synonym for an indexed fold. type IxFold i s a = Optic' A_Fold (WithIx i) s a -- | Obtain an indexed fold by lifting 'itraverse_' like function. -- -- @ -- 'ifoldVL' '.' 'itraverseOf_' ≡ 'id' -- 'itraverseOf_' '.' 'ifoldVL' ≡ 'id' -- @ ifoldVL :: (forall f. Applicative f => (i -> a -> f u) -> s -> f v) -> IxFold i s a ifoldVL f = Optic (ifoldVL__ f) {-# INLINE ifoldVL #-} -- | Fold with index via embedding into a monoid. ifoldMapOf :: (Is k A_Fold, Monoid m, is `HasSingleIndex` i) => Optic' k is s a -> (i -> a -> m) -> s -> m ifoldMapOf o = \f -> runIxForget (getOptic (castOptic @A_Fold o) (IxForget f)) id {-# INLINE ifoldMapOf #-} -- | Fold with index right-associatively. ifoldrOf :: (Is k A_Fold, is `HasSingleIndex` i) => Optic' k is s a -> (i -> a -> r -> r) -> r -> s -> r ifoldrOf o = \iarr r0 s -> (\e -> appEndo e r0) $ ifoldMapOf o (\i -> Endo #. iarr i) s {-# INLINE ifoldrOf #-} -- | Fold with index left-associatively, and strictly. ifoldlOf' :: (Is k A_Fold, is `HasSingleIndex` i) => Optic' k is s a -> (i -> r -> a -> r) -> r -> s -> r ifoldlOf' o = \irar r0 s -> ifoldrOf o (\i a rr r -> rr $! irar i r a) id s r0 {-# INLINE ifoldlOf' #-} -- | Fold with index to a list. -- -- >>> itoListOf (folded % ifolded) ["abc", "def"] -- [(0,'a'),(1,'b'),(2,'c'),(0,'d'),(1,'e'),(2,'f')] -- -- /Note:/ currently indexed optics can be used as non-indexed. -- -- >>> toListOf (folded % ifolded) ["abc", "def"] -- "abcdef" -- itoListOf :: (Is k A_Fold, is `HasSingleIndex` i) => Optic' k is s a -> s -> [(i, a)] itoListOf o = ifoldrOf o (\i -> (:) . (i, )) [] {-# INLINE itoListOf #-} ---------------------------------------- -- | Traverse over all of the targets of an 'IxFold', computing an -- 'Applicative'-based answer, but unlike 'Optics.IxTraversal.itraverseOf' do -- not construct a new structure. -- -- >>> itraverseOf_ each (curry print) ("hello","world") -- (0,"hello") -- (1,"world") -- itraverseOf_ :: (Is k A_Fold, Applicative f, is `HasSingleIndex` i) => Optic' k is s a -> (i -> a -> f r) -> s -> f () #if __GLASGOW_HASKELL__ == 802 -- GHC 8.2.2 needs this to optimize away profunctors when f is not supplied. itraverseOf_ o = \f -> #else itraverseOf_ o f = #endif runTraversed . ifoldMapOf o (\i -> Traversed #. f i) {-# INLINE itraverseOf_ #-} -- | A version of 'itraverseOf_' with the arguments flipped. iforOf_ :: (Is k A_Fold, Applicative f, is `HasSingleIndex` i) => Optic' k is s a -> s -> (i -> a -> f r) -> f () iforOf_ = flip . itraverseOf_ {-# INLINE iforOf_ #-} ---------------------------------------- -- | Indexed fold via 'FoldableWithIndex' class. ifolded :: FoldableWithIndex i f => IxFold i (f a) a ifolded = Optic ifolded__ {-# INLINE ifolded #-} -- | Obtain an 'IxFold' by lifting an operation that returns a -- 'FoldableWithIndex' result. -- -- This can be useful to lift operations from @Data.List@ and elsewhere into an -- 'IxFold'. -- -- >>> itoListOf (ifolding words) "how are you" -- [(0,"how"),(1,"are"),(2,"you")] ifolding :: FoldableWithIndex i f => (s -> f a) -> IxFold i s a ifolding f = Optic $ contrafirst f . ifolded__ {-# INLINE ifolding #-} -- | Obtain an 'IxFold' by lifting 'ifoldr' like function. -- -- >>> itoListOf (ifoldring ifoldr) "hello" -- [(0,'h'),(1,'e'),(2,'l'),(3,'l'),(4,'o')] ifoldring :: (forall f. Applicative f => (i -> a -> f u -> f u) -> f v -> s -> f w) -> IxFold i s a ifoldring fr = Optic (ifoldring__ fr) {-# INLINE ifoldring #-} -- | Convert an indexed fold to an 'IxAffineFold' that visits the first element -- of the original fold. -- -- For the traversal version see 'Optics.IxTraversal.isingular'. ipre :: (Is k A_Fold, is `HasSingleIndex` i) => Optic' k is s a -> IxAffineFold i s a ipre = iafolding . iheadOf {-# INLINE ipre #-} -- | Filter results of an 'IxFold' that don't satisfy a predicate. -- -- >>> toListOf (ifolded %& ifiltered (>)) [3,2,1,0] -- [1,0] -- ifiltered :: (Is k A_Fold, is `HasSingleIndex` i) => (i -> a -> Bool) -> Optic' k is s a -> IxFold i s a ifiltered p o = ifoldVL $ \f -> itraverseOf_ o (\i a -> if p i a then f i a else pure ()) {-# INLINE ifiltered #-} -- Note: technically this should be defined per optic kind: -- -- ifiltered :: _ -> IxFold i s a -> IxFold i s a -- ifiltered :: _ -> IxGetter i s a -> IxAffineFold i s a -- ifiltered :: _ -> IxAffineFold i s a -> IxAffineFold i s a -- -- and similarly for (non-existent) unsafeIFiltered. -- | This allows you to traverse the elements of an 'IxFold' in the opposite -- order. ibackwards_ :: (Is k A_Fold, is `HasSingleIndex` i) => Optic' k is s a -> IxFold i s a ibackwards_ o = conjoined (backwards_ o) $ ifoldVL $ \f -> forwards #. itraverseOf_ o (\i -> Backwards #. f i) {-# INLINE ibackwards_ #-} -- | Return entries of the first 'IxFold', then the second one. -- -- >>> itoListOf (ifolded `isumming` ibackwards_ ifolded) ["a","b"] -- [(0,"a"),(1,"b"),(1,"b"),(0,"a")] -- -- For the traversal version see 'Optics.IxTraversal.iadjoin'. isumming :: (Is k A_Fold, Is l A_Fold, is1 `HasSingleIndex` i, is2 `HasSingleIndex` i) => Optic' k is1 s a -> Optic' l is2 s a -> IxFold i s a isumming a b = conjoined (summing a b) $ ifoldVL $ \f s -> itraverseOf_ a f s *> itraverseOf_ b f s infixr 6 `isumming` -- Same as (<>) {-# INLINE isumming #-} -- | Try the first 'IxFold'. If it returns no entries, try the second one. -- -- >>> itoListOf (_1 % ifolded `ifailing` _2 % ifolded) (["a"], ["b","c"]) -- [(0,"a")] -- >>> itoListOf (_1 % ifolded `ifailing` _2 % ifolded) ([], ["b","c"]) -- [(0,"b"),(1,"c")] -- ifailing :: (Is k A_Fold, Is l A_Fold, is1 `HasSingleIndex` i, is2 `HasSingleIndex` i) => Optic' k is1 s a -> Optic' l is2 s a -> IxFold i s a ifailing a b = conjoined (failing a b) $ ifoldVL $ \f s -> let OrT visited fu = itraverseOf_ a (\i -> wrapOrT . f i) s in if visited then fu else itraverseOf_ b f s infixl 3 `ifailing` -- Same as (<|>) {-# INLINE ifailing #-} ---------------------------------------- -- Special folds -- | Retrieve the first entry of an 'IxFold' along with its index. -- -- >>> iheadOf ifolded [1..10] -- Just (0,1) iheadOf :: (Is k A_Fold, is `HasSingleIndex` i) => Optic' k is s a -> s -> Maybe (i, a) iheadOf o = getLeftmost . ifoldMapOf o (\i -> LLeaf . (i, )) {-# INLINE iheadOf #-} -- | Retrieve the last entry of an 'IxFold' along with its index. -- -- >>> ilastOf ifolded [1..10] -- Just (9,10) ilastOf :: (Is k A_Fold, is `HasSingleIndex` i) => Optic' k is s a -> s -> Maybe (i, a) ilastOf o = getRightmost . ifoldMapOf o (\i -> RLeaf . (i, )) {-# INLINE ilastOf #-} -- | Return whether or not any element viewed through an 'IxFold' satisfies a -- predicate, with access to the @i@. -- -- When you don't need access to the index then 'anyOf' is more flexible in what -- it accepts. -- -- @ -- 'anyOf' o ≡ 'ianyOf' o '.' 'const' -- @ ianyOf :: (Is k A_Fold, is `HasSingleIndex` i) => Optic' k is s a -> (i -> a -> Bool) -> s -> Bool ianyOf o = \f -> getAny #. ifoldMapOf o (\i -> Any #. f i) {-# INLINE ianyOf #-} -- | Return whether or not all elements viewed through an 'IxFold' satisfy a -- predicate, with access to the @i@. -- -- When you don't need access to the index then 'allOf' is more flexible in what -- it accepts. -- -- @ -- 'allOf' o ≡ 'iallOf' o '.' 'const' -- @ iallOf :: (Is k A_Fold, is `HasSingleIndex` i) => Optic' k is s a -> (i -> a -> Bool) -> s -> Bool iallOf o = \f -> getAll #. ifoldMapOf o (\i -> All #. f i) {-# INLINE iallOf #-} -- | Return whether or not none of the elements viewed through an 'IxFold' -- satisfy a predicate, with access to the @i@. -- -- When you don't need access to the index then 'noneOf' is more flexible in -- what it accepts. -- -- @ -- 'noneOf' o ≡ 'inoneOf' o '.' 'const' -- @ inoneOf :: (Is k A_Fold, is `HasSingleIndex` i) => Optic' k is s a -> (i -> a -> Bool) -> s -> Bool inoneOf o = \f -> not . ianyOf o f {-# INLINE inoneOf #-} -- | The 'ifindOf' function takes an 'IxFold', a predicate that is also supplied -- the index, a structure and returns the left-most element of the structure -- along with its index matching the predicate, or 'Nothing' if there is no such -- element. -- -- When you don't need access to the index then 'findOf' is more flexible in -- what it accepts. ifindOf :: (Is k A_Fold, is `HasSingleIndex` i) => Optic' k is s a -> (i -> a -> Bool) -> s -> Maybe (i, a) ifindOf o = \p -> iheadOf (ifiltered p o) {-# INLINE ifindOf #-} -- | The 'ifindMOf' function takes an 'IxFold', a monadic predicate that is also -- supplied the index, a structure and returns in the monad the left-most -- element of the structure matching the predicate, or 'Nothing' if there is no -- such element. -- -- When you don't need access to the index then 'findMOf' is more flexible in -- what it accepts. ifindMOf :: (Is k A_Fold, Monad m, is `HasSingleIndex` i) => Optic' k is s a -> (i -> a -> m Bool) -> s -> m (Maybe (i, a)) ifindMOf o = \f -> ifoldrOf o (\i a y -> f i a >>= \r -> if r then pure (Just (i, a)) else y) (pure Nothing) {-# INLINE ifindMOf #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/IxGetter.hs0000644000000000000000000000311407346545000016411 0ustar0000000000000000-- | -- Module: Optics.IxGetter -- Description: An indexed version of a 'Optics.Getter.Getter'. -- -- An 'IxGetter' is an indexed version of a 'Optics.Getter.Getter'. See the -- "Indexed optics" section of the overview documentation in the @Optics@ module -- of the main @optics@ package for more details on indexed optics. -- module Optics.IxGetter ( -- * Formation IxGetter -- * Introduction , ito , selfIndex -- * Elimination , iview , iviews -- * Subtyping , A_Getter ) where import Data.Profunctor.Indexed import Optics.Internal.Bi import Optics.Internal.Indexed import Optics.Internal.Optic import Optics.Internal.Utils -- | Type synonym for an indexed getter. type IxGetter i s a = Optic' A_Getter (WithIx i) s a -- | Build an indexed getter from a function. -- -- >>> iview (ito id) ('i', 'x') -- ('i','x') ito :: (s -> (i, a)) -> IxGetter i s a ito f = Optic (lmap f . ilinear uncurry' . rphantom) {-# INLINE ito #-} -- | Use a value itself as its own index. This is essentially an indexed version -- of 'Optics.Iso.equality'. selfIndex :: IxGetter a a a selfIndex = ito (\a -> (a, a)) {-# INLINE selfIndex #-} -- | View the value pointed to by an indexed getter. iview :: (Is k A_Getter, is `HasSingleIndex` i) => Optic' k is s a -> s -> (i, a) iview o = iviews o (,) {-# INLINE iview #-} -- | View the function of the value pointed to by an indexed getter. iviews :: (Is k A_Getter, is `HasSingleIndex` i) => Optic' k is s a -> (i -> a -> r) -> s -> r iviews o = \f -> runIxForget (getOptic (castOptic @A_Getter o) (IxForget f)) id {-# INLINE iviews #-} optics-core-0.4.1.1/src/Optics/IxLens.hs0000644000000000000000000000752007346545000016065 0ustar0000000000000000-- | -- Module: Optics.IxLens -- Description: An indexed version of a 'Optics.Lens.Lens'. -- -- An 'IxLens' is an indexed version of a 'Optics.Lens.Lens'. See the "Indexed -- optics" section of the overview documentation in the @Optics@ module of the -- main @optics@ package for more details on indexed optics. -- module Optics.IxLens ( -- * Formation IxLens , IxLens' -- * Introduction , ilens -- * Elimination -- | An 'IxLens' is in particular an 'Optics.IxGetter.IxGetter' and an -- 'Optics.IxSetter.IxSetter', therefore you can specialise types to obtain: -- -- @ -- 'Optics.IxGetter.iview' :: 'IxLens' i s t a b -> s -> (i, a) -- @ -- -- @ -- 'Optics.IxSetter.iover' :: 'IxLens' i s t a b -> (i -> a -> b) -> s -> t -- 'Optics.IxSetter.iset' :: 'IxLens' i s t a b -> (i -> b) -> s -> t -- @ -- * Additional introduction forms , chosen , devoid , ifst , isnd -- * Subtyping , A_Lens -- * van Laarhoven encoding , IxLensVL , IxLensVL' , ilensVL , toIxLensVL , withIxLensVL ) where import Data.Void import Data.Profunctor.Indexed import Optics.Internal.Indexed import Optics.Internal.Optic import Optics.Internal.Utils -- | Type synonym for a type-modifying indexed lens. type IxLens i s t a b = Optic A_Lens (WithIx i) s t a b -- | Type synonym for a type-preserving indexed lens. type IxLens' i s a = Optic' A_Lens (WithIx i) s a -- | Type synonym for a type-modifying van Laarhoven indexed lens. type IxLensVL i s t a b = forall f. Functor f => (i -> a -> f b) -> s -> f t -- | Type synonym for a type-preserving van Laarhoven indexed lens. type IxLensVL' i s a = IxLensVL i s s a a -- | Build an indexed lens from a getter and a setter. -- -- If you want to build an 'IxLens' from the van Laarhoven representation, use -- 'ilensVL'. ilens :: (s -> (i, a)) -> (s -> b -> t) -> IxLens i s t a b ilens get set = ilensVL $ \f s -> set s <$> uncurry' f (get s) {-# INLINE ilens #-} -- | Build an indexed lens from the van Laarhoven representation. ilensVL :: IxLensVL i s t a b -> IxLens i s t a b ilensVL f = Optic (ilinear f) {-# INLINE ilensVL #-} -- | Convert an indexed lens to its van Laarhoven representation. toIxLensVL :: (Is k A_Lens, is `HasSingleIndex` i) => Optic k is s t a b -> IxLensVL i s t a b toIxLensVL o = \f -> runIxStar (getOptic (castOptic @A_Lens o) (IxStar f)) id {-# INLINE toIxLensVL #-} -- | Work with an indexed lens in the van Laarhoven representation. withIxLensVL :: (Is k A_Lens, is `HasSingleIndex` i) => Optic k is s t a b -> (IxLensVL i s t a b -> r) -> r withIxLensVL o k = k (toIxLensVL o) {-# INLINE withIxLensVL #-} ---------------------------------------- -- Lenses -- | Focus on both sides of an 'Either'. chosen :: IxLens (Either () ()) (Either a a) (Either b b) a b chosen = ilensVL $ \f -> \case Left a -> Left <$> f (Left ()) a Right a -> Right <$> f (Right ()) a {-# INLINE chosen #-} -- | There is an indexed field for every type in the 'Void'. -- -- >>> set (mapped % devoid) 1 [] -- [] -- -- >>> over (_Just % devoid) abs Nothing -- Nothing -- devoid :: IxLens' i Void a devoid = ilens absurd const {-# INLINE devoid #-} -- | Indexed '_1' with other half of a pair as an index. -- -- See 'isnd' for examples. -- -- @since 0.4 -- ifst :: IxLens i (a, i) (b, i) a b ifst = ilens (\(a, i) -> (i, a)) (\(_,i) b -> (b, i)) -- | Indexed '_2' with other half of a pair as an index. -- Specialized version of 'itraversed' to pairs, which can be 'IxLens'. -- -- >>> iview isnd ('a', True) -- ('a',True) -- -- That is not possible with 'itraversed', because it is an 'IxTraversal'. -- -- >>> :t itraversed :: IxTraversal i (i, a) (i, b) a b -- itraversed :: IxTraversal i (i, a) (i, b) a b -- :: IxTraversal i (i, a) (i, b) a b -- -- @since 0.4 -- isnd :: IxLens i (i, a) (i, b) a b isnd = ilens id (\(i,_) b -> (i, b)) -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/IxSetter.hs0000644000000000000000000000574007346545000016434 0ustar0000000000000000{-# LANGUAGE DataKinds #-} -- | -- Module: Optics.IxSetter -- Description: An indexed version of a 'Optics.Setter.Setter'. -- -- An 'IxSetter' is an indexed version of a 'Optics.Setter.Setter'. See the -- "Indexed optics" section of the overview documentation in the @Optics@ module -- of the main @optics@ package for more details on indexed optics. -- module Optics.IxSetter ( -- * Formation IxSetter , IxSetter' -- * Introduction , isets -- * Elimination , iover -- * Computation -- | -- -- @ -- 'iover' ('isets' f) ≡ f -- @ -- * Well-formedness -- | -- -- * __PutPut__: Setting twice is the same as setting once: -- -- @ -- 'Optics.Setter.iset' l v' ('Optics.Setter.iset' l v s) ≡ 'Optics.Setter.iset' l v' s -- @ -- -- * __Functoriality__: 'IxSetter's must preserve identities and composition: -- -- @ -- 'iover' s ('const' 'id') ≡ 'id' -- 'iover' s f '.' 'iover' s g ≡ 'iover' s (\i -> f i '.' g i) -- @ -- * Additional introduction forms , imapped -- * Additional elimination forms , iset , iset' , iover' -- * Subtyping , A_Setter -- * Re-exports , FunctorWithIndex(..) ) where import Data.Profunctor.Indexed import Optics.Internal.Indexed import Optics.Internal.Indexed.Classes import Optics.Internal.IxSetter import Optics.Internal.Optic import Optics.Internal.Utils -- | Type synonym for a type-modifying indexed setter. type IxSetter i s t a b = Optic A_Setter (WithIx i) s t a b -- | Type synonym for a type-preserving indexed setter. type IxSetter' i s a = Optic' A_Setter (WithIx i) s a -- | Apply an indexed setter as a modifier. iover :: (Is k A_Setter, is `HasSingleIndex` i) => Optic k is s t a b -> (i -> a -> b) -> s -> t iover o = \f -> runIxFunArrow (getOptic (castOptic @A_Setter o) (IxFunArrow f)) id {-# INLINE iover #-} -- | Apply an indexed setter as a modifier, strictly. iover' :: (Is k A_Setter, is `HasSingleIndex` i) => Optic k is s t a b -> (i -> a -> b) -> s -> t iover' o = \f -> let star = getOptic (castOptic @A_Setter o) $ IxStar (\i -> wrapIdentity' . f i) in unwrapIdentity' . runIxStar star id {-# INLINE iover' #-} -- | Apply an indexed setter. -- -- @ -- 'iset' o f ≡ 'iover' o (\i _ -> f i) -- @ -- iset :: (Is k A_Setter, is `HasSingleIndex` i) => Optic k is s t a b -> (i -> b) -> s -> t iset o = \f -> iover o (\i _ -> f i) {-# INLINE iset #-} -- | Apply an indexed setter, strictly. iset' :: (Is k A_Setter, is `HasSingleIndex` i) => Optic k is s t a b -> (i -> b) -> s -> t iset' o = \f -> iover' o (\i _ -> f i) {-# INLINE iset' #-} -- | Build an indexed setter from a function to modify the element(s). isets :: ((i -> a -> b) -> s -> t) -> IxSetter i s t a b isets f = Optic (iroam f) {-# INLINE isets #-} -- | Indexed setter via the 'FunctorWithIndex' class. -- -- @ -- 'iover' 'imapped' ≡ 'imap' -- @ imapped :: FunctorWithIndex i f => IxSetter i (f a) (f b) a b imapped = Optic imapped__ {-# INLINE imapped #-} optics-core-0.4.1.1/src/Optics/IxTraversal.hs0000644000000000000000000003533707346545000017136 0ustar0000000000000000{-# LANGUAGE DataKinds #-} -- | -- Module: Optics.IxTraversal -- Description: An indexed version of a 'Optics.Traversal.Traversal'. -- -- An 'IxTraversal' is an indexed version of a 'Optics.Traversal.Traversal'. -- See the "Indexed optics" section of the overview documentation in the -- @Optics@ module of the main @optics@ package for more details on indexed -- optics. -- module Optics.IxTraversal ( -- * Formation IxTraversal , IxTraversal' -- * Introduction , itraversalVL -- * Elimination , itraverseOf -- * Computation -- | -- -- @ -- 'itraverseOf' ('itraversalVL' f) ≡ f -- @ -- * Well-formedness -- | -- -- @ -- 'itraverseOf' o ('const' 'pure') ≡ 'pure' -- 'fmap' ('itraverseOf' o f) . 'itraverseOf' o g ≡ 'Data.Functor.Compose.getCompose' . 'itraverseOf' o (\\ i -> 'Data.Functor.Compose.Compose' . 'fmap' (f i) . g i) -- @ -- -- * Additional introduction forms -- | See also 'Optics.Each.Core.each', which is an 'IxTraversal' over each element of a (potentially monomorphic) container. , itraversed , ignored , elementsOf , elements , elementOf , element -- * Additional elimination forms , iforOf , imapAccumLOf , imapAccumROf , iscanl1Of , iscanr1Of , ifailover , ifailover' -- * Combinators , indices , ibackwards , ipartsOf , isingular -- * Monoid structure -- | 'IxTraversal' admits a (partial) monoid structure where 'iadjoin' -- combines non-overlapping indexed traversals, and the identity element is -- 'ignored' (which traverses no elements). -- -- If you merely need an 'IxFold', you can use indexed traversals as indexed -- folds and combine them with one of the monoid structures on indexed folds -- (see "Optics.IxFold#monoids"). In particular, 'isumming' can be used to -- concatenate results from two traversals, and 'ifailing' will returns -- results from the second traversal only if the first returns no results. -- -- There is no 'Semigroup' or 'Monoid' instance for 'IxTraversal', because -- there is not a unique choice of monoid to use that works for all optics, -- and the ('<>') operator could not be used to combine optics of different -- kinds. , iadjoin -- * Subtyping , A_Traversal -- * van Laarhoven encoding -- | The van Laarhoven representation of an 'IxTraversal' directly expresses -- how it lifts an effectful operation @I -> A -> F B@ on elements and their -- indices to act on structures @S -> F T@. Thus 'itraverseOf' converts an -- 'IxTraversal' to an 'IxTraversalVL'. , IxTraversalVL , IxTraversalVL' -- * Re-exports , TraversableWithIndex(..) ) where import Control.Applicative.Backwards import Control.Monad.Trans.State import Data.Functor.Identity import Data.Profunctor.Indexed import Optics.Internal.Indexed import Optics.Internal.Indexed.Classes import Optics.Internal.IxTraversal import Optics.Internal.Optic import Optics.Internal.Utils import Optics.IxAffineTraversal import Optics.IxLens import Optics.IxFold import Optics.ReadOnly import Optics.Traversal -- | Type synonym for a type-modifying indexed traversal. type IxTraversal i s t a b = Optic A_Traversal (WithIx i) s t a b -- | Type synonym for a type-preserving indexed traversal. type IxTraversal' i s a = Optic' A_Traversal (WithIx i) s a -- | Type synonym for a type-modifying van Laarhoven indexed traversal. type IxTraversalVL i s t a b = forall f. Applicative f => (i -> a -> f b) -> s -> f t -- | Type synonym for a type-preserving van Laarhoven indexed traversal. type IxTraversalVL' i s a = IxTraversalVL i s s a a -- | Build an indexed traversal from the van Laarhoven representation. -- -- @ -- 'itraversalVL' '.' 'itraverseOf' ≡ 'id' -- 'itraverseOf' '.' 'itraversalVL' ≡ 'id' -- @ itraversalVL :: IxTraversalVL i s t a b -> IxTraversal i s t a b itraversalVL t = Optic (iwander t) {-# INLINE itraversalVL #-} ---------------------------------------- -- | Map each element of a structure targeted by an 'IxTraversal' (supplying the -- index), evaluate these actions from left to right, and collect the results. -- -- This yields the van Laarhoven representation of an indexed traversal. itraverseOf :: (Is k A_Traversal, Applicative f, is `HasSingleIndex` i) => Optic k is s t a b -> (i -> a -> f b) -> s -> f t itraverseOf o = \f -> runIxStar (getOptic (castOptic @A_Traversal o) (IxStar f)) id {-# INLINE itraverseOf #-} -- | A version of 'itraverseOf' with the arguments flipped. iforOf :: (Is k A_Traversal, Applicative f, is `HasSingleIndex` i) => Optic k is s t a b -> s -> (i -> a -> f b) -> f t iforOf = flip . itraverseOf {-# INLINE iforOf #-} -- | Generalizes 'Data.Traversable.mapAccumL' to an arbitrary 'IxTraversal'. -- -- 'imapAccumLOf' accumulates state from left to right. -- -- @ -- 'Optics.Traversal.mapAccumLOf' o ≡ 'imapAccumLOf' o '.' 'const' -- @ imapAccumLOf :: (Is k A_Traversal, is `HasSingleIndex` i) => Optic k is s t a b -> (i -> acc -> a -> (b, acc)) -> acc -> s -> (t, acc) imapAccumLOf o = \f acc0 s -> let g i a = state $ \acc -> f i acc a in runState (itraverseOf o g s) acc0 {-# INLINE imapAccumLOf #-} -- | Generalizes 'Data.Traversable.mapAccumR' to an arbitrary 'IxTraversal'. -- -- 'imapAccumROf' accumulates state from right to left. -- -- @ -- 'Optics.Traversal.mapAccumROf' o ≡ 'imapAccumROf' o '.' 'const' -- @ imapAccumROf :: (Is k A_Traversal, is `HasSingleIndex` i) => Optic k is s t a b -> (i -> acc -> a -> (b, acc)) -> acc -> s -> (t, acc) imapAccumROf = imapAccumLOf . ibackwards {-# INLINE imapAccumROf #-} -- | This permits the use of 'scanl1' over an arbitrary 'IxTraversal'. iscanl1Of :: (Is k A_Traversal, is `HasSingleIndex` i) => Optic k is s t a a -> (i -> a -> a -> a) -> s -> t iscanl1Of o = \f -> let step i ms a = case ms of Nothing -> (a, Just a) Just s -> let r = f i s a in (r, Just r) in fst . imapAccumLOf o step Nothing {-# INLINE iscanl1Of #-} -- | This permits the use of 'scanr1' over an arbitrary 'IxTraversal'. iscanr1Of :: (Is k A_Traversal, is `HasSingleIndex` i) => Optic k is s t a a -> (i -> a -> a -> a) -> s -> t iscanr1Of o f = fst . imapAccumROf o step Nothing where step i ms a = case ms of Nothing -> (a, Just a) Just s -> let r = f i a s in (r, Just r) {-# INLINE iscanr1Of #-} -- | Try to map a function which uses the index over this 'IxTraversal', -- returning 'Nothing' if the 'IxTraversal' has no targets. ifailover :: (Is k A_Traversal, is `HasSingleIndex` i) => Optic k is s t a b -> (i -> a -> b) -> s -> Maybe t ifailover o = \f s -> let OrT visited t = itraverseOf o (\i -> wrapOrT . Identity #. f i) s in if visited then Just (runIdentity t) else Nothing {-# INLINE ifailover #-} -- | Version of 'ifailover' strict in the application of the function. ifailover' :: (Is k A_Traversal, is `HasSingleIndex` i) => Optic k is s t a b -> (i -> a -> b) -> s -> Maybe t ifailover' o = \f s -> let OrT visited t = itraverseOf o (\i -> wrapOrT . wrapIdentity' . f i) s in if visited then Just (unwrapIdentity' t) else Nothing {-# INLINE ifailover' #-} ---------------------------------------- -- Traversals -- | Indexed traversal via the 'TraversableWithIndex' class. -- -- @ -- 'itraverseOf' 'itraversed' ≡ 'itraverse' -- @ -- -- >>> iover (itraversed <%> itraversed) (,) ["ab", "cd"] -- [[((0,0),'a'),((0,1),'b')],[((1,0),'c'),((1,1),'d')]] -- itraversed :: TraversableWithIndex i f => IxTraversal i (f a) (f b) a b itraversed = Optic itraversed__ {-# INLINE itraversed #-} ---------------------------------------- -- Traversal combinators -- | Filter results of an 'IxTraversal' that don't satisfy a predicate on the -- indices. -- -- >>> toListOf (itraversed %& indices even) "foobar" -- "foa" -- indices :: (Is k A_Traversal, is `HasSingleIndex` i) => (i -> Bool) -> Optic k is s t a a -> IxTraversal i s t a a indices p o = itraversalVL $ \f -> itraverseOf o $ \i a -> if p i then f i a else pure a {-# INLINE indices #-} -- | This allows you to 'traverse' the elements of an indexed traversal in the -- opposite order. ibackwards :: (Is k A_Traversal, is `HasSingleIndex` i) => Optic k is s t a b -> IxTraversal i s t a b ibackwards o = conjoined (backwards o) $ itraversalVL $ \f -> forwards #. itraverseOf o (\i -> Backwards #. f i) {-# INLINE ibackwards #-} -- | Traverse selected elements of a 'Traversal' where their ordinal positions -- match a predicate. elementsOf :: Is k A_Traversal => Optic k is s t a a -> (Int -> Bool) -> IxTraversal Int s t a a elementsOf o = \p -> itraversalVL $ \f -> indexing (traverseOf o) $ \i a -> if p i then f i a else pure a {-# INLINE elementsOf #-} -- | Traverse elements of a 'Traversable' container where their ordinal -- positions match a predicate. -- -- @ -- 'elements' ≡ 'elementsOf' 'traverse' -- @ elements :: Traversable f => (Int -> Bool) -> IxTraversal' Int (f a) a elements = elementsOf traversed {-# INLINE elements #-} -- | Traverse the /nth/ element of a 'Traversal' if it exists. elementOf :: Is k A_Traversal => Optic' k is s a -> Int -> IxAffineTraversal' Int s a elementOf o = \i -> isingular $ elementsOf o (== i) {-# INLINE elementOf #-} -- | Traverse the /nth/ element of a 'Traversable' container. -- -- @ -- 'element' ≡ 'elementOf' 'traversed' -- @ element :: Traversable f => Int -> IxAffineTraversal' Int (f a) a element = elementOf traversed {-# INLINE element #-} -- | An indexed version of 'partsOf' that receives the entire list of indices as -- its indices. ipartsOf :: forall k is i s t a. (Is k A_Traversal, is `HasSingleIndex` i) => Optic k is s t a a -> IxLens [i] s t [a] [a] ipartsOf o = conjoined (partsOf o) $ ilensVL $ \f s -> evalState (traverseOf o update s) <$> uncurry' f (unzip $ itoListOf (getting $ castOptic @A_Traversal o) s) where update a = get >>= \case [] -> pure a a' : as' -> put as' >> pure a' {-# INLINE ipartsOf #-} -- | Convert an indexed traversal to an 'IxAffineTraversal' that visits the -- first element of the original traversal. -- -- For the fold version see 'Optics.IxFold.ipre'. -- -- >>> [1,2,3] & iover (isingular itraversed) (-) -- [-1,2,3] -- -- @since 0.3 isingular :: forall k is i s a. (Is k A_Traversal, is `HasSingleIndex` i) => Optic' k is s a -> IxAffineTraversal' i s a isingular o = conjoined (singular o) $ iatraversalVL $ \point f s -> case iheadOf (castOptic @A_Traversal o) s of Nothing -> point s Just (i, a) -> evalState (traverseOf o update s) . Just <$> f i a where update a = get >>= \case Just a' -> put Nothing >> pure a' Nothing -> pure a {-# INLINE isingular #-} -- | Combine two disjoint indexed traversals into one. -- -- >>> iover (_1 % itraversed `iadjoin` _2 % itraversed) (+) ([0, 0, 0], (3, 5)) -- ([0,1,2],(3,8)) -- -- /Note:/ if the argument traversals are not disjoint, the result will not -- respect the 'IxTraversal' laws, because it will visit the same element multiple -- times. See section 7 of -- -- by Bird et al. for why this is illegal. -- -- >>> iview (ipartsOf (each `iadjoin` each)) ("x","y") -- ([0,1,0,1],["x","y","x","y"]) -- >>> iset (ipartsOf (each `iadjoin` each)) (const ["a","b","c","d"]) ("x","y") -- ("c","d") -- -- For the 'IxFold' version see 'Optics.IxFold.isumming'. -- -- @since 0.4 -- iadjoin :: (Is k A_Traversal, Is l A_Traversal, is `HasSingleIndex` i) => Optic' k is s a -> Optic' l is s a -> IxTraversal' i s a iadjoin o1 o2 = conjoined (adjoin o1 o2) (combined % traversed % itraversed) where combined = traversalVL $ \f s0 -> (\r1 r2 -> let s1 = evalState (traverseOf o1 update s0) r1 s2 = evalState (traverseOf o2 update s1) r2 in s2 ) <$> f (itoListOf (castOptic @A_Traversal o1) s0) <*> f (itoListOf (castOptic @A_Traversal o2) s0) update a = get >>= \case (_, a') : as' -> put as' >> pure a' [] -> pure a infixr 6 `iadjoin` -- Same as (<>) {-# INLINE [1] iadjoin #-} {-# RULES "iadjoin_12_3" forall o1 o2 o3. iadjoin o1 (iadjoin o2 o3) = iadjoin3 o1 o2 o3 "iadjoin_21_3" forall o1 o2 o3. iadjoin (iadjoin o1 o2) o3 = iadjoin3 o1 o2 o3 "iadjoin_13_4" forall o1 o2 o3 o4. iadjoin o1 (iadjoin3 o2 o3 o4) = iadjoin4 o1 o2 o3 o4 "iadjoin_31_4" forall o1 o2 o3 o4. iadjoin (iadjoin3 o1 o2 o3) o4 = iadjoin4 o1 o2 o3 o4 #-} -- | Triple 'iadjoin' for optimizing multiple 'iadjoin's with rewrite rules. iadjoin3 :: (Is k1 A_Traversal, Is k2 A_Traversal, Is k3 A_Traversal, is `HasSingleIndex` i ) => Optic' k1 is s a -> Optic' k2 is s a -> Optic' k3 is s a -> IxTraversal' i s a iadjoin3 o1 o2 o3 = conjoined (o1 `adjoin` o2 `adjoin` o3) (combined % traversed % itraversed) where combined = traversalVL $ \f s0 -> (\r1 r2 r3 -> let s1 = evalState (traverseOf o1 update s0) r1 s2 = evalState (traverseOf o2 update s1) r2 s3 = evalState (traverseOf o3 update s2) r3 in s3 ) <$> f (itoListOf (castOptic @A_Traversal o1) s0) <*> f (itoListOf (castOptic @A_Traversal o2) s0) <*> f (itoListOf (castOptic @A_Traversal o3) s0) update a = get >>= \case (_, a') : as' -> put as' >> pure a' [] -> pure a {-# INLINE [1] iadjoin3 #-} {-# RULES "iadjoin_211_4" forall o1 o2 o3 o4. iadjoin3 (iadjoin o1 o2) o3 o4 = iadjoin4 o1 o2 o3 o4 "iadjoin_121_4" forall o1 o2 o3 o4. iadjoin3 o1 (iadjoin o2 o3) o4 = iadjoin4 o1 o2 o3 o4 "iadjoin_112_4" forall o1 o2 o3 o4. iadjoin3 o1 o2 (iadjoin o3 o4) = iadjoin4 o1 o2 o3 o4 #-} -- | Quadruple 'iadjoin' for optimizing multiple 'iadjoin's with rewrite rules. iadjoin4 :: ( Is k1 A_Traversal, Is k2 A_Traversal, Is k3 A_Traversal, Is k4 A_Traversal , is `HasSingleIndex` i) => Optic' k1 is s a -> Optic' k2 is s a -> Optic' k3 is s a -> Optic' k4 is s a -> IxTraversal' i s a iadjoin4 o1 o2 o3 o4 = conjoined (o1 `adjoin` o2 `adjoin` o3 `adjoin` o4) (combined % traversed % itraversed) where combined = traversalVL $ \f s0 -> (\r1 r2 r3 r4 -> let s1 = evalState (traverseOf o1 update s0) r1 s2 = evalState (traverseOf o2 update s1) r2 s3 = evalState (traverseOf o3 update s2) r3 s4 = evalState (traverseOf o4 update s3) r4 in s4 ) <$> f (itoListOf (castOptic @A_Traversal o1) s0) <*> f (itoListOf (castOptic @A_Traversal o2) s0) <*> f (itoListOf (castOptic @A_Traversal o3) s0) <*> f (itoListOf (castOptic @A_Traversal o4) s0) update a = get >>= \case (_, a') : as' -> put as' >> pure a' [] -> pure a {-# INLINE [1] iadjoin4 #-} -- $setup -- >>> import Data.Void -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Label.hs0000644000000000000000000005151307346545000015703 0ustar0000000000000000{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeInType #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -Wno-orphans #-} -- | -- Module: Optics.Label -- Description: Overloaded labels as optics. -- -- Overloaded labels are a solution to Haskell's namespace problem for records. -- The @-XOverloadedLabels@ extension allows a new expression syntax for labels, -- a prefix @#@ sign followed by an identifier, e.g. @#foo@. These expressions -- can then be given an interpretation that depends on the type at which they -- are used and the text of the label. module Optics.Label ( -- * How to use labels as optics to make working with Haskell's records more convenient -- -- ** The problem -- $problem -- ** The solution -- $solution -- ** The result -- $result -- * Sample usage -- $sampleUsage -- * Technical details -- ** 'LabelOptic' type class LabelOptic(..) , LabelOptic' , GenericLabelOptics(..) -- ** Structure of 'LabelOptic' instances -- $instanceStructure -- ** Explanation of functional dependencies -- $fundepExplanation ) where import Data.Type.Bool import Data.Type.Equality import GHC.Generics import GHC.OverloadedLabels import GHC.TypeLits import Optics.Internal.Generic import Optics.Internal.Magic import Optics.Internal.Optic -- $sampleUsage -- -- #usage# -- -- An example showing how overloaded labels can be used as optics for fields of -- types having a 'Generic' instance. -- -- >>> :set -XDeriveAnyClass -- >>> :set -XDeriveGeneric -- >>> :set -XDuplicateRecordFields -- >>> :set -XOverloadedLabels -- >>> import GHC.Generics (Generic) -- -- >>> :{ -- data Pet -- = Cat { name :: String, age :: Int, lazy :: Bool } -- | Fish { name :: String, age :: Int, lazy :: Bool } -- deriving (Show, Generic) -- :} -- -- >>> :{ -- data Human = Human -- { name :: String -- , age :: Integer -- , pets :: [Pet] -- } deriving (Show, Generic) -- :} -- -- /Note:/ Generic deriving of optics works well on a moderate scale, but for -- ubiquitous usage (and in production in general) we recommend generating them -- with Template Haskell as it scales better in terms of compilation time. For -- more details see @makeFieldLabelsNoPrefix@ from -- -- in the package. -- -- Here is some test data: -- -- >>> :{ -- peter :: Human -- peter = Human { name = "Peter" -- , age = 13 -- , pets = [ Fish { name = "Goldie" -- , age = 1 -- , lazy = False -- } -- , Cat { name = "Loopy" -- , age = 3 -- , lazy = False -- } -- , Cat { name = "Sparky" -- , age = 2 -- , lazy = True -- } -- ] -- } -- :} -- -- Now we can ask for Peter's name: -- -- >>> peter ^. #name -- "Peter" -- -- or for names of his pets: -- -- >>> peter ^.. #pets % folded % #name -- ["Goldie","Loopy","Sparky"] -- -- We can check whether any of his pets is lazy: -- -- >>> orOf (#pets % folded % #lazy) peter -- True -- -- or how things might be be a year from now: -- -- >>> peter & #age %~ (+1) & #pets % mapped % #age %~ (+1) -- Human {name = "Peter", age = 14, pets = [Fish {name = "Goldie", age = 2, lazy = False},Cat {name = "Loopy", age = 4, lazy = False},Cat {name = "Sparky", age = 3, lazy = True}]} -- -- Perhaps Peter is going on vacation and needs to leave his pets at home: -- -- >>> peter & #pets .~ [] -- Human {name = "Peter", age = 13, pets = []} -- $problem -- -- Standard Haskell records are a common source of frustration amongst seasoned -- Haskell programmers. Their main issues are: -- -- (1) Inability to define multiple data types sharing field names in the same -- module. -- -- (2) Pollution of global namespace as every field accessor is also a top-level -- function. -- -- (3) Clunky update syntax, especially when nested fields get involved. -- -- Over the years multiple language extensions were proposed and implemented to -- alleviate these issues. We're quite close to having a reasonable solution -- with the following trifecta: -- -- - @@ - introduced in GHC 8.0.1, addresses (1) -- -- - @@ and @@ - introduced in GHC 9.2.1, addresses (2) -- -- - @@ - restricted version introduced in GHC 9.2.1, addresses (3) -- -- It needs to be noted however that @OverloadedRecordUpdate@ is not yet usable -- out of the box as it requires the user to enable @RebindableSyntax@ and -- provide their own @HasField@ class. -- -- Is there no hope then for people who would like to work with records in a -- reasonable way without waiting? Not necessarily, as by following a couple of -- simple patterns we can get pretty much the same (and more) features with -- labels as optics, just with a slightly more verbose syntax. -- $solution -- -- === Prefixless fields with @DuplicateRecordFields@ -- -- We necessarily want field names to be prefixless, i.e. @field@ to be a field -- name and @#field@ to be an overloaded label that becomes an optic refering to -- this field in the appropriate context. With this approach we get working -- autocompletion and jump-to-definition in editors supporting @ctags@/@etags@ -- in combination with @@, -- both of which (especially the latter) are very important for developer's -- productivity in real-world code bases. -- -- Let's look at data types defined with this approach in mind: -- -- @ -- {-\# LANGUAGE DuplicateRecordFields \#-} -- -- import Data.Time -- -- data User = User { id :: Int -- , name :: String -- , joined :: UTCTime -- , movies :: [Movie] -- } -- -- data Movie = Movie { id :: Int -- , name :: String -- , releaseDate :: UTCTime -- } -- @ -- -- Then appropriate 'LabelOptic' instances can be either written by hand, -- seamlessly derived via generic representation (see the -- section for more details) -- or generated with Template Haskell functions -- (defined in -- -- module from -- package) with -- -- @ -- makeFieldLabelsNoPrefix ''User -- makeFieldLabelsNoPrefix ''Movie -- @ -- -- Generally speaking, both techniques trade blows in terms of compile time and -- run time resources. Generic optics are a bit slower to compile without -- optimizations than Template Haskell generated ones and their updating part -- might be slightly slower for larger data types with GHC < 9.2. On the other -- hand, generic optics are much more developer friendly. -- -- /Note:/ there exists a similar approach that involves prefixing field names -- (either with the underscore or name of the data type) and generation of -- lenses as ordinary functions so that @prefixField@ is the ordinary field name -- and @field@ is the lens referencing it. The drawback of such solution is -- inability to get working jump-to-definition for field names, which makes -- navigation in unfamiliar code bases significantly harder, so it's not -- recommended. -- -- === Emulation of @NoFieldSelectors@ -- -- Prefixless fields (especially ones with common names such as @id@ or @name@) -- leak into global namespace as accessor functions and can generate a lot of -- name clashes. If you can't use GHC >= 9.2 and take advantage of the -- @NoFieldSelectors@ language extension, this can be alleviated by splitting -- modules defining types into two, namely: -- -- (1) A private one that exports full type definitions, i.e. with their fields -- and constructors. -- -- (2) A public one that exports only constructors (or no constructors at all if -- the data type in question is opaque). -- -- There is no notion of private and public modules within a single cabal -- target, but we can hint at it e.g. by naming the public module @T@ and -- private @T.Internal@. -- -- An example: -- -- Private module: -- -- @ -- {-\# LANGUAGE DataKinds \#-} -- {-\# LANGUAGE FlexibleInstances \#-} -- {-\# LANGUAGE MultiParamTypeClasses \#-} -- {-\# LANGUAGE TemplateHaskell \#-} -- {-\# LANGUAGE TypeFamilies \#-} -- {-\# LANGUAGE UndecidableInstances \#-} -- module User.Internal (User(..)) where -- -- import Optics.TH -- -- data User = User { id :: Int -- , name :: String -- } -- -- makeFieldLabelsNoPrefix ''User -- -- ... -- @ -- -- Public module: -- -- @ -- module User (User(User)) where -- -- import User.Internal -- -- ... -- @ -- -- Then, whenever we're dealing with a value of type @User@ and want to read or -- modify its fields, we can use corresponding labels without having to import -- @User.Internal@. Importing @User@ is enough because it provides appropriate -- 'LabelOptic' instances through @User.Internal@ which enables labels to be -- interpreted as optics in the appropriate context. -- -- /Note:/ if you plan to completely hide (some of) the fields of a data type, -- you need to skip defining the corresponding 'LabelOptic' instances for them -- (in case you want fields to be read only, you can make the optic kind of the -- coresponding 'LabelOptic' 'A_Getter' instead of 'A_Lens'). It's because -- Haskell makes it impossible to selectively hide instances, so once a -- 'LabelOptic' instance is defined, it'll always be possible to use a label -- that desugars to its usage whenever a module with its definition is -- (transitively) imported. -- -- @ -- {-\# LANGUAGE OverloadedLabels #-} -- -- import Optics -- import User -- -- greetUser :: User -> String -- greetUser user = "Hello " ++ user ^. #name ++ "!" -- -- addSurname :: String -> User -> User -- addSurname surname user = user & #name %~ (++ " " ++ surname) -- @ -- -- But what if we want to create a new @User@ with the record syntax? Importing -- @User@ module is not sufficient since it doesn't export @User@'s -- fields. However, if we import @User.Internal@ /fully qualified/ and make use -- of the fact that field names used within the record syntax don't have to be -- prefixed when @DisambiguateRecordFields@ language extension is enabled, it -- works out: -- -- @ -- {-\# LANGUAGE DisambiguateRecordFields \#-} -- -- import User -- import qualified User.Internal -- -- newUser :: User -- newUser = User { id = 1 -- not User.Internal.id -- , name = \"Ian\" -- not User.Internal.name -- } -- @ -- -- This way top-level field accessor functions stay in their own qualified -- namespace and don't generate name clashes, yet they can be used without -- prefix within the record syntax. -- $result -- -- When we follow the above conventions for data types in our application, we -- get: -- -- (1) Prefixless field names that don't pollute global namespace (with the -- internal module qualification trick). -- -- (2) Working tags based jump-to-definition for field names (as @field@ is the -- ordinary field, whereas @#field@ is the lens referencing it). -- -- (3) The full power of optics at our disposal, should we ever need it. -- $instanceStructure #structure# -- -- You might wonder why instances generated with Template Haskell have the -- following form: -- -- @ -- instance (k ~ A_Lens, a ~ [Pet], b ~ [Pet]) => LabelOptic "pets" k Human Human a b where -- ... -- @ -- -- instead of -- -- @ -- instance LabelOptic "pets" A_Lens Human Human [Pet] [Pet] where -- ... -- @ -- -- The reason is that using the first form ensures that it is enough for GHC to -- match on the instance if either @s@ or @t@ is known (as equality constraints -- are solved after the instance matches), which not only makes type inference -- better, but also allows it to generate better error messages. -- -- >>> :set -XDataKinds -- >>> :set -XFlexibleInstances -- >>> :set -XMultiParamTypeClasses -- >>> :set -XTypeFamilies -- >>> :set -XUndecidableInstances -- >>> :{ -- data Pet = Dog { name :: String } -- | Cat { name :: String } -- deriving Show -- :} -- -- >>> :{ -- data Human1 = Human1 { pets :: [Pet] } -- deriving Show -- instance LabelOptic "pets" A_Lens Human1 Human1 [Pet] [Pet] where -- labelOptic = lensVL $ \f (Human1 pets) -> Human1 <$> f pets -- :} -- -- >>> :{ -- data Human2 = Human2 { pets :: [Pet] } -- deriving Show -- instance (k ~ A_Lens, a ~ [Pet], b ~ [Pet]) => LabelOptic "pets" k Human2 Human2 a b where -- labelOptic = lensVL $ \f (Human2 pets) -> Human2 <$> f pets -- :} -- -- >>> let human1 = Human1 [Dog "Lucky"] -- >>> let human2 = Human2 [Cat "Sleepy"] -- -- Let's have a look how these two instance definitions differ. -- -- >>> human1 & #pets .~ [] -- ... -- ...No instance for LabelOptic "pets" ‘A_Lens’ ‘Human1’ ‘()’ ‘[Pet]’ ‘[a0]’ -- ... -- -- >>> human2 & #pets .~ [] -- Human2 {pets = []} -- -- That's because an empty list doesn't have a type @[Pet]@, it has a type @[r]@ -- and GHC doesn't have enough information to match on the instance we -- provided. We'd need to either annotate the list: -- -- >>> human1 & #pets .~ ([] :: [Pet]) -- Human1 {pets = []} -- -- or the result type: -- -- >>> human1 & #pets .~ [] :: Human1 -- Human1 {pets = []} -- -- both of which are a nuisance. -- -- Here are more examples of confusing error messages if the instance for -- @LabelOptic "pets"@ is written without type equalities: -- -- >>> human1 ^. #pets :: Char -- ... -- ...No instance for LabelOptic "pets" ‘A_Lens’ ‘Human1’ ‘Human1’ ‘Char’ ‘Char’ -- ... -- -- >>> human1 & #pets .~ 'x' -- ... -- ...No instance for LabelOptic "pets" ‘A_Lens’ ‘Human1’ ‘Human1’ ‘[Pet]’ ‘Char’ -- ... -- -- >>> let pets = #pets :: Iso' Human1 [Pet] -- ... -- ...No instance for LabelOptic "pets" ‘An_Iso’ ‘Human1’ ‘Human1’ ‘[Pet]’ ‘[Pet]’ -- ... -- -- If we use the second form, error messages become much more accurate: -- -- >>> human2 ^. #pets :: Char -- ... -- ...Couldn't match type ‘Char’ with ‘[Pet]’ -- ... arising from the overloaded label ‘#pets’ -- ... -- -- >>> human2 & #pets .~ 'x' -- ... -- ...Couldn't match type ‘Char’ with ‘[Pet]’ -- ... arising from the overloaded label ‘#pets’ -- ... -- -- >>> let pets = #pets :: Iso' Human2 [Pet] -- ... -- ...Couldn't match type ‘An_Iso’ with ‘A_Lens’ -- ... arising from the overloaded label ‘#pets’ -- ... -- $fundepExplanation -- -- 'LabelOptic' uses the following functional dependencies to guarantee good -- type inference: -- -- 1. @name s -> k a@ (the optic for the field @name@ in @s@ is of type @k@ and -- focuses on @a@) -- -- 2. @name t -> k b@ (the optic for the field @name@ in @t@ is of type @k@ and -- focuses on @b@) -- -- 3. @name s b -> t@ (replacing the field @name@ in @s@ with @b@ yields @t@) -- -- 4. @name t a -> s@ (replacing the field @name@ in @t@ with @a@ yields @s@) -- -- Dependencies (1) and (2) ensure that when we compose two optics, the middle -- type is unambiguous. -- -- Dependencies (3) and (4) ensure that when we perform a chain of updates, the -- middle type is unambiguous. ---------------------------------------- -- Definitions -- | Support for overloaded labels as optics. -- -- An overloaded label @#foo@ can be used as an optic if there is an instance -- @'LabelOptic' "foo" k s t a b@. -- -- Alternatively, if both @s@ and @t@ have a 'Generic' ('GenericLabelOptics' if -- @explicit-generic-labels@ flag is enabled) instance, a total field of @s@ is -- accessible by a label @#field@ of kind 'A_Lens', whereas its constructor by a -- label @#_Constructor@ of kind 'A_Prism'. class LabelOptic (name :: Symbol) k s t a b | name s -> k a , name t -> k b , name s b -> t , name t a -> s where -- | Used to interpret overloaded label syntax. An overloaded label @#foo@ -- corresponds to @'labelOptic' \@"foo"@. labelOptic :: Optic k NoIx s t a b -- | Type synonym for a type-preserving optic as overloaded label. type LabelOptic' name k s a = LabelOptic name k s s a a data Void0 -- | If for an overloaded label @#label@ there is no instance starting with -- @LabelOptic "label"@ in scope, using it in the context of optics makes GHC -- immediately pick the overlappable instance defined below (since no other -- instance could match). If at this point GHC has no information about @s@ or -- @t@, it ends up picking incoherent instance of 'GenericLabelOptic' defined -- below. Prevent that (if only to be able to inspect most polymorphic types of -- @#foo % #bar@ or @view #foo@ in GHCi) by defining a dummy instance that -- matches all names, thus postponing instance resolution until @s@ or @t@ is -- known. instance ( k ~ An_Iso, a ~ Void0, b ~ Void0 ) => LabelOptic name k Void0 Void0 a b where labelOptic = Optic id -- | If no instance matches, try to use 'Generic' machinery for field access. -- -- For more information have a look at 'Optics.Generic.gfield' and -- 'Optics.Generic.gconstructor'. -- -- @since 0.4 instance {-# OVERLAPPABLE #-} ( GenericLabelOpticContext repDefined name k s t a b ) => LabelOptic name k s t a b where labelOptic = genericOptic @repDefined @name -- | Hide implementation from haddock. type GenericLabelOpticContext repDefined name k s t a b = ( s `HasShapeOf` t , t `HasShapeOf` s #ifdef EXPLICIT_GENERIC_LABELS , repDefined ~ (HasGenericLabelOptics s && HasGenericLabelOptics t) #else , repDefined ~ (Defined (Rep s) && Defined (Rep t)) #endif , Unless repDefined (NoLabelOpticError name k s t a b) , k ~ If (CmpSymbol "_@" name == 'LT && CmpSymbol "_[" name == 'GT) A_Prism A_Lens , GenericOptic repDefined name k s t a b , Dysfunctional name k s t a b ) -- | If there is no specific 'LabelOptic' instance, display a custom type error. type family NoLabelOpticError name k s t a b where NoLabelOpticError name k s t a b = TypeError ('Text "No instance for LabelOptic " ':<>: 'ShowType name ':<>: 'Text " " ':<>: QuoteType k ':<>: 'Text " " ':<>: QuoteType s ':<>: 'Text " " ':<>: QuoteType t ':<>: 'Text " " ':<>: QuoteType a ':<>: 'Text " " ':<>: QuoteType b ':$$: 'Text "Possible solutions:" ':$$: 'Text "- Check and correct spelling of the label" ':$$: 'Text "- Define the LabelOptic instance by hand or via Template Haskell" #ifdef EXPLICIT_GENERIC_LABELS ':$$: 'Text "- Derive a GenericLabelOptics instance for " ':<>: QuoteType s #else ':$$: 'Text "- Derive a Generic instance for " ':<>: QuoteType s #endif ) ---------------------------------------- -- | If the @explicit-generic-labels@ Cabal flag is enabled, only types with -- this instance (which can be trivially derived with @DeriveAnyClass@ -- extension) will be able to use labels as generic optics with a specific type. -- -- It's an option for application developers to disable implicit fallback to -- generic optics for more control. -- -- Libraries using generic labels with their data types should derive this -- instance for compatibility with the @explicit-generic-labels@ flag. -- -- /Note:/ the flag @explicit-generic-labels@ is disabled by default. Enabling -- it is generally unsupported as it might lead to compilation errors of -- dependencies relying on implicit fallback to generic optics. -- -- @since 0.4 class Generic a => GenericLabelOptics a where type HasGenericLabelOptics a :: Bool type HasGenericLabelOptics a = 'True ---------------------------------------- class GenericOptic (repDefined :: Bool) name k s t a b where genericOptic :: Optic k NoIx s t a b instance ( -- We always let GHC enter the GFieldImpl instance because doing so doesn't -- generate any additional error messages and we might get type improvements -- from the HasField constraint to show in the error message. GFieldImpl name s t a b ) => GenericOptic repDefined name A_Lens s t a b where genericOptic = gfieldImpl @name instance ( GConstructorImpl repDefined name s t a b , _name ~ AppendSymbol "_" name ) => GenericOptic repDefined _name A_Prism s t a b where genericOptic = gconstructorImpl @repDefined @name ---------------------------------------- instance (LabelOptic name k s t a b, is ~ NoIx ) => IsLabel name (Optic k is s t a b) where fromLabel = labelOptic @name -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Lens.hs0000644000000000000000000001375107346545000015567 0ustar0000000000000000-- | -- Module: Optics.Lens -- Description: A generalised or first-class field. -- -- A 'Lens' is a generalised or first-class field. -- -- If we have a value @s :: S@, and a @l :: 'Lens'' S A@, we can /get/ -- the "field value" of type @A@ using @'Optics.Getter.view' l s@. We -- can also /update/ (or /put/ or /set/) the value using -- 'Optics.Setter.over' (or 'Optics.Setter.set'). -- -- For example, given the following definitions: -- -- >>> data Human = Human { _name :: String, _location :: String } deriving Show -- >>> let human = Human "Bob" "London" -- -- we can make a 'Lens' for @_name@ field: -- -- >>> let name = lens _name $ \s x -> s { _name = x } -- -- which we can use as a 'Optics.Getter.Getter': -- -- >>> view name human -- "Bob" -- -- or a 'Optics.Setter.Setter': -- -- >>> set name "Robert" human -- Human {_name = "Robert", _location = "London"} -- module Optics.Lens ( -- * Formation Lens , Lens' -- * Introduction , lens -- * Elimination -- | A 'Lens' is in particular a 'Optics.Getter.Getter' and a -- 'Optics.Setter.Setter', therefore you can specialise types to obtain: -- -- @ -- 'Optics.Getter.view' :: 'Lens'' s a -> s -> a -- @ -- -- @ -- 'Optics.Setter.over' :: 'Lens' s t a b -> (a -> b) -> s -> t -- 'Optics.Setter.set' :: 'Lens' s t a b -> b -> s -> t -- @ -- -- If you want to 'Optics.Getter.view' a type-modifying 'Lens' that is -- insufficiently polymorphic to be used as a type-preserving 'Lens'', use -- 'Optics.ReadOnly.getting': -- -- @ -- 'Optics.Getter.view' . 'Optics.ReadOnly.getting' :: 'Lens' s t a b -> s -> a -- @ -- * Computation -- | -- -- @ -- 'Optics.Getter.view' ('lens' f g) s ≡ f s -- 'Optics.Setter.set' ('lens' f g) a s ≡ g s a -- @ -- * Well-formedness -- | -- -- * __GetPut__: You get back what you put in: -- -- @ -- 'Optics.Getter.view' l ('Optics.Setter.set' l v s) ≡ v -- @ -- -- * __PutGet__: Putting back what you got doesn’t change anything: -- -- @ -- 'Optics.Setter.set' l ('Optics.Getter.view' l s) s ≡ s -- @ -- -- * __PutPut__: Setting twice is the same as setting once: -- -- @ -- 'Optics.Setter.set' l v' ('Optics.Setter.set' l v s) ≡ 'Optics.Setter.set' l v' s -- @ -- -- * Additional introduction forms -- | See "Data.Tuple.Optics" for 'Lens'es for tuples. -- -- If you're looking for 'Optics.IxLens.chosen', it was moved to "Optics.IxLens". , equality' , alongside , united -- * Additional elimination forms , withLens -- * Subtyping , A_Lens -- | <> -- * van Laarhoven encoding -- | The van Laarhoven encoding of lenses is isomorphic to the profunctor -- encoding used internally by @optics@, but converting back and forth may -- have a performance penalty. , LensVL , LensVL' , lensVL , toLensVL , withLensVL ) where import Data.Profunctor.Indexed import Optics.Internal.Optic -- | Type synonym for a type-modifying lens. type Lens s t a b = Optic A_Lens NoIx s t a b -- | Type synonym for a type-preserving lens. type Lens' s a = Optic' A_Lens NoIx s a -- | Type synonym for a type-modifying van Laarhoven lens. type LensVL s t a b = forall f. Functor f => (a -> f b) -> s -> f t -- | Type synonym for a type-preserving van Laarhoven lens. type LensVL' s a = LensVL s s a a -- | Build a lens from a getter and a setter, which must respect the -- well-formedness laws. -- -- If you want to build a 'Lens' from the van Laarhoven representation, use -- 'lensVL'. lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b lens get set = Optic $ -- Do not define lens in terms of lensVL, mixing profunctor-style definitions -- with VL style implementation can lead to subpar generated code, -- i.e. updating often gets and then sets as opposed to updating in place. dimap (\s -> (get s, s)) (\(b, s) -> set s b) . first' {-# INLINE lens #-} -- | Work with a lens as a getter and a setter. -- -- @ -- 'withLens' ('lens' f g) k ≡ k f g -- @ withLens :: Is k A_Lens => Optic k is s t a b -> ((s -> a) -> (s -> b -> t) -> r) -> r withLens o k = case getOptic (castOptic @A_Lens o) $ Store id (\_ -> id) of Store get set -> k get set {-# INLINE withLens #-} -- | Build a lens from the van Laarhoven representation. lensVL :: LensVL s t a b -> Lens s t a b lensVL l = Optic (linear l) {-# INLINE lensVL #-} -- | Convert a lens to the van Laarhoven representation. toLensVL :: Is k A_Lens => Optic k is s t a b -> LensVL s t a b toLensVL o = runStar #. getOptic (castOptic @A_Lens o) .# Star {-# INLINE toLensVL #-} -- | Work with a lens in the van Laarhoven representation. withLensVL :: Is k A_Lens => Optic k is s t a b -> (LensVL s t a b -> r) -> r withLensVL o k = k (toLensVL o) {-# INLINE withLensVL #-} ---------------------------------------- -- Lenses -- | Strict version of 'Optics.Iso.equality'. -- -- Useful for strictifying optics with lazy (irrefutable) pattern matching by -- precomposition, e.g. -- -- @ -- 'Data.Tuple.Optics._1'' = 'equality'' % 'Data.Tuple.Optics._1' -- @ equality' :: Lens a b a b equality' = lensVL ($!) {-# INLINE equality' #-} -- | Make a 'Lens' from two other lenses by executing them on their respective -- halves of a product. -- -- >>> (Left 'a', Right 'b') ^. alongside chosen chosen -- ('a','b') -- -- >>> (Left 'a', Right 'b') & alongside chosen chosen .~ ('c','d') -- (Left 'c',Right 'd') alongside :: (Is k A_Lens, Is l A_Lens) => Optic k is s t a b -> Optic l js s' t' a' b' -> Lens (s, s') (t, t') (a, a') (b, b') alongside l r = withLens l $ \getl setl -> withLens r $ \getr setr -> lens (\(s, s') -> (getl s, getr s' )) (\(s, s') (b, b') -> (setl s b, setr s' b')) {-# INLINE alongside #-} -- | We can always retrieve a @()@ from any type. -- -- >>> view united "hello" -- () -- -- >>> set united () "hello" -- "hello" united :: Lens' a () united = lens (const ()) const {-# INLINE united #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Mapping.hs0000644000000000000000000000567307346545000016265 0ustar0000000000000000-- | -- Module: Optics.Mapping -- Description: Lifting optics using 'Functor's 'map'. -- -- This module defines 'mapping', which turns an @'Optic'' k 'NoIx' s a@ into an -- @'Optic'' ('MappedOptic' k) 'NoIx' (f s) (f a)@, in other words optic operating on values -- in a 'Functor'. -- {-# LANGUAGE DataKinds #-} module Optics.Mapping ( MappingOptic (..) ) where import Optics.Getter import Optics.Internal.Indexed import Optics.Internal.Optic import Optics.Iso import Optics.Review -- $setup -- >>> import Optics.Core -- >>> import Optics.Operators -- | Class for optics supporting 'mapping' through a 'Functor'. -- -- @since 0.3 class MappingOptic k f g s t a b where -- | Type family that maps an optic to the optic kind produced by -- 'mapping' using it. type MappedOptic k -- | The 'Optics.Mapping.mapping' can be used to lift optic through a 'Functor'. -- -- @ -- 'mapping' :: 'Iso' s t a b -> 'Iso' (f s) (g t) (f a) (g b) -- 'mapping' :: 'Optics.Lens.Lens' s a -> 'Getter' (f s) (f a) -- 'mapping' :: 'Getter' s a -> 'Getter' (f s) (f a) -- 'mapping' :: 'Optics.Prism.Prism' t b -> 'Review' (g t) (g b) -- 'mapping' :: 'Review' t b -> 'Review' (g t) (g b) -- @ mapping :: "mapping" `AcceptsEmptyIndices` is => Optic k is s t a b -> Optic (MappedOptic k) is (f s) (g t) (f a) (g b) instance (Functor f, Functor g) => MappingOptic An_Iso f g s t a b where type MappedOptic An_Iso = An_Iso mapping k = withIso k $ \sa bt -> iso (fmap sa) (fmap bt) {-# INLINE mapping #-} -- Getter-y optics -- | -- >>> [('a', True), ('b', False)] ^. _1 %& mapping -- "ab" -- -- >>> let v = [[ (('a', True), "foo"), (('b', False), "bar")], [ (('c', True), "xyz") ] ] -- >>> v ^. _1 % _2 %& mapping %& mapping -- [[True,False],[True]] -- instance (Functor f, f ~ g, s ~ t, a ~ b) => MappingOptic A_Getter f g s t a b where type MappedOptic A_Getter = A_Getter mapping o = to (fmap (view o)) {-# INLINE mapping #-} instance (Functor f, f ~ g, s ~ t, a ~ b) => MappingOptic A_ReversedPrism f g s t a b where type MappedOptic A_ReversedPrism = A_Getter mapping o = to (fmap (view o)) {-# INLINE mapping #-} instance (Functor f, f ~ g, s ~ t, a ~ b) => MappingOptic A_Lens f g s t a b where type MappedOptic A_Lens = A_Getter mapping o = to (fmap (view o)) {-# INLINE mapping #-} -- Review-y optics instance (Functor f, f ~ g, s ~ t, a ~ b) => MappingOptic A_Review f g s t a b where type MappedOptic A_Review = A_Review mapping o = unto (fmap (review o)) {-# INLINE mapping #-} instance (Functor f, f ~ g, s ~ t, a ~ b) => MappingOptic A_Prism f g s t a b where type MappedOptic A_Prism = A_Review mapping o = unto (fmap (review o)) {-# INLINE mapping #-} instance (Functor f, f ~ g, s ~ t, a ~ b) => MappingOptic A_ReversedLens f g s t a b where type MappedOptic A_ReversedLens = A_Review mapping o = unto (fmap (review o)) {-# INLINE mapping #-} optics-core-0.4.1.1/src/Optics/Operators.hs0000644000000000000000000000435207346545000016641 0ustar0000000000000000-- | -- Module: Optics.Operators -- Description: Definitions of infix operators for optics. -- -- Defines some infix operators for optics operations. This is a deliberately -- small collection. -- -- If you like operators, you may also wish to import @Optics.State.Operators@ -- from the @optics-extra@ package. -- module Optics.Operators ( (^.) , (^..) , (^?) , (#) , (%~) , (%!~) , (.~) , (!~) , (?~) , (?!~) ) where import Optics.AffineFold import Optics.Fold import Optics.Getter import Optics.Optic import Optics.Review import Optics.Setter -- | Flipped infix version of 'view'. (^.) :: Is k A_Getter => s -> Optic' k is s a -> a (^.) = flip view {-# INLINE (^.) #-} infixl 8 ^. -- | Flipped infix version of 'preview'. (^?) :: Is k An_AffineFold => s -> Optic' k is s a -> Maybe a (^?) = flip preview {-# INLINE (^?) #-} infixl 8 ^? -- | Flipped infix version of 'toListOf'. (^..) :: Is k A_Fold => s -> Optic' k is s a -> [a] (^..) = flip toListOf {-# INLINE (^..) #-} infixl 8 ^.. -- | Infix version of 'review'. (#) :: Is k A_Review => Optic' k is t b -> b -> t (#) = review {-# INLINE (#) #-} infixr 8 # -- | Infix version of 'over'. (%~) :: Is k A_Setter => Optic k is s t a b -> (a -> b) -> s -> t (%~) = over {-# INLINE (%~) #-} infixr 4 %~ -- | Infix version of 'over''. (%!~) :: Is k A_Setter => Optic k is s t a b -> (a -> b) -> s -> t (%!~) = over' {-# INLINE (%!~) #-} infixr 4 %!~ -- | Infix version of 'set'. (.~) :: Is k A_Setter => Optic k is s t a b -> b -> s -> t (.~) = set {-# INLINE (.~) #-} infixr 4 .~ -- | Infix version of 'set''. (!~) :: Is k A_Setter => Optic k is s t a b -> b -> s -> t (!~) = set' {-# INLINE (!~) #-} infixr 4 !~ -- | Set the target of a 'Setter' to 'Just' a value. -- -- @ -- o '?~' b ≡ 'set' o ('Just' b) -- @ -- -- >>> Nothing & equality ?~ 'x' -- Just 'x' -- -- >>> Map.empty & at 3 ?~ 'x' -- fromList [(3,'x')] (?~) :: Is k A_Setter => Optic k is s t a (Maybe b) -> b -> s -> t (?~) = \o -> set o . Just {-# INLINE (?~) #-} infixr 4 ?~ -- | Strict version of ('?~'). (?!~) :: Is k A_Setter => Optic k is s t a (Maybe b) -> b -> s -> t (?!~) = \o !b -> set' o (Just b) {-# INLINE (?!~) #-} infixr 4 ?!~ -- $setup -- >>> import qualified Data.Map as Map -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Operators/0000755000000000000000000000000007346545000016301 5ustar0000000000000000optics-core-0.4.1.1/src/Optics/Operators/Unsafe.hs0000644000000000000000000000134207346545000020056 0ustar0000000000000000-- | -- Module: Optics.Operators.Unsafe -- Description: Definitions of unsafe infix operators for optics. -- module Optics.Operators.Unsafe ( (^?!) ) where import Data.Maybe (fromMaybe) import GHC.Stack (HasCallStack) import Optics.AffineFold import Optics.Optic import Optics.Operators -- | Perform an *UNSAFE* 'head' of an affine fold assuming that it is there. -- -- >>> Left 4 ^?! _Left -- 4 -- -- >>> "world" ^?! ix 3 -- 'l' -- -- >>> [] ^?! _head -- *** Exception: (^?!): empty affine fold -- ... -- -- @since 0.3 (^?!) :: (HasCallStack, Is k An_AffineFold) => s -> Optic' k is s a -> a s ^?! o = fromMaybe (error "(^?!): empty affine fold") (s ^? o) {-# INLINE (^?!) #-} infixl 8 ^?! -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Optic.hs0000644000000000000000000000501507346545000015736 0ustar0000000000000000{-# LANGUAGE CPP #-} -- | -- Module: Optics.Optic -- Description: Common abstraction for all kinds of optics. -- -- This module provides core definitions: -- -- * an opaque 'Optic' type, which is parameterised over a type representing an -- optic kind (instantiated with tag types such as 'A_Lens'); -- -- * the optic composition operator ('%'); -- -- * the subtyping relation 'Is' with an accompanying 'castOptic' function to -- convert an optic kind; -- -- * the 'JoinKinds' class used to find the optic kind resulting from a -- composition. -- -- Each optic kind is identified by a "tag type" (such as 'A_Lens'), which is an -- empty data type. The type of the actual optics (such as 'Optics.Lens.Lens') -- is obtained by applying 'Optic' to the tag type. -- -- See the @Optics@ module in the main @optics@ package for overview -- documentation. -- module Optics.Optic ( OpticKind , Optic , Optic' -- * Subtyping , castOptic , Is , JoinKinds -- * Composition -- | The usual operator for composing optics is ('%'), which allows different -- optic kinds to be composed, automatically calculating the resulting optic -- kind using 'JoinKinds'. -- -- The ('.') function composition operator cannot be used to compose optics, -- because /optics are not functions/. The ('Control.Category..') operator -- from "Control.Category" cannot be used either, because it would not support -- type-changing optics or composing optics of different kinds. , (%) , (%%) , (%&) -- * Monoid structures -- | 'Optics.Fold.Fold'-like optics admit various monoid structures (e.g. see -- "Optics.Fold#monoids"). There is no 'Semigroup' or 'Monoid' instance for -- 'Optic', however, because there is not a unique choice of monoid to use, -- and the ('<>') operator could not be used to combine optics of different -- kinds. -- * Indexed optics -- | See the "Indexed optics" section of the overview documentation in the -- @Optics@ module of the main @optics@ package for more details on indexed -- optics. , IxList , NoIx , WithIx , AppendIndices , NonEmptyIndices , HasSingleIndex , AcceptsEmptyIndices , Curry , CurryCompose(..) -- * Base re-exports , (&) , (<&>) ) where import Data.Function import Optics.Internal.Indexed import Optics.Internal.Optic #if MIN_VERSION_base(4,11,0) import Data.Functor ((<&>)) #else -- | Infix flipped 'fmap'. -- -- @ -- ('<&>') = 'flip' 'fmap' -- @ (<&>) :: Functor f => f a -> (a -> b) -> f b as <&> f = f <$> as {-# INLINE (<&>) #-} infixl 1 <&> #endif optics-core-0.4.1.1/src/Optics/Prism.hs0000644000000000000000000001330707346545000015755 0ustar0000000000000000-- | -- Module: Optics.Prism -- Description: A generalised or first-class constructor. -- -- A 'Prism' generalises the notion of a constructor (just as a -- 'Optics.Lens.Lens' generalises the notion of a field). -- module Optics.Prism ( -- * Formation Prism , Prism' -- * Introduction , prism -- * Elimination -- | A 'Prism' is in particular an 'Optics.AffineFold.AffineFold', -- an 'Optics.AffineTraversal.AffineTraversal', a -- 'Optics.Review.Review' and a 'Optics.Setter.Setter', therefore you can -- specialise types to obtain: -- -- @ -- 'Optics.AffineFold.preview' :: 'Prism'' s a -> s -> Maybe a -- 'Optics.Review.review' :: 'Prism'' s a -> a -> s -- @ -- -- @ -- 'Optics.Setter.over' :: 'Prism' s t a b -> (a -> b) -> s -> t -- 'Optics.Setter.set' :: 'Prism' s t a b -> b -> s -> t -- 'Optics.AffineTraversal.matching' :: 'Prism' s t a b -> s -> Either t a -- @ -- -- If you want to 'Optics.AffineFold.preview' a type-modifying 'Prism' that is -- insufficiently polymorphic to be used as a type-preserving 'Prism'', use -- 'Optics.ReadOnly.getting': -- -- @ -- 'Optics.AffineFold.preview' . 'Optics.ReadOnly.getting' :: 'Prism' s t a b -> s -> 'Maybe' a -- @ -- * Computation -- | -- -- @ -- 'Optics.Review.review' ('prism' f g) ≡ f -- 'Optics.AffineTraversal.matching' ('prism' f g) ≡ g -- @ -- * Well-formedness -- | -- -- @ -- 'Optics.AffineTraversal.matching' o ('Optics.Review.review' o b) ≡ 'Right' b -- 'Optics.AffineTraversal.matching' o s ≡ 'Right' a => 'Optics.Review.review' o a ≡ s -- @ -- * Additional introduction forms -- | See "Data.Maybe.Optics" and "Data.Either.Optics" for 'Prism's for the -- corresponding types, and 'Optics.Cons.Core._Cons', 'Optics.Cons.Core._Snoc' -- and 'Optics.Empty.Core._Empty' for 'Prism's for container types. , prism' , only , nearly -- * Additional elimination forms , withPrism -- * Combinators , aside , without , below -- * Subtyping , A_Prism -- | <> ) where import Control.Monad import Data.Bifunctor import Data.Profunctor.Indexed import Optics.Internal.Optic -- | Type synonym for a type-modifying prism. type Prism s t a b = Optic A_Prism NoIx s t a b -- | Type synonym for a type-preserving prism. type Prism' s a = Optic' A_Prism NoIx s a -- | Build a prism from a constructor and a matcher, which must respect the -- well-formedness laws. -- -- If you want to build a 'Prism' from the van Laarhoven representation, use -- @prismVL@ from the @optics-vl@ package. prism :: (b -> t) -> (s -> Either t a) -> Prism s t a b prism construct match = Optic $ dimap match (either id construct) . right' {-# INLINE prism #-} -- | This is usually used to build a 'Prism'', when you have to use an operation -- like 'Data.Typeable.cast' which already returns a 'Maybe'. prism' :: (b -> s) -> (s -> Maybe a) -> Prism s s a b prism' bs sma = prism bs (\s -> maybe (Left s) Right (sma s)) {-# INLINE prism' #-} -- | Work with a 'Prism' as a constructor and a matcher. withPrism :: Is k A_Prism => Optic k is s t a b -> ((b -> t) -> (s -> Either t a) -> r) -> r withPrism o k = case getOptic (castOptic @A_Prism o) (Market id Right) of Market construct match -> k construct match {-# INLINE withPrism #-} ---------------------------------------- -- | Use a 'Prism' to work over part of a structure. aside :: Is k A_Prism => Optic k is s t a b -> Prism (e, s) (e, t) (e, a) (e, b) aside k = withPrism k $ \bt seta -> prism (fmap bt) $ \(e,s) -> case seta s of Left t -> Left (e,t) Right a -> Right (e,a) {-# INLINE aside #-} -- | Given a pair of prisms, project sums. -- -- Viewing a 'Prism' as a co-'Optics.Lens.Lens', this combinator can be seen to -- be dual to 'Optics.Lens.alongside'. without :: (Is k A_Prism, Is l A_Prism) => Optic k is s t a b -> Optic l is u v c d -> Prism (Either s u) (Either t v) (Either a c) (Either b d) without k = withPrism k $ \bt seta k' -> withPrism k' $ \dv uevc -> prism (bimap bt dv) $ \su -> case su of Left s -> bimap Left Left (seta s) Right u -> bimap Right Right (uevc u) {-# INLINE without #-} -- | Lift a 'Prism' through a 'Traversable' functor, giving a 'Prism' that -- matches only if all the elements of the container match the 'Prism'. below :: (Is k A_Prism, Traversable f) => Optic' k is s a -> Prism' (f s) (f a) below k = withPrism k $ \bt seta -> prism (fmap bt) $ \s -> case traverse seta s of Left _ -> Left s Right t -> Right t {-# INLINE below #-} -- | This 'Prism' compares for exact equality with a given value. -- -- >>> only 4 # () -- 4 -- -- >>> 5 ^? only 4 -- Nothing only :: Eq a => a -> Prism' a () only a = prism' (\() -> a) $ guard . (a ==) {-# INLINE only #-} -- | This 'Prism' compares for approximate equality with a given value and a -- predicate for testing, an example where the value is the empty list and the -- predicate checks that a list is empty (same as 'Optics.Empty._Empty' with the -- 'Optics.Empty.AsEmpty' list instance): -- -- >>> nearly [] null # () -- [] -- >>> [1,2,3,4] ^? nearly [] null -- Nothing -- -- @'nearly' [] 'Prelude.null' :: 'Prism'' [a] ()@ -- -- To comply with the 'Prism' laws the arguments you supply to @nearly a p@ are -- somewhat constrained. -- -- We assume @p x@ holds iff @x ≡ a@. Under that assumption then this is a valid -- 'Prism'. -- -- This is useful when working with a type where you can test equality for only -- a subset of its values, and the prism selects such a value. nearly :: a -> (a -> Bool) -> Prism' a () nearly a p = prism' (\() -> a) $ guard . p {-# INLINE nearly #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Re.hs0000644000000000000000000001210007346545000015217 0ustar0000000000000000-- | -- Module: Optics.Re -- Description: The 're' operator allows some optics to be reversed. -- -- Some optics can be reversed with 're'. This is mainly useful to invert -- 'Optics.Iso.Iso's: -- -- >>> let _Identity = iso runIdentity Identity -- >>> view (_1 % re _Identity) ('x', "yz") -- Identity 'x' -- -- Yet we can use a 'Optics.Lens.Lens' as a 'Optics.Review.Review' too: -- -- >>> review (re _1) ('x', "yz") -- 'x' -- -- In the following diagram, red arrows illustrate how 're' transforms optics. -- The 'Optics.ReversedLens.ReversedLens' and -- 'Optics.ReversedPrism.ReversedPrism' optic kinds are backwards versions of -- 'Optics.Lens.Lens' and 'Optics.Prism.Prism' respectively, and are present so -- that @'re' . 're'@ does not change the optic kind. -- -- <> -- {-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeFamilyDependencies #-} module Optics.Re ( ReversibleOptic(..) ) where import Data.Coerce import Data.Profunctor.Indexed import Optics.Internal.Bi import Optics.Internal.Indexed import Optics.Internal.Optic -- | Class for optics that can be 're'versed. class ReversibleOptic k where -- | Injective type family that maps an optic kind to the optic kind produced -- by 're'versing it. -- -- @ -- 'ReversedOptic' 'An_Iso' = 'An_Iso' -- 'ReversedOptic' 'A_Prism' = 'A_ReversedPrism' -- 'ReversedOptic' 'A_ReversedPrism' = 'A_Prism' -- 'ReversedOptic' 'A_Lens' = 'A_ReversedLens' -- 'ReversedOptic' 'A_ReversedLens' = 'A_Lens' -- 'ReversedOptic' 'A_Getter' = 'A_Review' -- 'ReversedOptic' 'A_Review' = 'A_Getter' -- @ type ReversedOptic k = r | r -> k -- | Reverses optics, turning around 'Optics.Iso.Iso' into 'Optics.Iso.Iso', -- 'Optics.Prism.Prism' into 'Optics.ReversedPrism.ReversedPrism' (and -- back), 'Optics.Lens.Lens' into 'Optics.ReversedLens.ReversedLens' (and back) -- and 'Optics.Getter.Getter' into 'Optics.Review.Review' (and back). re :: "re" `AcceptsEmptyIndices` is => Optic k is s t a b -> Optic (ReversedOptic k) is b a t s instance ReversibleOptic An_Iso where type ReversedOptic An_Iso = An_Iso re o = Optic (re__ o) {-# INLINE re #-} instance ReversibleOptic A_Prism where type ReversedOptic A_Prism = A_ReversedPrism re o = Optic (re__ o) {-# INLINE re #-} instance ReversibleOptic A_ReversedPrism where type ReversedOptic A_ReversedPrism = A_Prism re o = Optic (re__ o) {-# INLINE re #-} instance ReversibleOptic A_Lens where type ReversedOptic A_Lens = A_ReversedLens re o = Optic (re__ o) {-# INLINE re #-} instance ReversibleOptic A_ReversedLens where type ReversedOptic A_ReversedLens = A_Lens re o = Optic (re__ o) {-# INLINE re #-} instance ReversibleOptic A_Getter where type ReversedOptic A_Getter = A_Review re o = Optic (re__ o) {-# INLINE re #-} instance ReversibleOptic A_Review where type ReversedOptic A_Review = A_Getter re o = Optic (re__ o) {-# INLINE re #-} -- | Internal implementation of re. re__ :: (Profunctor p, Constraints k (Re p a b)) => Optic k NoIx s t a b -> Optic__ p i i b a t s re__ o = unRe (getOptic o (Re id)) {-# INLINE re__ #-} ---------------------------------------- -- | Helper for reversing optics. newtype Re p s t i a b = Re { unRe :: p i b a -> p i t s } instance Profunctor p => Profunctor (Re p s t) where dimap f g (Re p) = Re (p . dimap g f) lmap f (Re p) = Re (p . rmap f) rmap g (Re p) = Re (p . lmap g) {-# INLINE dimap #-} {-# INLINE lmap #-} {-# INLINE rmap #-} lcoerce' = lmap coerce rcoerce' = rmap coerce {-# INLINE lcoerce' #-} {-# INLINE rcoerce' #-} conjoined__ = error "conjoined__(Re) shouldn't be reachable" ixcontramap = error "ixcontramap(Re) shouldn't be reachable" instance Bicontravariant p => Bifunctor (Re p s t) where bimap f g (Re p) = Re (p . contrabimap g f) first f (Re p) = Re (p . contrasecond f) second g (Re p) = Re (p . contrafirst g) {-# INLINE bimap #-} {-# INLINE first #-} {-# INLINE second #-} instance Bifunctor p => Bicontravariant (Re p s t) where contrabimap f g (Re p) = Re (p . bimap g f) contrafirst f (Re p) = Re (p . second f) contrasecond g (Re p) = Re (p . first g) {-# INLINE contrabimap #-} {-# INLINE contrafirst #-} {-# INLINE contrasecond #-} instance Strong p => Costrong (Re p s t) where unfirst (Re p) = Re (p . first') unsecond (Re p) = Re (p . second') {-# INLINE unfirst #-} {-# INLINE unsecond #-} instance Costrong p => Strong (Re p s t) where first' (Re p) = Re (p . unfirst) second' (Re p) = Re (p . unsecond) {-# INLINE first' #-} {-# INLINE second' #-} ilinear _ = error "ilinear(Re) shouldn't be reachable" instance Choice p => Cochoice (Re p s t) where unleft (Re p) = Re (p . left') unright (Re p) = Re (p . right') {-# INLINE unleft #-} {-# INLINE unright #-} instance Cochoice p => Choice (Re p s t) where left' (Re p) = Re (p . unleft) right' (Re p) = Re (p . unright) {-# INLINE left' #-} {-# INLINE right' #-} -- $setup -- >>> import Data.Functor.Identity -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/ReadOnly.hs0000644000000000000000000000557207346545000016405 0ustar0000000000000000{-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeInType #-} -- | -- Module: Optics.ReadOnly -- Description: Converting read-write optics into their read-only counterparts. -- -- This module defines 'getting', which turns a read-write optic into its -- read-only counterpart. -- module Optics.ReadOnly ( ToReadOnly(..) ) where import Data.Profunctor.Indexed import Optics.Internal.Bi import Optics.Internal.Optic -- | Class for read-write optics that have their read-only counterparts. class ToReadOnly k s t a b where type ReadOnlyOptic k :: OpticKind -- | Turn read-write optic into its read-only counterpart (or leave read-only -- optics as-is). -- -- This is useful when you have an @optic :: 'Optic' k is s t a b@ of read-write -- kind @k@ such that @s@, @t@, @a@, @b@ are rigid, there is no evidence that -- @s ~ t@ and @a ~ b@ and you want to pass @optic@ to one of the functions -- that accept read-only optic kinds. -- -- Example: -- -- >>> let fstIntToChar = _1 :: Lens (Int, r) (Char, r) Int Char -- -- >>> :t view fstIntToChar -- ... -- ...Couldn't match type ‘Char’ with ‘Int’ -- ... -- -- >>> :t view (getting fstIntToChar) -- view (getting fstIntToChar) :: (Int, r) -> Int getting :: Optic k is s t a b -> Optic' (ReadOnlyOptic k) is s a instance ToReadOnly An_Iso s t a b where type ReadOnlyOptic An_Iso = A_Getter getting o = Optic (getting__ o) {-# INLINE getting #-} instance ToReadOnly A_Lens s t a b where type ReadOnlyOptic A_Lens = A_Getter getting o = Optic (getting__ o) {-# INLINE getting #-} instance ToReadOnly A_Prism s t a b where type ReadOnlyOptic A_Prism = An_AffineFold getting o = Optic (getting__ o) {-# INLINE getting #-} instance ToReadOnly An_AffineTraversal s t a b where type ReadOnlyOptic An_AffineTraversal = An_AffineFold getting o = Optic (getting__ o) {-# INLINE getting #-} instance ToReadOnly A_Traversal s t a b where type ReadOnlyOptic A_Traversal = A_Fold getting o = Optic (getting__ o) {-# INLINE getting #-} instance ToReadOnly A_ReversedPrism s t a b where type ReadOnlyOptic A_ReversedPrism = A_Getter getting o = Optic (getting__ o) {-# INLINE getting #-} instance (s ~ t, a ~ b) => ToReadOnly A_Getter s t a b where type ReadOnlyOptic A_Getter = A_Getter getting = id {-# INLINE getting #-} instance (s ~ t, a ~ b) => ToReadOnly An_AffineFold s t a b where type ReadOnlyOptic An_AffineFold = An_AffineFold getting = id {-# INLINE getting #-} instance (s ~ t, a ~ b) => ToReadOnly A_Fold s t a b where type ReadOnlyOptic A_Fold = A_Fold getting = id {-# INLINE getting #-} -- | Internal implementation of 'getting'. getting__ :: (Profunctor p, Bicontravariant p, Constraints k p) => Optic k is s t a b -> Optic__ p i (Curry is i) s s a a getting__ (Optic o) = rphantom . o . rphantom {-# INLINE getting__ #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/ReversedLens.hs0000644000000000000000000000360607346545000017265 0ustar0000000000000000-- | -- Module: Optics.ReversedLens -- Description: A backwards 'Optics.Lens.Lens'. -- -- A 'ReversedLens' is a backwards 'Optics.Lens.Lens', i.e. a @'ReversedLens' s t -- a b@ is equivalent to a @'Optics.Lens.Lens' b a t s@. These are typically -- produced by calling 'Optics.Re.re' on a 'Optics.Lens.Lens'. They are -- distinguished from a 'Optics.Review.Review' so that @'Optics.Re.re' -- . 'Optics.Re.re'@ on a 'Optics.Lens.Lens' returns a 'Optics.Lens.Lens'. -- module Optics.ReversedLens ( -- * Formation ReversedLens , ReversedLens' -- * Introduction -- | -- -- There is no canonical introduction form for 'ReversedLens', but you can use -- 'Optics.Re.re' to construct one from a 'Optics.Lens.Lens': -- -- @ -- (\\ f g -> 'Optics.Re.re' ('Optics.Lens.lens' f g)) :: (b -> t) -> (b -> s -> a) -> 'ReversedLens' s t a b -- @ -- * Elimination -- | -- -- A 'ReversedLens' is a 'Optics.Review.Review', so you can specialise types to obtain: -- -- @ -- 'Optics.Review.review' :: 'ReversedLens'' s a -> a -> s -- @ -- -- There is no corresponding optic kind for a backwards -- 'Optics.Setter.Setter', but a reversed 'Optics.Setter.set' is definable -- using 'Optics.Re.re': -- -- @ -- 'Optics.Setter.set' . 'Optics.Re.re' :: 'ReversedLens' s t a b -> s -> b -> a -- @ -- * Computation -- | -- -- @ -- 'Optics.Review.review' $ 'Optics.Re.re' ('Optics.Lens.lens' f g) ≡ f -- 'Optics.Setter.set' . 'Optics.Re.re' $ 'Optics.Re.re' ('Optics.Lens.lens' f g) ≡ g -- @ -- * Subtyping , A_ReversedLens -- | <> ) where import Optics.Internal.Optic -- | Type synonym for a type-modifying reversed lens. type ReversedLens s t a b = Optic A_ReversedLens NoIx s t a b -- | Type synonym for a type-preserving reversed lens. type ReversedLens' t b = Optic' A_ReversedLens NoIx t b optics-core-0.4.1.1/src/Optics/ReversedPrism.hs0000644000000000000000000000365507346545000017462 0ustar0000000000000000-- | -- Module: Optics.ReversedPrism -- Description: A backwards 'Optics.Prism.Prism'. -- -- A 'ReversedPrism' is a backwards 'Optics.Prism.Prism', i.e. a -- @'ReversedPrism' s t a b@ is equivalent to a @'Optics.Prism.Prism' b a t -- s@. These are typically produced by calling 'Optics.Re.re' on a -- 'Optics.Prism.Prism'. They are distinguished from a 'Optics.Getter.Getter' -- so that @'Optics.Re.re' . 'Optics.Re.re'@ on a 'Optics.Prism.Prism' returns a -- 'Optics.Prism.Prism'. -- module Optics.ReversedPrism ( -- * Formation ReversedPrism , ReversedPrism' -- * Introduction -- | -- -- There is no canonical introduction form for 'ReversedPrism', but you can -- use 'Optics.Re.re' to construct one from a 'Optics.Prism.Prism': -- -- @ -- (\\ f g -> 'Optics.Re.re' ('Optics.Prism.prism' f g)) :: (s -> a) -> (b -> Either a t) -> 'ReversedPrism' s t a b -- @ -- * Elimination -- | -- -- A 'ReversedPrism' is a 'Optics.Getter.Getter', so you can specialise -- types to obtain: -- -- @ -- 'Optics.Getter.view' :: 'ReversedPrism'' s a -> s -> a -- @ -- -- There is no reversed 'Optics.AffineTraversal.matching' defined, but it is -- definable using 'Optics.Re.re': -- -- @ -- 'Optics.AffineTraversal.matching' . 'Optics.Re.re' :: 'ReversedPrism' s t a b -> b -> Either a t -- @ -- * Computation -- | -- -- @ -- 'Optics.Getter.view' $ 'Optics.Re.re' ('Optics.Prism.prism' f g) ≡ f -- 'Optics.AffineTraversal.matching' . 'Optics.Re.re' $ 'Optics.Re.re' ('Optics.Prism.prism' f g) ≡ g -- @ -- * Subtyping , A_ReversedPrism -- | <> ) where import Optics.Internal.Optic -- | Type synonym for a type-modifying reversed prism. type ReversedPrism s t a b = Optic A_ReversedPrism NoIx s t a b -- | Type synonym for a type-preserving reversed prism. type ReversedPrism' s a = Optic' A_ReversedPrism NoIx s a optics-core-0.4.1.1/src/Optics/Review.hs0000644000000000000000000000206507346545000016123 0ustar0000000000000000-- | -- Module: Optics.Review -- Description: A backwards 'Optics.Getter.Getter', i.e. a function. -- -- A 'Review' is a backwards 'Optics.Getter.Getter', i.e. a -- @'Review' T B@ is just a function @B -> T@. -- module Optics.Review ( -- * Formation Review -- * Introduction , unto -- * Elimination , review -- * Computation -- | -- -- @ -- 'review' ('unto' f) = f -- @ -- * Subtyping , A_Review -- | <> ) where import Data.Profunctor.Indexed import Optics.Internal.Bi import Optics.Internal.Optic -- | Type synonym for a review. type Review t b = Optic' A_Review NoIx t b -- | Retrieve the value targeted by a 'Review'. -- -- >>> review _Left "hi" -- Left "hi" review :: Is k A_Review => Optic' k is t b -> b -> t review o = unTagged #. getOptic (castOptic @A_Review o) .# Tagged {-# INLINE review #-} -- | An analogue of 'Optics.Getter.to' for reviews. unto :: (b -> t) -> Review t b unto f = Optic (lphantom . rmap f) {-# INLINE unto #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Setter.hs0000644000000000000000000001075507346545000016135 0ustar0000000000000000-- | -- Module: Optics.Setter -- Description: Applies an update to all contained values. -- -- A @'Setter' S T A B@ has the ability to lift a function of type -- @A -> B@ 'over' a function of type @S -> T@, applying the function -- to update all the @A@s contained in @S@. This can be used to 'set' -- all the @A@s to a single value (by lifting a constant function). -- -- This can be seen as a generalisation of 'fmap', where the type @S@ -- does not need to be a type constructor with @A@ as its last -- parameter. -- module Optics.Setter ( -- * Formation Setter , Setter' -- * Introduction , sets -- * Elimination , over -- * Computation -- | -- -- @ -- 'over' ('sets' f) ≡ f -- @ -- * Well-formedness -- | -- -- * __PutPut__: Setting twice is the same as setting once: -- -- @ -- 'Optics.Setter.set' l v' ('Optics.Setter.set' l v s) ≡ 'Optics.Setter.set' l v' s -- @ -- -- * __Functoriality__: 'Setter's must preserve identities and composition: -- -- @ -- 'over' s 'id' ≡ 'id' -- 'over' s f '.' 'over' s g ≡ 'over' s (f '.' g) -- @ -- * Additional introduction forms -- | See also 'Data.Set.Optics.setmapped', which changes the elements of a 'Data.Set.Set'. , mapped -- * Additional elimination forms , set , set' , over' , rewriteOf , transformOf -- * Subtyping , A_Setter -- | <> ) where import Data.Profunctor.Indexed import Optics.Internal.Optic import Optics.Internal.Setter import Optics.Internal.Utils -- | Type synonym for a type-modifying setter. type Setter s t a b = Optic A_Setter NoIx s t a b -- | Type synonym for a type-preserving setter. type Setter' s a = Optic' A_Setter NoIx s a -- | Apply a setter as a modifier. over :: Is k A_Setter => Optic k is s t a b -> (a -> b) -> s -> t over o = \f -> runFunArrow $ getOptic (castOptic @A_Setter o) (FunArrow f) {-# INLINE over #-} -- | Apply a setter as a modifier, strictly. -- -- TODO DOC: what exactly is the strictness property? -- -- Example: -- -- @ -- f :: Int -> (Int, a) -> (Int, a) -- f k acc -- | k > 0 = f (k - 1) $ 'over'' 'Data.Tuple.Optics._1' (+1) acc -- | otherwise = acc -- @ -- -- runs in constant space, but would result in a space leak if used with 'over'. -- -- Note that replacing '$' with '$!' or 'Data.Tuple.Optics._1' with -- 'Data.Tuple.Optics._1'' (which amount to the same thing) doesn't help when -- 'over' is used, because the first coordinate of a pair is never forced. -- over' :: Is k A_Setter => Optic k is s t a b -> (a -> b) -> s -> t over' o = \f -> let star = getOptic (castOptic @A_Setter o) $ Star (wrapIdentity' . f) in unwrapIdentity' . runStar star {-# INLINE over' #-} -- | Apply a setter. -- -- @ -- 'set' o v ≡ 'over' o ('const' v) -- @ -- -- >>> set _1 'x' ('y', 'z') -- ('x','z') -- set :: Is k A_Setter => Optic k is s t a b -> b -> s -> t set o = over o . const {-# INLINE set #-} -- | Apply a setter, strictly. -- -- TODO DOC: what exactly is the strictness property? -- set' :: Is k A_Setter => Optic k is s t a b -> b -> s -> t set' o = over' o . const {-# INLINE set' #-} -- | Build a setter from a function to modify the element(s), which must respect -- the well-formedness laws. sets :: ((a -> b) -> s -> t) -> Setter s t a b sets f = Optic (roam f) {-# INLINE sets #-} -- | Create a 'Setter' for a 'Functor'. -- -- @ -- 'over' 'mapped' ≡ 'fmap' -- @ -- mapped :: Functor f => Setter (f a) (f b) a b mapped = Optic mapped__ {-# INLINE mapped #-} -- | Rewrite by applying a rule everywhere you can. Ensures that the rule cannot -- be applied anywhere in the result: -- -- @ -- propRewriteOf l r x = 'all' ('Data.Just.isNothing' '.' r) ('universeOf' l ('rewriteOf' l r x)) -- @ -- -- Usually 'transformOf' is more appropriate, but 'rewriteOf' can give better -- compositionality. Given two single transformations @f@ and @g@, you can -- construct @\\a -> f a '<|>' g a@ which performs both rewrites until a fixed -- point. -- -- @since 0.4.1 rewriteOf :: Is k A_Setter => Optic k is a b a b -> (b -> Maybe a) -> a -> b rewriteOf o f = go where go = transformOf o $ \x -> maybe x go (f x) {-# INLINE rewriteOf #-} -- | Transform every element by recursively applying a given 'Setter' in a -- bottom-up manner. -- -- @since 0.4.1 transformOf :: Is k A_Setter => Optic k is a b a b -> (b -> b) -> a -> b transformOf o f = go where go = f . over o go {-# INLINE transformOf #-} -- $setup -- >>> import Optics.Core optics-core-0.4.1.1/src/Optics/Traversal.hs0000644000000000000000000003577607346545000016644 0ustar0000000000000000{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE UndecidableInstances #-} -- | -- Module: Optics.Traversal -- Description: Lifts an effectful operation on elements to act on structures. -- -- A 'Traversal' lifts an effectful operation on elements to act on structures -- containing those elements. -- -- That is, given a function @op :: A -> F B@ where @F@ is 'Applicative', a -- @'Traversal' S T A B@ can produce a function @S -> F T@ that applies @op@ to -- all the @A@s contained in the @S@. -- -- This can be seen as a generalisation of 'traverse', where the type @S@ does -- not need to be a type constructor with @A@ as the last parameter. -- -- A 'Lens' is a 'Traversal' that acts on a single value. -- -- A close relative is the 'Optics.AffineTraversal.AffineTraversal', which is a -- 'Traversal' that acts on at most one value. -- module Optics.Traversal ( -- * Formation Traversal , Traversal' -- * Introduction , traversalVL -- * Elimination , traverseOf -- * Computation -- | -- -- @ -- 'traverseOf' ('traversalVL' f) ≡ f -- @ -- * Well-formedness -- | -- -- @ -- 'traverseOf' o 'pure' ≡ 'pure' -- 'fmap' ('traverseOf' o f) . 'traverseOf' o g ≡ 'Data.Functor.Compose.getCompose' . 'traverseOf' o ('Data.Functor.Compose.Compose' . 'fmap' f . g) -- @ -- * Additional introduction forms , traversed , both -- * Additional elimination forms , forOf , sequenceOf , transposeOf , mapAccumROf , mapAccumLOf , scanr1Of , scanl1Of , rewriteMOf , transformMOf , failover , failover' -- * Combinators , backwards , partsOf , singular -- * Monoid structure -- | 'Traversal' admits a (partial) monoid structure where 'adjoin' combines -- non-overlapping traversals, and the identity element is -- 'Optics.IxAffineTraversal.ignored' (which traverses no elements). -- -- If you merely need a 'Fold', you can use traversals as folds and combine -- them with one of the monoid structures on folds (see -- "Optics.Fold#monoids"). In particular, 'summing' can be used to concatenate -- results from two traversals, and 'failing' will returns results from the -- second traversal only if the first returns no results. -- -- There is no 'Semigroup' or 'Monoid' instance for 'Traversal', because there -- is not a unique choice of monoid to use that works for all optics, and the -- ('<>') operator could not be used to combine optics of different kinds. , adjoin -- * Subtyping , A_Traversal -- | <> -- * van Laarhoven encoding -- | The van Laarhoven representation of a 'Traversal' directly expresses how -- it lifts an effectful operation @A -> F B@ on elements to act on structures -- @S -> F T@. Thus 'traverseOf' converts a 'Traversal' to a 'TraversalVL'. , TraversalVL , TraversalVL' ) where import Control.Applicative import Control.Applicative.Backwards import Control.Monad.Trans.State import Data.Bitraversable import Data.Functor.Identity import Data.Profunctor.Indexed import Optics.AffineTraversal import Optics.Fold import Optics.Internal.Optic import Optics.Internal.Traversal import Optics.Internal.Utils import Optics.Lens import Optics.ReadOnly -- | Type synonym for a type-modifying traversal. type Traversal s t a b = Optic A_Traversal NoIx s t a b -- | Type synonym for a type-preserving traversal. type Traversal' s a = Optic' A_Traversal NoIx s a -- | Type synonym for a type-modifying van Laarhoven traversal. type TraversalVL s t a b = forall f. Applicative f => (a -> f b) -> s -> f t -- | Type synonym for a type-preserving van Laarhoven traversal. type TraversalVL' s a = TraversalVL s s a a -- | Build a traversal from the van Laarhoven representation. -- -- @ -- 'traversalVL' '.' 'traverseOf' ≡ 'id' -- 'traverseOf' '.' 'traversalVL' ≡ 'id' -- @ traversalVL :: TraversalVL s t a b -> Traversal s t a b traversalVL t = Optic (wander t) {-# INLINE traversalVL #-} -- | Map each element of a structure targeted by a 'Traversal', evaluate these -- actions from left to right, and collect the results. traverseOf :: (Is k A_Traversal, Applicative f) => Optic k is s t a b -> (a -> f b) -> s -> f t traverseOf o = \f -> runStar $ getOptic (castOptic @A_Traversal o) (Star f) {-# INLINE traverseOf #-} -- | A version of 'traverseOf' with the arguments flipped. forOf :: (Is k A_Traversal, Applicative f) => Optic k is s t a b -> s -> (a -> f b) -> f t forOf = flip . traverseOf {-# INLINE forOf #-} -- | Evaluate each action in the structure from left to right, and collect the -- results. -- -- >>> sequenceOf each ([1,2],[3,4]) -- [(1,3),(1,4),(2,3),(2,4)] -- -- @ -- 'sequence' ≡ 'sequenceOf' 'traversed' ≡ 'traverse' 'id' -- 'sequenceOf' o ≡ 'traverseOf' o 'id' -- @ sequenceOf :: (Is k A_Traversal, Applicative f) => Optic k is s t (f b) b -> s -> f t sequenceOf o = traverseOf o id {-# INLINE sequenceOf #-} -- | This generalizes 'Data.List.transpose' to an arbitrary 'Traversal'. -- -- Note: 'Data.List.transpose' handles ragged inputs more intelligently, but for -- non-ragged inputs: -- -- >>> transposeOf traversed [[1,2,3],[4,5,6]] -- [[1,4],[2,5],[3,6]] -- -- @ -- 'Data.List.transpose' ≡ 'transposeOf' 'traverse' -- @ transposeOf :: Is k A_Traversal => Optic k is s t [a] a -> s -> [t] transposeOf o = getZipList #. traverseOf o ZipList {-# INLINE transposeOf #-} -- | This generalizes 'Data.Traversable.mapAccumL' to an arbitrary 'Traversal'. -- -- @ -- 'Data.Traversable.mapAccumL' ≡ 'mapAccumLOf' 'traverse' -- @ -- -- 'mapAccumLOf' accumulates 'State' from left to right. mapAccumLOf :: Is k A_Traversal => Optic k is s t a b -> (acc -> a -> (b, acc)) -> acc -> s -> (t, acc) mapAccumLOf o = \f acc0 s -> let g a = state $ \acc -> f acc a in runState (traverseOf o g s) acc0 {-# INLINE mapAccumLOf #-} -- | This generalizes 'Data.Traversable.mapAccumR' to an arbitrary 'Traversal'. -- -- @ -- 'Data.Traversable.mapAccumR' ≡ 'mapAccumROf' 'traversed' -- @ -- -- 'mapAccumROf' accumulates 'State' from right to left. mapAccumROf :: Is k A_Traversal => Optic k is s t a b -> (acc -> a -> (b, acc)) -> acc -> s -> (t, acc) mapAccumROf = mapAccumLOf . backwards {-# INLINE mapAccumROf #-} -- | This permits the use of 'scanl1' over an arbitrary 'Traversal'. -- -- @ -- 'scanl1' ≡ 'scanl1Of' 'traversed' -- @ scanl1Of :: Is k A_Traversal => Optic k is s t a a -> (a -> a -> a) -> s -> t scanl1Of o = \f -> let step Nothing a = (a, Just a) step (Just s) a = let r = f s a in (r, Just r) in fst . mapAccumLOf o step Nothing {-# INLINE scanl1Of #-} -- | This permits the use of 'scanr1' over an arbitrary 'Traversal'. -- -- @ -- 'scanr1' ≡ 'scanr1Of' 'traversed' -- @ scanr1Of :: Is k A_Traversal => Optic k is s t a a -> (a -> a -> a) -> s -> t scanr1Of o = \f -> let step Nothing a = (a, Just a) step (Just s) a = let r = f a s in (r, Just r) in fst . mapAccumROf o step Nothing {-# INLINE scanr1Of #-} -- | Rewrite by applying a monadic rule everywhere you recursing with a -- user-specified 'Traversal'. -- -- Ensures that the rule cannot be applied anywhere in the result. -- -- @since 0.4.1 rewriteMOf :: (Is k A_Traversal, Monad m) => Optic k is a b a b -> (b -> m (Maybe a)) -> a -> m b rewriteMOf l f = go where go = transformMOf l (\x -> f x >>= maybe (return x) go) {-# INLINE rewriteMOf #-} -- | Transform every element in a tree using a user supplied 'Traversal' in a -- bottom-up manner with a monadic effect. -- -- @since 0.4.1 transformMOf :: (Is k A_Traversal, Monad m) => Optic k is a b a b -> (b -> m b) -> a -> m b transformMOf l f = go where go t = traverseOf l go t >>= f {-# INLINE transformMOf #-} -- | Try to map a function over this 'Traversal', returning Nothing if the -- traversal has no targets. -- -- >>> failover (element 3) (*2) [1,2] -- Nothing -- -- >>> failover _Left (*2) (Right 4) -- Nothing -- -- >>> failover _Right (*2) (Right 4) -- Just (Right 8) -- failover :: Is k A_Traversal => Optic k is s t a b -> (a -> b) -> s -> Maybe t failover o = \f s -> let OrT visited t = traverseOf o (wrapOrT . Identity #. f) s in if visited then Just (runIdentity t) else Nothing {-# INLINE failover #-} -- | Version of 'failover' strict in the application of @f@. failover' :: Is k A_Traversal => Optic k is s t a b -> (a -> b) -> s -> Maybe t failover' o = \f s -> let OrT visited t = traverseOf o (wrapOrT . wrapIdentity' . f) s in if visited then Just (unwrapIdentity' t) else Nothing {-# INLINE failover' #-} ---------------------------------------- -- Traversals -- | Construct a 'Traversal' via the 'Traversable' class. -- -- @ -- 'traverseOf' 'traversed' = 'traverse' -- @ -- traversed :: Traversable t => Traversal (t a) (t b) a b traversed = Optic traversed__ {-# INLINE traversed #-} -- | Traverse both parts of a 'Bitraversable' container with matching types. -- -- /Note:/ for traversing a pair or an 'Either' it's better to use -- 'Optics.Each.Core.each' and 'Optics.IxLens.chosen' respectively to reduce -- potential for bugs due to too much polymorphism. -- -- >>> (1,2) & both %~ (*10) -- (10,20) -- -- >>> over both length ("hello","world") -- (5,5) -- -- >>> foldOf both ("hello","world") -- "helloworld" -- -- @since 0.4 -- both :: Bitraversable r => Traversal (r a a) (r b b) a b both = traversalVL $ \f -> bitraverse f f {-# INLINE both #-} ---------------------------------------- -- Traversal combinators -- | This allows you to 'traverse' the elements of a traversal in the opposite -- order. backwards :: Is k A_Traversal => Optic k is s t a b -> Traversal s t a b backwards o = traversalVL $ \f -> forwards #. traverseOf o (Backwards #. f) {-# INLINE backwards #-} -- | 'partsOf' turns a 'Traversal' into a 'Lens'. -- -- /Note:/ You should really try to maintain the invariant of the number of -- children in the list. -- -- >>> ('a','b','c') & partsOf each .~ ['x','y','z'] -- ('x','y','z') -- -- Any extras will be lost. If you do not supply enough, then the remainder will -- come from the original structure. -- -- >>> ('a','b','c') & partsOf each .~ ['w','x','y','z'] -- ('w','x','y') -- -- >>> ('a','b','c') & partsOf each .~ ['x','y'] -- ('x','y','c') -- -- >>> ('b', 'a', 'd', 'c') & partsOf each %~ sort -- ('a','b','c','d') -- -- So technically, this is only a 'Lens' if you do not change the number of -- results it returns. partsOf :: forall k is s t a. Is k A_Traversal => Optic k is s t a a -> Lens s t [a] [a] partsOf o = lensVL $ \f s -> evalState (traverseOf o update s) <$> f (toListOf (getting $ castOptic @A_Traversal o) s) where update a = get >>= \case a' : as' -> put as' >> pure a' [] -> pure a {-# INLINE partsOf #-} -- | Convert a traversal to an 'AffineTraversal' that visits the first element -- of the original traversal. -- -- For the fold version see 'Optics.Fold.pre'. -- -- >>> "foo" & singular traversed .~ 'z' -- "zoo" -- -- @since 0.3 singular :: forall k is s a. Is k A_Traversal => Optic' k is s a -> AffineTraversal' s a singular o = atraversalVL $ \point f s -> case headOf (castOptic @A_Traversal o) s of Nothing -> point s Just a -> evalState (traverseOf o update s) . Just <$> f a where update a = get >>= \case Just a' -> put Nothing >> pure a' Nothing -> pure a {-# INLINE singular #-} -- | Combine two disjoint traversals into one. -- -- >>> over (_1 % _Just `adjoin` _2 % _Right) not (Just True, Right False) -- (Just False,Right True) -- -- /Note:/ if the argument traversals are not disjoint, the result will not -- respect the 'Traversal' laws, because it will visit the same element multiple -- times. See section 7 of -- -- by Bird et al. for why this is illegal. -- -- >>> view (partsOf (each `adjoin` _1)) ('x','y') -- "xyx" -- >>> set (partsOf (each `adjoin` _1)) "abc" ('x','y') -- ('c','b') -- -- For the 'Fold' version see 'Optics.Fold.summing'. -- -- @since 0.4 -- adjoin :: (Is k A_Traversal, Is l A_Traversal) => Optic' k is s a -> Optic' l js s a -> Traversal' s a adjoin o1 o2 = combined % traversed where combined = traversalVL $ \f s0 -> (\r1 r2 -> let s1 = evalState (traverseOf o1 update s0) r1 s2 = evalState (traverseOf o2 update s1) r2 in s2 ) <$> f (toListOf (castOptic @A_Traversal o1) s0) <*> f (toListOf (castOptic @A_Traversal o2) s0) update a = get >>= \case a' : as' -> put as' >> pure a' [] -> pure a infixr 6 `adjoin` -- Same as (<>) {-# INLINE [1] adjoin #-} {-# RULES "adjoin_12_3" forall o1 o2 o3. adjoin o1 (adjoin o2 o3) = adjoin3 o1 o2 o3 "adjoin_21_3" forall o1 o2 o3. adjoin (adjoin o1 o2) o3 = adjoin3 o1 o2 o3 "adjoin_13_4" forall o1 o2 o3 o4. adjoin o1 (adjoin3 o2 o3 o4) = adjoin4 o1 o2 o3 o4 "adjoin_31_4" forall o1 o2 o3 o4. adjoin (adjoin3 o1 o2 o3) o4 = adjoin4 o1 o2 o3 o4 #-} -- | Triple 'adjoin' for optimizing multiple 'adjoin's with rewrite rules. adjoin3 :: (Is k1 A_Traversal, Is k2 A_Traversal, Is k3 A_Traversal) => Optic' k1 is1 s a -> Optic' k2 is2 s a -> Optic' k3 is3 s a -> Traversal' s a adjoin3 o1 o2 o3 = combined % traversed where combined = traversalVL $ \f s0 -> (\r1 r2 r3 -> let s1 = evalState (traverseOf o1 update s0) r1 s2 = evalState (traverseOf o2 update s1) r2 s3 = evalState (traverseOf o3 update s2) r3 in s3 ) <$> f (toListOf (castOptic @A_Traversal o1) s0) <*> f (toListOf (castOptic @A_Traversal o2) s0) <*> f (toListOf (castOptic @A_Traversal o3) s0) update a = get >>= \case a' : as' -> put as' >> pure a' [] -> pure a {-# INLINE [1] adjoin3 #-} {-# RULES "adjoin_211_4" forall o1 o2 o3 o4. adjoin3 (adjoin o1 o2) o3 o4 = adjoin4 o1 o2 o3 o4 "adjoin_121_4" forall o1 o2 o3 o4. adjoin3 o1 (adjoin o2 o3) o4 = adjoin4 o1 o2 o3 o4 "adjoin_112_4" forall o1 o2 o3 o4. adjoin3 o1 o2 (adjoin o3 o4) = adjoin4 o1 o2 o3 o4 #-} -- | Quadruple 'adjoin' for optimizing multiple 'adjoin's with rewrite rules. adjoin4 :: (Is k1 A_Traversal, Is k2 A_Traversal, Is k3 A_Traversal, Is k4 A_Traversal) => Optic' k1 is1 s a -> Optic' k2 is2 s a -> Optic' k3 is3 s a -> Optic' k4 is4 s a -> Traversal' s a adjoin4 o1 o2 o3 o4 = combined % traversed where combined = traversalVL $ \f s0 -> (\r1 r2 r3 r4 -> let s1 = evalState (traverseOf o1 update s0) r1 s2 = evalState (traverseOf o2 update s1) r2 s3 = evalState (traverseOf o3 update s2) r3 s4 = evalState (traverseOf o4 update s3) r4 in s4 ) <$> f (toListOf (castOptic @A_Traversal o1) s0) <*> f (toListOf (castOptic @A_Traversal o2) s0) <*> f (toListOf (castOptic @A_Traversal o3) s0) <*> f (toListOf (castOptic @A_Traversal o4) s0) update a = get >>= \case a' : as' -> put as' >> pure a' [] -> pure a {-# INLINE [1] adjoin4 #-} -- $setup -- >>> import Data.List -- >>> import Optics.Core