<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">I think the idea is, as Nick describes, that an equality constraint approach might make improvement more powerful (i.e. we get more unifications) but has the unfortunate (but necessary) side effect of making variables untouchable. So neither approach is better than the other, and Nick wants to let users choose which one they want.<div class=""><br class=""></div><div class="">Directly responding to Simon's example: Yes I agree with what you say here.</div><div class=""><br class=""></div><div class="">Richard<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On May 21, 2019, at 9:43 AM, Simon Peyton Jones via Libraries <<a href="mailto:libraries@haskell.org" class="">libraries@haskell.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="WordSection1" style="page: WordSection1; caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;"><p class="MsoNormal" style="margin: 0cm 0cm 6pt 36pt; font-size: 11pt; font-family: Calibri, sans-serif;">Therefore many uses of `mkFin` et al *require* that I introduce local equality constraints. And those sadly spoil lots of desired type inference by making outer tyvars untouchable.<o:p class=""></o:p></p><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><span class=""><o:p class=""> </o:p></span></div><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><span class="">One would need to think carefully here. For example, just changing (a~b) to (IsEqual a b) doesn’t really make it less of an equality constraint, does it? Yet (IsEqual a b) isn’t an equality constraint, and hence would not make outer type variables untouchable. Does that threaten predictable type inference, as an (a~b) constraint does? I’m not sure.<o:p class=""></o:p></span></div><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><span class=""><o:p class=""> </o:p></span></div><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><span class="">Perhaps if it was defined as<o:p class=""></o:p></span></div><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><span class=""> class IsEqual a b<o:p class=""></o:p></span></div><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><span class=""> instance IsEqual a a<o:p class=""></o:p></span></div><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><span class="">all would be well. But NOT if you defined it as<o:p class=""></o:p></span></div><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><span class=""> class (a~b) => IsEqual2 a b<o:p class=""></o:p></span></div><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><span class=""> instance IsEqual2 a a<o:p class=""></o:p></span></div><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><span class="">because of the superclass.<o:p class=""></o:p></span></div><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><span class=""><o:p class=""> </o:p></span></div><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><span class="">Interesting. I’d never thought of that. cc’ing Richard.<o:p class=""></o:p></span></div><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><span class=""><o:p class=""> </o:p></span></div><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><span class="">Simon<o:p class=""></o:p></span></div><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><span class=""><o:p class=""> </o:p></span></div><div style="border-style: none none none solid; border-left-width: 1.5pt; border-left-color: blue; padding: 0cm 0cm 0cm 4pt;" class=""><div class=""><div style="border-style: solid none none; border-top-width: 1pt; border-top-color: rgb(225, 225, 225); padding: 3pt 0cm 0cm;" class=""><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><b class=""><span lang="EN-US" class="">From:</span></b><span lang="EN-US" class=""><span class="Apple-converted-space"> </span>Libraries <<a href="mailto:libraries-bounces@haskell.org" class="">libraries-bounces@haskell.org</a>><span class="Apple-converted-space"> </span><b class="">On Behalf Of<span class="Apple-converted-space"> </span></b>Nicolas Frisby<br class=""><b class="">Sent:</b><span class="Apple-converted-space"> </span>21 May 2019 02:48<br class=""><b class="">To:</b><span class="Apple-converted-space"> </span>Haskell Libraries <<a href="mailto:libraries@haskell.org" class="">libraries@haskell.org</a>><br class=""><b class="">Subject:</b><span class="Apple-converted-space"> </span>request: a Nat ordering constraint that is not an equality constraint<o:p class=""></o:p></span></div></div></div><div style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif;" class=""><o:p class=""> </o:p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">This email proposes an extension and possible change to GHC.TypeLits module in the core `base` library.<o:p class=""></o:p></p><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p></div><div class=""><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">Is there support for this kind of extension/change to GHC.TypeLits? If so, I'll open a GHC GitLab Issue.<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">(If not, I would be very appreciate if someone were able to suggest a nice workaround.)<o:p class=""></o:p></p></div><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"># The Proposed Extension<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">Please add an alternative to <= that is not defined via ~. For example:<o:p class=""></o:p></p><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">```<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">module GHC.TypeLits.Passive where<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"> <o:p class=""></o:p></p></div><div class=""><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">class IsTrue (a :: Bool)<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">instance IsTrue 'True<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">instance TypeError ... => IsTrue 'False<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">type (<=) x y = IsTrue (x <=? y)<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">```<o:p class=""></o:p></p></div></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">as opposed to the existing definition:<o:p class=""></o:p></p></div><p class="MsoNormal" style="margin: 0cm 0cm 12pt; font-size: 11pt; font-family: Calibri, sans-serif;"><br class="">```<br class="">module GHC.TypeLits where<o:p class=""></o:p></p><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">type (<=) x y = (x <=? y) ~ 'True<o:p class=""></o:p></p></div><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">```<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">Its name should be an operator and should be somewhat obvious -- I can't think of one other than <=, so I hedged here by putting in a new module instead.<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 12pt; font-size: 11pt; font-family: Calibri, sans-serif;"><br class="">There should be a means of *explicitly* converting back and forth between evidence of the two constraints; they are equi-satisfiable but affect type inference in their scope differently.<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 12pt; font-size: 11pt; font-family: Calibri, sans-serif;"># The Optional Change<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 12pt; font-size: 11pt; font-family: Calibri, sans-serif;">I anticipate most users would prefer Passive.<= to today's <=, so the optional library change in this proposal is to redefine <= and relegate its old definition to a new name. Perhaps:<o:p class=""></o:p></p><div class=""><div class=""><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">```<o:p class=""></o:p></p></div></div><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">module GHC.TypeLits where<o:p class=""></o:p></p><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><br class="">type (<=) x y = IsTrue (x <=? y)<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">type (<=!) x y = (x <=? y) ~ 'True<o:p class=""></o:p></p></div><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">```<o:p class=""></o:p></p></div><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p></div><div class=""><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"># The Motivation<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">I'll explain with an example for some concreteness. <o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">I wrote an interface for size-indexed vectors for my employer. It involves some code like this:<o:p class=""></o:p></p><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">```<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">import GHC.TypeLits<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"> <br class="">newtype Fin (n :: Nat) = Unsafe_MkFin{forgetFin :: Integer}<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 12pt; font-size: 11pt; font-family: Calibri, sans-serif;"><br class="">mkFin :: (KnownNat i,i <= n) => proxy i -> Fin n<br class="">mkFin = Unsafe_MkFin . natVal<br class="">```<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">Constraints like `(i <= n)` show up throughout the library's interface.<br class="">The problem is that <= is an equality constraint.<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">Therefore many uses of `mkFin` et al *require* that I introduce local equality constraints.<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">And those sadly spoil lots of desired type inference by making outer tyvars untouchable.<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">That's the problem: I have to choose between GHC's specialized solving of <= constraints and unspoiled type inference in their scope.<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"># Additional Context<o:p class=""></o:p></p></div><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">It is important that today's <= be an equality constraint, because it participates in some constraint improvements that introduce equality constraints. For example (x <= y,y <= x) implies x ~ y (c.f. the scary <a href="https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitlab.haskell.org%2Fghc%2Fghc%2Fissues%2F16586&data=02%7C01%7Csimonpj%40microsoft.com%7Cfd400e22fed34cacdc8108d6dd8e8002%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636940001438800796&sdata=M53kCihvu6RqXOutwOT4Ha7MzPHqmYgcfqzCA1%2BSvYE%3D&reserved=0" style="color: purple; text-decoration: underline;" class="">https://gitlab.haskell.org/ghc/ghc/issues/16586</a>). Because <= constraints have the potential to "become" an equality constraint, tyvars outside of a <= constraint must be untouchable in its scope from the get go.<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><br class="">However, neither my library nor any of its uses relies on such constraint improvements enabled by <= constraints.<o:p class=""></o:p></p></div></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 12pt; font-size: 11pt; font-family: Calibri, sans-serif;">In this context, I would much rather that <= could never "become" an equality constraint, so that it need not be an equality constraint, so that it would never render a tyvar untouchable.<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"># An Alternative<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><br class="">As a partial workaround, I could write<br class=""><br class="">```<br class="">data Dict i n = (i <= n) => MkDict<br class=""><br class="">mkFinD :: (KnownNat i) => Dict i n -> proxy i -> Fin n<br class="">mkFinD MkDict = mkFin<br class="">```<br class=""><br class="">and then take pains to only introduce the <= constraints in the argument of `mkFinD`. By limiting the scope of the ~ constraints like that, I could prevent them from spoiling the desired type inference. But it's very cumbersome to manage their scopes manually.<br class=""><br class=""># Work Estimation<o:p class=""></o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p></div><div class=""><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">I just thought of the `IsTrue`-based approach while writing this email, so that detail is somewhat half-baked. It has the right *indicative* semantics, but I doubt today's GHC solver would know what to do with a Given `IsTrue (3 <=? 5)` constraint -- so I'm guessing that exact approach at least would require some significant changes in TcTypeNats.<o:p class=""></o:p></p></div><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;"><o:p class=""> </o:p></p></div><div class=""><p class="MsoNormal" style="margin: 0cm 0cm 6pt; font-size: 11pt; font-family: Calibri, sans-serif;">Thank you for your time. -Nick<br class=""><br class="">P.S. - Some of the issue tracker links at <a href="https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwiki.haskell.org%2FLibrary_submissions%23The_Libraries&data=02%7C01%7Csimonpj%40microsoft.com%7Cfd400e22fed34cacdc8108d6dd8e8002%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636940001438810751&sdata=0mdfCDTlrytqy%2Fu4htfH4kF%2F9l9NcJnJNcaPHIi0lRk%3D&reserved=0" style="color: purple; text-decoration: underline;" class="">https://wiki.haskell.org/Library_submissions#The_Libraries</a> respond with 404.<br class=""><br class="">P.P.S. - Is there a standard place to find something like `IsTrue`? More generally: a test for type equality that does not drive unification? Thanks again.<o:p class=""></o:p></p></div></div></div></div></div></div><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">_______________________________________________</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">Libraries mailing list</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class=""><a href="mailto:Libraries@haskell.org" class="">Libraries@haskell.org</a></span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class=""><a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" class="">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a></span></div></blockquote></div><br class=""></div></body></html>