<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:Wingdings;
        panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin-top:6.0pt;
        margin-right:0cm;
        margin-bottom:6.0pt;
        margin-left:0cm;
        font-size:12.0pt;
        font-family:"Times New Roman",serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#0563C1;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
p.MsoPlainText, li.MsoPlainText, div.MsoPlainText
        {mso-style-priority:99;
        mso-style-link:"Plain Text Char";
        margin:0cm;
        margin-bottom:.0001pt;
        font-size:10.0pt;
        font-family:"Courier New";}
pre
        {mso-style-priority:99;
        mso-style-link:"HTML Preformatted Char";
        margin:0cm;
        margin-bottom:.0001pt;
        font-size:10.0pt;
        font-family:"Courier New";}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:6.0pt;
        margin-right:0cm;
        margin-bottom:6.0pt;
        margin-left:36.0pt;
        font-size:12.0pt;
        font-family:"Times New Roman",serif;}
p.Code, li.Code, div.Code
        {mso-style-name:Code;
        margin-top:0cm;
        margin-right:0cm;
        margin-bottom:0cm;
        margin-left:36.0pt;
        margin-bottom:.0001pt;
        font-size:9.0pt;
        font-family:"Courier New";}
span.HTMLPreformattedChar
        {mso-style-name:"HTML Preformatted Char";
        mso-style-priority:99;
        mso-style-link:"HTML Preformatted";
        font-family:"Courier New";
        mso-fareast-language:EN-GB;}
p.msonormal0, li.msonormal0, div.msonormal0
        {mso-style-name:msonormal;
        mso-margin-top-alt:auto;
        margin-right:0cm;
        mso-margin-bottom-alt:auto;
        margin-left:0cm;
        font-size:12.0pt;
        font-family:"Times New Roman",serif;}
span.PlainTextChar
        {mso-style-name:"Plain Text Char";
        mso-style-priority:99;
        mso-style-link:"Plain Text";
        font-family:"Courier New";
        mso-fareast-language:EN-GB;}
span.nf
        {mso-style-name:nf;}
span.o
        {mso-style-name:o;}
span.ow
        {mso-style-name:ow;}
span.p
        {mso-style-name:p;}
span.EmailStyle27
        {mso-style-type:personal-compose;
        font-family:"Calibri",sans-serif;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;
        mso-fareast-language:EN-US;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 86.95pt 72.0pt 86.95pt;}
div.WordSection1
        {page:WordSection1;}
/* List Definitions */
@list l0
        {mso-list-id:816144991;
        mso-list-type:hybrid;
        mso-list-template-ids:-1765665020 134807553 134807555 134807557 134807553 134807555 134807557 134807553 134807555 134807557;}
@list l0:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:Symbol;}
@list l0:level2
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:"Courier New";}
@list l0:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:Wingdings;}
@list l0:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:Symbol;}
@list l0:level5
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:"Courier New";}
@list l0:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:Wingdings;}
@list l0:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:Symbol;}
@list l0:level8
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:"Courier New";}
@list l0:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:Wingdings;}
ol
        {margin-bottom:0cm;}
ul
        {margin-bottom:0cm;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-GB" link="#0563C1" vlink="#954F72">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-family:"Calibri",sans-serif">David, Edward<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Calibri",sans-serif">Here’s my take on this thread about reflection.   I’ll ignore Tagged and the ‘s’ parameter, and the proxy arguments, since they are incidental.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Calibri",sans-serif">I can finally see a reasonable path; I think there’s a potential GHC proposal here.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Calibri",sans-serif">Simon<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Calibri",sans-serif"><o:p> </o:p></span></p>
<p class="MsoNormal"><b><span style="font-family:"Calibri",sans-serif">First thing</span></b><span style="font-family:"Calibri",sans-serif">: PLEASE let's give a Core rendering of whatever is proposed. If it's expressible in Core that's reassuring.  If it requires
 an extension to Core, that's a whole different thing.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Calibri",sans-serif"><o:p> </o:p></span></p>
<p class="MsoNormal"><b><span style="font-family:"Calibri",sans-serif">Second</span></b><span style="font-family:"Calibri",sans-serif">.  For any
<i>particular</i> class, I think it's easy to express reify in Core.  Example (in Core):<o:p></o:p></span></p>
<p class="Code">reifyTypeable :: (Typeable a => b) -> TypeRep a -> b<o:p></o:p></p>
<p class="Code">reifyTypable k = k |> co<o:p></o:p></p>
<p class="MsoNormal"><span style="font-family:"Calibri",sans-serif">where co is a coercion that witnesses<o:p></o:p></span></p>
<p class="Code">  co :: (forall a b. Typeable a => b) ~ forall a b. (TypeRep a -> b)<o:p></o:p></p>
<p class="MsoNormal"><b><span style="font-family:"Calibri",sans-serif"><o:p> </o:p></span></b></p>
<p class="MsoNormal"><b><span style="font-family:"Calibri",sans-serif">Third.  </span>
</b><span style="font-family:"Calibri",sans-serif">This does not depend, and should not depend, on the fact that single-method classes are represented with a newtype.  E.g. if we changed Typeable to be represented with a data type thus (in Core)<o:p></o:p></span></p>
<p class="Code">data Typeable a = MkTypeable (TypeRep a)<o:p></o:p></p>
<p class="MsoNormal"><span style="font-family:"Calibri",sans-serif">using data rather than newtype, then we could still write reifyTypable.<o:p></o:p></span></p>
<p class="Code">reifyTypeable :: (Typeable a => b) -> TypeRep a -> b<o:p></o:p></p>
<p class="Code">reifyTypable = /\ab. \(f :: Typeable a => b). \(r :: TypeRep a).<o:p></o:p></p>
<p class="Code">               f (MkTypeable r)<o:p></o:p></p>
<p class="MsoNormal"><span style="font-family:"Calibri",sans-serif">The efficiency of newtype is nice, but it’s not essential.<o:p></o:p></span></p>
<p class="MsoNormal"><b><span style="font-family:"Calibri",sans-serif"><o:p> </o:p></span></b></p>
<p class="MsoNormal"><b><span style="font-family:"Calibri",sans-serif">Fourth</span></b><span style="font-family:"Calibri",sans-serif">.   As you point out, reify# is far too polymorphic.
<b>Clearly you need reify# to be a class method!</b>  Something like this<o:p></o:p></span></p>
<p class="Code">class Reifiable a where<o:p></o:p></p>
<p class="Code">  type RC a :: Constraint  -- Short for Reified Constraint<o:p></o:p></p>
<p class="Code">  reify# :: forall r. (RC a => r) -> a -> r<o:p></o:p></p>
<p class="MsoNormal"><span style="font-family:"Calibri",sans-serif">Now (in Core at least) we can make instances<o:p></o:p></span></p>
<p class="Code">instance Reifiable (TypeRep a) where<o:p></o:p></p>
<p class="Code">  type RC (TypeRep a) = Typeable a<o:p></o:p></p>
<p class="Code">  reify# k = k |> co  -- For a suitable co<o:p></o:p></p>
<p class="MsoNormal"><span style="font-family:"Calibri",sans-serif">Now, we can’t write those instances in Haskell, but we could make the ‘deriving’ mechanism deal with it, thus:<o:p></o:p></span></p>
<p class="Code">deriving instance Reifiable (Typeable a)<o:p></o:p></p>
<p class="MsoNormal"><span style="font-family:"Calibri",sans-serif">You can supply a ‘where’ part if you like, but if you don’t GHC will fill in the implementation for you.  It’ll check that Typeable is a single-method class; produce a suitable implementation
 (in Core, as above) for reify#, and a suitable instance for RC. Pretty simple.   Now the solver can use those instances.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Calibri",sans-serif">There are lots of details<o:p></o:p></span></p>
<p class="MsoListParagraph" style="text-indent:-18.0pt;mso-list:l0 level1 lfo1"><![if !supportLists]><span style="font-family:Symbol"><span style="mso-list:Ignore">·<span style="font:7.0pt "Times New Roman"">       
</span></span></span><![endif]><span style="font-family:"Calibri",sans-serif">I’ve used a single parameter class and a type function, because the call site of reify# will provide no information about the ‘c’ in (c => r) argument.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="text-indent:-18.0pt;mso-list:l0 level1 lfo1"><![if !supportLists]><span style="font-family:Symbol"><span style="mso-list:Ignore">·<span style="font:7.0pt "Times New Roman"">       
</span></span></span><![endif]><span style="font-family:"Calibri",sans-serif">What if some other class has the same method type?  E.g. if someone wrote 
<o:p></o:p></span></p>
<p class="Code">class MyTR a where op :: TypeRep a<o:p></o:p></p>
<p class="MsoListParagraph"><span style="font-family:"Calibri",sans-serif">would that mess up the use of reify# for Typeable?   Well it would if they also did<o:p></o:p></span></p>
<p class="Code">deriving instance Reifiable (MyTR a)<o:p></o:p></p>
<p class="MsoListParagraph"><span style="font-family:"Calibri",sans-serif">And there really is an ambiguity: what should (reify# k (tr :: TypeRep Int)) do?  Apply k to a TypeRep or to a MyTR?  So a complaint here would be entirely legitimate.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="text-indent:-18.0pt;mso-list:l0 level1 lfo1"><![if !supportLists]><span style="font-family:Symbol"><span style="mso-list:Ignore">·<span style="font:7.0pt "Times New Roman"">       
</span></span></span><![endif]><span style="font-family:"Calibri",sans-serif">I suppose that another formulation might be to abstract over the constraint, rather than the method type, and use explicit type application at calls of reify#.  So<o:p></o:p></span></p>
<p class="Code">class Reifiable c where<o:p></o:p></p>
<p class="Code">  type RL c :: *<o:p></o:p></p>
<p class="Code">  reify# :: (c => r) -> RL c -> r<o:p></o:p></p>
<p class="MsoListParagraph"><span style="font-family:"Calibri",sans-serif">Now all calls of reify# would have to look like
<o:p></o:p></span></p>
<p class="Code">reify# @(Typeable Int) k tr<o:p></o:p></p>
<p class="MsoListParagraph"><span style="font-family:"Calibri",sans-serif">Maybe that’s acceptable.  But it doesn’t seem as nice to me.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="text-indent:-18.0pt;mso-list:l0 level1 lfo1"><![if !supportLists]><span style="font-family:Symbol"><span style="mso-list:Ignore">·<span style="font:7.0pt "Times New Roman"">       
</span></span></span><![endif]><span style="font-family:"Calibri",sans-serif">One could use functional dependencies and a 2-parameter type class, but I don’t think it would change anything much.  If type functions work, they are more robust than fundeps.<o:p></o:p></span></p>
<p class="MsoListParagraph" style="text-indent:-18.0pt;mso-list:l0 level1 lfo1"><![if !supportLists]><span style="font-family:Symbol"><span style="mso-list:Ignore">·<span style="font:7.0pt "Times New Roman"">       
</span></span></span><![endif]><span style="font-family:"Calibri",sans-serif">One could abstract over the type constructor rather than the type.  I see no advantage and some disadvantages<o:p></o:p></span></p>
<p class="Code">class Reifiable t where<o:p></o:p></p>
<p class="Code">  type RC t :: * -> Constraint  -- Short for Reified Constraint<o:p></o:p></p>
<p class="Code">  reify# :: forall r. (RC t a => r) -> t a -> r<o:p></o:p></p>
<p class="MsoNormal"><span style="font-family:"Calibri",sans-serif"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Calibri",sans-serif"><o:p> </o:p></span></p>
<p class="MsoPlainText">|  <span lang="EN-US">-----Original Message-----</span><o:p></o:p></p>
<p class="MsoPlainText">|  <span lang="EN-US">From: ghc-devs [<a href="mailto:ghc-devs-bounces@haskell.org">mailto:ghc-devs-bounces@haskell.org</a>] On Behalf Of David</span><o:p></o:p></p>
<p class="MsoPlainText">|  <span lang="EN-US">Feuer</span><o:p></o:p></p>
<p class="MsoPlainText">|  <span lang="EN-US">Sent: 11 December 2016 05:01</span><o:p></o:p></p>
<p class="MsoPlainText">|  <span lang="EN-US">To: ghc-devs <<a href="mailto:ghc-devs@haskell.org">ghc-devs@haskell.org</a>>; Edward Kmett <<a href="mailto:ekmett@gmail.com">ekmett@gmail.com</a>></span><o:p></o:p></p>
<p class="MsoPlainText">|  <span lang="EN-US">Subject: Magical function to support reflection</span><o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  The following proposal (with fancier formatting and some improved<o:p></o:p></p>
<p class="MsoPlainText">|  wording) can be viewed at<o:p></o:p></p>
<p class="MsoPlainText">|  <a href="https://ghc.haskell.org/trac/ghc/wiki/MagicalReflectionSupport">
<span style="color:windowtext;text-decoration:none">https://ghc.haskell.org/trac/ghc/wiki/MagicalReflectionSupport</span></a><o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  Using the Data.Reflection has some runtime costs. Notably, there can be no<o:p></o:p></p>
<p class="MsoPlainText">|  inlining or unboxing of reified values. I think it would be nice to add a<o:p></o:p></p>
<p class="MsoPlainText">|  GHC special to support it. I'll get right to the point of what I want, and<o:p></o:p></p>
<p class="MsoPlainText">|  then give a bit of background about why.<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  === What I want<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  I propose the following absurdly over-general lie:<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  reify# :: (forall s . c s a => t s r) -> a -> r<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  `c` is assumed to be a single-method class with no superclasses whose<o:p></o:p></p>
<p class="MsoPlainText">|  dictionary representation is exactly the same as the representation of `a`,<o:p></o:p></p>
<p class="MsoPlainText">|  and `t s r` is assumed to be a newtype wrapper around `r`. In desugaring,<o:p></o:p></p>
<p class="MsoPlainText">|  reify# f would be compiled to f@S, where S is a fresh type. I believe it's<o:p></o:p></p>
<p class="MsoPlainText">|  necessary to use a fresh type to prevent specialization from mixing up<o:p></o:p></p>
<p class="MsoPlainText">|  different reified values.<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  === Background<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  Let me set up a few pieces. These pieces are slightly modified from what the<o:p></o:p></p>
<p class="MsoPlainText">|  package actually does to make things cleaner under the hood, but the<o:p></o:p></p>
<p class="MsoPlainText">|  differences are fairly shallow.<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  newtype Tagged s a = Tagged { unTagged :: a }<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  unproxy :: (Proxy s -> a) -> Tagged s a<o:p></o:p></p>
<p class="MsoPlainText">|  unproxy f = Tagged (f Proxy)<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  class Reifies s a | s -> a where<o:p></o:p></p>
<p class="MsoPlainText">|    reflect' :: Tagged s a<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  -- For convenience<o:p></o:p></p>
<p class="MsoPlainText">|  reflect :: forall s a proxy . Reifies s a => proxy s -> a reflect _ =<o:p></o:p></p>
<p class="MsoPlainText">|  unTagged (reflect' :: Tagged s a)<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  -- The key function--see below regarding implementation reify' :: (forall s<o:p></o:p></p>
<p class="MsoPlainText">|  . Reifies s a => Tagged s r) -> a -> r<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  -- For convenience<o:p></o:p></p>
<p class="MsoPlainText">|  reify :: a -> (forall s . Reifies s a => Proxy s -> r) -> r reify a f =<o:p></o:p></p>
<p class="MsoPlainText">|  reify' (unproxy f) a<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  The key idea of reify' is that something of type<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  forall s . Reifies s a => Tagged s r<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  is represented in memory exactly the same as a function of type<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  a -> r<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  So we can currently use unsafeCoerce to interpret one as the other.<o:p></o:p></p>
<p class="MsoPlainText">|  Following the general approach of the library, we can do this as such:<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  newtype Magic a r = Magic (forall s . Reifies s a => Tagged s r) reify' ::<o:p></o:p></p>
<p class="MsoPlainText">|  (forall s . Reifies s a => Tagged s r) -> a -> r reify' f = unsafeCoerce<o:p></o:p></p>
<p class="MsoPlainText">|  (Magic f)<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  This certainly works. The trouble is that any knowledge about what is<o:p></o:p></p>
<p class="MsoPlainText">|  reflected is totally lost. For instance, if I write<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  reify 12 $ \p -> reflect p + 3<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  then GHC will not see, at compile time, that the result is 15. If I write<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  reify (+1) $ \p -> reflect p x<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  then GHC will never inline the application of (+1). Etc.<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  I'd like to replace reify' with reify# to avoid this problem.<o:p></o:p></p>
<p class="MsoPlainText">|  <o:p></o:p></p>
<p class="MsoPlainText">|  Thanks,<o:p></o:p></p>
<p class="MsoPlainText">|  David Feuer<o:p></o:p></p>
<p class="MsoPlainText">|  _______________________________________________<o:p></o:p></p>
<p class="MsoPlainText">|  ghc-devs mailing list<o:p></o:p></p>
<p class="MsoPlainText">|  <a href="mailto:ghc-devs@haskell.org"><span style="color:windowtext;text-decoration:none">ghc-devs@haskell.org</span></a><o:p></o:p></p>
<p class="MsoPlainText">|  <a href="https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail.haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc-devs&data=02%7C01%7Csimonpj%40microsoft.com%7C488bf00986e34ac0833208d42182c47a%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636170292905032831&sdata=quvCny8vD%2Fw%2BjIIypEtungW3OWbVmCQxFAK4%2FXrX%2Bb8%3D&reserved=0">
<span style="color:windowtext;text-decoration:none">https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail.haskell</span></a><o:p></o:p></p>
<p class="MsoPlainText"><a href="https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail.haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc-devs&data=02%7C01%7Csimonpj%40microsoft.com%7C488bf00986e34ac0833208d42182c47a%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636170292905032831&sdata=quvCny8vD%2Fw%2BjIIypEtungW3OWbVmCQxFAK4%2FXrX%2Bb8%3D&reserved=0"><span style="color:windowtext;text-decoration:none">| 
 .org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc-</span></a><o:p></o:p></p>
<p class="MsoPlainText"><a href="https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail.haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc-devs&data=02%7C01%7Csimonpj%40microsoft.com%7C488bf00986e34ac0833208d42182c47a%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636170292905032831&sdata=quvCny8vD%2Fw%2BjIIypEtungW3OWbVmCQxFAK4%2FXrX%2Bb8%3D&reserved=0"><span style="color:windowtext;text-decoration:none">| 
 devs&data=02%7C01%7Csimonpj%40microsoft.com%7C488bf00986e34ac0833208d42182c4</span></a><o:p></o:p></p>
<p class="MsoPlainText"><a href="https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail.haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc-devs&data=02%7C01%7Csimonpj%40microsoft.com%7C488bf00986e34ac0833208d42182c47a%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636170292905032831&sdata=quvCny8vD%2Fw%2BjIIypEtungW3OWbVmCQxFAK4%2FXrX%2Bb8%3D&reserved=0"><span style="color:windowtext;text-decoration:none">| 
 7a%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636170292905032831&sdata=quv</span></a><o:p></o:p></p>
<p class="MsoPlainText"><a href="https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail.haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc-devs&data=02%7C01%7Csimonpj%40microsoft.com%7C488bf00986e34ac0833208d42182c47a%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636170292905032831&sdata=quvCny8vD%2Fw%2BjIIypEtungW3OWbVmCQxFAK4%2FXrX%2Bb8%3D&reserved=0"><span style="color:windowtext;text-decoration:none">| 
 Cny8vD%2Fw%2BjIIypEtungW3OWbVmCQxFAK4%2FXrX%2Bb8%3D&reserved=0</span></a><o:p></o:p></p>
</div>
</body>
</html>