From alfredo.dinapoli at gmail.com Thu Apr 1 06:00:59 2021 From: alfredo.dinapoli at gmail.com (Alfredo Di Napoli) Date: Thu, 1 Apr 2021 08:00:59 +0200 Subject: Why TcLclEnv and DsGblEnv need to store the same IORef for errors? In-Reply-To: <55053410-6363-607a-10fa-3bd170a7f006@obsidian.systems> References: <010f0178837c2155-3d83b309-0bf4-4321-90a1-694a1936f811-000000@us-east-2.amazonses.com> <55053410-6363-607a-10fa-3bd170a7f006@obsidian.systems> Message-ID: Hello all, John: right, I am not opposed to what you describe, but at the end of the day we need to add all these messages to a single IORef (unless we go with the two IORef idea that Richard is not fond of), and for that we need a single monomorphic type, which could be, initially, even something like: type TcRnDsMessage = Either DsMessage TcRnMessage I guess I'll have to iterate on this until we get something meaningful and that passes the full testsuite :) A. On Wed, 31 Mar 2021 at 16:36, John Ericson wrote: > I might still be tempted to do: > data DsMessage = > ... > | DsLiftedTcRnMessage !TcRnMessage > -- ^ A diagnostic coming straight from the Typecheck-renamer. > > data TcRnMessage = > ... > | TcRnLiftedDsMessage !DsMessage > -- ^ A diagnostic coming straight from the Desugarer. > > tying them together with hs-boot. Yes, that means one can do some silly > `TcRnLiftedDsMessage . DsLiftedTcRnMessage . TcRnLiftedDsMessage ...`, but > that could even show up in a render as "while desugaring a splice during > type checking, while typechecking during desguaring, ..." so arguably the > information the wrapping isn't purely superfluous. > > I think this would pose no practical problem today, while still "soft > enforcing" the abstraction boundaries we want. > > On 3/31/21 3:45 AM, Alfredo Di Napoli wrote: > > Follow up: > > Argh! I have just seen that I have a bunch of test failures related to my > MR (which, needless to say, it's still WIP). > > For example: > > run/T9140.run.stdout.normalised 2021-03-31 09:35:48.000000000 +0200 > @@ -1,12 +1,4 @@ > > -:2:5: > - You can't mix polymorphic and unlifted bindings: a = (# 1 #) > - Probable fix: add a type signature > - > -:3:5: > - You can't mix polymorphic and unlifted bindings: a = (# 1, 3 #) > - Probable fix: add a type signature > - > > So it looks like some diagnostic is now not being reported and, surprise > surprise, this was emitted from the DsM monad. > > I have the suspect that indeed Richard was right (like he always is :) ) > -- when we go from a DsM to a TcM monad (See `initDsTc`) for example, I > think we also need to carry into the new monad all the diagnostics we > collected so far. > > This implies indeed a mutual dependency (as Simon pointed out, heh). > > > So I think my cunning plan of embedding is crumbling -- I suspect we would > end up with a type `TcRnDsMessage` which captures the dependency. > > Sorry for not seeing it sooner! > > > > > > > > > On Wed, 31 Mar 2021 at 08:05, Alfredo Di Napoli < > alfredo.dinapoli at gmail.com> wrote: > >> Morning all, >> >> *Richard*: sorry! Unfortunately MR !4798 is the cornerstone of this >> refactoring work but it's also gargantuan. Let's discuss a plan to attack >> it, but fundamentally there is a critical mass of changes that needs to >> happen atomically or it wouldn't make much sense, and alas this doesn't >> play in our favour when it comes to MR size and ease of review. However, to >> quickly reply to your remak: currently (for the sake of the >> "minimum-viable-product") I am trying to stabilise the external interfaces, >> by which I mean giving functions their final type signature while I do >> what's easiest to make things typecheck. In this phase what I think is the >> easiest is to wrap the majority of diagnostics into the `xxUnknownxx` >> constructor, and change them gradually later. A fair warning, though: you >> say "I would think that a DsMessage would later be wrapped in an >> envelope." This might be true for Ds messages (didn't actually invest any >> brain cycles to check that) but in general we have to turn a message into >> an envelope as soon as we have a chance to do so, because we need to grab >> the `SrcSpan` and the `DynFlags` *at the point of creation* of the >> diagnostics. Carrying around a message and make it bubble up at some random >> point won't be a good plan (even for Ds messages). Having said that, I >> clearly have very little knowledge about this area of GHC, so feel free to >> disagree :) >> >> *John*: Although it's a bit hard to predict how well this is going to >> evolve, my current embedding, to refresh everyone's memory, is the >> following: >> >> data DsMessage = >> >> DsUnknownMessage !DiagnosticMessage >> >> -- ^ Stop-gap constructor to ease the migration. >> >> | DsLiftedTcRnMessage !TcRnMessage >> >> -- ^ A diagnostic coming straight from the Typecheck-renamer. >> >> -- More messages added in the future, of course >> >> >> At first I thought this was the wrong way around, due to Simon's comment, >> but this actually creates pleasant external interfaces. To give you a bunch >> of examples from MR !4798: >> >> >> deSugar :: HscEnv -> ModLocation -> TcGblEnv -> IO (Messages DsMessage, >> Maybe ModGuts) >> deSugarExpr :: HscEnv -> LHsExpr GhcTc -> IO (Messages DsMessage, Maybe >> CoreExpr) >> >> Note something interesting: the second function actually calls >> `runTcInteractive` inside the body, but thanks to the `DsLiftedTcRnMessage` >> we can still expose to the consumer an opaque `DsMessage` , which is what I >> would expect to see from a function called "deSugarExpr". Conversely, I >> would be puzzled to find those functions returning a `TcRnDsMessage`. >> >> >> Having said all of that, I am not advocating this design is "the best". I >> am sure we will iterate on it. I am just reporting that even this baseline >> seems to be decent from an API perspective :) >> >> >> On Wed, 31 Mar 2021 at 05:45, John Ericson >> wrote: >> >>> Alfredo also replied to this pointing his embedding plan. I also prefer >>> that, because I really wish TH didn't smear together the phases so much. >>> Moreover, I hope with >>> >>> - GHC proposals https://github.com/ghc-proposals/ghc-proposals/pull/412 >>> / https://github.com/ghc-proposals/ghc-proposals/pull/243 >>> >>> - The parallelism work currently be planned in >>> https://gitlab.haskell.org/ghc/ghc/-/wikis/Plan-for-increased-parallelism-and-more-detailed-intermediate-output >>> >>> we might actually have an opportunity/extra motivation to do that. >>> Splices and quotes will still induce intricate inter-phase dependencies, >>> but I hope that could be mediated by the driver rather than just baked into >>> each phase. >>> >>> (One final step would be the "stuck macros" technique of >>> https://www.youtube.com/watch?v=nUvKoG_V_U0 / >>> https://github.com/gelisam/klister, where TH splices would be able to >>> making "blocking queries" of the the compiler in ways that induce more of >>> these fine-grained dependencies.) >>> >>> Anyways, while we could also do a "RnTsDsError" and split later, I hope >>> Alfredo's alternative of embedding won't be too much harder and prepare us >>> for these exciting areas of exploration. >>> >>> John >>> On 3/30/21 10:14 AM, Richard Eisenberg wrote: >>> >>> >>> >>> On Mar 30, 2021, at 4:57 AM, Alfredo Di Napoli < >>> alfredo.dinapoli at gmail.com> wrote: >>> >>> I'll explore the idea of adding a second IORef. >>> >>> >>> Renaming/type-checking is already mutually recursive. (The renamer must >>> call the type-checker in order to rename -- that is, evaluate -- untyped >>> splices. I actually can't recall why the type-checker needs to call the >>> renamer.) So we will have a TcRnError. Now we see that the desugarer ends >>> up mixed in, too. We could proceed how Alfredo suggests, by adding a second >>> IORef. Or we could just make TcRnDsError (maybe renaming that). >>> >>> What's the disadvantage? Clients will have to potentially know about all >>> the different error forms with either approach (that is, using my combined >>> type or using multiple IORefs). The big advantage to separating is maybe >>> module dependencies? But my guess is that the dependencies won't be an >>> issue here, due to the fact that these components are already leaning on >>> each other. Maybe the advantage is just in having smaller types? Maybe. >>> >>> I don't have a great sense as to what to do here, but I would want a >>> clear reason that e.g. the TcRn monad would have two IORefs, while other >>> monads will work with GhcMessage (instead of a whole bunch of IORefs). >>> >>> Richard >>> >>> _______________________________________________ >>> ghc-devs mailing listghc-devs at haskell.orghttp://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >>> >>> _______________________________________________ >>> ghc-devs mailing list >>> ghc-devs at haskell.org >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >>> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From john.ericson at obsidian.systems Thu Apr 1 15:02:17 2021 From: john.ericson at obsidian.systems (John Ericson) Date: Thu, 1 Apr 2021 11:02:17 -0400 Subject: Why TcLclEnv and DsGblEnv need to store the same IORef for errors? In-Reply-To: References: <010f0178837c2155-3d83b309-0bf4-4321-90a1-694a1936f811-000000@us-east-2.amazonses.com> <55053410-6363-607a-10fa-3bd170a7f006@obsidian.systems> Message-ID: <1cc5fee2-348c-efd0-c21e-cf4ee5a1bc74@obsidian.systems> Yeah good point. Ultimately, I hope we can abstract over things like the IORef itself so that while TcM can kick off DsM and vice-versa, each monad can only log messages of the right type, but that can come later. Good luck, very excited to see this work happen! John On 4/1/21 2:00 AM, Alfredo Di Napoli wrote: > Hello all, > > John: right, I am not opposed to what you describe, but at the end of > the day we need to add all these messages to a single IORef (unless we > go with the two IORef idea that Richard is not fond of), and for that > we need a single monomorphic type, which could be, initially, even > something like: > > type TcRnDsMessage = Either DsMessage TcRnMessage > > I guess I'll have to iterate on this until we get something meaningful > and that passes the full testsuite :) > > A. > > > > On Wed, 31 Mar 2021 at 16:36, John Ericson > wrote: > > I might still be tempted to do: > > data DsMessage = >     ... >   | DsLiftedTcRnMessage !TcRnMessage >   -- ^ A diagnostic coming straight from the Typecheck-renamer. > > data TcRnMessage = >     ... >   | TcRnLiftedDsMessage !DsMessage >   -- ^ A diagnostic coming straight from the Desugarer. > > tying them together with hs-boot. Yes, that means one can do some > silly `TcRnLiftedDsMessage . DsLiftedTcRnMessage . > TcRnLiftedDsMessage ...`, but that could even show up in a render > as "while desugaring a splice during type checking, while > typechecking during desguaring, ..." so arguably the information > the wrapping isn't purely superfluous. > > I think this would pose no practical problem today, while still > "soft enforcing" the abstraction boundaries we want. > > On 3/31/21 3:45 AM, Alfredo Di Napoli wrote: >> Follow up: >> >> Argh! I have just seen that I have a bunch of test failures >> related to my MR (which, needless to say, it's still WIP). >> >> For example: >> >> run/T9140.run.stdout.normalised 2021-03-31 09:35:48.000000000 +0200 >> @@ -1,12 +1,4 @@ >> -:2:5: >> -    You can't mix polymorphic and unlifted bindings: a = (# 1 #) >> -    Probable fix: add a type signature >> - >> -:3:5: >> -    You can't mix polymorphic and unlifted bindings: a = (# 1, 3 #) >> -    Probable fix: add a type signature >> - >> >> So it looks like some diagnostic is now not being reported and, >> surprise surprise, this was emitted from the DsM monad. >> >> I have the suspect that indeed Richard was right (like he always >> is :) ) -- when we go from a DsM to a TcM monad (See `initDsTc`) >> for example, I think we also need to carry into the new monad all >> the diagnostics we collected so far. >> >> This implies indeed a mutual dependency (as Simon pointed out, heh). >> >> >> So I think my cunning plan of embedding is crumbling -- I suspect >> we would end up with a type `TcRnDsMessage` which captures the >> dependency. >> >> Sorry for not seeing it sooner! >> >> >> >> >> >> >> >> >> On Wed, 31 Mar 2021 at 08:05, Alfredo Di Napoli >> > >> wrote: >> >> Morning all, >> >> *Richard*: sorry! Unfortunately MR !4798 is the cornerstone >> of this refactoring work but it's also gargantuan. Let's >> discuss a plan to attack it, but fundamentally there is a >> critical mass of changes that needs to happen atomically or >> it wouldn't make much sense, and alas this doesn't play in >> our favour when it comes to MR size and ease of review. >> However, to quickly reply to your remak: currently (for the >> sake of the "minimum-viable-product") I am trying to >> stabilise the external interfaces, by which I mean giving >> functions their final type signature while I do what's >> easiest to make things typecheck. In this phase what I think >> is the easiest is to wrap the majority of diagnostics into >> the `xxUnknownxx` constructor, and change them gradually >> later. A fair warning, though: you say "I would think that a >> DsMessage would later be wrapped in an envelope." This might >> be true for Ds messages (didn't actually invest any brain >> cycles to check that) but in general we have to turn a >> message into an envelope as soon as we have a chance to do >> so, because we need to grab the `SrcSpan` and the `DynFlags` >> *at the point of creation* of the diagnostics. Carrying >> around a message and make it bubble up at some random point >> won't be a good plan (even for Ds messages). Having said >> that, I clearly have very little knowledge about this area of >> GHC, so feel free to disagree :) >> >> *John*: Although it's a bit hard to predict how well this is >> going to evolve, my current embedding, to refresh everyone's >> memory, is the following: >> >> data DsMessage = >> >>   DsUnknownMessage !DiagnosticMessage >> >> -- ^ Stop-gap constructor to ease the migration. >> >> | DsLiftedTcRnMessage !TcRnMessage >> >> -- ^ A diagnostic coming straight from the Typecheck-renamer. >> >> -- More messages added in the future, of course >> >> >> At first I thought this was the wrong way around, due to >> Simon's comment, but this actually creates pleasant external >> interfaces. To give you a bunch of examples from MR !4798: >> >> >> deSugar :: HscEnv -> ModLocation -> TcGblEnv -> IO (Messages >> DsMessage, Maybe ModGuts) >> >> deSugarExpr :: HscEnv -> LHsExpr GhcTc -> IO (Messages >> DsMessage, Maybe CoreExpr) >> >> Note something interesting: the second function actually >> calls `runTcInteractive` inside the body, but thanks to the >> `DsLiftedTcRnMessage` we can still expose to the consumer an >> opaque `DsMessage` , which is what I would expect to see from >> a function called "deSugarExpr". Conversely, I would be >> puzzled to find those functions returning a `TcRnDsMessage`. >> >> >> Having said all of that, I am not advocating this design is >> "the best". I am sure we will iterate on it. I am just >> reporting that even this baseline seems to be decent from an >> API perspective :) >> >> >> On Wed, 31 Mar 2021 at 05:45, John Ericson >> >> wrote: >> >> Alfredo also replied to this pointing his embedding plan. >> I also prefer that, because I really wish TH didn't smear >> together the phases so much. Moreover, I hope with >> >>  - GHC proposals >> https://github.com/ghc-proposals/ghc-proposals/pull/412 >> >> / https://github.com/ghc-proposals/ghc-proposals/pull/243 >> >> >>  - The parallelism work currently be planned in >> https://gitlab.haskell.org/ghc/ghc/-/wikis/Plan-for-increased-parallelism-and-more-detailed-intermediate-output >> >> >> >> we might actually have an opportunity/extra motivation to >> do that. Splices and quotes will still induce intricate >> inter-phase dependencies, but I hope that could be >> mediated by the driver rather than just baked into each >> phase. >> >> (One final step would be the "stuck macros" technique of >> https://www.youtube.com/watch?v=nUvKoG_V_U0 >> / >> https://github.com/gelisam/klister >> , where TH splices >> would be able to making "blocking queries" of the the >> compiler in ways that induce more of these fine-grained >> dependencies.) >> >> Anyways, while we could also do a "RnTsDsError" and split >> later, I hope Alfredo's alternative of embedding won't be >> too much harder and prepare us for these exciting areas >> of exploration. >> >> John >> >> On 3/30/21 10:14 AM, Richard Eisenberg wrote: >>> >>> >>>> On Mar 30, 2021, at 4:57 AM, Alfredo Di Napoli >>>> >>> > wrote: >>>> >>>> I'll explore the idea of adding a second IORef. >>> >>> Renaming/type-checking is already mutually recursive. >>> (The renamer must call the type-checker in order to >>> rename -- that is, evaluate -- untyped splices. I >>> actually can't recall why the type-checker needs to call >>> the renamer.) So we will have a TcRnError. Now we see >>> that the desugarer ends up mixed in, too. We could >>> proceed how Alfredo suggests, by adding a second IORef. >>> Or we could just make TcRnDsError (maybe renaming that). >>> >>> What's the disadvantage? Clients will have to >>> potentially know about all the different error forms >>> with either approach (that is, using my combined type or >>> using multiple IORefs). The big advantage to separating >>> is maybe module dependencies? But my guess is that the >>> dependencies won't be an issue here, due to the fact >>> that these components are already leaning on each other. >>> Maybe the advantage is just in having smaller types? Maybe. >>> >>> I don't have a great sense as to what to do here, but I >>> would want a clear reason that e.g. the TcRn monad would >>> have two IORefs, while other monads will work with >>> GhcMessage (instead of a whole bunch of IORefs). >>> >>> Richard >>> >>> _______________________________________________ >>> ghc-devs mailing list >>> ghc-devs at haskell.org >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From ben at well-typed.com Thu Apr 1 16:42:57 2021 From: ben at well-typed.com (Ben Gamari) Date: Thu, 01 Apr 2021 12:42:57 -0400 Subject: [ANNOUNCE] GHC 9.2.1-alpha1 now available Message-ID: <87y2e2t0q8.fsf@smart-cactus.org> Hi all, The GHC developers are very happy to announce the availability of the first alpha release in the 9.2.1 series. Binary distributions, source distributions, and documentation are available at https://downloads.haskell.org/ghc/9.2.1-alpha1 GHC 9.2 will bring a number of exciting features including: * Many changes in the area of records, including the new `RecordDotSyntax` and `NoFieldSelectors` language extensions, as well as Support for `DuplicateRecordFields` with `PatternSynonyms`. * Introduction of the new `GHC2021` language extension set, giving users convenient access to a larger set of language extensions which have been long considered stable. * Merge of `ghc-exactprint` into the GHC tree, providing infrastructure for source-to-source program rewriting out-of-the-box. * Introduction of a `BoxedRep` `RuntimeRep`, allowing for polymorphism over levity of boxed objects (#17526) * Implementation of the `UnliftedDataTypes` extension, allowing users to define types which do not admit lazy evaluation ([proposal]) * The new [-hi profiling] mechanism which provides significantly improved insight into thunk leaks. * Support for the `ghc-debug` out-of-process heap inspection library [ghc-debug] * Support for profiling of pinned objects with the cost-centre profiler (#7275) * Introduction of Haddock documentation support in TemplateHaskell (#5467) In addition, the final 9.2.1 release will bring a new native code generator for ARM, providing fast, first-class for Haskell on Apple ARM hardware [apple-m1], although this functionality is not yet present in this alpha. As always, do give this a try and open a [ticket] if you see anything amiss. Happy testing, - Ben [apple-m1]: https://www.haskell.org/ghc/blog/20210309-apple-m1-story.html [proposal]: https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0265-unlifted-datatypes.rst [-hi profiling]: https://well-typed.com/blog/2021/01/first-look-at-hi-profiling-mode/ [ghc-debug]: http://ghc.gitlab.haskell.org/ghc-debug/ [ticket]: https://gitlab.haskell.org/ghc/ghc/-/issues/new -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: not available URL: From lonetiger at gmail.com Fri Apr 2 10:59:38 2021 From: lonetiger at gmail.com (Phyx) Date: Fri, 2 Apr 2021 11:59:38 +0100 Subject: [ANNOUNCE] GHC 9.2.1-alpha1 now available In-Reply-To: <87y2e2t0q8.fsf@smart-cactus.org> References: <87y2e2t0q8.fsf@smart-cactus.org> Message-ID: Hi, Typically a GHC release is tied to a new cabal release as well. I however can't find a new tag for Cabal. Does this mean I need to use cabal-head or can I use Cabal 3.4? Thanks, Tamar On Thu, Apr 1, 2021 at 5:44 PM Ben Gamari wrote: > Hi all, > > The GHC developers are very happy to announce the availability of the > first alpha release in the 9.2.1 series. Binary distributions, source > distributions, and documentation are available at > > https://downloads.haskell.org/ghc/9.2.1-alpha1 > > GHC 9.2 will bring a number of exciting features including: > > * Many changes in the area of records, including the new > `RecordDotSyntax` and `NoFieldSelectors` language extensions, as well > as Support for `DuplicateRecordFields` with `PatternSynonyms`. > > * Introduction of the new `GHC2021` language extension set, giving > users convenient access to a larger set of language extensions which > have been long considered stable. > > * Merge of `ghc-exactprint` into the GHC tree, providing infrastructure > for source-to-source program rewriting out-of-the-box. > > * Introduction of a `BoxedRep` `RuntimeRep`, allowing for polymorphism > over levity of boxed objects (#17526) > > * Implementation of the `UnliftedDataTypes` extension, allowing users > to define types which do not admit lazy evaluation ([proposal]) > > * The new [-hi profiling] mechanism which provides significantly > improved insight into thunk leaks. > > * Support for the `ghc-debug` out-of-process heap inspection library > [ghc-debug] > > * Support for profiling of pinned objects with the cost-centre profiler > (#7275) > > * Introduction of Haddock documentation support in TemplateHaskell (#5467) > > In addition, the final 9.2.1 release will bring a new native code > generator for ARM, providing fast, first-class for Haskell on Apple > ARM hardware [apple-m1], although this functionality is not yet > present in this alpha. > > As always, do give this a try and open a [ticket] if you see anything > amiss. > > Happy testing, > > - Ben > > > [apple-m1]: https://www.haskell.org/ghc/blog/20210309-apple-m1-story.html > [proposal]: > https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0265-unlifted-datatypes.rst > [-hi > > profiling]: > https://well-typed.com/blog/2021/01/first-look-at-hi-profiling-mode/ > [ghc-debug > ]: > http://ghc.gitlab.haskell.org/ghc-debug/ > [ticket]: https://gitlab.haskell.org/ghc/ghc/-/issues/new > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From george.colpitts at gmail.com Fri Apr 2 14:32:49 2021 From: george.colpitts at gmail.com (George Colpitts) Date: Fri, 2 Apr 2021 11:32:49 -0300 Subject: [ANNOUNCE] GHC 9.2.1-alpha1 now available In-Reply-To: <87y2e2t0q8.fsf@smart-cactus.org> References: <87y2e2t0q8.fsf@smart-cactus.org> Message-ID: Great news! I couldn't find a mention of the supported llvm version in the release notes here . Also will the llvm compiler option be supported for 9.2.1? Thanks George On Thu, Apr 1, 2021 at 1:44 PM Ben Gamari wrote: > Hi all, > > The GHC developers are very happy to announce the availability of the > first alpha release in the 9.2.1 series. Binary distributions, source > distributions, and documentation are available at > > https://downloads.haskell.org/ghc/9.2.1-alpha1 > > GHC 9.2 will bring a number of exciting features including: > > * Many changes in the area of records, including the new > `RecordDotSyntax` and `NoFieldSelectors` language extensions, as well > as Support for `DuplicateRecordFields` with `PatternSynonyms`. > > * Introduction of the new `GHC2021` language extension set, giving > users convenient access to a larger set of language extensions which > have been long considered stable. > > * Merge of `ghc-exactprint` into the GHC tree, providing infrastructure > for source-to-source program rewriting out-of-the-box. > > * Introduction of a `BoxedRep` `RuntimeRep`, allowing for polymorphism > over levity of boxed objects (#17526) > > * Implementation of the `UnliftedDataTypes` extension, allowing users > to define types which do not admit lazy evaluation ([proposal]) > > * The new [-hi profiling] mechanism which provides significantly > improved insight into thunk leaks. > > * Support for the `ghc-debug` out-of-process heap inspection library > [ghc-debug] > > * Support for profiling of pinned objects with the cost-centre profiler > (#7275) > > * Introduction of Haddock documentation support in TemplateHaskell (#5467) > > In addition, the final 9.2.1 release will bring a new native code > generator for ARM, providing fast, first-class for Haskell on Apple > ARM hardware [apple-m1], although this functionality is not yet > present in this alpha. > > As always, do give this a try and open a [ticket] if you see anything > amiss. > > Happy testing, > > - Ben > > > [apple-m1]: https://www.haskell.org/ghc/blog/20210309-apple-m1-story.html > [proposal]: > https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0265-unlifted-datatypes.rst > [-hi > > profiling]: > https://well-typed.com/blog/2021/01/first-look-at-hi-profiling-mode/ > [ghc-debug > ]: > http://ghc.gitlab.haskell.org/ghc-debug/ > [ticket]: https://gitlab.haskell.org/ghc/ghc/-/issues/new > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ben at well-typed.com Fri Apr 2 21:31:56 2021 From: ben at well-typed.com (Ben Gamari) Date: Fri, 02 Apr 2021 17:31:56 -0400 Subject: [ANNOUNCE] GHC 9.2.1-alpha1 now available In-Reply-To: References: <87y2e2t0q8.fsf@smart-cactus.org> Message-ID: <87r1jstltf.fsf@smart-cactus.org> Phyx writes: > Hi, > > Typically a GHC release is tied to a new cabal release as well. I however > can't find a new tag for Cabal. > > Does this mean I need to use cabal-head or can I use Cabal 3.4? > There will be a Cabal 3.6 release associated with this release however this branch hasn't happened yet. Hopefully this will be sorted by the next alpha. Cheers, - Ben -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: not available URL: From ben at well-typed.com Fri Apr 2 21:33:28 2021 From: ben at well-typed.com (Ben Gamari) Date: Fri, 02 Apr 2021 17:33:28 -0400 Subject: [ANNOUNCE] GHC 9.2.1-alpha1 now available In-Reply-To: References: <87y2e2t0q8.fsf@smart-cactus.org> Message-ID: <87o8ewtlqw.fsf@smart-cactus.org> George Colpitts writes: > Great news! I couldn't find a mention of the supported llvm version in the > release notes here > . > > Also will the llvm compiler option be supported for 9.2.1? > This is mentioned in the users guide associated with the 9.2.1-alpha1 release [1]. We will support both LLVM 10 and 11 in this release. Cheers, - Ben [1] http://downloads.haskell.org/ghc/9.2.1-alpha1/docs/html/users_guide/9.2.1-notes.html -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: not available URL: From alfredo.dinapoli at gmail.com Sat Apr 3 07:17:23 2021 From: alfredo.dinapoli at gmail.com (Alfredo Di Napoli) Date: Sat, 3 Apr 2021 09:17:23 +0200 Subject: Error and Warning Messages practical migration guidelines Message-ID: *TL;DR If you recently had merge conflicts related to error and messages in GHC, here I give migration guidelines. Otherwise, feel free to ignore this email.* Good morning all, If you had some work-in-progress branch that was emitting errors or warnings (either adding new ones or modifying existing ones), chances are you noticed that now the API and types changed slightly and you had to deal with the conflicts. What you noticed was the initial chunk of work for [#18516]. See the [Wiki] for more info. Our work is not done yet, but the API changed enough to warrant me writing this little email to help folks out with their rebasing (because we are *all* rebasing at least daily, aren't we? :) ). First of all, sorry for all the churning! I am trying to stabilise the external interfaces (i.e the type signatures of the GHC API functions) so things will become a bit more stable in the future. In the meantime, I wanted to give you some practical guidelines on how to migrate your code: * Rather than "errors" or "warnings", we are trying to shift our vocabulary to talk about "diagnostics". In GHC this distinction is not so "strict", in the sense warnings can become errors and errors can become warnings if deferred. Rather we talk about diagnostics, i.e. facts about the compiled program, that can be, at the very end, classified as errors or warnings based on their `Severity`; * *If you skip this whole email, read just this:* the key insight is that there is a clear separation between the *reason* this diagnostic was created and the final `Severity`! Example: we emit a diagnostic because `Opt_WarnMonomorphism` is on. That's the raison d'être of this diagnostic. Therefore, we would create a new message (more on this later) with reason `WarningWithFlag Opt_WarnMonomorphism`; * A `Severity` of a diagnostic is computed using the `DynFlags`, because that's the only way to correctly classify a diagnostic. Back to our little example above, if `Opt_WarnMonomorphism` was set as fatal (or -Werror enabled), now the final `Severity` of the diagnostic above would be `SevError`. That's why it's important to keep them separate; * We separated out the logging messages with the diagnostics proper, this is why we now have a new [MessageClass] type which can be used to log all sort of messages (debug ones, informational etc) *and* diagnostics, which has a dedicated type constructor; * If you want to emit something which is not an error or a warning, use [putLogMsg]. Here is an example: https://gitlab.haskell.org/ghc/ghc/-/blob/master/compiler/GHC/Core/Lint.hs#L402 (we could argue if the example shouldn't be a diagnostic, but we didn't go that far in the refactoring yet, this is just to give you an idea of the usage); * The most general function which can be used to produce a diagnostic is [mkMsgEnvelope], which takes as input the `DynFlags` to compute the `Severity` under the hood. * You can't just pass a random `DynFlags` to `mkMsgEnvelope`, but the former should be acquired as close as possible to the construction/emission site of the diagnostics. This is because `DynFlags` evolves and are mangled all the time inside GHC, and we want to produce the `Severity` using the most faithful "snapshot" of the state of the world at the time the diagnostic was produced. * Most of the times you don't have to worry about all of this; if you know for sure a diagnostic is an error and is not recoverable, then you can use `mkMsgErrorEnvelope` that doesn't need the `DynFlags` and always produces a diagnostic with `SevError` and `ErrorWithoutFlags`. * Once #18516 will be completed, this will require a bit less cognitive overhead. We will have proper types (not SDocs or generic `DecoratedMessage`s), and all the working GHC hacker will have to worry about would be to create a brand new Haskell type for the diagnostic, give it a `Diagnostic` instance (or extend the instance declaration if that's an existing type) and then just call whichever high-level API we will have available. Hope this helps! Alfredo [#18516]: https://gitlab.haskell.org/ghc/ghc/-/issues/18516 [Wiki]: https://gitlab.haskell.org/ghc/ghc/-/wikis/Errors-as-(structured)-values [MessageClass]: https://gitlab.haskell.org/ghc/ghc/-/blob/master/compiler/GHC/Types/Error.hs#L209 [putLogMsg]: https://gitlab.haskell.org/ghc/ghc/-/blob/master/compiler/GHC/Utils/Logger.hs#L128 [mkMsgEnvelope]: https://gitlab.haskell.org/ghc/ghc/-/blob/master/compiler/GHC/Utils/Error.hs#L116 -------------- next part -------------- An HTML attachment was scrubbed... URL: From hecate at glitchbra.in Sat Apr 3 16:09:38 2021 From: hecate at glitchbra.in (=?UTF-8?Q?H=c3=a9cate?=) Date: Sat, 3 Apr 2021 18:09:38 +0200 Subject: GHC Proposal: GHC Maintainer Preview Message-ID: Hi everyone! I would like to share with you all the proposal I opened, called "GHC Maintainer Preview", to shape the release schedule of our beloved compiler. The concept is that we let a certain period of time pass between the final "release" of a major (X.Y) GHC version, and its official, public, user-targeting release, so that we can focus our efforts in helping library maintainers to migrate and change their code to accommodate the whatever breaking change the new major version introduces. The proposal is located here: https://github.com/ghc-proposals/ghc-proposals/pull/417 Have a nice week-end! -- Hécate ✨ 🐦: @TechnoEmpress IRC: Uniaika WWW: https://glitchbra.in RUN: BSD From lexi.lambda at gmail.com Sun Apr 4 00:04:45 2021 From: lexi.lambda at gmail.com (Alexis King) Date: Sat, 3 Apr 2021 19:04:45 -0500 Subject: How does GHC implement layout? Message-ID: <22b079f6-e288-eb8c-799a-004b020c7e0b@gmail.com> Hi all, I’m wondering if there are any resources that discuss the design of GHC’s implementation of layout. (I haven’t been able to find any.) From looking at the code, here’s what I’ve gathered so far: * Layout is implemented in the lexer (compiler/GHC/Parser/Lexer.x). * The implementation is similar in some respects to the approach described in the Haskell Report, but still fairly different. Virtual braces and semicolons are inserted during the lexing process itself with the assistance of Alex lexer states (aka “start codes”). * In order to handle particularly tricky cases like if e then do x; y else z where the virtual close brace must be inserted in the middle of a line, tokens such as in and else are given special context-sensitive treatment. This appears to be quite subtle. Overall, I can mostly follow the code, but I still have a few unanswered questions: * The layout-related code consistently uses the phrase “alternative layout rule”—what does “alternative” mean here? Does it refer to GHC’s implementation of layout? Or maybe it refers to NondecreasingIndentation? It isn’t clear. * The implementation of layout seems quite complex, in large part because it has to worry about parsing concerns in the lexer in order to handle tricky cases like the one I provided above. Is there are reason all this is done in the lexer, rather than deferring some more of the work to the parser? I’ve found remarkably little information about implementing layout in general, so perhaps I’m missing some resources or keywords to search for, but any information or perspectives would be appreciated! Thanks, Alexis -------------- next part -------------- An HTML attachment was scrubbed... URL: From iavor.diatchki at gmail.com Sun Apr 4 18:52:47 2021 From: iavor.diatchki at gmail.com (Iavor Diatchki) Date: Sun, 4 Apr 2021 11:52:47 -0700 Subject: How does GHC implement layout? In-Reply-To: <22b079f6-e288-eb8c-799a-004b020c7e0b@gmail.com> References: <22b079f6-e288-eb8c-799a-004b020c7e0b@gmail.com> Message-ID: Hi Alexis, I wasn't sure what the "alternative layout" is either and did some googling, and it appears that it is something that was never really documented properly. The following link contains pointers to the commit that introduced it (in 2009!) (not the main ticket but some of the comments) https://ghc-tickets.haskell.narkive.com/htgwkF80/13087-alternativelayoutrule-breaks-lambdacase Overall, I do think that Haskell's layout rule is more complicated than it needs to be, and this is mostly because of the rule that requires the insertion of a "virtual close curly" on a parse error. This means that the parser and lexer have to communicate. I've implemented a few languages with layout, and usually use a simpler version of layout that just omits that case. The benefit is that layout can be implemented as a simple pre-processor pass on the stream of tokens, which is much simpler to specify and implement. The drawback is that sometimes you have to write programs in a slightly different way, but nothing that can't be easily worked around. My feeling is that it'd be pretty tricky to do layout in the parser with grammar rules, but you may be able to do something with the parser state. I wonder how different it would end up looking though, as in a way that's exactly what we are doing now, it is just that some of the state is the lexer. -Iavor On Sat, Apr 3, 2021 at 5:05 PM Alexis King wrote: > Hi all, > > I’m wondering if there are any resources that discuss the design of GHC’s > implementation of layout. (I haven’t been able to find any.) From looking > at the code, here’s what I’ve gathered so far: > > - Layout is implemented in the lexer (compiler/GHC/Parser/Lexer.x). > > - The implementation is similar in some respects to the approach > described in the Haskell Report, but still fairly different. Virtual braces > and semicolons are inserted during the lexing process itself with the > assistance of Alex lexer states (aka “start codes”). > > - In order to handle particularly tricky cases like > > if e then do x; y else z > > > where the virtual close brace must be inserted in the middle of a > line, tokens such as in and else are given special context-sensitive > treatment. This appears to be quite subtle. > > Overall, I can mostly follow the code, but I still have a few unanswered > questions: > > - The layout-related code consistently uses the phrase “alternative > layout rule”—what does “alternative” mean here? Does it refer to GHC’s > implementation of layout? Or maybe it refers to > NondecreasingIndentation? It isn’t clear. > > - The implementation of layout seems quite complex, in large part > because it has to worry about parsing concerns in the lexer in order to > handle tricky cases like the one I provided above. Is there are reason all > this is done in the lexer, rather than deferring some more of the work to > the parser? > > I’ve found remarkably little information about implementing layout in > general, so perhaps I’m missing some resources or keywords to search for, > but any information or perspectives would be appreciated! > > Thanks, > Alexis > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From lexi.lambda at gmail.com Sun Apr 4 22:18:52 2021 From: lexi.lambda at gmail.com (Alexis King) Date: Sun, 4 Apr 2021 17:18:52 -0500 Subject: How does GHC implement layout? In-Reply-To: References: <22b079f6-e288-eb8c-799a-004b020c7e0b@gmail.com> Message-ID: <326ac03c-9c6e-975e-3f4f-2ab045dfc382@gmail.com> On 4/4/21 1:52 PM, Iavor Diatchki wrote: > Hi Alexis, > > I wasn't sure what the "alternative layout" is either and did some > googling, and it appears that it is something that was never really > documented properly.   The following link contains pointers to the > commit that introduced it (in 2009!) (not the main ticket but some of > the comments) Thanks, that’s a helpful pointer, though of course it still doesn’t explain very much. I’m still interested in understanding what the purpose of “alternative layout” is and how it operates, if anyone else has any idea. > Overall, I do think that Haskell's layout rule is more complicated > than it needs to be, and this is mostly because of the rule that > requires the insertion of a "virtual close curly" on a parse error. Yes, this does seem to be by far the trickiest bit. But I’d be sad not to have it, as without it, even simple things like let x = 3 in e would not be grammatically valid. > My feeling is that it'd be pretty tricky to do layout in the parser > with grammar rules, but you may be able to do something with the > parser state. Yes, I have some vague ideas, but none of them are particularly fleshed out. It’s entirely possible that I just don’t understand the relationship between the lexer and the parser (which seems somewhat obscured by the “alternative layout” stuff), and the ideas I have are what’s already implemented today. I’ll have to study the implementation more closely. In any case, thank you for your response! The ALR-related pointer certainly clarifies at least a little. Alexis -------------- next part -------------- An HTML attachment was scrubbed... URL: From sgraf1337 at gmail.com Mon Apr 5 12:14:29 2021 From: sgraf1337 at gmail.com (Sebastian Graf) Date: Mon, 5 Apr 2021 14:14:29 +0200 Subject: How does GHC implement layout? In-Reply-To: <326ac03c-9c6e-975e-3f4f-2ab045dfc382@gmail.com> References: <22b079f6-e288-eb8c-799a-004b020c7e0b@gmail.com> <326ac03c-9c6e-975e-3f4f-2ab045dfc382@gmail.com> Message-ID: Hi Alexis, Hi Iavor, I'm afraid I'm not particularly acquainted with how GHC implements indentation-sensitive parsing, but I really like the way in which this book frames the problem. If you look at the preview for the first chapter, you'll notice that (they call the lexer scanner, and) they introduce an additional pass between lexer and parser that handles the context-sensitive bits about indentation-sensitive parsing, which doesn't fit well with the parser (which assumes a context-free grammar to stay sane) or with the lexer (which should better be just a simple DFA). In particular, the short section 1.3 about the screener explicitly mentions Haskell as use case: [image: 2021-04-05-140820_543x163_scrot.png] Although that doesn't really explain the how. Maybe section 2.5 (where impl of screeners is covered) provides more insight into that. Screeners are a bit like semantic analysis, but on the token stream instead of the parse tree. Reach out in private if you want more excerpts. Cheers, Sebastian Am Mo., 5. Apr. 2021 um 00:19 Uhr schrieb Alexis King : > On 4/4/21 1:52 PM, Iavor Diatchki wrote: > > Hi Alexis, > > I wasn't sure what the "alternative layout" is either and did some > googling, and it appears that it is something that was never really > documented properly. The following link contains pointers to the commit > that introduced it (in 2009!) (not the main ticket but some of the > comments) > > Thanks, that’s a helpful pointer, though of course it still doesn’t > explain very much. I’m still interested in understanding what the purpose > of “alternative layout” is and how it operates, if anyone else has any idea. > > Overall, I do think that Haskell's layout rule is more complicated than it > needs to be, and this is mostly because of the rule that requires the > insertion of a "virtual close curly" on a parse error. > > Yes, this does seem to be by far the trickiest bit. But I’d be sad not to > have it, as without it, even simple things like > > let x = 3 in e > > would not be grammatically valid. > > My feeling is that it'd be pretty tricky to do layout in the parser with > grammar rules, but you may be able to do something with the parser state. > > Yes, I have some vague ideas, but none of them are particularly fleshed > out. It’s entirely possible that I just don’t understand the relationship > between the lexer and the parser (which seems somewhat obscured by the > “alternative layout” stuff), and the ideas I have are what’s already > implemented today. I’ll have to study the implementation more closely. > > In any case, thank you for your response! The ALR-related pointer > certainly clarifies at least a little. > > Alexis > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 2021-04-05-140820_543x163_scrot.png Type: image/png Size: 32946 bytes Desc: not available URL: From carter.schonwald at gmail.com Mon Apr 5 19:42:02 2021 From: carter.schonwald at gmail.com (Carter Schonwald) Date: Mon, 5 Apr 2021 15:42:02 -0400 Subject: How does GHC implement layout? In-Reply-To: <326ac03c-9c6e-975e-3f4f-2ab045dfc382@gmail.com> References: <22b079f6-e288-eb8c-799a-004b020c7e0b@gmail.com> <326ac03c-9c6e-975e-3f4f-2ab045dfc382@gmail.com> Message-ID: while not totally perfectly related, i have wondered if something like the the recent pika parsing paper https://arxiv.org/abs/2005.06444 could be used to provide better error recovery from layout related errors in haskell and similar languages. On Sun, Apr 4, 2021 at 6:19 PM Alexis King wrote: > On 4/4/21 1:52 PM, Iavor Diatchki wrote: > > Hi Alexis, > > I wasn't sure what the "alternative layout" is either and did some > googling, and it appears that it is something that was never really > documented properly. The following link contains pointers to the commit > that introduced it (in 2009!) (not the main ticket but some of the > comments) > > Thanks, that’s a helpful pointer, though of course it still doesn’t > explain very much. I’m still interested in understanding what the purpose > of “alternative layout” is and how it operates, if anyone else has any idea. > > Overall, I do think that Haskell's layout rule is more complicated than it > needs to be, and this is mostly because of the rule that requires the > insertion of a "virtual close curly" on a parse error. > > Yes, this does seem to be by far the trickiest bit. But I’d be sad not to > have it, as without it, even simple things like > > let x = 3 in e > > would not be grammatically valid. > > My feeling is that it'd be pretty tricky to do layout in the parser with > grammar rules, but you may be able to do something with the parser state. > > Yes, I have some vague ideas, but none of them are particularly fleshed > out. It’s entirely possible that I just don’t understand the relationship > between the lexer and the parser (which seems somewhat obscured by the > “alternative layout” stuff), and the ideas I have are what’s already > implemented today. I’ll have to study the implementation more closely. > > In any case, thank you for your response! The ALR-related pointer > certainly clarifies at least a little. > > Alexis > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From igloo at earth.li Mon Apr 5 19:36:03 2021 From: igloo at earth.li (Ian Lynagh) Date: Mon, 5 Apr 2021 20:36:03 +0100 Subject: How does GHC implement layout? In-Reply-To: References: <22b079f6-e288-eb8c-799a-004b020c7e0b@gmail.com> Message-ID: <20210405193603.GA29627@matrix.chaos.earth.li> On Mon, Apr 05, 2021 at 05:09:21PM +0000, Simon Peyton-Jones wrote: > Two people who may know more about the alternative layout rule are Simon Marlow and Ian Lynagh (cc'd). It was originally designed by John Meacham: https://gitlab.haskell.org/haskell/prime/-/wikis/alternative-layout-rule https://www.mail-archive.com/haskell-prime at haskell.org/msg01938.html It isn't exactly equivalent to the Haskell layout rule, but it's fairly close and much simpler (due to not having the "on a parse error" case). Thanks IAn From igloo at earth.li Mon Apr 5 20:24:53 2021 From: igloo at earth.li (Ian Lynagh) Date: Mon, 5 Apr 2021 21:24:53 +0100 Subject: How does GHC implement layout? In-Reply-To: <326ac03c-9c6e-975e-3f4f-2ab045dfc382@gmail.com> References: <22b079f6-e288-eb8c-799a-004b020c7e0b@gmail.com> <326ac03c-9c6e-975e-3f4f-2ab045dfc382@gmail.com> Message-ID: <20210405202453.GA32644@matrix.chaos.earth.li> On Sun, Apr 04, 2021 at 05:18:52PM -0500, Alexis King wrote: > On 4/4/21 1:52 PM, Iavor Diatchki wrote: > > > > Overall, I do think that Haskell's layout rule is more complicated than > > it needs to be, and this is mostly because of the rule that requires the > > insertion of a "virtual close curly" on a parse error. > > Yes, this does seem to be by far the trickiest bit. But I’d be sad not to > have it, as without it, even simple things like > > let x = 3 in e > > would not be grammatically valid. That is accepted by the AlternativeLayoutRule. Thanks Ian From lexi.lambda at gmail.com Tue Apr 6 00:35:59 2021 From: lexi.lambda at gmail.com (Alexis King) Date: Mon, 5 Apr 2021 19:35:59 -0500 Subject: How does GHC implement layout? In-Reply-To: <20210405193603.GA29627@matrix.chaos.earth.li> References: <22b079f6-e288-eb8c-799a-004b020c7e0b@gmail.com> <20210405193603.GA29627@matrix.chaos.earth.li> Message-ID: <8b42aec3-4a98-6b7a-5379-ccad3b770010@gmail.com> On 4/5/21 2:36 PM, Ian Lynagh wrote: > It was originally designed by John Meacham: > https://gitlab.haskell.org/haskell/prime/-/wikis/alternative-layout-rule > https://www.mail-archive.com/haskell-prime at haskell.org/msg01938.html Thanks, Ian—I had stumbled across a link to the old Haskell Prime trac wiki while I was searching for information, but I didn’t realize where it had been migrated to. > It isn't exactly equivalent to the Haskell layout rule, but it's > fairly close and much simpler (due to not having the "on a parse > error" case). Yes, I gathered as much from the implementation. The idea makes sense, but of course it doesn’t provide much benefit to have a simpler implementation unless it actually /replaces/ the “on parse error” approach. Given this appears to be a long-defunct proposal, a natural followup question is to ask whether there’s any reason this code is still in GHC. Is it used for any purpose, or could it be removed? Alexis -------------- next part -------------- An HTML attachment was scrubbed... URL: From shanth2600 at gmail.com Tue Apr 6 02:24:36 2021 From: shanth2600 at gmail.com (Shant Hairapetian) Date: Mon, 5 Apr 2021 19:24:36 -0700 Subject: Newcomer looking for help with changes to kind system Message-ID: Hello, I’m a master’s student working on implementing the changes outlined in “Kinds are Calling Conventions“ ( https://www.microsoft.com/en-us/research/uploads/prod/2020/03/kacc.pdf). I have been working directly with Paul Downen but have hit some roadblocks. To sum up the changes to the kind system, I am attempting to modify the “TYPE” type constructor to accept, rather than just a RuntimeRep, a record type (called RuntimeInfo) comprised of a RuntimeRep and a CallingConv (calling convention). The calling convention has an “Eval” constructor which accepts a levity (effectively moving the levity information from the representation to the calling convention. LiftedRep and UnliftedRep would also be collapsed into a single PtrRep constructor) and a “Call” constructor (denoting the arity of primitive, extensional functions, see: Making a Faster Curry with Extensional Types ) which accepts a list of RuntimeRep’s. I have created and wired-in the new RuntimeInfo and CallingConv types in GHC.Builtin.Types, as well as the corresponding primitive types in GHC.Builtin.Types.Prim and have modified the “TYPE” constructor to accept a RuntimeInfo rather than a RuntimeRep. My issue (well, one of my issues) is that, for unboxed tuples, though the actual kind is being built up correctly, the expected type is still in the old (or current) representation. (expected) Couldn't match type: 'TupleRep ('[] @RuntimeRep) (actual) with: 'RInfo ('TupleRep ('[] @RuntimeRep)) 'GHC.Types.ConvEval I have not been able to locate where this expected kind is being constructed. Any help this issue or general guidance would be greatly appreciated. Thanks, Shant -------------- next part -------------- An HTML attachment was scrubbed... URL: From ben at smart-cactus.org Tue Apr 6 02:41:01 2021 From: ben at smart-cactus.org (Ben Gamari) Date: Mon, 05 Apr 2021 22:41:01 -0400 Subject: Newcomer looking for help with changes to kind system In-Reply-To: References: Message-ID: <877dlgt9s4.fsf@smart-cactus.org> Shant Hairapetian writes: > Hello, > > I’m a master’s student working on implementing the changes outlined in > “Kinds are Calling Conventions“ ( > https://www.microsoft.com/en-us/research/uploads/prod/2020/03/kacc.pdf). I > have been working directly with Paul Downen but have hit some roadblocks. > > To sum up the changes to the kind system, I am attempting to modify the > “TYPE” type constructor to accept, rather than just a RuntimeRep, a record > type (called RuntimeInfo) comprised of a RuntimeRep and a CallingConv > (calling convention). The calling convention has an “Eval” constructor > which accepts a levity (effectively moving the levity information from the > representation to the calling convention. LiftedRep and UnliftedRep would > also be collapsed into a single PtrRep constructor) and a “Call” > constructor (denoting the arity of primitive, extensional functions, > see: Making > a Faster Curry with Extensional Types > ) > which accepts a list of RuntimeRep’s. I have created and wired-in the new > RuntimeInfo and CallingConv types in GHC.Builtin.Types, as well as the > corresponding primitive types in GHC.Builtin.Types.Prim and have modified > the “TYPE” constructor to accept a RuntimeInfo rather than a RuntimeRep. > Hi Shant, It would be helpful to have a bit more information on the nature of your failure. Can you provide a program that your patch rejects, as well as the full error that is produced? Incidentally, the collapse of LiftedRep and UnliftedRep will happen in GHC 9.2 (turning into `BoxedRep :: Levity -> RuntimeRep`). Cheers, - Ben -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: not available URL: From marlowsd at gmail.com Tue Apr 6 11:10:39 2021 From: marlowsd at gmail.com (Simon Marlow) Date: Tue, 6 Apr 2021 12:10:39 +0100 Subject: How does GHC implement layout? In-Reply-To: <8b42aec3-4a98-6b7a-5379-ccad3b770010@gmail.com> References: <22b079f6-e288-eb8c-799a-004b020c7e0b@gmail.com> <20210405193603.GA29627@matrix.chaos.earth.li> <8b42aec3-4a98-6b7a-5379-ccad3b770010@gmail.com> Message-ID: The history here: several people independently noticed that it might be better to implement the "parse error" part of layout by doing something simpler than full parsing. For example, if we just count brackets in the lexer, then we can handle things like f (case x of y -> z) and if we treat let/in as a pair of brackets too, then the common case of let x = y in z also works. The AlternativeLayoutRule was Ian's implementation of this idea, and (if I remember correctly) contains a number of fixes that arose from discovering interesting cases of code in the wild that weren't handled by the obvious bracket-matching techniques. My conclusion from this experiment - which is a bit subjective and might differ from others - is that * you need a lot of special cases to handle code that Haskell users expect to parse * and then the specification becomes pretty complex, and hard to explain to someone So ultimately it didn't solve the problem in a nice way, unfortunately. The "parse error" rule is hard for implementers, but it's not actually that hard for users. If other people agree with this conclusion, we should kill off the ALR code now. Someone is going to ask me for examples of those "special cases", I'm afraid I don't remember - I only cached the answer to the question, not the working :) You'd probably have to go digging through the ALR code. Cheers Simon On Tue, 6 Apr 2021 at 01:36, Alexis King wrote: > On 4/5/21 2:36 PM, Ian Lynagh wrote: > > It was originally designed by John Meacham: > https://gitlab.haskell.org/haskell/prime/-/wikis/alternative-layout-rule > https://www.mail-archive.com/haskell-prime at haskell.org/msg01938.html > > Thanks, Ian—I had stumbled across a link to the old Haskell Prime trac > wiki while I was searching for information, but I didn’t realize where it > had been migrated to. > > It isn't exactly equivalent to the Haskell layout rule, but it's fairly > close and much simpler (due to not having the "on a parse error" case). > > Yes, I gathered as much from the implementation. The idea makes sense, but > of course it doesn’t provide much benefit to have a simpler implementation > unless it actually *replaces* the “on parse error” approach. > > Given this appears to be a long-defunct proposal, a natural followup > question is to ask whether there’s any reason this code is still in GHC. Is > it used for any purpose, or could it be removed? > > Alexis > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From compl.yue at icloud.com Tue Apr 6 11:12:51 2021 From: compl.yue at icloud.com (YueCompl) Date: Tue, 6 Apr 2021 19:12:51 +0800 Subject: How to ensure optimization for large immutable vectors to be shared w.r.t. Referential Transparency Message-ID: <32447B11-A587-41D3-8617-30132561AF7F@icloud.com> Hello Cafe and respected GHC Devs, I would like to ensure some immutable vectors (can be quite large) are always shared instead of copied, and I think that should be straight forward w.r.t. referential transparency we enjoy. In an attempt to determine whether two immutable vectors can be treated as the same one to enable specific optimizations for that case, I tried to use ST to determine their respective backing foreign ptrs for comparison. But appears it can be copied when wrapped in a newtype, I wonder why it is the case, and how to avoid the copy? Here's my minimum reproducible snippet: ```hs λ> :set -XBangPatterns λ> λ> :set -package vector package flags have changed, resetting and loading new packages... λ> λ> import Prelude λ> λ> import Control.Monad.ST λ> import qualified Data.Vector.Storable as VS λ> λ> :{ λ| λ| newtype SomeVector = SomeVector (VS.Vector Int) λ| λ| isSameVector :: SomeVector -> SomeVector -> Bool λ| isSameVector (SomeVector !x) (SomeVector !y) = runST $ do λ| mx@(VS.MVector !x'offset !x'fp) <- VS.unsafeThaw x λ| my@(VS.MVector !y'offset !y'fp) <- VS.unsafeThaw y λ| _ <- VS.unsafeFreeze mx λ| _ <- VS.unsafeFreeze my λ| return $ x'offset == y'offset && x'fp == y'fp λ| λ| :} λ> λ> let !v = VS.fromList [3,2,5] in isSameVector (SomeVector v) (SomeVector v) False λ> λ> let !v = SomeVector (VS.fromList [3,2,5]) in isSameVector v v True λ> ``` Thanks with best regards, Compl -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Tue Apr 6 12:00:07 2021 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Tue, 6 Apr 2021 14:00:07 +0200 (CEST) Subject: [Haskell-cafe] How to ensure optimization for large immutable vectors to be shared w.r.t. Referential Transparency In-Reply-To: <32447B11-A587-41D3-8617-30132561AF7F@icloud.com> References: <32447B11-A587-41D3-8617-30132561AF7F@icloud.com> Message-ID: On Tue, 6 Apr 2021, YueCompl via Haskell-Cafe wrote: > In an attempt to determine whether two immutable vectors can be treated > as the same one to enable specific optimizations for that case, I tried > to use ST to determine their respective backing foreign ptrs for > comparison. But appears it can be copied when wrapped in a newtype, I > wonder why it is the case, and how to avoid the copy? You compare the ForeignPtrs of the mutable vectors. What about comparing the ForeignPtrs of the original immutable vectors? From compl.yue at icloud.com Tue Apr 6 12:29:19 2021 From: compl.yue at icloud.com (YueCompl) Date: Tue, 6 Apr 2021 20:29:19 +0800 Subject: [Haskell-cafe] How to ensure optimization for large immutable vectors to be shared w.r.t. Referential Transparency In-Reply-To: References: <32447B11-A587-41D3-8617-30132561AF7F@icloud.com> Message-ID: <56867838-1078-4D85-BEA2-DAC193196C43@icloud.com> Thanks, it's a good idea. Unfortunately the result remains, making me even more curious. ```hs λ> :set -XBangPatterns λ> λ> :set -package vector package flags have changed, resetting and loading new packages... λ> λ> import Prelude λ> λ> import Control.Monad.ST λ> import qualified Data.Vector.Storable as VS λ> λ> :{ λ| λ| newtype SomeVector = SomeVector (VS.Vector Int) λ| λ| isSameVector :: SomeVector -> SomeVector -> Bool λ| isSameVector (SomeVector !x) (SomeVector !y) = λ| x'offset == y'offset && x'fp == y'fp λ| where λ| (x'fp, x'offset, _x'len) = VS.unsafeToForeignPtr x λ| (y'fp, y'offset, _y'len) = VS.unsafeToForeignPtr y λ| :} λ> λ> let !v = VS.fromList [5..200000] in isSameVector (SomeVector v) (SomeVector v) False λ> λ> let !v = SomeVector (VS.fromList [3,2,5]) in isSameVector v v True λ> ``` > On 2021-04-06, at 20:00, Henning Thielemann wrote: > > > On Tue, 6 Apr 2021, YueCompl via Haskell-Cafe wrote: > >> In an attempt to determine whether two immutable vectors can be treated as the same one to enable specific optimizations for that case, I tried to use ST to determine their respective backing foreign ptrs for comparison. But appears it can be copied when wrapped in a newtype, I wonder why it is the case, and how to avoid the copy? > > You compare the ForeignPtrs of the mutable vectors. What about comparing the ForeignPtrs of the original immutable vectors? -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Tue Apr 6 12:34:25 2021 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Tue, 6 Apr 2021 14:34:25 +0200 (CEST) Subject: [Haskell-cafe] How to ensure optimization for large immutable vectors to be shared w.r.t. Referential Transparency In-Reply-To: <56867838-1078-4D85-BEA2-DAC193196C43@icloud.com> References: <32447B11-A587-41D3-8617-30132561AF7F@icloud.com> <56867838-1078-4D85-BEA2-DAC193196C43@icloud.com> Message-ID: <8955c0f6-c6ac-8c9-22c5-56b47c933b1@henning-thielemann.de> On Tue, 6 Apr 2021, YueCompl wrote: > Thanks, it's a good idea. Unfortunately the result remains, making me even more curious. > ```hs > λ> :set -XBangPatterns > λ>  > λ> :set -package vector > package flags have changed, resetting and loading new packages... > λ>  > λ> import Prelude > λ>  > λ> import Control.Monad.ST > λ> import qualified Data.Vector.Storable as VS > λ>  > λ> :{ > λ|  > λ| newtype SomeVector = SomeVector (VS.Vector Int) > λ|  > λ| isSameVector :: SomeVector -> SomeVector -> Bool > λ| isSameVector (SomeVector !x) (SomeVector !y) =  > λ|   x'offset == y'offset && x'fp == y'fp > λ|  where > λ|   (x'fp, x'offset, _x'len) = VS.unsafeToForeignPtr x > λ|   (y'fp, y'offset, _y'len) = VS.unsafeToForeignPtr y > λ| :} > λ>  > λ> let !v = VS.fromList [5..200000] in isSameVector (SomeVector v) (SomeVector v) > False What happens for [3,2,5]? > λ>  > λ> let !v = SomeVector (VS.fromList [3,2,5]) in isSameVector v v > True > λ>  > ``` From compl.yue at icloud.com Tue Apr 6 12:41:33 2021 From: compl.yue at icloud.com (YueCompl) Date: Tue, 6 Apr 2021 20:41:33 +0800 Subject: [Haskell-cafe] How to ensure optimization for large immutable vectors to be shared w.r.t. Referential Transparency In-Reply-To: <8955c0f6-c6ac-8c9-22c5-56b47c933b1@henning-thielemann.de> References: <32447B11-A587-41D3-8617-30132561AF7F@icloud.com> <56867838-1078-4D85-BEA2-DAC193196C43@icloud.com> <8955c0f6-c6ac-8c9-22c5-56b47c933b1@henning-thielemann.de> Message-ID: ```hs λ> let !v = VS.fromList [3,2,5] in isSameVector (SomeVector v) (SomeVector v) False λ> λ> let !v = SomeVector (VS.fromList [3,2,5]) in isSameVector v v True λ> ``` > On 2021-04-06, at 20:34, Henning Thielemann wrote: > > > On Tue, 6 Apr 2021, YueCompl wrote: > >> Thanks, it's a good idea. Unfortunately the result remains, making me even more curious. >> ```hs >> λ> :set -XBangPatterns >> λ> >> λ> :set -package vector >> package flags have changed, resetting and loading new packages... >> λ> >> λ> import Prelude >> λ> >> λ> import Control.Monad.ST >> λ> import qualified Data.Vector.Storable as VS >> λ> >> λ> :{ >> λ| >> λ| newtype SomeVector = SomeVector (VS.Vector Int) >> λ| >> λ| isSameVector :: SomeVector -> SomeVector -> Bool >> λ| isSameVector (SomeVector !x) (SomeVector !y) = >> λ| x'offset == y'offset && x'fp == y'fp >> λ| where >> λ| (x'fp, x'offset, _x'len) = VS.unsafeToForeignPtr x >> λ| (y'fp, y'offset, _y'len) = VS.unsafeToForeignPtr y >> λ| :} >> λ> >> λ> let !v = VS.fromList [5..200000] in isSameVector (SomeVector v) (SomeVector v) >> False > > What happens for [3,2,5]? > > >> λ> >> λ> let !v = SomeVector (VS.fromList [3,2,5]) in isSameVector v v >> True >> λ> >> ``` -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Tue Apr 6 12:50:20 2021 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Tue, 6 Apr 2021 14:50:20 +0200 (CEST) Subject: [Haskell-cafe] How to ensure optimization for large immutable vectors to be shared w.r.t. Referential Transparency In-Reply-To: References: <32447B11-A587-41D3-8617-30132561AF7F@icloud.com> <56867838-1078-4D85-BEA2-DAC193196C43@icloud.com> <8955c0f6-c6ac-8c9-22c5-56b47c933b1@henning-thielemann.de> Message-ID: <3d6175-7b8e-5779-5b69-6def28ed8ba@henning-thielemann.de> On Tue, 6 Apr 2021, YueCompl wrote: > ```hsλ> let !v = VS.fromList [3,2,5] in isSameVector (SomeVector v) (SomeVector v) > False > λ>  > λ> let !v = SomeVector (VS.fromList [3,2,5]) in isSameVector v v > True > λ>  > ``` Then I have no idea. Maybe ghc-heap-view/ghc-vis can reveal the mystery. https://github.com/nomeata/haskell-bytes-bobkonf2021 From ietf-dane at dukhovni.org Tue Apr 6 13:51:30 2021 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Tue, 6 Apr 2021 09:51:30 -0400 Subject: How to ensure optimization for large immutable vectors to be shared w.r.t. Referential Transparency In-Reply-To: <32447B11-A587-41D3-8617-30132561AF7F@icloud.com> References: <32447B11-A587-41D3-8617-30132561AF7F@icloud.com> Message-ID: On Tue, Apr 06, 2021 at 07:12:51PM +0800, YueCompl via ghc-devs wrote: > λ> import Control.Monad.ST > λ> import qualified Data.Vector.Storable as VS > λ> > λ> :{ > λ| > λ| newtype SomeVector = SomeVector (VS.Vector Int) > λ| > λ| isSameVector :: SomeVector -> SomeVector -> Bool > λ| isSameVector (SomeVector !x) (SomeVector !y) = runST $ do > λ| mx@(VS.MVector !x'offset !x'fp) <- VS.unsafeThaw x > λ| my@(VS.MVector !y'offset !y'fp) <- VS.unsafeThaw y > λ| _ <- VS.unsafeFreeze mx > λ| _ <- VS.unsafeFreeze my > λ| return $ x'offset == y'offset && x'fp == y'fp > λ| > λ| :} > λ> > λ> let !v = VS.fromList [3,2,5] in isSameVector (SomeVector v) (SomeVector v) > False > λ> > λ> let !v = SomeVector (VS.fromList [3,2,5]) in isSameVector v v > True In GHCi, but not in compiled programs, by default the `NoMonomorphismRestriction` extension is enabled. If I compile your code with that restriction, I can reproduce your results (the values are not shared). If I either skip the extension, or add an explicit type annotation to for the vector, then the values are shared. {-# LANGUAGE BangPatterns #-} {-# LANGUAGE NoMonomorphismRestriction #-} import Control.Monad.ST import qualified Data.Vector.Storable as VS newtype SomeVector = SomeVector (VS.Vector Int) isSameVector :: SomeVector -> SomeVector -> Bool isSameVector (SomeVector !x) (SomeVector !y) = runST $ do mx@(VS.MVector !x'offset !x'fp) <- VS.unsafeThaw x my@(VS.MVector !y'offset !y'fp) <- VS.unsafeThaw y _ <- VS.unsafeFreeze mx _ <- VS.unsafeFreeze my return $ x'offset == y'offset && x'fp == y'fp main :: IO () main = let !v = VS.fromList [0..1023] -- :: VS.Vector Int in print $ isSameVector (SomeVector v) (SomeVector v) Since newtypes are always strict in their argument, I don't think the BangPattern does what you'd like it to do, it just makes "main" strict in v. As defined with `NoMonomorphismRestriction` v is a polymorphic function, and I guess it is specialised at the call site. -- Viktor. From compl.yue at icloud.com Tue Apr 6 13:51:29 2021 From: compl.yue at icloud.com (YueCompl) Date: Tue, 6 Apr 2021 21:51:29 +0800 Subject: [Haskell-cafe] How to ensure optimization for large immutable vectors to be shared w.r.t. Referential Transparency In-Reply-To: <3d6175-7b8e-5779-5b69-6def28ed8ba@henning-thielemann.de> References: <32447B11-A587-41D3-8617-30132561AF7F@icloud.com> <56867838-1078-4D85-BEA2-DAC193196C43@icloud.com> <8955c0f6-c6ac-8c9-22c5-56b47c933b1@henning-thielemann.de> <3d6175-7b8e-5779-5b69-6def28ed8ba@henning-thielemann.de> Message-ID: Appears it'd work as expected when the immutable vector is originally created from foreign ptr, I think it'll work for my cases. (Though it's still strangely unexpected for ad hoc immutable vectors unshared when wrapped.) ```hs λ> :set -XBangPatterns λ> λ> :set -package vector package flags have changed, resetting and loading new packages... λ> λ> import Prelude λ> λ> import Foreign.Marshal.Alloc λ> import Foreign.Storable λ> import Foreign.ForeignPtr λ> λ> import qualified Data.Vector.Storable as VS λ> λ> :{ λ| λ| data SomeVector = SomeVector (VS.Vector Int) λ| λ| isSameVector :: Storable a => VS.Vector a -> VS.Vector a -> Bool λ| isSameVector !x !y = λ| x'offset == y'offset && x'fp == y'fp λ| where λ| (x'fp, x'offset, _x'len) = VS.unsafeToForeignPtr x λ| (y'fp, y'offset, _y'len) = VS.unsafeToForeignPtr y λ| λ| isSame :: SomeVector -> SomeVector -> Bool λ| isSame (SomeVector !x) (SomeVector !y) = isSameVector x y λ| λ| :} λ> λ> let !v = VS.fromList [3,2,5] in isSame (SomeVector v) (SomeVector v) False λ> λ> let !v = SomeVector (VS.fromList [3,2,5]) in isSame v v True λ> λ> λ> (fp :: ForeignPtr Int) <- mallocBytes 256 >>= newForeignPtr_ λ> let !v = VS.unsafeFromForeignPtr fp 0 32 λ| λ> isSame (SomeVector v) (SomeVector v) True λ> ``` > On 2021-04-06, at 20:50, Henning Thielemann wrote: > > > On Tue, 6 Apr 2021, YueCompl wrote: > >> ```hsλ> let !v = VS.fromList [3,2,5] in isSameVector (SomeVector v) (SomeVector v) >> False >> λ> >> λ> let !v = SomeVector (VS.fromList [3,2,5]) in isSameVector v v >> True >> λ> >> ``` > > Then I have no idea. > > Maybe ghc-heap-view/ghc-vis can reveal the mystery. > > https://github.com/nomeata/haskell-bytes-bobkonf2021 -------------- next part -------------- An HTML attachment was scrubbed... URL: From compl.yue at icloud.com Tue Apr 6 14:19:34 2021 From: compl.yue at icloud.com (YueCompl) Date: Tue, 6 Apr 2021 22:19:34 +0800 Subject: How to ensure optimization for large immutable vectors to be shared w.r.t. Referential Transparency In-Reply-To: References: <32447B11-A587-41D3-8617-30132561AF7F@icloud.com> Message-ID: <0F37F11D-D3D1-4EB3-935C-89CDA1816B1D@icloud.com> Thanks very much for the diagnostic and explanation! I was wrong in assuming the `in isSameVector (SomeVector v) (SomeVector v)` part is enough to have type of v in `let !v = VS.fromList [3,2,5]` inferred as monomorphic, totally unaware about "NoMonomorphismRestriction" before, I've learned it today :D > On 2021-04-06, at 21:51, Viktor Dukhovni wrote: > > On Tue, Apr 06, 2021 at 07:12:51PM +0800, YueCompl via ghc-devs wrote: > >> λ> import Control.Monad.ST >> λ> import qualified Data.Vector.Storable as VS >> λ> >> λ> :{ >> λ| >> λ| newtype SomeVector = SomeVector (VS.Vector Int) >> λ| >> λ| isSameVector :: SomeVector -> SomeVector -> Bool >> λ| isSameVector (SomeVector !x) (SomeVector !y) = runST $ do >> λ| mx@(VS.MVector !x'offset !x'fp) <- VS.unsafeThaw x >> λ| my@(VS.MVector !y'offset !y'fp) <- VS.unsafeThaw y >> λ| _ <- VS.unsafeFreeze mx >> λ| _ <- VS.unsafeFreeze my >> λ| return $ x'offset == y'offset && x'fp == y'fp >> λ| >> λ| :} >> λ> >> λ> let !v = VS.fromList [3,2,5] in isSameVector (SomeVector v) (SomeVector v) >> False >> λ> >> λ> let !v = SomeVector (VS.fromList [3,2,5]) in isSameVector v v >> True > > In GHCi, but not in compiled programs, by default the > `NoMonomorphismRestriction` extension is enabled. If I compile your > code with that restriction, I can reproduce your results (the values are > not shared). > > If I either skip the extension, or add an explicit type annotation to > for the vector, then the values are shared. > > {-# LANGUAGE BangPatterns #-} > {-# LANGUAGE NoMonomorphismRestriction #-} > import Control.Monad.ST > import qualified Data.Vector.Storable as VS > > newtype SomeVector = SomeVector (VS.Vector Int) > > isSameVector :: SomeVector -> SomeVector -> Bool > isSameVector (SomeVector !x) (SomeVector !y) = runST $ do > mx@(VS.MVector !x'offset !x'fp) <- VS.unsafeThaw x > my@(VS.MVector !y'offset !y'fp) <- VS.unsafeThaw y > _ <- VS.unsafeFreeze mx > _ <- VS.unsafeFreeze my > return $ x'offset == y'offset && x'fp == y'fp > > main :: IO () > main = > let !v = VS.fromList [0..1023] -- :: VS.Vector Int > in print $ isSameVector (SomeVector v) (SomeVector v) > > Since newtypes are always strict in their argument, I don't think the > BangPattern does what you'd like it to do, it just makes "main" strict > in v. As defined with `NoMonomorphismRestriction` v is a polymorphic > function, and I guess it is specialised at the call site. > > -- > Viktor. > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs From compl.yue at icloud.com Tue Apr 6 14:58:20 2021 From: compl.yue at icloud.com (YueCompl) Date: Tue, 6 Apr 2021 22:58:20 +0800 Subject: How to ensure optimization for large immutable vectors to be shared w.r.t. Referential Transparency In-Reply-To: <0F37F11D-D3D1-4EB3-935C-89CDA1816B1D@icloud.com> References: <32447B11-A587-41D3-8617-30132561AF7F@icloud.com> <0F37F11D-D3D1-4EB3-935C-89CDA1816B1D@icloud.com> Message-ID: <333AB632-4025-4B5D-9DB2-6A1CBFA842C8@icloud.com> On a second thought, maybe GHCi's silence is a bad thing here? Maybe it should complain loudly as GHC does? ```hs λ> :set -package vector package flags have changed, resetting and loading new packages... λ> λ> import Prelude λ> λ> import qualified Data.Vector.Storable as VS λ> λ> :{ λ| λ| newtype SomeVector = SomeVector (VS.Vector Int) λ| λ| isSameVector :: SomeVector -> SomeVector -> Bool λ| isSameVector (SomeVector x) (SomeVector y) = λ| x'offset == y'offset && x'fp == y'fp λ| where λ| (x'fp, x'offset, _x'len) = VS.unsafeToForeignPtr x λ| (y'fp, y'offset, _y'len) = VS.unsafeToForeignPtr y λ| λ| :} λ> λ> let (v :: VS.Vector Int) = VS.fromList [3,2,5] in isSameVector (SomeVector v) (SomeVector v) True λ> λ> λ> :set -XMonomorphismRestriction λ> λ> let v = VS.fromList [3,2,5] in isSameVector (SomeVector v) (SomeVector v) True λ> λ> :set -XNoMonomorphismRestriction λ> λ> let v = VS.fromList [3,2,5] in isSameVector (SomeVector v) (SomeVector v) False λ> ``` Further more, my intuition about GHC's type inference here is proved wrong by it, right. But I still think that with a single piece of `let-in` construct, types are better to be inferred as specific as possible, then the result would not be affected by some extension's semantics modification. Here v's type can obviously be inferred to `VS.Vector Int` according to its usage in the `SomeVector` data constructor, I wonder why GHC is not doing this? > On 2021-04-06, at 22:19, YueCompl via ghc-devs wrote: > > Thanks very much for the diagnostic and explanation! > > I was wrong in assuming the `in isSameVector (SomeVector v) (SomeVector v)` part is enough to have type of v in `let !v = VS.fromList [3,2,5]` inferred as monomorphic, totally unaware about "NoMonomorphismRestriction" before, I've learned it today :D > >> On 2021-04-06, at 21:51, Viktor Dukhovni wrote: >> >> On Tue, Apr 06, 2021 at 07:12:51PM +0800, YueCompl via ghc-devs wrote: >> >>> λ> import Control.Monad.ST >>> λ> import qualified Data.Vector.Storable as VS >>> λ> >>> λ> :{ >>> λ| >>> λ| newtype SomeVector = SomeVector (VS.Vector Int) >>> λ| >>> λ| isSameVector :: SomeVector -> SomeVector -> Bool >>> λ| isSameVector (SomeVector !x) (SomeVector !y) = runST $ do >>> λ| mx@(VS.MVector !x'offset !x'fp) <- VS.unsafeThaw x >>> λ| my@(VS.MVector !y'offset !y'fp) <- VS.unsafeThaw y >>> λ| _ <- VS.unsafeFreeze mx >>> λ| _ <- VS.unsafeFreeze my >>> λ| return $ x'offset == y'offset && x'fp == y'fp >>> λ| >>> λ| :} >>> λ> >>> λ> let !v = VS.fromList [3,2,5] in isSameVector (SomeVector v) (SomeVector v) >>> False >>> λ> >>> λ> let !v = SomeVector (VS.fromList [3,2,5]) in isSameVector v v >>> True >> >> In GHCi, but not in compiled programs, by default the >> `NoMonomorphismRestriction` extension is enabled. If I compile your >> code with that restriction, I can reproduce your results (the values are >> not shared). >> >> If I either skip the extension, or add an explicit type annotation to >> for the vector, then the values are shared. >> >> {-# LANGUAGE BangPatterns #-} >> {-# LANGUAGE NoMonomorphismRestriction #-} >> import Control.Monad.ST >> import qualified Data.Vector.Storable as VS >> >> newtype SomeVector = SomeVector (VS.Vector Int) >> >> isSameVector :: SomeVector -> SomeVector -> Bool >> isSameVector (SomeVector !x) (SomeVector !y) = runST $ do >> mx@(VS.MVector !x'offset !x'fp) <- VS.unsafeThaw x >> my@(VS.MVector !y'offset !y'fp) <- VS.unsafeThaw y >> _ <- VS.unsafeFreeze mx >> _ <- VS.unsafeFreeze my >> return $ x'offset == y'offset && x'fp == y'fp >> >> main :: IO () >> main = >> let !v = VS.fromList [0..1023] -- :: VS.Vector Int >> in print $ isSameVector (SomeVector v) (SomeVector v) >> >> Since newtypes are always strict in their argument, I don't think the >> BangPattern does what you'd like it to do, it just makes "main" strict >> in v. As defined with `NoMonomorphismRestriction` v is a polymorphic >> function, and I guess it is specialised at the call site. >> >> -- >> Viktor. >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs -------------- next part -------------- An HTML attachment was scrubbed... URL: From ietf-dane at dukhovni.org Tue Apr 6 15:10:51 2021 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Tue, 6 Apr 2021 11:10:51 -0400 Subject: How to ensure optimization for large immutable vectors to be shared w.r.t. Referential Transparency In-Reply-To: <333AB632-4025-4B5D-9DB2-6A1CBFA842C8@icloud.com> References: <32447B11-A587-41D3-8617-30132561AF7F@icloud.com> <0F37F11D-D3D1-4EB3-935C-89CDA1816B1D@icloud.com> <333AB632-4025-4B5D-9DB2-6A1CBFA842C8@icloud.com> Message-ID: On Tue, Apr 06, 2021 at 10:58:20PM +0800, YueCompl via ghc-devs wrote: > On a second thought, maybe GHCi's silence is a bad thing here? Maybe > it should complain loudly as GHC does? No, GHCi is doing the expected thing. Because GHCi's REPL sees one line at a time, it is not generally possible for it to infer specific monomorphic types on the spot, so GHCi infers the polymorphic type. And as for the complaint, that was because I prepended: v `seq` ... in which the type of `v` is ambiguous when polymorphic. GHCi also complains if you try that. > λ> let v = VS.fromList [3,2,5] in isSameVector (SomeVector v) (SomeVector v) One thing I'm not sure about, that perhaps someone else can shed light on, is whether with optimisation one might expect the two (SomeVector v) values to be subject to CSE, given that they both invoke `v` at the same type. Is there a non-default optimisation flag that makes CSE more aggressive that would make that happen? -- Viktor. From ietf-dane at dukhovni.org Tue Apr 6 16:27:27 2021 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Tue, 6 Apr 2021 12:27:27 -0400 Subject: How to ensure optimization for large immutable vectors to be shared w.r.t. Referential Transparency In-Reply-To: References: <32447B11-A587-41D3-8617-30132561AF7F@icloud.com> <0F37F11D-D3D1-4EB3-935C-89CDA1816B1D@icloud.com> <333AB632-4025-4B5D-9DB2-6A1CBFA842C8@icloud.com> Message-ID: On Tue, Apr 06, 2021 at 11:10:51AM -0400, Viktor Dukhovni wrote: > > λ> let v = VS.fromList [3,2,5] in isSameVector (SomeVector v) (SomeVector v) > > One thing I'm not sure about, that perhaps someone else can shed light > on, is whether with optimisation one might expect the two (SomeVector v) > values to be subject to CSE, given that they both invoke `v` at the same > type. Is there a non-default optimisation flag that makes CSE more > aggressive that would make that happen? On a hunch I tried suppressing the inlining of the definition of `v`, and CSE then kicked in... {-# LANGUAGE BangPatterns #-} {-# LANGUAGE NoMonomorphismRestriction #-} import Control.Monad.ST import Data.Coerce import qualified Data.Vector.Storable as VS newtype SomeVector = SomeVector (VS.Vector Int) isSameVector :: SomeVector -> SomeVector -> Bool isSameVector !(SomeVector x) !(SomeVector y) = runST $ do mx@(VS.MVector !x'offset !x'fp) <- VS.unsafeThaw x my@(VS.MVector !y'offset !y'fp) <- VS.unsafeThaw y _ <- VS.unsafeFreeze mx _ <- VS.unsafeFreeze my return $ x'offset == y'offset && x'fp == y'fp makev = VS.fromList [0..1023] {-# NOINLINE makev #-} main :: IO () main = let !v = makev in print $ isSameVector (SomeVector v) (SomeVector v) So it appears that inlining of `v` into (SomeVector v) is the proximate barrier to identifying the two (SomeVector v) terms. Is this expected? -- Viktor. From shanth2600 at gmail.com Tue Apr 6 17:34:01 2021 From: shanth2600 at gmail.com (Shant Hairapetian) Date: Tue, 6 Apr 2021 10:34:01 -0700 Subject: Newcomer looking for help with changes to kind system In-Reply-To: <877dlgt9s4.fsf@smart-cactus.org> References: <877dlgt9s4.fsf@smart-cactus.org> Message-ID: Hi Ben, Thanks for the reply > Incidentally, the collapse of LiftedRep and UnliftedRep will happen in > GHC 9.2 (turning into `BoxedRep :: Levity -> RuntimeRep`). Yes I believe this change was accidentally merged a few months ago then reverted? I will keep that in mind. > Can you provide a program that your patch rejects, as well as > the full error that is produced? My error is in stage 1 in the building of the ghc-bignum library. I have attached the full error as well as the patch itself. Thanks, Shant On Mon, Apr 5, 2021 at 7:41 PM Ben Gamari wrote: > Shant Hairapetian writes: > > > Hello, > > > > I’m a master’s student working on implementing the changes outlined in > > “Kinds are Calling Conventions“ ( > > https://www.microsoft.com/en-us/research/uploads/prod/2020/03/kacc.pdf). > I > > have been working directly with Paul Downen but have hit some roadblocks. > > > > To sum up the changes to the kind system, I am attempting to modify the > > “TYPE” type constructor to accept, rather than just a RuntimeRep, a > record > > type (called RuntimeInfo) comprised of a RuntimeRep and a CallingConv > > (calling convention). The calling convention has an “Eval” constructor > > which accepts a levity (effectively moving the levity information from > the > > representation to the calling convention. LiftedRep and UnliftedRep would > > also be collapsed into a single PtrRep constructor) and a “Call” > > constructor (denoting the arity of primitive, extensional functions, > > see: Making > > a Faster Curry with Extensional Types > > < > https://www.microsoft.com/en-us/research/uploads/prod/2019/07/arity-haskell-symposium-2019.pdf > >) > > which accepts a list of RuntimeRep’s. I have created and wired-in the new > > RuntimeInfo and CallingConv types in GHC.Builtin.Types, as well as the > > corresponding primitive types in GHC.Builtin.Types.Prim and have modified > > the “TYPE” constructor to accept a RuntimeInfo rather than a RuntimeRep. > > > Hi Shant, > > It would be helpful to have a bit more information on the nature of your > failure. Can you provide a program that your patch rejects, as well as > the full error that is produced? > > Incidentally, the collapse of LiftedRep and UnliftedRep will happen in > GHC 9.2 (turning into `BoxedRep :: Levity -> RuntimeRep`). > > Cheers, > > - Ben > > -- Shant Hairapetian -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- libraries/ghc-bignum/src/GHC/Num/WordArray.hs:78:22: error: • Couldn't match type: 'TupleRep ('[] @RuntimeRep) with: 'RInfo ('TupleRep ('[] @RuntimeRep)) 'GHC.Types.ConvEval Expected: (# State# s, MutableWordArray# s #) Actual: (# State# s, MutableByteArray# s #) • In the expression: newByteArray# (wordsToBytes# sz) s In an equation for ‘newWordArray#’: newWordArray# sz s = newByteArray# (wordsToBytes# sz) s | 78 | newWordArray# sz s = newByteArray# (wordsToBytes# sz) s | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ libraries/ghc-bignum/src/GHC/Num/WordArray.hs:112:71: error: • Couldn't match a lifted type with an unlifted type When matching types b0 :: TYPE ('RInfo 'LiftedRep 'GHC.Types.ConvEval) WordArray# :: TYPE ('RInfo 'UnliftedRep 'GHC.Types.ConvEval) Expected: (# () | WordArray# #) Actual: (# () | b0 #) • In the expression: a In a case alternative: (# _, a #) -> a In the expression: case runRW# io of { (# _, a #) -> a } • Relevant bindings include a :: (# () | b0 #) (bound at libraries/ghc-bignum/src/GHC/Num/WordArray.hs:112:63) | 112 | withNewWordArrayTrimedMaybe# sz act = case runRW# io of (# _, a #) -> a | ^ libraries/ghc-bignum/src/GHC/Num/WordArray.hs:117:40: error: • Couldn't match kind ‘RuntimeInfo’ with ‘RuntimeRep’ When matching the kind of ‘'RInfo 'LiftedRep 'GHC.Types.ConvEval’ • In the expression: () In the expression: (# () | #) In the expression: (# s, (# () | #) #) | 117 | (# s, 0# #) -> (# s, (# () | #) #) | ^^ libraries/ghc-bignum/src/GHC/Num/WordArray.hs:120:48: error: • Couldn't match kind ‘RuntimeInfo’ with ‘RuntimeRep’ When matching kinds 'RInfo 'LiftedRep 'GHC.Types.ConvEval :: RuntimeInfo 'RInfo 'UnliftedRep 'GHC.Types.ConvEval :: RuntimeInfo • In the expression: ba In the expression: (# | ba #) In the expression: (# s, (# | ba #) #) | 120 | (# s, ba #) -> (# s, (# | ba #) #) | ^^ libraries/ghc-bignum/src/GHC/Num/WordArray.hs:431:31: error: • Couldn't match type: 'TupleRep ('[] @RuntimeRep) with: 'RInfo ('TupleRep ('[] @RuntimeRep)) 'GHC.Types.ConvEval Expected: (# State# s, Word# #) Actual: (# State# s, Word# #) • In the expression: readWordArray# mwa i s2 In a case alternative: (# s2, sz #) | isTrue# (i >=# sz) -> (# s2, 0## #) | isTrue# (i <# 0#) -> (# s2, 0## #) | True -> readWordArray# mwa i s2 In the expression: case mwaSize# mwa s of { (# s2, sz #) | isTrue# (i >=# sz) -> (# s2, 0## #) | isTrue# (i <# 0#) -> (# s2, 0## #) | True -> readWordArray# mwa i s2 } | 431 | | True -> readWordArray# mwa i s2 | ^^^^^^^^^^^^^^^^^^^^^^^ libraries/ghc-bignum/src/GHC/Num/WordArray.hs:434:12: error: • Couldn't match type: 'TupleRep ('[] @RuntimeRep) with: 'RInfo ('TupleRep ('[] @RuntimeRep)) 'GHC.Types.ConvEval Expected: MutableWordArray# s -> Int# -> State# s -> (# State# s, Word# #) Actual: MutableByteArray# s -> Int# -> State# s -> (# State# s, Word# #) • In the expression: readWordArray# In an equation for ‘mwaRead#’: mwaRead# = readWordArray# | 434 | mwaRead# = readWordArray# -------------- next part -------------- A non-text attachment was scrubbed... Name: KACC.patch Type: application/octet-stream Size: 45138 bytes Desc: not available URL: From ben at smart-cactus.org Wed Apr 7 15:29:17 2021 From: ben at smart-cactus.org (Ben Gamari) Date: Wed, 07 Apr 2021 11:29:17 -0400 Subject: Newcomer looking for help with changes to kind system In-Reply-To: References: <877dlgt9s4.fsf@smart-cactus.org> Message-ID: <87y2duru45.fsf@smart-cactus.org> Shant Hairapetian writes: > Hi Ben, > Thanks for the reply > >> Incidentally, the collapse of LiftedRep and UnliftedRep will happen in >> GHC 9.2 (turning into `BoxedRep :: Levity -> RuntimeRep`). > > Yes I believe this change was accidentally merged a few months ago then > reverted? I will keep that in mind. > It was briefly accidentally merged, then reverted, then re-applied. The final commit is 3e082f8ff5ea2f42c5e6430094683b26b5818fb8. >> Can you provide a program that your patch rejects, as well as >> the full error that is produced? > > My error is in stage 1 in the building of the ghc-bignum library. I have > attached the full error as well as the patch itself. > See below. > Thanks, > Shant > > > > On Mon, Apr 5, 2021 at 7:41 PM Ben Gamari wrote: > >> Shant Hairapetian writes: >> >> > Hello, >> > >> > I’m a master’s student working on implementing the changes outlined in >> > “Kinds are Calling Conventions“ ( >> > https://www.microsoft.com/en-us/research/uploads/prod/2020/03/kacc.pdf). >> I >> > have been working directly with Paul Downen but have hit some roadblocks. >> > >> > To sum up the changes to the kind system, I am attempting to modify the >> > “TYPE” type constructor to accept, rather than just a RuntimeRep, a >> record >> > type (called RuntimeInfo) comprised of a RuntimeRep and a CallingConv >> > (calling convention). The calling convention has an “Eval” constructor >> > which accepts a levity (effectively moving the levity information from >> the >> > representation to the calling convention. LiftedRep and UnliftedRep would >> > also be collapsed into a single PtrRep constructor) and a “Call” >> > constructor (denoting the arity of primitive, extensional functions, >> > see: Making >> > a Faster Curry with Extensional Types >> > < >> https://www.microsoft.com/en-us/research/uploads/prod/2019/07/arity-haskell-symposium-2019.pdf >> >) >> > which accepts a list of RuntimeRep’s. I have created and wired-in the new >> > RuntimeInfo and CallingConv types in GHC.Builtin.Types, as well as the >> > corresponding primitive types in GHC.Builtin.Types.Prim and have modified >> > the “TYPE” constructor to accept a RuntimeInfo rather than a RuntimeRep. >> > >> Hi Shant, >> >> It would be helpful to have a bit more information on the nature of your >> failure. Can you provide a program that your patch rejects, as well as >> the full error that is produced? >> >> Incidentally, the collapse of LiftedRep and UnliftedRep will happen in >> GHC 9.2 (turning into `BoxedRep :: Levity -> RuntimeRep`). >> >> Cheers, >> >> - Ben >> >> > > -- > Shant Hairapetian > > libraries/ghc-bignum/src/GHC/Num/WordArray.hs:78:22: error: > • Couldn't match type: 'TupleRep ('[] @RuntimeRep) > with: 'RInfo ('TupleRep ('[] @RuntimeRep)) 'GHC.Types.ConvEval > Expected: (# State# s, MutableWordArray# s #) > Actual: (# State# s, MutableByteArray# s #) > • In the expression: newByteArray# (wordsToBytes# sz) s > In an equation for ‘newWordArray#’: > newWordArray# sz s = newByteArray# (wordsToBytes# sz) s > | > 78 | newWordArray# sz s = newByteArray# (wordsToBytes# sz) s > | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > libraries/ghc-bignum/src/GHC/Num/WordArray.hs:112:71: error: > • Couldn't match a lifted type with an unlifted type > When matching types > b0 :: TYPE ('RInfo 'LiftedRep 'GHC.Types.ConvEval) > WordArray# :: TYPE ('RInfo 'UnliftedRep 'GHC.Types.ConvEval) > Expected: (# () | WordArray# #) > Actual: (# () | b0 #) > • In the expression: a > In a case alternative: (# _, a #) -> a > In the expression: case runRW# io of { (# _, a #) -> a } > • Relevant bindings include > a :: (# () | b0 #) > (bound at libraries/ghc-bignum/src/GHC/Num/WordArray.hs:112:63) > | > 112 | withNewWordArrayTrimedMaybe# sz act = case runRW# io of (# _, a #) -> a > | ^ > > libraries/ghc-bignum/src/GHC/Num/WordArray.hs:117:40: error: > • Couldn't match kind ‘RuntimeInfo’ with ‘RuntimeRep’ > When matching the kind of ‘'RInfo 'LiftedRep 'GHC.Types.ConvEval’ > • In the expression: () > In the expression: (# () | #) > In the expression: (# s, (# () | #) #) > | > 117 | (# s, 0# #) -> (# s, (# () | #) #) > | ^^ > > libraries/ghc-bignum/src/GHC/Num/WordArray.hs:120:48: error: > • Couldn't match kind ‘RuntimeInfo’ with ‘RuntimeRep’ > When matching kinds > 'RInfo 'LiftedRep 'GHC.Types.ConvEval :: RuntimeInfo > 'RInfo 'UnliftedRep 'GHC.Types.ConvEval :: RuntimeInfo > • In the expression: ba > In the expression: (# | ba #) > In the expression: (# s, (# | ba #) #) > | > 120 | (# s, ba #) -> (# s, (# | ba #) #) > | ^^ > > libraries/ghc-bignum/src/GHC/Num/WordArray.hs:431:31: error: > • Couldn't match type: 'TupleRep ('[] @RuntimeRep) > with: 'RInfo ('TupleRep ('[] @RuntimeRep)) 'GHC.Types.ConvEval > Expected: (# State# s, Word# #) > Actual: (# State# s, Word# #) > • In the expression: readWordArray# mwa i s2 > In a case alternative: > (# s2, sz #) > | isTrue# (i >=# sz) -> (# s2, 0## #) > | isTrue# (i <# 0#) -> (# s2, 0## #) > | True -> readWordArray# mwa i s2 > In the expression: > case mwaSize# mwa s of { > (# s2, sz #) > | isTrue# (i >=# sz) -> (# s2, 0## #) > | isTrue# (i <# 0#) -> (# s2, 0## #) > | True -> readWordArray# mwa i s2 } > | > 431 | | True -> readWordArray# mwa i s2 > | ^^^^^^^^^^^^^^^^^^^^^^^ > > libraries/ghc-bignum/src/GHC/Num/WordArray.hs:434:12: error: > • Couldn't match type: 'TupleRep ('[] @RuntimeRep) > with: 'RInfo ('TupleRep ('[] @RuntimeRep)) 'GHC.Types.ConvEval > Expected: MutableWordArray# s > -> Int# -> State# s -> (# State# s, Word# #) > Actual: MutableByteArray# s > -> Int# -> State# s -> (# State# s, Word# #) > • In the expression: readWordArray# > In an equation for ‘mwaRead#’: mwaRead# = readWordArray# > | > 434 | mwaRead# = readWordArray# > diff --git a/compiler/GHC/Builtin/Names.hs b/compiler/GHC/Builtin/Names.hs > index cf0f72c50f..78c84147cb 100644 > --- a/compiler/GHC/Builtin/Names.hs > +++ b/compiler/GHC/Builtin/Names.hs > @@ -1949,6 +1949,15 @@ unrestrictedFunTyConKey = mkPreludeTyConUnique 193 > multMulTyConKey :: Unique > multMulTyConKey = mkPreludeTyConUnique 194 > > +-- CallingConv > +runtimeInfoTyConKey, runtimeInfoDataConKey, callingConvTyConKey, > + convEvalDataConKey, convCallDataConKey :: Unique > +runtimeInfoTyConKey = mkPreludeTyConUnique 195 > +runtimeInfoDataConKey = mkPreludeDataConUnique 196 > +callingConvTyConKey = mkPreludeTyConUnique 197 > +convEvalDataConKey = mkPreludeDataConUnique 198 > +convCallDataConKey = mkPreludeDataConUnique 199 > + > ---------------- Template Haskell ------------------- > -- GHC.Builtin.Names.TH: USES TyConUniques 200-299 > ----------------------------------------------------- > diff --git a/compiler/GHC/Builtin/Types.hs b/compiler/GHC/Builtin/Types.hs > index d06bc4a12b..1bb6a263c6 100644 > --- a/compiler/GHC/Builtin/Types.hs > +++ b/compiler/GHC/Builtin/Types.hs > @@ -109,6 +109,7 @@ module GHC.Builtin.Types ( > > -- * RuntimeRep and friends > runtimeRepTyCon, vecCountTyCon, vecElemTyCon, > + runtimeInfoTyCon, rInfo, > > runtimeRepTy, liftedRepTy, liftedRepDataCon, liftedRepDataConTyCon, > > @@ -131,6 +132,9 @@ module GHC.Builtin.Types ( > > doubleElemRepDataConTy, > > + runtimeInfoTy, runtimeInfoDataConTyCon, callingConvTy, liftedRepEvalTy, > + convEvalDataConTy, > + > -- * Multiplicity and friends > multiplicityTyConName, oneDataConName, manyDataConName, multiplicityTy, > multiplicityTyCon, oneDataCon, manyDataCon, oneDataConTy, manyDataConTy, > @@ -189,6 +193,7 @@ import GHC.Utils.Outputable > import GHC.Utils.Misc > import GHC.Utils.Panic > > +import qualified GHC.Core.TyCo.Rep as TyCoRep (Type(TyConApp)) > import qualified Data.ByteString.Char8 as BS > > import Data.List ( elemIndex ) > @@ -266,6 +271,8 @@ wiredInTyCons = [ -- Units are not treated like other tuples, because they > , multiplicityTyCon > , naturalTyCon > , integerTyCon > + , runtimeInfoTyCon > + , callingConvTyCon > ] > > mkWiredInTyConName :: BuiltInSyntax -> Module -> FastString -> Unique -> TyCon -> Name > @@ -689,7 +696,7 @@ constraintKindTyCon :: TyCon > constraintKindTyCon = pcTyCon constraintKindTyConName Nothing [] [] > > liftedTypeKind, typeToTypeKind, constraintKind :: Kind > -liftedTypeKind = tYPE liftedRepTy > +liftedTypeKind = TyCoRep.TyConApp liftedTypeKindTyCon [] > typeToTypeKind = liftedTypeKind `mkVisFunTyMany` liftedTypeKind > constraintKind = mkTyConApp constraintKindTyCon [] > > @@ -1027,7 +1034,7 @@ cTupleArr = listArray (0,mAX_CTUPLE_SIZE) [mk_ctuple i | i <- [0..mAX_CTUPLE_SIZ > -- [IntRep, LiftedRep])@ > unboxedTupleSumKind :: TyCon -> [Type] -> Kind > unboxedTupleSumKind tc rr_tys > - = tYPE (mkTyConApp tc [mkPromotedListTy runtimeRepTy rr_tys]) > + = tYPE $ mkTyConApp runtimeInfoDataConTyCon [(mkTyConApp tc [mkPromotedListTy runtimeRepTy rr_tys]), convEvalDataConTy] > > -- | Specialization of 'unboxedTupleSumKind' for tuples > unboxedTupleKind :: [Type] -> Kind > @@ -1064,7 +1071,7 @@ mk_tuple Unboxed arity = (tycon, tuple_con) > > -- See Note [Unboxed tuple RuntimeRep vars] in GHC.Core.TyCon > -- Kind: forall (k1:RuntimeRep) (k2:RuntimeRep). TYPE k1 -> TYPE k2 -> # > - tc_binders = mkTemplateTyConBinders (replicate arity runtimeRepTy) > + tc_binders = mkTemplateTyConBinders (replicate arity runtimeInfoTy) > (\ks -> map tYPE ks) > > tc_res_kind = unboxedTupleKind rr_tys > @@ -1388,11 +1395,11 @@ unrestrictedFunTyCon :: TyCon > unrestrictedFunTyCon = buildSynTyCon unrestrictedFunTyConName [] arrowKind [] unrestrictedFunTy > where arrowKind = mkTyConKind binders liftedTypeKind > -- See also funTyCon > - binders = [ Bndr runtimeRep1TyVar (NamedTCB Inferred) > - , Bndr runtimeRep2TyVar (NamedTCB Inferred) > + binders = [ Bndr runtimeInfo1TyVar (NamedTCB Inferred) > + , Bndr runtimeInfo2TyVar (NamedTCB Inferred) > ] > - ++ mkTemplateAnonTyConBinders [ tYPE runtimeRep1Ty > - , tYPE runtimeRep2Ty > + ++ mkTemplateAnonTyConBinders [ tYPE runtimeInfo1Ty > + , tYPE runtimeInfo2Ty > ] > > unrestrictedFunTyConName :: Name > @@ -1400,7 +1407,7 @@ unrestrictedFunTyConName = mkWiredInTyConName BuiltInSyntax gHC_TYPES (fsLit "-> > > {- ********************************************************************* > * * > - Kinds and RuntimeRep > + Kinds, RuntimeRep and CallingConv > * * > ********************************************************************* -} > > @@ -1413,8 +1420,8 @@ runtimeRepTy = mkTyConTy runtimeRepTyCon > -- type Type = tYPE 'LiftedRep > liftedTypeKindTyCon :: TyCon > liftedTypeKindTyCon = buildSynTyCon liftedTypeKindTyConName > - [] liftedTypeKind [] > - (tYPE liftedRepTy) > + [] liftedTypeKind [] rhs > + where rhs = TyCoRep.TyConApp tYPETyCon [mkTyConApp runtimeInfoDataConTyCon [liftedRepTy, convEvalDataConTy]] > > runtimeRepTyCon :: TyCon > runtimeRepTyCon = pcTyCon runtimeRepTyConName Nothing [] > @@ -1425,13 +1432,13 @@ vecRepDataCon :: DataCon > vecRepDataCon = pcSpecialDataCon vecRepDataConName [ mkTyConTy vecCountTyCon > , mkTyConTy vecElemTyCon ] > runtimeRepTyCon > - (RuntimeRep prim_rep_fun) > + (RuntimeInfo prim_rep_fun) > where > -- See Note [Getting from RuntimeRep to PrimRep] in GHC.Types.RepType > prim_rep_fun [count, elem] > | VecCount n <- tyConRuntimeRepInfo (tyConAppTyCon count) > , VecElem e <- tyConRuntimeRepInfo (tyConAppTyCon elem) > - = [VecRep n e] > + = [RInfo [(VecRep n e)] ConvEval] > prim_rep_fun args > = pprPanic "vecRepDataCon" (ppr args) > > @@ -1440,11 +1447,11 @@ vecRepDataConTyCon = promoteDataCon vecRepDataCon > > tupleRepDataCon :: DataCon > tupleRepDataCon = pcSpecialDataCon tupleRepDataConName [ mkListTy runtimeRepTy ] > - runtimeRepTyCon (RuntimeRep prim_rep_fun) > + runtimeRepTyCon (RuntimeInfo prim_rep_fun) > where > -- See Note [Getting from RuntimeRep to PrimRep] in GHC.Types.RepType > prim_rep_fun [rr_ty_list] > - = concatMap (runtimeRepPrimRep doc) rr_tys > + = [RInfo (concatMap (runtimeRepPrimRep doc) rr_tys) ConvEval] > where > rr_tys = extractPromotedList rr_ty_list > doc = text "tupleRepDataCon" <+> ppr rr_tys > @@ -1456,11 +1463,11 @@ tupleRepDataConTyCon = promoteDataCon tupleRepDataCon > > sumRepDataCon :: DataCon > sumRepDataCon = pcSpecialDataCon sumRepDataConName [ mkListTy runtimeRepTy ] > - runtimeRepTyCon (RuntimeRep prim_rep_fun) > + runtimeRepTyCon (RuntimeInfo prim_rep_fun) > where > -- See Note [Getting from RuntimeRep to PrimRep] in GHC.Types.RepType > prim_rep_fun [rr_ty_list] > - = map slotPrimRep (ubxSumRepType prim_repss) > + = [RInfo (map slotPrimRep (ubxSumRepType prim_repss)) ConvEval] > where > rr_tys = extractPromotedList rr_ty_list > doc = text "sumRepDataCon" <+> ppr rr_tys > @@ -1488,7 +1495,7 @@ runtimeRepSimpleDataCons@(liftedRepDataCon : _) > runtimeRepSimpleDataConNames > where > mk_runtime_rep_dc primrep name > - = pcSpecialDataCon name [] runtimeRepTyCon (RuntimeRep (\_ -> [primrep])) > + = pcSpecialDataCon name [] runtimeRepTyCon (RuntimeInfo (\_ -> [RInfo [primrep] ConvEval])) > > -- See Note [Wiring in RuntimeRep] > liftedRepDataConTy, unliftedRepDataConTy, > @@ -1558,6 +1565,79 @@ liftedRepDataConTyCon = promoteDataCon liftedRepDataCon > liftedRepTy :: Type > liftedRepTy = liftedRepDataConTy > > +-- The type ('BoxedRep 'UnliftedRep) > +unliftedRepTy :: Type > +unliftedRepTy = unliftedRepDataConTy > + > +unliftedRepEvalTy :: Type > +unliftedRepEvalTy = mkTyConApp runtimeInfoDataConTyCon [unliftedRepTy, convEvalDataConTy] > + > +liftedRepEvalTy :: Type > +liftedRepEvalTy = mkTyConApp runtimeInfoDataConTyCon [liftedRepTy, convEvalDataConTy] > + > +callingConvTyConName, convEvalDataConName, convCallDataConName :: Name > +callingConvTyConName = mkWiredInTyConName UserSyntax gHC_TYPES (fsLit "CallingConv") callingConvTyConKey callingConvTyCon > +convEvalDataConName = mkWiredInDataConName UserSyntax gHC_TYPES (fsLit "ConvEval") convEvalDataConKey convEvalDataCon > +-- convCallDataConName = mkWiredInDataConName UserSyntax gHC_TYPES (fsLit "ConvCall") convCallDataConKey convCallDataCon > +convCallDataConName = undefined > + > +convEvalDataCon = pcSpecialDataCon convEvalDataConName [] callingConvTyCon (CallingConvInfo $ \_ -> [ConvEval]) > + > +convEvalDataConTyCon :: TyCon > +convEvalDataConTyCon = promoteDataCon convEvalDataCon > + > +convEvalDataConTy :: Type > +convEvalDataConTy = mkTyConTy convEvalDataConTyCon > + > + > +callingConvTyCon :: TyCon > +callingConvTyCon = pcTyCon callingConvTyConName Nothing [] > + [convEvalDataCon] > + > +callingConvTy :: Type > +callingConvTy = mkTyConTy callingConvTyCon > + > +{- ********************************************************************* > +* * > + RuntimeInfo Types > +* * > +********************************************************************* -} > + > +runtimeInfoTyConName, runtimeInfoDataConName :: Name > +runtimeInfoTyConName = mkWiredInTyConName UserSyntax gHC_TYPES (fsLit "RuntimeInfo") runtimeInfoTyConKey runtimeInfoTyCon > +runtimeInfoDataConName = mkWiredInDataConName UserSyntax gHC_TYPES (fsLit "RInfo") runtimeInfoDataConKey runtimeInfoDataCon > + > +runtimeInfoTyCon :: TyCon > +runtimeInfoTyCon = pcTyCon runtimeInfoTyConName Nothing [] > + [runtimeInfoDataCon] > + > +runtimeInfoDataCon :: DataCon > +runtimeInfoDataCon = pcSpecialDataCon runtimeInfoDataConName [ runtimeRepTy > + , mkTyConTy callingConvTyCon ] > + runtimeInfoTyCon > + (RuntimeInfo prim_info_fun) > + where > + -- See Note [Getting from RuntimeRep to PrimRep] in GHC.Types.RepType > + prim_info_fun tys@[rep, conv] > + = pprPanic "here runtimeInfoDataCon" (ppr tys) > + -- [RInfo (runtimeRepPrimRep doc rep) ConvEval] > + where doc = text "runtimeInfoDataCon" <+> ppr tys > + prim_info_fun args > + = pprPanic "runtimeInfoDataCon" (ppr args) > + > +runtimeInfoDataConTyCon :: TyCon > +runtimeInfoDataConTyCon = promoteDataCon runtimeInfoDataCon > + > +runtimeInfoDataConTy :: Type > +runtimeInfoDataConTy = mkTyConTy runtimeInfoDataConTyCon > + > +runtimeInfoTy :: Type > +runtimeInfoTy = mkTyConTy runtimeInfoTyCon > + > +rInfo :: Type -> Type -> Type > +rInfo rep conv = TyCoRep.TyConApp runtimeInfoTyCon [rep, conv] > + > + > {- ********************************************************************* > * * > The boxed primitive types: Char, Int, etc > diff --git a/compiler/GHC/Builtin/Types.hs-boot b/compiler/GHC/Builtin/Types.hs-boot > index 000df212c3..fc82f9d7b9 100644 > --- a/compiler/GHC/Builtin/Types.hs-boot > +++ b/compiler/GHC/Builtin/Types.hs-boot > @@ -23,6 +23,13 @@ constraintKind :: Kind > runtimeRepTyCon, vecCountTyCon, vecElemTyCon :: TyCon > runtimeRepTy :: Type > > + > +runtimeInfoTy, callingConvTy, convEvalDataConTy :: Type > + > +runtimeInfoTyCon, runtimeInfoDataConTyCon :: TyCon > + > +rInfo :: Type -> Type -> Type > + > liftedRepDataConTyCon, vecRepDataConTyCon, tupleRepDataConTyCon :: TyCon > > liftedRepDataConTy, unliftedRepDataConTy, > diff --git a/compiler/GHC/Builtin/Types/Prim.hs b/compiler/GHC/Builtin/Types/Prim.hs > index fc74596e45..5fb750649c 100644 > --- a/compiler/GHC/Builtin/Types/Prim.hs > +++ b/compiler/GHC/Builtin/Types/Prim.hs > @@ -24,6 +24,7 @@ module GHC.Builtin.Types.Prim( > alphaTyVarsUnliftedRep, alphaTyVarUnliftedRep, > alphaTysUnliftedRep, alphaTyUnliftedRep, > runtimeRep1TyVar, runtimeRep2TyVar, runtimeRep1Ty, runtimeRep2Ty, > + runtimeInfo1TyVar, runtimeInfo2TyVar, runtimeInfo1Ty, runtimeInfo2Ty, > openAlphaTy, openBetaTy, openAlphaTyVar, openBetaTyVar, > > multiplicityTyVar, > @@ -97,6 +98,7 @@ import GHC.Prelude > > import {-# SOURCE #-} GHC.Builtin.Types > ( runtimeRepTy, unboxedTupleKind, liftedTypeKind > + , runtimeInfoTy, runtimeInfoDataConTyCon, convEvalDataConTy > , vecRepDataConTyCon, tupleRepDataConTyCon > , liftedRepDataConTy, unliftedRepDataConTy > , intRepDataConTy > @@ -382,11 +384,19 @@ runtimeRep1Ty, runtimeRep2Ty :: Type > runtimeRep1Ty = mkTyVarTy runtimeRep1TyVar > runtimeRep2Ty = mkTyVarTy runtimeRep2TyVar > > +runtimeInfo1TyVar, runtimeInfo2TyVar :: TyVar > +(runtimeInfo1TyVar : runtimeInfo2TyVar : _) > + = drop 16 (mkTemplateTyVars (repeat runtimeInfoTy)) -- selects 'q','r' > + > +runtimeInfo1Ty, runtimeInfo2Ty :: Type > +runtimeInfo1Ty = mkTyVarTy runtimeInfo1TyVar > +runtimeInfo2Ty = mkTyVarTy runtimeInfo2TyVar > + > openAlphaTyVar, openBetaTyVar :: TyVar > -- alpha :: TYPE r1 > -- beta :: TYPE r2 > [openAlphaTyVar,openBetaTyVar] > - = mkTemplateTyVars [tYPE runtimeRep1Ty, tYPE runtimeRep2Ty] > + = mkTemplateTyVars [tYPE runtimeInfo1Ty, tYPE runtimeInfo2Ty] > > openAlphaTy, openBetaTy :: Type > openAlphaTy = mkTyVarTy openAlphaTyVar > @@ -432,10 +442,10 @@ funTyCon = mkFunTyCon funTyConName tc_bndrs tc_rep_nm > where > -- See also unrestrictedFunTyCon > tc_bndrs = [ mkNamedTyConBinder Required multiplicityTyVar > - , mkNamedTyConBinder Inferred runtimeRep1TyVar > - , mkNamedTyConBinder Inferred runtimeRep2TyVar ] > - ++ mkTemplateAnonTyConBinders [ tYPE runtimeRep1Ty > - , tYPE runtimeRep2Ty > + , mkNamedTyConBinder Inferred runtimeInfo1TyVar > + , mkNamedTyConBinder Inferred runtimeInfo2TyVar ] > + ++ mkTemplateAnonTyConBinders [ tYPE runtimeInfo1Ty > + , tYPE runtimeInfo2Ty > ] > tc_rep_nm = mkPrelTyConRepName funTyConName > > @@ -529,7 +539,7 @@ tYPETyCon :: TyCon > tYPETyConName :: Name > > tYPETyCon = mkKindTyCon tYPETyConName > - (mkTemplateAnonTyConBinders [runtimeRepTy]) > + (mkTemplateAnonTyConBinders [runtimeInfoTy]) > liftedTypeKind > [Nominal] > (mkPrelTyConRepName tYPETyConName) > @@ -574,7 +584,7 @@ pcPrimTyCon name roles rep > = mkPrimTyCon name binders result_kind roles > where > binders = mkTemplateAnonTyConBinders (map (const liftedTypeKind) roles) > - result_kind = tYPE (primRepToRuntimeRep rep) > + result_kind = tYPE $ TyConApp runtimeInfoDataConTyCon [(primRepToRuntimeRep rep), convEvalDataConTy] > > -- | Convert a 'PrimRep' to a 'Type' of kind RuntimeRep > -- Defined here to avoid (more) module loops > diff --git a/compiler/GHC/Core/Make.hs b/compiler/GHC/Core/Make.hs > index 6d6dd38b29..da285a6455 100644 > --- a/compiler/GHC/Core/Make.hs > +++ b/compiler/GHC/Core/Make.hs > @@ -913,7 +913,7 @@ mkRuntimeErrorId name > runtimeErrorTy :: Type > -- forall (rr :: RuntimeRep) (a :: rr). Addr# -> a > -- See Note [Error and friends have an "open-tyvar" forall] > -runtimeErrorTy = mkSpecForAllTys [runtimeRep1TyVar, openAlphaTyVar] > +runtimeErrorTy = mkSpecForAllTys [runtimeInfo1TyVar, openAlphaTyVar] > (mkVisFunTyMany addrPrimTy openAlphaTy) > > {- Note [Error and friends have an "open-tyvar" forall] > diff --git a/compiler/GHC/Core/TyCon.hs b/compiler/GHC/Core/TyCon.hs > index 198b66959b..5c59548ebf 100644 > --- a/compiler/GHC/Core/TyCon.hs > +++ b/compiler/GHC/Core/TyCon.hs > @@ -120,6 +120,7 @@ module GHC.Core.TyCon( > > -- * Primitive representations of Types > PrimRep(..), PrimElemRep(..), > + PrimConv (..), PrimInfo (..), > isVoidRep, isGcPtrRep, > primRepSizeB, > primElemRepSizeB, > @@ -172,6 +173,10 @@ import GHC.Unit.Module > > import qualified Data.Data as Data > > +import {-# SOURCE #-} GHC.Core.Type (splitTyConApp_maybe) > +-- import {-# SOURCE #-} GHC.Builtin.Types.Prim (mutableByteArrayPrimTyConKey) > +import GHC.Builtin.Names > + > {- > ----------------------------------------------- > Notes about type families > @@ -1073,6 +1078,8 @@ data RuntimeRepInfo > -- be the list of arguments to the promoted datacon. > | VecCount Int -- ^ A constructor of @VecCount@ > | VecElem PrimElemRep -- ^ A constructor of @VecElem@ > + | RuntimeInfo ([Type] -> [PrimInfo]) > + | CallingConvInfo ([Type] -> [PrimConv]) > > -- | Extract those 'DataCon's that we are able to learn about. Note > -- that visibility in this sense does not correspond to visibility in > @@ -1550,6 +1557,26 @@ primRepIsFloat DoubleRep = Just True > primRepIsFloat (VecRep _ _) = Nothing > primRepIsFloat _ = Just False > > +{- > +************************************************************************ > +* * > + PrimConv > +* * > +************************************************************************ > + > +Note [PrimConv] > + > +A type for representing the calling convention of a type. Either the arity > +for extensional functions or the levity for data terms. > +-} > + > +data PrimConv = > + ConvEval > + -- | ConvCall [PrimRep] > + deriving (Show) > + > +data PrimInfo = RInfo {reps :: [PrimRep], conv :: PrimConv} > + > > {- > ************************************************************************ > @@ -2326,11 +2353,17 @@ expandSynTyCon_maybe > > -- ^ Expand a type synonym application, if any > expandSynTyCon_maybe tc tys > + -- | SynonymTyCon { tyConTyVars = tvs, synTcRhs = rhs, tyConArity = arity } <- tc > + -- , Just (tc' , _) <- splitTyConApp_maybe rhs > + -- , tc' `hasKey` (mutableByteArrayPrimTyConKey) > + -- = pprPanic "here" (ppr tc) > + > | SynonymTyCon { tyConTyVars = tvs, synTcRhs = rhs, tyConArity = arity } <- tc > = case tys `listLengthCmp` arity of > GT -> Just (tvs `zip` tys, rhs, drop arity tys) > EQ -> Just (tvs `zip` tys, rhs, []) > LT -> Nothing > + > | otherwise > = Nothing > > diff --git a/compiler/GHC/Core/Type.hs b/compiler/GHC/Core/Type.hs > index 3164e2626b..5f3ab18925 100644 > --- a/compiler/GHC/Core/Type.hs > +++ b/compiler/GHC/Core/Type.hs > @@ -68,6 +68,7 @@ module GHC.Core.Type ( > isPredTy, > > getRuntimeRep_maybe, kindRep_maybe, kindRep, > + getRuntimeInfo, getRuntimeInfo_maybe, kindInfo, > > mkCastTy, mkCoercionTy, splitCastTy_maybe, > > @@ -125,6 +126,7 @@ module GHC.Core.Type ( > isAlgType, isDataFamilyAppType, > isPrimitiveType, isStrictType, > isRuntimeRepTy, isRuntimeRepVar, isRuntimeRepKindedTy, > + isRuntimeInfoTy, isRuntimeInfoVar, > dropRuntimeRepArgs, > getRuntimeRep, > > @@ -554,6 +556,11 @@ kindRep k = case kindRep_maybe k of > Just r -> r > Nothing -> pprPanic "kindRep" (ppr k) > > +kindInfo :: HasDebugCallStack => Kind -> Type > +kindInfo k = case kindInfo_maybe k of > + Just r -> r > + Nothing -> pprPanic "kindInfo" (ppr k) > + > -- | Given a kind (TYPE rr), extract its RuntimeRep classifier rr. > -- For example, @kindRep_maybe * = Just LiftedRep@ > -- Returns 'Nothing' if the kind is not of form (TYPE rr) > @@ -561,18 +568,33 @@ kindRep k = case kindRep_maybe k of > kindRep_maybe :: HasDebugCallStack => Kind -> Maybe Type > kindRep_maybe kind > | TyConApp tc [arg] <- coreFullView kind > - , tc `hasKey` tYPETyConKey = Just arg > - | otherwise = Nothing > + , tc `hasKey` tYPETyConKey > + , TyConApp rinfo [rep, conv] <- coreFullView arg > + , rinfo `hasKey` runtimeInfoDataConKey = Just rep > + | TyConApp tc [arg] <- coreFullView kind > + , tc `hasKey` tYPETyConKey = Just arg > + | otherwise = Nothing > + > +kindInfo_maybe :: HasDebugCallStack => Kind -> Maybe Type > +kindInfo_maybe kind > + | TyConApp tc [arg] <- coreFullView kind > + , tc `hasKey` tYPETyConKey > + , TyConApp rinfo [rep, conv] <- coreFullView arg > + , rinfo `hasKey` runtimeInfoDataConKey = Just arg > + | TyConApp tc [arg] <- coreFullView kind > + , tc `hasKey` tYPETyConKey = Just arg > + | otherwise = Nothing > > -- | This version considers Constraint to be the same as *. Returns True > -- if the argument is equivalent to Type/Constraint and False otherwise. > -- See Note [Kind Constraint and kind Type] > isLiftedTypeKind :: Kind -> Bool > isLiftedTypeKind kind > - = case kindRep_maybe kind of > - Just rep -> isLiftedRuntimeRep rep > + = case kindInfo_maybe kind of > + Just rinfo -> isLiftedRuntimeInfo rinfo > Nothing -> False > > + > pickyIsLiftedTypeKind :: Kind -> Bool > -- Checks whether the kind is literally > -- TYPE LiftedRep > @@ -599,13 +621,23 @@ isLiftedRuntimeRep rep > , rr_tc `hasKey` liftedRepDataConKey = ASSERT( null args ) True > | otherwise = False > > +isLiftedRuntimeInfo :: Type -> Bool > +-- isLiftedRuntimeRep is true of LiftedRep :: RuntimeRep > +-- False of type variables (a :: RuntimeRep) > +-- and of other reps e.g. (IntRep :: RuntimeRep) > +isLiftedRuntimeInfo rep > + | TyConApp rr_tc [rep,conv] <- coreFullView rep > + , rr_tc `hasKey` runtimeInfoDataConKey = isLiftedRuntimeRep rep > + | otherwise > + = False > + > -- | Returns True if the kind classifies unlifted types and False otherwise. > -- Note that this returns False for levity-polymorphic kinds, which may > -- be specialized to a kind that classifies unlifted types. > isUnliftedTypeKind :: Kind -> Bool > isUnliftedTypeKind kind > - = case kindRep_maybe kind of > - Just rep -> isUnliftedRuntimeRep rep > + = case kindInfo_maybe kind of > + Just rep -> isUnliftedRuntimeInfo rep > Nothing -> False > > isUnliftedRuntimeRep :: Type -> Bool > @@ -622,6 +654,17 @@ isUnliftedRuntimeRep rep > | otherwise {- Variables, applications -} > = False > > +isUnliftedRuntimeInfo rep > + | TyConApp rinfo [rep, conv] <- coreFullView rep -- NB: args might be non-empty > + , rinfo `hasKey` runtimeInfoDataConKey > + = isUnliftedRuntimeRep rep > + -- Avoid searching all the unlifted RuntimeRep type cons > + -- In the RuntimeRep data type, only LiftedRep is lifted > + -- But be careful of type families (F tys) :: RuntimeRep > + | otherwise {- Variables, applications -} > + = False > + > + > -- | Is this the type 'RuntimeRep'? > isRuntimeRepTy :: Type -> Bool > isRuntimeRepTy ty > @@ -644,6 +687,17 @@ isMultiplicityTy ty > isMultiplicityVar :: TyVar -> Bool > isMultiplicityVar = isMultiplicityTy . tyVarKind > > +-- | Is this the type 'RuntimeInfo'? > +isRuntimeInfoTy :: Type -> Bool > +isRuntimeInfoTy ty > + | TyConApp tc args <- coreFullView ty > + , tc `hasKey` runtimeInfoTyConKey = True > + | otherwise = False > + > +-- | Is a tyvar of type 'RuntimeInfo'? > +isRuntimeInfoVar :: TyVar -> Bool > +isRuntimeInfoVar = isRuntimeInfoTy . tyVarKind > + > {- ********************************************************************* > * * > mapType > @@ -927,8 +981,8 @@ repSplitAppTy_maybe :: HasDebugCallStack => Type -> Maybe (Type,Type) > repSplitAppTy_maybe (FunTy _ w ty1 ty2) > = Just (TyConApp funTyCon [w, rep1, rep2, ty1], ty2) > where > - rep1 = getRuntimeRep ty1 > - rep2 = getRuntimeRep ty2 > + rep1 = getRuntimeInfo ty1 > + rep2 = getRuntimeInfo ty2 > > repSplitAppTy_maybe (AppTy ty1 ty2) > = Just (ty1, ty2) > @@ -2049,6 +2103,10 @@ getRuntimeRep_maybe :: HasDebugCallStack > => Type -> Maybe Type > getRuntimeRep_maybe = kindRep_maybe . typeKind > > +getRuntimeInfo_maybe :: HasDebugCallStack > + => Type -> Maybe Type > +getRuntimeInfo_maybe = kindInfo_maybe . typeKind > + > -- | Extract the RuntimeRep classifier of a type. For instance, > -- @getRuntimeRep_maybe Int = LiftedRep at . Panics if this is not possible. > getRuntimeRep :: HasDebugCallStack => Type -> Type > @@ -2057,6 +2115,12 @@ getRuntimeRep ty > Just r -> r > Nothing -> pprPanic "getRuntimeRep" (ppr ty <+> dcolon <+> ppr (typeKind ty)) > > +getRuntimeInfo :: HasDebugCallStack => Type -> Type > +getRuntimeInfo ty > + = case getRuntimeInfo_maybe ty of > + Just r -> r > + Nothing -> pprPanic "getRuntimeInfo" (ppr ty <+> dcolon <+> ppr (typeKind ty)) > + > isUnboxedTupleType :: Type -> Bool > isUnboxedTupleType ty > = tyConAppTyCon (getRuntimeRep ty) `hasKey` tupleRepDataConKey > @@ -2584,7 +2648,9 @@ tcIsLiftedTypeKind :: Kind -> Bool > tcIsLiftedTypeKind ty > | Just (tc, [arg]) <- tcSplitTyConApp_maybe ty -- Note: tcSplit here > , tc `hasKey` tYPETyConKey > - = isLiftedRuntimeRep arg > + , Just (rinfo, [rep, conv]) <- tcSplitTyConApp_maybe arg > + , rinfo `hasKey` runtimeInfoDataConKey > + = isLiftedRuntimeRep rep > | otherwise > = False > > diff --git a/compiler/GHC/HsToCore.hs b/compiler/GHC/HsToCore.hs > index 9cf33aa02a..3522ad6fab 100644 > --- a/compiler/GHC/HsToCore.hs > +++ b/compiler/GHC/HsToCore.hs > @@ -714,7 +714,7 @@ mkUnsafeCoercePrimPair _old_id old_expr > > ; let [unsafe_refl_data_con] = tyConDataCons unsafe_equality_tc > > - rhs = mkLams [ runtimeRep1TyVar, runtimeRep2TyVar > + rhs = mkLams [ runtimeInfo1TyVar, runtimeInfo2TyVar > , openAlphaTyVar, openBetaTyVar > , x ] $ > mkSingleAltCase scrut1 > @@ -742,10 +742,10 @@ mkUnsafeCoercePrimPair _old_id old_expr > -- NB: UnsafeRefl :: (b ~# a) -> UnsafeEquality a b, so we have to > -- carefully swap the arguments above > > - (scrut1, scrut1_ty, rr_cv_ty) = unsafe_equality runtimeRepTy > - runtimeRep1Ty > - runtimeRep2Ty > - (scrut2, scrut2_ty, ab_cv_ty) = unsafe_equality (tYPE runtimeRep2Ty) > + (scrut1, scrut1_ty, rr_cv_ty) = unsafe_equality runtimeInfoTy > + runtimeInfo1Ty > + runtimeInfo2Ty > + (scrut2, scrut2_ty, ab_cv_ty) = unsafe_equality (tYPE runtimeInfo2Ty) > (openAlphaTy `mkCastTy` alpha_co) > openBetaTy > > @@ -761,7 +761,7 @@ mkUnsafeCoercePrimPair _old_id old_expr > info = noCafIdInfo `setInlinePragInfo` alwaysInlinePragma > `setUnfoldingInfo` mkCompulsoryUnfolding' rhs > > - ty = mkSpecForAllTys [ runtimeRep1TyVar, runtimeRep2TyVar > + ty = mkSpecForAllTys [ runtimeInfo1TyVar, runtimeInfo2TyVar > , openAlphaTyVar, openBetaTyVar ] $ > mkVisFunTyMany openAlphaTy openBetaTy > > diff --git a/compiler/GHC/HsToCore/Utils.hs b/compiler/GHC/HsToCore/Utils.hs > index 01085b3270..688d227a6e 100644 > --- a/compiler/GHC/HsToCore/Utils.hs > +++ b/compiler/GHC/HsToCore/Utils.hs > @@ -407,7 +407,7 @@ mkErrorAppDs err_id ty msg = do > full_msg = showSDoc dflags (hcat [ppr src_loc, vbar, msg]) > core_msg = Lit (mkLitString full_msg) > -- mkLitString returns a result of type String# > - return (mkApps (Var err_id) [Type (getRuntimeRep ty), Type ty, core_msg]) > + return (mkApps (Var err_id) [Type (getRuntimeInfo ty), Type ty, core_msg]) > > {- > 'mkCoreAppDs' and 'mkCoreAppsDs' handle the special-case desugaring of 'seq'. > diff --git a/compiler/GHC/IfaceToCore.hs b/compiler/GHC/IfaceToCore.hs > index de0fa6f023..b6d1281684 100644 > --- a/compiler/GHC/IfaceToCore.hs > +++ b/compiler/GHC/IfaceToCore.hs > @@ -1438,7 +1438,7 @@ tcIfaceExpr (IfaceTuple sort args) > ; let con_tys = map exprType args' > some_con_args = map Type con_tys ++ args' > con_args = case sort of > - UnboxedTuple -> map (Type . getRuntimeRep) con_tys ++ some_con_args > + UnboxedTuple -> map (Type . getRuntimeInfo) con_tys ++ some_con_args > _ -> some_con_args > -- Put the missing type arguments back in > con_id = dataConWorkId (tyConSingleDataCon tc) > diff --git a/compiler/GHC/Tc/Gen/HsType.hs b/compiler/GHC/Tc/Gen/HsType.hs > index bf4b1c91d1..22283296e1 100644 > --- a/compiler/GHC/Tc/Gen/HsType.hs > +++ b/compiler/GHC/Tc/Gen/HsType.hs > @@ -1331,7 +1331,7 @@ finish_tuple rn_ty tup_sort tau_tys tau_kinds exp_kind = do > check_expected_kind (mkTyConApp tycon tau_tys) liftedTypeKind > UnboxedTuple -> do > let tycon = tupleTyCon Unboxed arity > - tau_reps = map kindRep tau_kinds > + tau_reps = map kindInfo tau_kinds > -- See also Note [Unboxed tuple RuntimeRep vars] in GHC.Core.TyCon > arg_tys = tau_reps ++ tau_tys > res_kind = unboxedTupleKind tau_reps > @@ -1340,7 +1340,8 @@ finish_tuple rn_ty tup_sort tau_tys tau_kinds exp_kind = do > where > arity = length tau_tys > check_expected_kind ty act_kind = > - checkExpectedKind rn_ty ty act_kind exp_kind > + pprPanic "here" (ppr exp_kind) > + -- checkExpectedKind rn_ty ty act_kind exp_kind > > {- > Note [Ignore unary constraint tuples] > diff --git a/compiler/GHC/Tc/Instance/Typeable.hs b/compiler/GHC/Tc/Instance/Typeable.hs > index e4eb7a1b2d..51f0816860 100644 > --- a/compiler/GHC/Tc/Instance/Typeable.hs > +++ b/compiler/GHC/Tc/Instance/Typeable.hs > @@ -28,7 +28,7 @@ import GHC.Builtin.Names > import GHC.Builtin.Types.Prim ( primTyCons ) > import GHC.Builtin.Types > ( tupleTyCon, sumTyCon, runtimeRepTyCon > - , vecCountTyCon, vecElemTyCon > + , runtimeInfoTyCon, vecCountTyCon, vecElemTyCon > , nilDataCon, consDataCon ) > import GHC.Types.Name > import GHC.Types.Id > @@ -564,7 +564,7 @@ mkKindRepRhs stuff@(Stuff {..}) in_scope = new_kind_rep > | not (tcIsConstraintKind k) > -- Typeable respects the Constraint/Type distinction > -- so do not follow the special case here > - , Just arg <- kindRep_maybe k > + , Just arg <- kindInfo_maybe k > , Just (tc, []) <- splitTyConApp_maybe arg > , Just dc <- isPromotedDataCon_maybe tc > = return $ nlHsDataCon kindRepTYPEDataCon `nlHsApp` nlHsDataCon dc > diff --git a/compiler/GHC/Tc/Solver.hs b/compiler/GHC/Tc/Solver.hs > index 8b21b72768..ae8609541f 100644 > --- a/compiler/GHC/Tc/Solver.hs > +++ b/compiler/GHC/Tc/Solver.hs > @@ -53,7 +53,7 @@ import GHC.Core.Predicate > import GHC.Tc.Types.Origin > import GHC.Tc.Utils.TcType > import GHC.Core.Type > -import GHC.Builtin.Types ( liftedRepTy, manyDataConTy ) > +import GHC.Builtin.Types ( liftedRepEvalTy, manyDataConTy ) > import GHC.Core.Unify ( tcMatchTyKi ) > import GHC.Utils.Misc > import GHC.Utils.Panic > @@ -2283,13 +2283,13 @@ promoteTyVarTcS tv > -- | Like 'defaultTyVar', but in the TcS monad. > defaultTyVarTcS :: TcTyVar -> TcS Bool > defaultTyVarTcS the_tv > - | isRuntimeRepVar the_tv > + | isRuntimeInfoVar the_tv > , not (isTyVarTyVar the_tv) > -- TyVarTvs should only be unified with a tyvar > -- never with a type; c.f. GHC.Tc.Utils.TcMType.defaultTyVar > -- and Note [Inferring kinds for type declarations] in GHC.Tc.TyCl > - = do { traceTcS "defaultTyVarTcS RuntimeRep" (ppr the_tv) > - ; unifyTyVar the_tv liftedRepTy > + = do { traceTcS "defaultTyVarTcS RuntimeInfo" (ppr the_tv) > + ; unifyTyVar the_tv liftedRepEvalTy > ; return True } > | isMultiplicityVar the_tv > , not (isTyVarTyVar the_tv) -- TyVarTvs should only be unified with a tyvar > diff --git a/compiler/GHC/Tc/TyCl/PatSyn.hs b/compiler/GHC/Tc/TyCl/PatSyn.hs > index 3f5b10f343..de9f28fbd9 100644 > --- a/compiler/GHC/Tc/TyCl/PatSyn.hs > +++ b/compiler/GHC/Tc/TyCl/PatSyn.hs > @@ -756,7 +756,7 @@ tcPatSynMatcher (L loc name) lpat > (args, arg_tys) pat_ty > = do { rr_name <- newNameAt (mkTyVarOcc "rep") loc > ; tv_name <- newNameAt (mkTyVarOcc "r") loc > - ; let rr_tv = mkTyVar rr_name runtimeRepTy > + ; let rr_tv = mkTyVar rr_name runtimeInfoTy > rr = mkTyVarTy rr_tv > res_tv = mkTyVar tv_name (tYPE rr) > res_ty = mkTyVarTy res_tv > diff --git a/compiler/GHC/Tc/Utils/TcMType.hs b/compiler/GHC/Tc/Utils/TcMType.hs > index ccb9152e01..67295ac3f5 100644 > --- a/compiler/GHC/Tc/Utils/TcMType.hs > +++ b/compiler/GHC/Tc/Utils/TcMType.hs > @@ -492,7 +492,7 @@ inferResultToType (IR { ir_uniq = u, ir_lvl = tc_lvl > Just ty -> do { ensureMonoType ty > -- See Note [inferResultToType] > ; return ty } > - Nothing -> do { rr <- newMetaTyVarTyAtLevel tc_lvl runtimeRepTy > + Nothing -> do { rr <- newMetaTyVarTyAtLevel tc_lvl runtimeInfoTy > ; tau <- newMetaTyVarTyAtLevel tc_lvl (tYPE rr) > -- See Note [TcLevel of ExpType] > ; writeMutVar ref (Just tau) > @@ -667,10 +667,10 @@ promoteTcType dest_lvl ty > else promote_it } > where > promote_it :: TcM (TcCoercion, TcType) > - promote_it -- Emit a constraint (alpha :: TYPE rr) ~ ty > + promote_it -- Emit a constraint (alpha :: TYPE ri) ~ ty > -- where alpha and rr are fresh and from level dest_lvl > - = do { rr <- newMetaTyVarTyAtLevel dest_lvl runtimeRepTy > - ; prom_ty <- newMetaTyVarTyAtLevel dest_lvl (tYPE rr) > + = do { ri <- newMetaTyVarTyAtLevel dest_lvl runtimeInfoTy > + ; prom_ty <- newMetaTyVarTyAtLevel dest_lvl (tYPE ri) > ; let eq_orig = TypeEqOrigin { uo_actual = ty > , uo_expected = prom_ty > , uo_thing = Nothing > @@ -1048,7 +1048,7 @@ newFlexiTyVarTys n kind = replicateM n (newFlexiTyVarTy kind) > > newOpenTypeKind :: TcM TcKind > newOpenTypeKind > - = do { rr <- newFlexiTyVarTy runtimeRepTy > + = do { rr <- newFlexiTyVarTy runtimeInfoTy > ; return (tYPE rr) } > > -- | Create a tyvar that can be a lifted or unlifted type. > @@ -1765,11 +1765,16 @@ defaultTyVar default_kind tv > -- See Note [Inferring kinds for type declarations] in GHC.Tc.TyCl > = return False > > + | isRuntimeInfoVar tv -- Do not quantify over a RuntimeRep var > + -- unless it is a TyVarTv, handled earlier > + = do { traceTc "Defaulting a RuntimeRep var to LiftedRep" (ppr tv) > + ; writeMetaTyVar tv liftedRepEvalTy > + ; return True } > > | isRuntimeRepVar tv -- Do not quantify over a RuntimeRep var > -- unless it is a TyVarTv, handled earlier > = do { traceTc "Defaulting a RuntimeRep var to LiftedRep" (ppr tv) > - ; writeMetaTyVar tv liftedRepTy > + ; writeMetaTyVar tv liftedRepEvalTy I believe your bug is here. You have filled in a RuntimeRep metavar with a RuntimeInfo. Leave this as liftedRepTy. Cheers, - Ben -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: not available URL: From shanth2600 at gmail.com Wed Apr 7 22:45:27 2021 From: shanth2600 at gmail.com (Shant Hairapetian) Date: Wed, 7 Apr 2021 15:45:27 -0700 Subject: Newcomer looking for help with changes to kind system In-Reply-To: <87y2duru45.fsf@smart-cactus.org> References: <877dlgt9s4.fsf@smart-cactus.org> <87y2duru45.fsf@smart-cactus.org> Message-ID: Thanks, Ben. That doesn't seem to have an effect on the error I'm getting but Simon suggested that a meeting would be a better way to discuss this modification and the problems we're having. I appreciate you taking the time to look at this. - Shant On Wed, Apr 7, 2021 at 8:29 AM Ben Gamari wrote: > Shant Hairapetian writes: > > > Hi Ben, > > Thanks for the reply > > > >> Incidentally, the collapse of LiftedRep and UnliftedRep will happen in > >> GHC 9.2 (turning into `BoxedRep :: Levity -> RuntimeRep`). > > > > Yes I believe this change was accidentally merged a few months ago then > > reverted? I will keep that in mind. > > > It was briefly accidentally merged, then reverted, then re-applied. The > final commit is 3e082f8ff5ea2f42c5e6430094683b26b5818fb8. > > >> Can you provide a program that your patch rejects, as well as > >> the full error that is produced? > > > > My error is in stage 1 in the building of the ghc-bignum library. I have > > attached the full error as well as the patch itself. > > > See below. > > > Thanks, > > Shant > > > > > > > > On Mon, Apr 5, 2021 at 7:41 PM Ben Gamari wrote: > > > >> Shant Hairapetian writes: > >> > >> > Hello, > >> > > >> > I’m a master’s student working on implementing the changes outlined in > >> > “Kinds are Calling Conventions“ ( > >> > > https://www.microsoft.com/en-us/research/uploads/prod/2020/03/kacc.pdf). > >> I > >> > have been working directly with Paul Downen but have hit some > roadblocks. > >> > > >> > To sum up the changes to the kind system, I am attempting to modify > the > >> > “TYPE” type constructor to accept, rather than just a RuntimeRep, a > >> record > >> > type (called RuntimeInfo) comprised of a RuntimeRep and a CallingConv > >> > (calling convention). The calling convention has an “Eval” constructor > >> > which accepts a levity (effectively moving the levity information from > >> the > >> > representation to the calling convention. LiftedRep and UnliftedRep > would > >> > also be collapsed into a single PtrRep constructor) and a “Call” > >> > constructor (denoting the arity of primitive, extensional functions, > >> > see: Making > >> > a Faster Curry with Extensional Types > >> > < > >> > https://www.microsoft.com/en-us/research/uploads/prod/2019/07/arity-haskell-symposium-2019.pdf > >> >) > >> > which accepts a list of RuntimeRep’s. I have created and wired-in the > new > >> > RuntimeInfo and CallingConv types in GHC.Builtin.Types, as well as the > >> > corresponding primitive types in GHC.Builtin.Types.Prim and have > modified > >> > the “TYPE” constructor to accept a RuntimeInfo rather than a > RuntimeRep. > >> > > >> Hi Shant, > >> > >> It would be helpful to have a bit more information on the nature of your > >> failure. Can you provide a program that your patch rejects, as well as > >> the full error that is produced? > >> > >> Incidentally, the collapse of LiftedRep and UnliftedRep will happen in > >> GHC 9.2 (turning into `BoxedRep :: Levity -> RuntimeRep`). > >> > >> Cheers, > >> > >> - Ben > >> > >> > > > > -- > > Shant Hairapetian > > > > libraries/ghc-bignum/src/GHC/Num/WordArray.hs:78:22: error: > > • Couldn't match type: 'TupleRep ('[] @RuntimeRep) > > with: 'RInfo ('TupleRep ('[] @RuntimeRep)) > 'GHC.Types.ConvEval > > Expected: (# State# s, MutableWordArray# s #) > > Actual: (# State# s, MutableByteArray# s #) > > • In the expression: newByteArray# (wordsToBytes# sz) s > > In an equation for ‘newWordArray#’: > > newWordArray# sz s = newByteArray# (wordsToBytes# sz) s > > | > > 78 | newWordArray# sz s = newByteArray# (wordsToBytes# sz) s > > | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > > > libraries/ghc-bignum/src/GHC/Num/WordArray.hs:112:71: error: > > • Couldn't match a lifted type with an unlifted type > > When matching types > > b0 :: TYPE ('RInfo 'LiftedRep 'GHC.Types.ConvEval) > > WordArray# :: TYPE ('RInfo 'UnliftedRep 'GHC.Types.ConvEval) > > Expected: (# () | WordArray# #) > > Actual: (# () | b0 #) > > • In the expression: a > > In a case alternative: (# _, a #) -> a > > In the expression: case runRW# io of { (# _, a #) -> a } > > • Relevant bindings include > > a :: (# () | b0 #) > > (bound at > libraries/ghc-bignum/src/GHC/Num/WordArray.hs:112:63) > > | > > 112 | withNewWordArrayTrimedMaybe# sz act = case runRW# io of (# _, > a #) -> a > > | > ^ > > > > libraries/ghc-bignum/src/GHC/Num/WordArray.hs:117:40: error: > > • Couldn't match kind ‘RuntimeInfo’ with ‘RuntimeRep’ > > When matching the kind of ‘'RInfo 'LiftedRep > 'GHC.Types.ConvEval’ > > • In the expression: () > > In the expression: (# () | #) > > In the expression: (# s, (# () | #) #) > > | > > 117 | (# s, 0# #) -> (# s, (# () | #) #) > > | ^^ > > > > libraries/ghc-bignum/src/GHC/Num/WordArray.hs:120:48: error: > > • Couldn't match kind ‘RuntimeInfo’ with ‘RuntimeRep’ > > When matching kinds > > 'RInfo 'LiftedRep 'GHC.Types.ConvEval :: RuntimeInfo > > 'RInfo 'UnliftedRep 'GHC.Types.ConvEval :: RuntimeInfo > > • In the expression: ba > > In the expression: (# | ba #) > > In the expression: (# s, (# | ba #) #) > > | > > 120 | (# s, ba #) -> (# s, (# | ba #) #) > > | ^^ > > > > libraries/ghc-bignum/src/GHC/Num/WordArray.hs:431:31: error: > > • Couldn't match type: 'TupleRep ('[] @RuntimeRep) > > with: 'RInfo ('TupleRep ('[] @RuntimeRep)) > 'GHC.Types.ConvEval > > Expected: (# State# s, Word# #) > > Actual: (# State# s, Word# #) > > • In the expression: readWordArray# mwa i s2 > > In a case alternative: > > (# s2, sz #) > > | isTrue# (i >=# sz) -> (# s2, 0## #) > > | isTrue# (i <# 0#) -> (# s2, 0## #) > > | True -> readWordArray# mwa i s2 > > In the expression: > > case mwaSize# mwa s of { > > (# s2, sz #) > > | isTrue# (i >=# sz) -> (# s2, 0## #) > > | isTrue# (i <# 0#) -> (# s2, 0## #) > > | True -> readWordArray# mwa i s2 } > > | > > 431 | | True -> readWordArray# mwa i s2 > > | ^^^^^^^^^^^^^^^^^^^^^^^ > > > > libraries/ghc-bignum/src/GHC/Num/WordArray.hs:434:12: error: > > • Couldn't match type: 'TupleRep ('[] @RuntimeRep) > > with: 'RInfo ('TupleRep ('[] @RuntimeRep)) > 'GHC.Types.ConvEval > > Expected: MutableWordArray# s > > -> Int# -> State# s -> (# State# s, Word# #) > > Actual: MutableByteArray# s > > -> Int# -> State# s -> (# State# s, Word# #) > > • In the expression: readWordArray# > > In an equation for ‘mwaRead#’: mwaRead# = readWordArray# > > | > > 434 | mwaRead# = readWordArray# > > diff --git a/compiler/GHC/Builtin/Names.hs > b/compiler/GHC/Builtin/Names.hs > > index cf0f72c50f..78c84147cb 100644 > > --- a/compiler/GHC/Builtin/Names.hs > > +++ b/compiler/GHC/Builtin/Names.hs > > @@ -1949,6 +1949,15 @@ unrestrictedFunTyConKey = mkPreludeTyConUnique 193 > > multMulTyConKey :: Unique > > multMulTyConKey = mkPreludeTyConUnique 194 > > > > +-- CallingConv > > +runtimeInfoTyConKey, runtimeInfoDataConKey, callingConvTyConKey, > > + convEvalDataConKey, convCallDataConKey :: Unique > > +runtimeInfoTyConKey = mkPreludeTyConUnique 195 > > +runtimeInfoDataConKey = mkPreludeDataConUnique 196 > > +callingConvTyConKey = mkPreludeTyConUnique 197 > > +convEvalDataConKey = mkPreludeDataConUnique 198 > > +convCallDataConKey = mkPreludeDataConUnique 199 > > + > > ---------------- Template Haskell ------------------- > > -- GHC.Builtin.Names.TH: USES TyConUniques 200-299 > > ----------------------------------------------------- > > diff --git a/compiler/GHC/Builtin/Types.hs > b/compiler/GHC/Builtin/Types.hs > > index d06bc4a12b..1bb6a263c6 100644 > > --- a/compiler/GHC/Builtin/Types.hs > > +++ b/compiler/GHC/Builtin/Types.hs > > @@ -109,6 +109,7 @@ module GHC.Builtin.Types ( > > > > -- * RuntimeRep and friends > > runtimeRepTyCon, vecCountTyCon, vecElemTyCon, > > + runtimeInfoTyCon, rInfo, > > > > runtimeRepTy, liftedRepTy, liftedRepDataCon, > liftedRepDataConTyCon, > > > > @@ -131,6 +132,9 @@ module GHC.Builtin.Types ( > > > > doubleElemRepDataConTy, > > > > + runtimeInfoTy, runtimeInfoDataConTyCon, callingConvTy, > liftedRepEvalTy, > > + convEvalDataConTy, > > + > > -- * Multiplicity and friends > > multiplicityTyConName, oneDataConName, manyDataConName, > multiplicityTy, > > multiplicityTyCon, oneDataCon, manyDataCon, oneDataConTy, > manyDataConTy, > > @@ -189,6 +193,7 @@ import GHC.Utils.Outputable > > import GHC.Utils.Misc > > import GHC.Utils.Panic > > > > +import qualified GHC.Core.TyCo.Rep as TyCoRep (Type(TyConApp)) > > import qualified Data.ByteString.Char8 as BS > > > > import Data.List ( elemIndex ) > > @@ -266,6 +271,8 @@ wiredInTyCons = [ -- Units are not treated like > other tuples, because they > > , multiplicityTyCon > > , naturalTyCon > > , integerTyCon > > + , runtimeInfoTyCon > > + , callingConvTyCon > > ] > > > > mkWiredInTyConName :: BuiltInSyntax -> Module -> FastString -> Unique > -> TyCon -> Name > > @@ -689,7 +696,7 @@ constraintKindTyCon :: TyCon > > constraintKindTyCon = pcTyCon constraintKindTyConName Nothing [] [] > > > > liftedTypeKind, typeToTypeKind, constraintKind :: Kind > > -liftedTypeKind = tYPE liftedRepTy > > +liftedTypeKind = TyCoRep.TyConApp liftedTypeKindTyCon [] > > typeToTypeKind = liftedTypeKind `mkVisFunTyMany` liftedTypeKind > > constraintKind = mkTyConApp constraintKindTyCon [] > > > > @@ -1027,7 +1034,7 @@ cTupleArr = listArray (0,mAX_CTUPLE_SIZE) > [mk_ctuple i | i <- [0..mAX_CTUPLE_SIZ > > -- [IntRep, LiftedRep])@ > > unboxedTupleSumKind :: TyCon -> [Type] -> Kind > > unboxedTupleSumKind tc rr_tys > > - = tYPE (mkTyConApp tc [mkPromotedListTy runtimeRepTy rr_tys]) > > + = tYPE $ mkTyConApp runtimeInfoDataConTyCon [(mkTyConApp tc > [mkPromotedListTy runtimeRepTy rr_tys]), convEvalDataConTy] > > > > -- | Specialization of 'unboxedTupleSumKind' for tuples > > unboxedTupleKind :: [Type] -> Kind > > @@ -1064,7 +1071,7 @@ mk_tuple Unboxed arity = (tycon, tuple_con) > > > > -- See Note [Unboxed tuple RuntimeRep vars] in GHC.Core.TyCon > > -- Kind: forall (k1:RuntimeRep) (k2:RuntimeRep). TYPE k1 -> TYPE > k2 -> # > > - tc_binders = mkTemplateTyConBinders (replicate arity runtimeRepTy) > > + tc_binders = mkTemplateTyConBinders (replicate arity runtimeInfoTy) > > (\ks -> map tYPE ks) > > > > tc_res_kind = unboxedTupleKind rr_tys > > @@ -1388,11 +1395,11 @@ unrestrictedFunTyCon :: TyCon > > unrestrictedFunTyCon = buildSynTyCon unrestrictedFunTyConName [] > arrowKind [] unrestrictedFunTy > > where arrowKind = mkTyConKind binders liftedTypeKind > > -- See also funTyCon > > - binders = [ Bndr runtimeRep1TyVar (NamedTCB Inferred) > > - , Bndr runtimeRep2TyVar (NamedTCB Inferred) > > + binders = [ Bndr runtimeInfo1TyVar (NamedTCB Inferred) > > + , Bndr runtimeInfo2TyVar (NamedTCB Inferred) > > ] > > - ++ mkTemplateAnonTyConBinders [ tYPE runtimeRep1Ty > > - , tYPE runtimeRep2Ty > > + ++ mkTemplateAnonTyConBinders [ tYPE runtimeInfo1Ty > > + , tYPE runtimeInfo2Ty > > ] > > > > unrestrictedFunTyConName :: Name > > @@ -1400,7 +1407,7 @@ unrestrictedFunTyConName = mkWiredInTyConName > BuiltInSyntax gHC_TYPES (fsLit "-> > > > > {- ********************************************************************* > > * * > > - Kinds and RuntimeRep > > + Kinds, RuntimeRep and CallingConv > > * * > > ********************************************************************* -} > > > > @@ -1413,8 +1420,8 @@ runtimeRepTy = mkTyConTy runtimeRepTyCon > > -- type Type = tYPE 'LiftedRep > > liftedTypeKindTyCon :: TyCon > > liftedTypeKindTyCon = buildSynTyCon liftedTypeKindTyConName > > - [] liftedTypeKind [] > > - (tYPE liftedRepTy) > > + [] liftedTypeKind [] rhs > > + where rhs = TyCoRep.TyConApp tYPETyCon [mkTyConApp > runtimeInfoDataConTyCon [liftedRepTy, convEvalDataConTy]] > > > > runtimeRepTyCon :: TyCon > > runtimeRepTyCon = pcTyCon runtimeRepTyConName Nothing [] > > @@ -1425,13 +1432,13 @@ vecRepDataCon :: DataCon > > vecRepDataCon = pcSpecialDataCon vecRepDataConName [ mkTyConTy > vecCountTyCon > > , mkTyConTy > vecElemTyCon ] > > runtimeRepTyCon > > - (RuntimeRep prim_rep_fun) > > + (RuntimeInfo prim_rep_fun) > > where > > -- See Note [Getting from RuntimeRep to PrimRep] in > GHC.Types.RepType > > prim_rep_fun [count, elem] > > | VecCount n <- tyConRuntimeRepInfo (tyConAppTyCon count) > > , VecElem e <- tyConRuntimeRepInfo (tyConAppTyCon elem) > > - = [VecRep n e] > > + = [RInfo [(VecRep n e)] ConvEval] > > prim_rep_fun args > > = pprPanic "vecRepDataCon" (ppr args) > > > > @@ -1440,11 +1447,11 @@ vecRepDataConTyCon = promoteDataCon vecRepDataCon > > > > tupleRepDataCon :: DataCon > > tupleRepDataCon = pcSpecialDataCon tupleRepDataConName [ mkListTy > runtimeRepTy ] > > - runtimeRepTyCon (RuntimeRep > prim_rep_fun) > > + runtimeRepTyCon (RuntimeInfo > prim_rep_fun) > > where > > -- See Note [Getting from RuntimeRep to PrimRep] in > GHC.Types.RepType > > prim_rep_fun [rr_ty_list] > > - = concatMap (runtimeRepPrimRep doc) rr_tys > > + = [RInfo (concatMap (runtimeRepPrimRep doc) rr_tys) ConvEval] > > where > > rr_tys = extractPromotedList rr_ty_list > > doc = text "tupleRepDataCon" <+> ppr rr_tys > > @@ -1456,11 +1463,11 @@ tupleRepDataConTyCon = promoteDataCon > tupleRepDataCon > > > > sumRepDataCon :: DataCon > > sumRepDataCon = pcSpecialDataCon sumRepDataConName [ mkListTy > runtimeRepTy ] > > - runtimeRepTyCon (RuntimeRep > prim_rep_fun) > > + runtimeRepTyCon (RuntimeInfo > prim_rep_fun) > > where > > -- See Note [Getting from RuntimeRep to PrimRep] in > GHC.Types.RepType > > prim_rep_fun [rr_ty_list] > > - = map slotPrimRep (ubxSumRepType prim_repss) > > + = [RInfo (map slotPrimRep (ubxSumRepType prim_repss)) ConvEval] > > where > > rr_tys = extractPromotedList rr_ty_list > > doc = text "sumRepDataCon" <+> ppr rr_tys > > @@ -1488,7 +1495,7 @@ runtimeRepSimpleDataCons@(liftedRepDataCon : _) > > runtimeRepSimpleDataConNames > > where > > mk_runtime_rep_dc primrep name > > - = pcSpecialDataCon name [] runtimeRepTyCon (RuntimeRep (\_ -> > [primrep])) > > + = pcSpecialDataCon name [] runtimeRepTyCon (RuntimeInfo (\_ -> > [RInfo [primrep] ConvEval])) > > > > -- See Note [Wiring in RuntimeRep] > > liftedRepDataConTy, unliftedRepDataConTy, > > @@ -1558,6 +1565,79 @@ liftedRepDataConTyCon = promoteDataCon > liftedRepDataCon > > liftedRepTy :: Type > > liftedRepTy = liftedRepDataConTy > > > > +-- The type ('BoxedRep 'UnliftedRep) > > +unliftedRepTy :: Type > > +unliftedRepTy = unliftedRepDataConTy > > + > > +unliftedRepEvalTy :: Type > > +unliftedRepEvalTy = mkTyConApp runtimeInfoDataConTyCon [unliftedRepTy, > convEvalDataConTy] > > + > > +liftedRepEvalTy :: Type > > +liftedRepEvalTy = mkTyConApp runtimeInfoDataConTyCon [liftedRepTy, > convEvalDataConTy] > > + > > +callingConvTyConName, convEvalDataConName, convCallDataConName :: Name > > +callingConvTyConName = mkWiredInTyConName UserSyntax gHC_TYPES (fsLit > "CallingConv") callingConvTyConKey callingConvTyCon > > +convEvalDataConName = mkWiredInDataConName UserSyntax gHC_TYPES (fsLit > "ConvEval") convEvalDataConKey convEvalDataCon > > +-- convCallDataConName = mkWiredInDataConName UserSyntax gHC_TYPES > (fsLit "ConvCall") convCallDataConKey convCallDataCon > > +convCallDataConName = undefined > > + > > +convEvalDataCon = pcSpecialDataCon convEvalDataConName [] > callingConvTyCon (CallingConvInfo $ \_ -> [ConvEval]) > > + > > +convEvalDataConTyCon :: TyCon > > +convEvalDataConTyCon = promoteDataCon convEvalDataCon > > + > > +convEvalDataConTy :: Type > > +convEvalDataConTy = mkTyConTy convEvalDataConTyCon > > + > > + > > +callingConvTyCon :: TyCon > > +callingConvTyCon = pcTyCon callingConvTyConName Nothing [] > > + [convEvalDataCon] > > + > > +callingConvTy :: Type > > +callingConvTy = mkTyConTy callingConvTyCon > > + > > +{- ********************************************************************* > > +* * > > + RuntimeInfo Types > > +* * > > +********************************************************************* -} > > + > > +runtimeInfoTyConName, runtimeInfoDataConName :: Name > > +runtimeInfoTyConName = mkWiredInTyConName UserSyntax gHC_TYPES (fsLit > "RuntimeInfo") runtimeInfoTyConKey runtimeInfoTyCon > > +runtimeInfoDataConName = mkWiredInDataConName UserSyntax gHC_TYPES > (fsLit "RInfo") runtimeInfoDataConKey runtimeInfoDataCon > > + > > +runtimeInfoTyCon :: TyCon > > +runtimeInfoTyCon = pcTyCon runtimeInfoTyConName Nothing [] > > + [runtimeInfoDataCon] > > + > > +runtimeInfoDataCon :: DataCon > > +runtimeInfoDataCon = pcSpecialDataCon runtimeInfoDataConName [ > runtimeRepTy > > + , mkTyConTy > callingConvTyCon ] > > + runtimeInfoTyCon > > + (RuntimeInfo prim_info_fun) > > + where > > + -- See Note [Getting from RuntimeRep to PrimRep] in > GHC.Types.RepType > > + prim_info_fun tys@[rep, conv] > > + = pprPanic "here runtimeInfoDataCon" (ppr tys) > > + -- [RInfo (runtimeRepPrimRep doc rep) ConvEval] > > + where doc = text "runtimeInfoDataCon" <+> ppr tys > > + prim_info_fun args > > + = pprPanic "runtimeInfoDataCon" (ppr args) > > + > > +runtimeInfoDataConTyCon :: TyCon > > +runtimeInfoDataConTyCon = promoteDataCon runtimeInfoDataCon > > + > > +runtimeInfoDataConTy :: Type > > +runtimeInfoDataConTy = mkTyConTy runtimeInfoDataConTyCon > > + > > +runtimeInfoTy :: Type > > +runtimeInfoTy = mkTyConTy runtimeInfoTyCon > > + > > +rInfo :: Type -> Type -> Type > > +rInfo rep conv = TyCoRep.TyConApp runtimeInfoTyCon [rep, conv] > > + > > + > > {- ********************************************************************* > > * * > > The boxed primitive types: Char, Int, etc > > diff --git a/compiler/GHC/Builtin/Types.hs-boot > b/compiler/GHC/Builtin/Types.hs-boot > > index 000df212c3..fc82f9d7b9 100644 > > --- a/compiler/GHC/Builtin/Types.hs-boot > > +++ b/compiler/GHC/Builtin/Types.hs-boot > > @@ -23,6 +23,13 @@ constraintKind :: Kind > > runtimeRepTyCon, vecCountTyCon, vecElemTyCon :: TyCon > > runtimeRepTy :: Type > > > > + > > +runtimeInfoTy, callingConvTy, convEvalDataConTy :: Type > > + > > +runtimeInfoTyCon, runtimeInfoDataConTyCon :: TyCon > > + > > +rInfo :: Type -> Type -> Type > > + > > liftedRepDataConTyCon, vecRepDataConTyCon, tupleRepDataConTyCon :: TyCon > > > > liftedRepDataConTy, unliftedRepDataConTy, > > diff --git a/compiler/GHC/Builtin/Types/Prim.hs > b/compiler/GHC/Builtin/Types/Prim.hs > > index fc74596e45..5fb750649c 100644 > > --- a/compiler/GHC/Builtin/Types/Prim.hs > > +++ b/compiler/GHC/Builtin/Types/Prim.hs > > @@ -24,6 +24,7 @@ module GHC.Builtin.Types.Prim( > > alphaTyVarsUnliftedRep, alphaTyVarUnliftedRep, > > alphaTysUnliftedRep, alphaTyUnliftedRep, > > runtimeRep1TyVar, runtimeRep2TyVar, runtimeRep1Ty, > runtimeRep2Ty, > > + runtimeInfo1TyVar, runtimeInfo2TyVar, runtimeInfo1Ty, > runtimeInfo2Ty, > > openAlphaTy, openBetaTy, openAlphaTyVar, openBetaTyVar, > > > > multiplicityTyVar, > > @@ -97,6 +98,7 @@ import GHC.Prelude > > > > import {-# SOURCE #-} GHC.Builtin.Types > > ( runtimeRepTy, unboxedTupleKind, liftedTypeKind > > + , runtimeInfoTy, runtimeInfoDataConTyCon, convEvalDataConTy > > , vecRepDataConTyCon, tupleRepDataConTyCon > > , liftedRepDataConTy, unliftedRepDataConTy > > , intRepDataConTy > > @@ -382,11 +384,19 @@ runtimeRep1Ty, runtimeRep2Ty :: Type > > runtimeRep1Ty = mkTyVarTy runtimeRep1TyVar > > runtimeRep2Ty = mkTyVarTy runtimeRep2TyVar > > > > +runtimeInfo1TyVar, runtimeInfo2TyVar :: TyVar > > +(runtimeInfo1TyVar : runtimeInfo2TyVar : _) > > + = drop 16 (mkTemplateTyVars (repeat runtimeInfoTy)) -- selects > 'q','r' > > + > > +runtimeInfo1Ty, runtimeInfo2Ty :: Type > > +runtimeInfo1Ty = mkTyVarTy runtimeInfo1TyVar > > +runtimeInfo2Ty = mkTyVarTy runtimeInfo2TyVar > > + > > openAlphaTyVar, openBetaTyVar :: TyVar > > -- alpha :: TYPE r1 > > -- beta :: TYPE r2 > > [openAlphaTyVar,openBetaTyVar] > > - = mkTemplateTyVars [tYPE runtimeRep1Ty, tYPE runtimeRep2Ty] > > + = mkTemplateTyVars [tYPE runtimeInfo1Ty, tYPE runtimeInfo2Ty] > > > > openAlphaTy, openBetaTy :: Type > > openAlphaTy = mkTyVarTy openAlphaTyVar > > @@ -432,10 +442,10 @@ funTyCon = mkFunTyCon funTyConName tc_bndrs > tc_rep_nm > > where > > -- See also unrestrictedFunTyCon > > tc_bndrs = [ mkNamedTyConBinder Required multiplicityTyVar > > - , mkNamedTyConBinder Inferred runtimeRep1TyVar > > - , mkNamedTyConBinder Inferred runtimeRep2TyVar ] > > - ++ mkTemplateAnonTyConBinders [ tYPE runtimeRep1Ty > > - , tYPE runtimeRep2Ty > > + , mkNamedTyConBinder Inferred runtimeInfo1TyVar > > + , mkNamedTyConBinder Inferred runtimeInfo2TyVar ] > > + ++ mkTemplateAnonTyConBinders [ tYPE runtimeInfo1Ty > > + , tYPE runtimeInfo2Ty > > ] > > tc_rep_nm = mkPrelTyConRepName funTyConName > > > > @@ -529,7 +539,7 @@ tYPETyCon :: TyCon > > tYPETyConName :: Name > > > > tYPETyCon = mkKindTyCon tYPETyConName > > - (mkTemplateAnonTyConBinders [runtimeRepTy]) > > + (mkTemplateAnonTyConBinders [runtimeInfoTy]) > > liftedTypeKind > > [Nominal] > > (mkPrelTyConRepName tYPETyConName) > > @@ -574,7 +584,7 @@ pcPrimTyCon name roles rep > > = mkPrimTyCon name binders result_kind roles > > where > > binders = mkTemplateAnonTyConBinders (map (const > liftedTypeKind) roles) > > - result_kind = tYPE (primRepToRuntimeRep rep) > > + result_kind = tYPE $ TyConApp runtimeInfoDataConTyCon > [(primRepToRuntimeRep rep), convEvalDataConTy] > > > > -- | Convert a 'PrimRep' to a 'Type' of kind RuntimeRep > > -- Defined here to avoid (more) module loops > > diff --git a/compiler/GHC/Core/Make.hs b/compiler/GHC/Core/Make.hs > > index 6d6dd38b29..da285a6455 100644 > > --- a/compiler/GHC/Core/Make.hs > > +++ b/compiler/GHC/Core/Make.hs > > @@ -913,7 +913,7 @@ mkRuntimeErrorId name > > runtimeErrorTy :: Type > > -- forall (rr :: RuntimeRep) (a :: rr). Addr# -> a > > -- See Note [Error and friends have an "open-tyvar" forall] > > -runtimeErrorTy = mkSpecForAllTys [runtimeRep1TyVar, openAlphaTyVar] > > +runtimeErrorTy = mkSpecForAllTys [runtimeInfo1TyVar, openAlphaTyVar] > > (mkVisFunTyMany addrPrimTy openAlphaTy) > > > > {- Note [Error and friends have an "open-tyvar" forall] > > diff --git a/compiler/GHC/Core/TyCon.hs b/compiler/GHC/Core/TyCon.hs > > index 198b66959b..5c59548ebf 100644 > > --- a/compiler/GHC/Core/TyCon.hs > > +++ b/compiler/GHC/Core/TyCon.hs > > @@ -120,6 +120,7 @@ module GHC.Core.TyCon( > > > > -- * Primitive representations of Types > > PrimRep(..), PrimElemRep(..), > > + PrimConv (..), PrimInfo (..), > > isVoidRep, isGcPtrRep, > > primRepSizeB, > > primElemRepSizeB, > > @@ -172,6 +173,10 @@ import GHC.Unit.Module > > > > import qualified Data.Data as Data > > > > +import {-# SOURCE #-} GHC.Core.Type (splitTyConApp_maybe) > > +-- import {-# SOURCE #-} GHC.Builtin.Types.Prim > (mutableByteArrayPrimTyConKey) > > +import GHC.Builtin.Names > > + > > {- > > ----------------------------------------------- > > Notes about type families > > @@ -1073,6 +1078,8 @@ data RuntimeRepInfo > > -- be the list of arguments to the promoted datacon. > > | VecCount Int -- ^ A constructor of @VecCount@ > > | VecElem PrimElemRep -- ^ A constructor of @VecElem@ > > + | RuntimeInfo ([Type] -> [PrimInfo]) > > + | CallingConvInfo ([Type] -> [PrimConv]) > > > > -- | Extract those 'DataCon's that we are able to learn about. Note > > -- that visibility in this sense does not correspond to visibility in > > @@ -1550,6 +1557,26 @@ primRepIsFloat DoubleRep = Just True > > primRepIsFloat (VecRep _ _) = Nothing > > primRepIsFloat _ = Just False > > > > +{- > > +************************************************************************ > > +* * > > + PrimConv > > +* * > > +************************************************************************ > > + > > +Note [PrimConv] > > + > > +A type for representing the calling convention of a type. Either the > arity > > +for extensional functions or the levity for data terms. > > +-} > > + > > +data PrimConv = > > + ConvEval > > + -- | ConvCall [PrimRep] > > + deriving (Show) > > + > > +data PrimInfo = RInfo {reps :: [PrimRep], conv :: PrimConv} > > + > > > > {- > > ************************************************************************ > > @@ -2326,11 +2353,17 @@ expandSynTyCon_maybe > > > > -- ^ Expand a type synonym application, if any > > expandSynTyCon_maybe tc tys > > + -- | SynonymTyCon { tyConTyVars = tvs, synTcRhs = rhs, tyConArity = > arity } <- tc > > + -- , Just (tc' , _) <- splitTyConApp_maybe rhs > > + -- , tc' `hasKey` (mutableByteArrayPrimTyConKey) > > + -- = pprPanic "here" (ppr tc) > > + > > | SynonymTyCon { tyConTyVars = tvs, synTcRhs = rhs, tyConArity = > arity } <- tc > > = case tys `listLengthCmp` arity of > > GT -> Just (tvs `zip` tys, rhs, drop arity tys) > > EQ -> Just (tvs `zip` tys, rhs, []) > > LT -> Nothing > > + > > | otherwise > > = Nothing > > > > diff --git a/compiler/GHC/Core/Type.hs b/compiler/GHC/Core/Type.hs > > index 3164e2626b..5f3ab18925 100644 > > --- a/compiler/GHC/Core/Type.hs > > +++ b/compiler/GHC/Core/Type.hs > > @@ -68,6 +68,7 @@ module GHC.Core.Type ( > > isPredTy, > > > > getRuntimeRep_maybe, kindRep_maybe, kindRep, > > + getRuntimeInfo, getRuntimeInfo_maybe, kindInfo, > > > > mkCastTy, mkCoercionTy, splitCastTy_maybe, > > > > @@ -125,6 +126,7 @@ module GHC.Core.Type ( > > isAlgType, isDataFamilyAppType, > > isPrimitiveType, isStrictType, > > isRuntimeRepTy, isRuntimeRepVar, isRuntimeRepKindedTy, > > + isRuntimeInfoTy, isRuntimeInfoVar, > > dropRuntimeRepArgs, > > getRuntimeRep, > > > > @@ -554,6 +556,11 @@ kindRep k = case kindRep_maybe k of > > Just r -> r > > Nothing -> pprPanic "kindRep" (ppr k) > > > > +kindInfo :: HasDebugCallStack => Kind -> Type > > +kindInfo k = case kindInfo_maybe k of > > + Just r -> r > > + Nothing -> pprPanic "kindInfo" (ppr k) > > + > > -- | Given a kind (TYPE rr), extract its RuntimeRep classifier rr. > > -- For example, @kindRep_maybe * = Just LiftedRep@ > > -- Returns 'Nothing' if the kind is not of form (TYPE rr) > > @@ -561,18 +568,33 @@ kindRep k = case kindRep_maybe k of > > kindRep_maybe :: HasDebugCallStack => Kind -> Maybe Type > > kindRep_maybe kind > > | TyConApp tc [arg] <- coreFullView kind > > - , tc `hasKey` tYPETyConKey = Just arg > > - | otherwise = Nothing > > + , tc `hasKey` tYPETyConKey > > + , TyConApp rinfo [rep, conv] <- coreFullView arg > > + , rinfo `hasKey` runtimeInfoDataConKey = Just rep > > + | TyConApp tc [arg] <- coreFullView kind > > + , tc `hasKey` tYPETyConKey = Just arg > > + | otherwise = Nothing > > + > > +kindInfo_maybe :: HasDebugCallStack => Kind -> Maybe Type > > +kindInfo_maybe kind > > + | TyConApp tc [arg] <- coreFullView kind > > + , tc `hasKey` tYPETyConKey > > + , TyConApp rinfo [rep, conv] <- coreFullView arg > > + , rinfo `hasKey` runtimeInfoDataConKey = Just arg > > + | TyConApp tc [arg] <- coreFullView kind > > + , tc `hasKey` tYPETyConKey = Just arg > > + | otherwise = Nothing > > > > -- | This version considers Constraint to be the same as *. Returns True > > -- if the argument is equivalent to Type/Constraint and False otherwise. > > -- See Note [Kind Constraint and kind Type] > > isLiftedTypeKind :: Kind -> Bool > > isLiftedTypeKind kind > > - = case kindRep_maybe kind of > > - Just rep -> isLiftedRuntimeRep rep > > + = case kindInfo_maybe kind of > > + Just rinfo -> isLiftedRuntimeInfo rinfo > > Nothing -> False > > > > + > > pickyIsLiftedTypeKind :: Kind -> Bool > > -- Checks whether the kind is literally > > -- TYPE LiftedRep > > @@ -599,13 +621,23 @@ isLiftedRuntimeRep rep > > , rr_tc `hasKey` liftedRepDataConKey = ASSERT( null args ) True > > | otherwise = False > > > > +isLiftedRuntimeInfo :: Type -> Bool > > +-- isLiftedRuntimeRep is true of LiftedRep :: RuntimeRep > > +-- False of type variables (a :: RuntimeRep) > > +-- and of other reps e.g. (IntRep :: RuntimeRep) > > +isLiftedRuntimeInfo rep > > + | TyConApp rr_tc [rep,conv] <- coreFullView rep > > + , rr_tc `hasKey` runtimeInfoDataConKey = isLiftedRuntimeRep rep > > + | otherwise > > + = False > > + > > -- | Returns True if the kind classifies unlifted types and False > otherwise. > > -- Note that this returns False for levity-polymorphic kinds, which may > > -- be specialized to a kind that classifies unlifted types. > > isUnliftedTypeKind :: Kind -> Bool > > isUnliftedTypeKind kind > > - = case kindRep_maybe kind of > > - Just rep -> isUnliftedRuntimeRep rep > > + = case kindInfo_maybe kind of > > + Just rep -> isUnliftedRuntimeInfo rep > > Nothing -> False > > > > isUnliftedRuntimeRep :: Type -> Bool > > @@ -622,6 +654,17 @@ isUnliftedRuntimeRep rep > > | otherwise {- Variables, applications -} > > = False > > > > +isUnliftedRuntimeInfo rep > > + | TyConApp rinfo [rep, conv] <- coreFullView rep -- NB: args might > be non-empty > > + , rinfo `hasKey` runtimeInfoDataConKey > > + = isUnliftedRuntimeRep rep > > + -- Avoid searching all the unlifted RuntimeRep type cons > > + -- In the RuntimeRep data type, only LiftedRep is lifted > > + -- But be careful of type families (F tys) :: RuntimeRep > > + | otherwise {- Variables, applications -} > > + = False > > + > > + > > -- | Is this the type 'RuntimeRep'? > > isRuntimeRepTy :: Type -> Bool > > isRuntimeRepTy ty > > @@ -644,6 +687,17 @@ isMultiplicityTy ty > > isMultiplicityVar :: TyVar -> Bool > > isMultiplicityVar = isMultiplicityTy . tyVarKind > > > > +-- | Is this the type 'RuntimeInfo'? > > +isRuntimeInfoTy :: Type -> Bool > > +isRuntimeInfoTy ty > > + | TyConApp tc args <- coreFullView ty > > + , tc `hasKey` runtimeInfoTyConKey = True > > + | otherwise = False > > + > > +-- | Is a tyvar of type 'RuntimeInfo'? > > +isRuntimeInfoVar :: TyVar -> Bool > > +isRuntimeInfoVar = isRuntimeInfoTy . tyVarKind > > + > > {- ********************************************************************* > > * * > > mapType > > @@ -927,8 +981,8 @@ repSplitAppTy_maybe :: HasDebugCallStack => Type -> > Maybe (Type,Type) > > repSplitAppTy_maybe (FunTy _ w ty1 ty2) > > = Just (TyConApp funTyCon [w, rep1, rep2, ty1], ty2) > > where > > - rep1 = getRuntimeRep ty1 > > - rep2 = getRuntimeRep ty2 > > + rep1 = getRuntimeInfo ty1 > > + rep2 = getRuntimeInfo ty2 > > > > repSplitAppTy_maybe (AppTy ty1 ty2) > > = Just (ty1, ty2) > > @@ -2049,6 +2103,10 @@ getRuntimeRep_maybe :: HasDebugCallStack > > => Type -> Maybe Type > > getRuntimeRep_maybe = kindRep_maybe . typeKind > > > > +getRuntimeInfo_maybe :: HasDebugCallStack > > + => Type -> Maybe Type > > +getRuntimeInfo_maybe = kindInfo_maybe . typeKind > > + > > -- | Extract the RuntimeRep classifier of a type. For instance, > > -- @getRuntimeRep_maybe Int = LiftedRep at . Panics if this is not > possible. > > getRuntimeRep :: HasDebugCallStack => Type -> Type > > @@ -2057,6 +2115,12 @@ getRuntimeRep ty > > Just r -> r > > Nothing -> pprPanic "getRuntimeRep" (ppr ty <+> dcolon <+> ppr > (typeKind ty)) > > > > +getRuntimeInfo :: HasDebugCallStack => Type -> Type > > +getRuntimeInfo ty > > + = case getRuntimeInfo_maybe ty of > > + Just r -> r > > + Nothing -> pprPanic "getRuntimeInfo" (ppr ty <+> dcolon <+> ppr > (typeKind ty)) > > + > > isUnboxedTupleType :: Type -> Bool > > isUnboxedTupleType ty > > = tyConAppTyCon (getRuntimeRep ty) `hasKey` tupleRepDataConKey > > @@ -2584,7 +2648,9 @@ tcIsLiftedTypeKind :: Kind -> Bool > > tcIsLiftedTypeKind ty > > | Just (tc, [arg]) <- tcSplitTyConApp_maybe ty -- Note: tcSplit > here > > , tc `hasKey` tYPETyConKey > > - = isLiftedRuntimeRep arg > > + , Just (rinfo, [rep, conv]) <- tcSplitTyConApp_maybe arg > > + , rinfo `hasKey` runtimeInfoDataConKey > > + = isLiftedRuntimeRep rep > > | otherwise > > = False > > > > diff --git a/compiler/GHC/HsToCore.hs b/compiler/GHC/HsToCore.hs > > index 9cf33aa02a..3522ad6fab 100644 > > --- a/compiler/GHC/HsToCore.hs > > +++ b/compiler/GHC/HsToCore.hs > > @@ -714,7 +714,7 @@ mkUnsafeCoercePrimPair _old_id old_expr > > > > ; let [unsafe_refl_data_con] = tyConDataCons unsafe_equality_tc > > > > - rhs = mkLams [ runtimeRep1TyVar, runtimeRep2TyVar > > + rhs = mkLams [ runtimeInfo1TyVar, runtimeInfo2TyVar > > , openAlphaTyVar, openBetaTyVar > > , x ] $ > > mkSingleAltCase scrut1 > > @@ -742,10 +742,10 @@ mkUnsafeCoercePrimPair _old_id old_expr > > -- NB: UnsafeRefl :: (b ~# a) -> UnsafeEquality a b, so we > have to > > -- carefully swap the arguments above > > > > - (scrut1, scrut1_ty, rr_cv_ty) = unsafe_equality > runtimeRepTy > > - > runtimeRep1Ty > > - > runtimeRep2Ty > > - (scrut2, scrut2_ty, ab_cv_ty) = unsafe_equality (tYPE > runtimeRep2Ty) > > + (scrut1, scrut1_ty, rr_cv_ty) = unsafe_equality > runtimeInfoTy > > + > runtimeInfo1Ty > > + > runtimeInfo2Ty > > + (scrut2, scrut2_ty, ab_cv_ty) = unsafe_equality (tYPE > runtimeInfo2Ty) > > > (openAlphaTy `mkCastTy` alpha_co) > > openBetaTy > > > > @@ -761,7 +761,7 @@ mkUnsafeCoercePrimPair _old_id old_expr > > info = noCafIdInfo `setInlinePragInfo` alwaysInlinePragma > > `setUnfoldingInfo` > mkCompulsoryUnfolding' rhs > > > > - ty = mkSpecForAllTys [ runtimeRep1TyVar, runtimeRep2TyVar > > + ty = mkSpecForAllTys [ runtimeInfo1TyVar, runtimeInfo2TyVar > > , openAlphaTyVar, openBetaTyVar ] $ > > mkVisFunTyMany openAlphaTy openBetaTy > > > > diff --git a/compiler/GHC/HsToCore/Utils.hs > b/compiler/GHC/HsToCore/Utils.hs > > index 01085b3270..688d227a6e 100644 > > --- a/compiler/GHC/HsToCore/Utils.hs > > +++ b/compiler/GHC/HsToCore/Utils.hs > > @@ -407,7 +407,7 @@ mkErrorAppDs err_id ty msg = do > > full_msg = showSDoc dflags (hcat [ppr src_loc, vbar, msg]) > > core_msg = Lit (mkLitString full_msg) > > -- mkLitString returns a result of type String# > > - return (mkApps (Var err_id) [Type (getRuntimeRep ty), Type ty, > core_msg]) > > + return (mkApps (Var err_id) [Type (getRuntimeInfo ty), Type ty, > core_msg]) > > > > {- > > 'mkCoreAppDs' and 'mkCoreAppsDs' handle the special-case desugaring of > 'seq'. > > diff --git a/compiler/GHC/IfaceToCore.hs b/compiler/GHC/IfaceToCore.hs > > index de0fa6f023..b6d1281684 100644 > > --- a/compiler/GHC/IfaceToCore.hs > > +++ b/compiler/GHC/IfaceToCore.hs > > @@ -1438,7 +1438,7 @@ tcIfaceExpr (IfaceTuple sort args) > > ; let con_tys = map exprType args' > > some_con_args = map Type con_tys ++ args' > > con_args = case sort of > > - UnboxedTuple -> map (Type . getRuntimeRep) con_tys ++ > some_con_args > > + UnboxedTuple -> map (Type . getRuntimeInfo) con_tys ++ > some_con_args > > _ -> some_con_args > > -- Put the missing type arguments back in > > con_id = dataConWorkId (tyConSingleDataCon tc) > > diff --git a/compiler/GHC/Tc/Gen/HsType.hs > b/compiler/GHC/Tc/Gen/HsType.hs > > index bf4b1c91d1..22283296e1 100644 > > --- a/compiler/GHC/Tc/Gen/HsType.hs > > +++ b/compiler/GHC/Tc/Gen/HsType.hs > > @@ -1331,7 +1331,7 @@ finish_tuple rn_ty tup_sort tau_tys tau_kinds > exp_kind = do > > check_expected_kind (mkTyConApp tycon tau_tys) liftedTypeKind > > UnboxedTuple -> do > > let tycon = tupleTyCon Unboxed arity > > - tau_reps = map kindRep tau_kinds > > + tau_reps = map kindInfo tau_kinds > > -- See also Note [Unboxed tuple RuntimeRep vars] in > GHC.Core.TyCon > > arg_tys = tau_reps ++ tau_tys > > res_kind = unboxedTupleKind tau_reps > > @@ -1340,7 +1340,8 @@ finish_tuple rn_ty tup_sort tau_tys tau_kinds > exp_kind = do > > where > > arity = length tau_tys > > check_expected_kind ty act_kind = > > - checkExpectedKind rn_ty ty act_kind exp_kind > > + pprPanic "here" (ppr exp_kind) > > + -- checkExpectedKind rn_ty ty act_kind exp_kind > > > > {- > > Note [Ignore unary constraint tuples] > > diff --git a/compiler/GHC/Tc/Instance/Typeable.hs > b/compiler/GHC/Tc/Instance/Typeable.hs > > index e4eb7a1b2d..51f0816860 100644 > > --- a/compiler/GHC/Tc/Instance/Typeable.hs > > +++ b/compiler/GHC/Tc/Instance/Typeable.hs > > @@ -28,7 +28,7 @@ import GHC.Builtin.Names > > import GHC.Builtin.Types.Prim ( primTyCons ) > > import GHC.Builtin.Types > > ( tupleTyCon, sumTyCon, runtimeRepTyCon > > - , vecCountTyCon, vecElemTyCon > > + , runtimeInfoTyCon, vecCountTyCon, vecElemTyCon > > , nilDataCon, consDataCon ) > > import GHC.Types.Name > > import GHC.Types.Id > > @@ -564,7 +564,7 @@ mkKindRepRhs stuff@(Stuff {..}) in_scope = > new_kind_rep > > | not (tcIsConstraintKind k) > > -- Typeable respects the Constraint/Type distinction > > -- so do not follow the special case here > > - , Just arg <- kindRep_maybe k > > + , Just arg <- kindInfo_maybe k > > , Just (tc, []) <- splitTyConApp_maybe arg > > , Just dc <- isPromotedDataCon_maybe tc > > = return $ nlHsDataCon kindRepTYPEDataCon `nlHsApp` nlHsDataCon dc > > diff --git a/compiler/GHC/Tc/Solver.hs b/compiler/GHC/Tc/Solver.hs > > index 8b21b72768..ae8609541f 100644 > > --- a/compiler/GHC/Tc/Solver.hs > > +++ b/compiler/GHC/Tc/Solver.hs > > @@ -53,7 +53,7 @@ import GHC.Core.Predicate > > import GHC.Tc.Types.Origin > > import GHC.Tc.Utils.TcType > > import GHC.Core.Type > > -import GHC.Builtin.Types ( liftedRepTy, manyDataConTy ) > > +import GHC.Builtin.Types ( liftedRepEvalTy, manyDataConTy ) > > import GHC.Core.Unify ( tcMatchTyKi ) > > import GHC.Utils.Misc > > import GHC.Utils.Panic > > @@ -2283,13 +2283,13 @@ promoteTyVarTcS tv > > -- | Like 'defaultTyVar', but in the TcS monad. > > defaultTyVarTcS :: TcTyVar -> TcS Bool > > defaultTyVarTcS the_tv > > - | isRuntimeRepVar the_tv > > + | isRuntimeInfoVar the_tv > > , not (isTyVarTyVar the_tv) > > -- TyVarTvs should only be unified with a tyvar > > -- never with a type; c.f. GHC.Tc.Utils.TcMType.defaultTyVar > > -- and Note [Inferring kinds for type declarations] in GHC.Tc.TyCl > > - = do { traceTcS "defaultTyVarTcS RuntimeRep" (ppr the_tv) > > - ; unifyTyVar the_tv liftedRepTy > > + = do { traceTcS "defaultTyVarTcS RuntimeInfo" (ppr the_tv) > > + ; unifyTyVar the_tv liftedRepEvalTy > > ; return True } > > | isMultiplicityVar the_tv > > , not (isTyVarTyVar the_tv) -- TyVarTvs should only be unified with > a tyvar > > diff --git a/compiler/GHC/Tc/TyCl/PatSyn.hs > b/compiler/GHC/Tc/TyCl/PatSyn.hs > > index 3f5b10f343..de9f28fbd9 100644 > > --- a/compiler/GHC/Tc/TyCl/PatSyn.hs > > +++ b/compiler/GHC/Tc/TyCl/PatSyn.hs > > @@ -756,7 +756,7 @@ tcPatSynMatcher (L loc name) lpat > > (args, arg_tys) pat_ty > > = do { rr_name <- newNameAt (mkTyVarOcc "rep") loc > > ; tv_name <- newNameAt (mkTyVarOcc "r") loc > > - ; let rr_tv = mkTyVar rr_name runtimeRepTy > > + ; let rr_tv = mkTyVar rr_name runtimeInfoTy > > rr = mkTyVarTy rr_tv > > res_tv = mkTyVar tv_name (tYPE rr) > > res_ty = mkTyVarTy res_tv > > diff --git a/compiler/GHC/Tc/Utils/TcMType.hs > b/compiler/GHC/Tc/Utils/TcMType.hs > > index ccb9152e01..67295ac3f5 100644 > > --- a/compiler/GHC/Tc/Utils/TcMType.hs > > +++ b/compiler/GHC/Tc/Utils/TcMType.hs > > @@ -492,7 +492,7 @@ inferResultToType (IR { ir_uniq = u, ir_lvl = tc_lvl > > Just ty -> do { ensureMonoType ty > > -- See Note [inferResultToType] > > ; return ty } > > - Nothing -> do { rr <- newMetaTyVarTyAtLevel tc_lvl > runtimeRepTy > > + Nothing -> do { rr <- newMetaTyVarTyAtLevel tc_lvl > runtimeInfoTy > > ; tau <- newMetaTyVarTyAtLevel tc_lvl (tYPE > rr) > > -- See Note [TcLevel of ExpType] > > ; writeMutVar ref (Just tau) > > @@ -667,10 +667,10 @@ promoteTcType dest_lvl ty > > else promote_it } > > where > > promote_it :: TcM (TcCoercion, TcType) > > - promote_it -- Emit a constraint (alpha :: TYPE rr) ~ ty > > + promote_it -- Emit a constraint (alpha :: TYPE ri) ~ ty > > -- where alpha and rr are fresh and from level dest_lvl > > - = do { rr <- newMetaTyVarTyAtLevel dest_lvl runtimeRepTy > > - ; prom_ty <- newMetaTyVarTyAtLevel dest_lvl (tYPE rr) > > + = do { ri <- newMetaTyVarTyAtLevel dest_lvl runtimeInfoTy > > + ; prom_ty <- newMetaTyVarTyAtLevel dest_lvl (tYPE ri) > > ; let eq_orig = TypeEqOrigin { uo_actual = ty > > , uo_expected = prom_ty > > , uo_thing = Nothing > > @@ -1048,7 +1048,7 @@ newFlexiTyVarTys n kind = replicateM n > (newFlexiTyVarTy kind) > > > > newOpenTypeKind :: TcM TcKind > > newOpenTypeKind > > - = do { rr <- newFlexiTyVarTy runtimeRepTy > > + = do { rr <- newFlexiTyVarTy runtimeInfoTy > > ; return (tYPE rr) } > > > > -- | Create a tyvar that can be a lifted or unlifted type. > > @@ -1765,11 +1765,16 @@ defaultTyVar default_kind tv > > -- See Note [Inferring kinds for type declarations] in GHC.Tc.TyCl > > = return False > > > > + | isRuntimeInfoVar tv -- Do not quantify over a RuntimeRep var > > + -- unless it is a TyVarTv, handled earlier > > + = do { traceTc "Defaulting a RuntimeRep var to LiftedRep" (ppr tv) > > + ; writeMetaTyVar tv liftedRepEvalTy > > + ; return True } > > > > | isRuntimeRepVar tv -- Do not quantify over a RuntimeRep var > > -- unless it is a TyVarTv, handled earlier > > = do { traceTc "Defaulting a RuntimeRep var to LiftedRep" (ppr tv) > > - ; writeMetaTyVar tv liftedRepTy > > + ; writeMetaTyVar tv liftedRepEvalTy > > I believe your bug is here. You have filled in a RuntimeRep metavar with > a RuntimeInfo. Leave this as liftedRepTy. > > Cheers, > > - Ben > -- Shant Hairapetian -------------- next part -------------- An HTML attachment was scrubbed... URL: From csaba.hruska at gmail.com Sat Apr 10 10:48:48 2021 From: csaba.hruska at gmail.com (Csaba Hruska) Date: Sat, 10 Apr 2021 12:48:48 +0200 Subject: External STG Interpreter blog post Message-ID: Hello, I've written a blog post about GHC-WPC's external stg interpreter. https://www.patreon.com/posts/external-stg-49857800 Feedback is welcome. Cheers, Csaba -------------- next part -------------- An HTML attachment was scrubbed... URL: From simonpj at microsoft.com Mon Apr 12 08:51:07 2021 From: simonpj at microsoft.com (Simon Peyton Jones) Date: Mon, 12 Apr 2021 08:51:07 +0000 Subject: External STG Interpreter blog post In-Reply-To: References: Message-ID: That's extremely impressive, Csaba. Maybe of interest to folk who have been thinking about "fat interface files". Simon From: ghc-devs On Behalf Of Csaba Hruska Sent: 10 April 2021 11:49 To: GHC developers Subject: External STG Interpreter blog post Hello, I've written a blog post about GHC-WPC's external stg interpreter. https://www.patreon.com/posts/external-stg-49857800 Feedback is welcome. Cheers, Csaba -------------- next part -------------- An HTML attachment was scrubbed... URL: From compl.yue at icloud.com Mon Apr 12 11:34:19 2021 From: compl.yue at icloud.com (YueCompl) Date: Mon, 12 Apr 2021 19:34:19 +0800 Subject: What's the modern way to apply a polymorphic function to a Dynamic value in GHC 8.8 and onwards? Message-ID: <043B9A36-2014-4E02-9951-CBEC216C3CCA@icloud.com> Dear Cafe and GHC devs, There used to be a "principled way with pattern match on the constructor": ```hs data Dynamic where Dynamic :: Typeable a => a -> Dynamic apD :: Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic apD f (Dynamic a) = Dynamic $ f a ``` Source: https://www.reddit.com/r/haskell/comments/2kdcca/q_how_to_apply_a_polymorphic_function_to_a/ But now with GHC 8.8 as in my case, `Dynamic` constructor has changed its signature to: ```hs Dynamic :: forall a. TypeRep a -> a -> Dynamic ``` Which renders the `apD` not working anymore. And it seems missing dependencies now for an older solution Edward KMETT provides: ```hs apD :: forall f. Typeable1 f => (forall a. a -> f a) -> Dynamic -> Dynamic apD f a = dynApp df a where t = dynTypeRep a df = reify (mkFunTy t (typeOf1 (undefined :: f ()) `mkAppTy` t)) $ \(_ :: Proxy s) -> toDyn (WithRep f :: WithRep s (() -> f ())) ``` Source: https://stackoverflow.com/questions/10889682/how-to-apply-a-polymorphic-function-to-a-dynamic-value So, how can I do that nowadays? Thanks, Compl From vladislav at serokell.io Mon Apr 12 13:06:04 2021 From: vladislav at serokell.io (Vladislav Zavialov) Date: Mon, 12 Apr 2021 16:06:04 +0300 Subject: What's the modern way to apply a polymorphic function to a Dynamic value in GHC 8.8 and onwards? In-Reply-To: <043B9A36-2014-4E02-9951-CBEC216C3CCA@icloud.com> References: <043B9A36-2014-4E02-9951-CBEC216C3CCA@icloud.com> Message-ID: <7F106DE5-7E92-4D21-BB0A-E7FC4EEE4484@serokell.io> Would something like this work for you? import Type.Reflection import Data.Dynamic apD :: Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic apD f (Dynamic t a) = withTypeable t $ Dynamic typeRep (f a) - Vlad > On 12 Apr 2021, at 14:34, YueCompl via ghc-devs wrote: > > Dear Cafe and GHC devs, > > > There used to be a "principled way with pattern match on the constructor": > > ```hs > data Dynamic where > Dynamic :: Typeable a => a -> Dynamic > > apD :: Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic > apD f (Dynamic a) = Dynamic $ f a > ``` > Source: https://www.reddit.com/r/haskell/comments/2kdcca/q_how_to_apply_a_polymorphic_function_to_a/ > > > But now with GHC 8.8 as in my case, `Dynamic` constructor has changed its signature to: > > ```hs > Dynamic :: forall a. TypeRep a -> a -> Dynamic > ``` > > Which renders the `apD` not working anymore. > > > And it seems missing dependencies now for an older solution Edward KMETT provides: > > ```hs > apD :: forall f. Typeable1 f => (forall a. a -> f a) -> Dynamic -> Dynamic > apD f a = dynApp df a > where t = dynTypeRep a > df = reify (mkFunTy t (typeOf1 (undefined :: f ()) `mkAppTy` t)) $ > \(_ :: Proxy s) -> toDyn (WithRep f :: WithRep s (() -> f ())) > ``` > Source: https://stackoverflow.com/questions/10889682/how-to-apply-a-polymorphic-function-to-a-dynamic-value > > > So, how can I do that nowadays? > > Thanks, > Compl > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs From compl.yue at icloud.com Mon Apr 12 14:13:46 2021 From: compl.yue at icloud.com (YueCompl) Date: Mon, 12 Apr 2021 22:13:46 +0800 Subject: What's the modern way to apply a polymorphic function to a Dynamic value in GHC 8.8 and onwards? In-Reply-To: <7F106DE5-7E92-4D21-BB0A-E7FC4EEE4484@serokell.io> References: <043B9A36-2014-4E02-9951-CBEC216C3CCA@icloud.com> <7F106DE5-7E92-4D21-BB0A-E7FC4EEE4484@serokell.io> Message-ID: <68E8C92A-9BB2-46FF-8747-C3DD07DA1084@icloud.com> Thanks to Vlad and Jaro, your solution of `apD` compiles, I think it should work. But unfortunately my real case is a little different / more complex, a MWE appears like this: ```hs holdEvent :: Dynamic -> Dynamic holdEvent (Dynamic t evs') = withTypeable t $ Dynamic typeRep (hcHoldEvent evs') where hcHoldEvent :: forall a. EventSink a -> IO (TimeSeries a) hcHoldEvent !evs = do !holder <- newIORef Nothing listenEvents evs $ writeIORef holder . Just return $ TimeSeries $ readIORef holder data EventSink a = EventSink { listenEvents :: (a -> IO ()) -> IO (), closeStream :: IO () } instance Functor EventSink where fmap = undefined newtype TimeSeries a = TimeSeries {readTimeSeries :: IO (Maybe a)} instance Functor TimeSeries where fmap = undefined ``` Now I'm clueless how to use the `withTypeable` trick to apply my polymorphic `hcHoldEvent` to `Dynamic`, naively written as in above, the error is: ```log src/PoC/DynPoly.hs:20:49: error: • Couldn't match expected type ‘EventSink a0’ with actual type ‘a’ ‘a’ is a rigid type variable bound by a pattern with constructor: Dynamic :: forall a. base-4.13.0.0:Data.Typeable.Internal.TypeRep a -> a -> Dynamic, in an equation for ‘holdEvent’ at src/PoC/DynPoly.hs:19:12-25 • In the first argument of ‘hcHoldEvent’, namely ‘evs'’ In the second argument of ‘Dynamic’, namely ‘(hcHoldEvent evs')’ In the second argument of ‘($)’, namely ‘Dynamic typeRep (hcHoldEvent evs')’ • Relevant bindings include evs' :: a (bound at src/PoC/DynPoly.hs:19:22) t :: base-4.13.0.0:Data.Typeable.Internal.TypeRep a (bound at src/PoC/DynPoly.hs:19:20) | 20 | withTypeable t $ Dynamic typeRep (hcHoldEvent evs') | ^^^^ ``` Thanks with best regards, Compl > On 2021-04-12, at 22:04, Jaro Reinders wrote: > > I have no experience in this area, but this compiles: > > ``` > {-# LANGUAGE RankNTypes, ScopedTypeVariables #-} > import Type.Reflection > import Data.Dynamic > > appD :: forall f. Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic > appD f (Dynamic rep (x :: a)) = withTypeable rep (toDyn (f x)) > ``` > > Cheers, > > Jaro > On 2021-04-12, at 21:06, Vladislav Zavialov wrote: > > Would something like this work for you? > > import Type.Reflection > import Data.Dynamic > > apD :: Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic > apD f (Dynamic t a) = withTypeable t $ Dynamic typeRep (f a) > > - Vlad > >> On 12 Apr 2021, at 14:34, YueCompl via ghc-devs wrote: >> >> Dear Cafe and GHC devs, >> >> >> There used to be a "principled way with pattern match on the constructor": >> >> ```hs >> data Dynamic where >> Dynamic :: Typeable a => a -> Dynamic >> >> apD :: Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic >> apD f (Dynamic a) = Dynamic $ f a >> ``` >> Source: https://www.reddit.com/r/haskell/comments/2kdcca/q_how_to_apply_a_polymorphic_function_to_a/ >> >> >> But now with GHC 8.8 as in my case, `Dynamic` constructor has changed its signature to: >> >> ```hs >> Dynamic :: forall a. TypeRep a -> a -> Dynamic >> ``` >> >> Which renders the `apD` not working anymore. >> >> >> And it seems missing dependencies now for an older solution Edward KMETT provides: >> >> ```hs >> apD :: forall f. Typeable1 f => (forall a. a -> f a) -> Dynamic -> Dynamic >> apD f a = dynApp df a >> where t = dynTypeRep a >> df = reify (mkFunTy t (typeOf1 (undefined :: f ()) `mkAppTy` t)) $ >> \(_ :: Proxy s) -> toDyn (WithRep f :: WithRep s (() -> f ())) >> ``` >> Source: https://stackoverflow.com/questions/10889682/how-to-apply-a-polymorphic-function-to-a-dynamic-value >> >> >> So, how can I do that nowadays? >> >> Thanks, >> Compl >> >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hesselink at gmail.com Mon Apr 12 14:50:14 2021 From: hesselink at gmail.com (Erik Hesselink) Date: Mon, 12 Apr 2021 16:50:14 +0200 Subject: What's the modern way to apply a polymorphic function to a Dynamic value in GHC 8.8 and onwards? In-Reply-To: <68E8C92A-9BB2-46FF-8747-C3DD07DA1084@icloud.com> References: <043B9A36-2014-4E02-9951-CBEC216C3CCA@icloud.com> <7F106DE5-7E92-4D21-BB0A-E7FC4EEE4484@serokell.io> <68E8C92A-9BB2-46FF-8747-C3DD07DA1084@icloud.com> Message-ID: Your function is not `forall a. a -> f a`, as in your initial example, but requires its argument to be an `EventSink`. The value you unwrap from the `Dynamic` is any existential type, not necessarily an `EventSink`. You'll have to compare the TypeReps (with something like `eqTypeRep`[1], or wrap your function in a `Dynamic` and use `dynApply` [2], which does the comparison for you. Cheers, Erik [1] https://hackage.haskell.org/package/base-4.15.0.0/docs/Type-Reflection.html#v:eqTypeRep [2] https://hackage.haskell.org/package/base-4.15.0.0/docs/Data-Dynamic.html#v:dynApply On Mon, 12 Apr 2021 at 16:15, YueCompl via ghc-devs wrote: > Thanks to Vlad and Jaro, your solution of `apD` compiles, I think it > should work. > > But unfortunately my real case is a little different / more complex, a MWE > appears like this: > > ```hs > holdEvent :: Dynamic -> Dynamic > holdEvent (Dynamic t evs') = > withTypeable t $ Dynamic typeRep (hcHoldEvent evs') > where > hcHoldEvent :: forall a. EventSink a -> IO (TimeSeries a) > hcHoldEvent !evs = do > !holder <- newIORef Nothing > listenEvents evs $ writeIORef holder . Just > return $ TimeSeries $ readIORef holder > > data EventSink a = EventSink > { listenEvents :: (a -> IO ()) -> IO (), > closeStream :: IO () > } > > instance Functor EventSink where > fmap = undefined > > newtype TimeSeries a = TimeSeries {readTimeSeries :: IO (Maybe a)} > > instance Functor TimeSeries where > fmap = undefined > > ``` > > Now I'm clueless how to use the `withTypeable` trick to apply my > polymorphic `hcHoldEvent` to `Dynamic`, naively written as in above, the > error is: > > ```log > *src/PoC/DynPoly.hs:20:49: **error:* > • Couldn't match expected type ‘EventSink a0’ with actual type ‘a’ > ‘a’ is a rigid type variable bound by > a pattern with constructor: > Dynamic :: forall a. > base-4.13.0.0:Data.Typeable.Internal.TypeRep a -> a > -> Dynamic, > in an equation for ‘holdEvent’ > at src/PoC/DynPoly.hs:19:12-25 > • In the first argument of ‘hcHoldEvent’, namely ‘evs'’ > In the second argument of ‘Dynamic’, namely ‘(hcHoldEvent evs')’ > In the second argument of ‘($)’, namely > ‘Dynamic typeRep (hcHoldEvent evs')’ > • Relevant bindings include > evs' :: a (bound at src/PoC/DynPoly.hs:19:22) > t :: base-4.13.0.0:Data.Typeable.Internal.TypeRep a > (bound at src/PoC/DynPoly.hs:19:20) > * |* > *20 |* withTypeable t $ Dynamic typeRep (hcHoldEvent *evs'*) > * |** ^^^^* > > ``` > > Thanks with best regards, > Compl > > > On 2021-04-12, at 22:04, Jaro Reinders wrote: > > I have no experience in this area, but this compiles: > > ``` > {-# LANGUAGE RankNTypes, ScopedTypeVariables #-} > import Type.Reflection > import Data.Dynamic > > appD :: forall f. Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic > appD f (Dynamic rep (x :: a)) = withTypeable rep (toDyn (f x)) > ``` > > Cheers, > > Jaro > > > > On 2021-04-12, at 21:06, Vladislav Zavialov wrote: > > Would something like this work for you? > > import Type.Reflection > import Data.Dynamic > > apD :: Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic > apD f (Dynamic t a) = withTypeable t $ Dynamic typeRep (f a) > > - Vlad > > On 12 Apr 2021, at 14:34, YueCompl via ghc-devs > wrote: > > Dear Cafe and GHC devs, > > > There used to be a "principled way with pattern match on the constructor": > > ```hs > data Dynamic where > Dynamic :: Typeable a => a -> Dynamic > > apD :: Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic > apD f (Dynamic a) = Dynamic $ f a > ``` > Source: > https://www.reddit.com/r/haskell/comments/2kdcca/q_how_to_apply_a_polymorphic_function_to_a/ > > > But now with GHC 8.8 as in my case, `Dynamic` constructor has changed its > signature to: > > ```hs > Dynamic :: forall a. TypeRep a -> a -> Dynamic > ``` > > Which renders the `apD` not working anymore. > > > And it seems missing dependencies now for an older solution Edward KMETT > provides: > > ```hs > apD :: forall f. Typeable1 f => (forall a. a -> f a) -> Dynamic -> Dynamic > apD f a = dynApp df a > where t = dynTypeRep a > df = reify (mkFunTy t (typeOf1 (undefined :: f ()) `mkAppTy` t)) $ > \(_ :: Proxy s) -> toDyn (WithRep f :: WithRep s (() -> f > ())) > ``` > Source: > https://stackoverflow.com/questions/10889682/how-to-apply-a-polymorphic-function-to-a-dynamic-value > > > So, how can I do that nowadays? > > Thanks, > Compl > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From compl.yue at icloud.com Mon Apr 12 16:27:01 2021 From: compl.yue at icloud.com (YueCompl) Date: Tue, 13 Apr 2021 00:27:01 +0800 Subject: What's the modern way to apply a polymorphic function to a Dynamic value in GHC 8.8 and onwards? In-Reply-To: References: <043B9A36-2014-4E02-9951-CBEC216C3CCA@icloud.com> <7F106DE5-7E92-4D21-BB0A-E7FC4EEE4484@serokell.io> <68E8C92A-9BB2-46FF-8747-C3DD07DA1084@icloud.com> Message-ID: <34A44F73-E4D0-4F1D-BBC1-08A539FAC76A@icloud.com> Thanks Erik, With the help from Iceland_jack via /r/haskell , I end up with a working solution like this: ```hs data TypeableInstance a where -- data TypeableInstance :: forall k. k -> Type where TypeableInstance :: Typeable a => TypeableInstance a typeableInstance :: forall (k :: Type) (a :: k). TypeRep a -> TypeableInstance a typeableInstance typeRep' = withTypeable typeRep' TypeableInstance pattern TypeRep :: forall k (a :: k). () => Typeable a => TypeRep a pattern TypeRep <- (typeableInstance -> TypeableInstance) where TypeRep = typeRep holdEvent :: Dynamic -> Dynamic holdEvent !devs = case devs of Dynamic (App eventSink TypeRep) evs' -> case eqTypeRep (typeRep @EventSink) eventSink of Just HRefl -> Dynamic TypeRep (hcHoldEvent evs') Nothing -> error "not an EventSink" -- to be handled properly _ -> error "even not a poly-type" -- to be handled properly where hcHoldEvent :: forall a. EventSink a -> IO (TimeSeries a) hcHoldEvent !evs = do !holder <- newIORef Nothing listenEvents evs $ writeIORef holder . Just return $ TimeSeries $ readIORef holder data EventSink a = EventSink { listenEvents :: (a -> IO ()) -> IO (), closeStream :: IO () } instance Functor EventSink where fmap = undefined newtype TimeSeries a = TimeSeries {readTimeSeries :: IO (Maybe a)} instance Functor TimeSeries where fmap = undefined ``` I'm still wrapping my head around it, for how the `pattern TypeRep` works in this case. Or you think there exists a solution without using such a pattern? My function (hcHoldEvent) is polymorphic so not eligible to be wrapped as a Dynamic in the first place, or there also some way to specialize it at runtime? That'll be another interesting tool. Thanks with regards, Compl > On 2021-04-12, at 22:50, Erik Hesselink wrote: > > Your function is not `forall a. a -> f a`, as in your initial example, but requires its argument to be an `EventSink`. The value you unwrap from the `Dynamic` is any existential type, not necessarily an `EventSink`. You'll have to compare the TypeReps (with something like `eqTypeRep`[1], or wrap your function in a `Dynamic` and use `dynApply` [2], which does the comparison for you. > > Cheers, > > Erik > > [1] https://hackage.haskell.org/package/base-4.15.0.0/docs/Type-Reflection.html#v:eqTypeRep > [2] https://hackage.haskell.org/package/base-4.15.0.0/docs/Data-Dynamic.html#v:dynApply > On Mon, 12 Apr 2021 at 16:15, YueCompl via ghc-devs > wrote: > Thanks to Vlad and Jaro, your solution of `apD` compiles, I think it should work. > > But unfortunately my real case is a little different / more complex, a MWE appears like this: > > ```hs > holdEvent :: Dynamic -> Dynamic > holdEvent (Dynamic t evs') = > withTypeable t $ Dynamic typeRep (hcHoldEvent evs') > where > hcHoldEvent :: forall a. EventSink a -> IO (TimeSeries a) > hcHoldEvent !evs = do > !holder <- newIORef Nothing > listenEvents evs $ writeIORef holder . Just > return $ TimeSeries $ readIORef holder > > data EventSink a = EventSink > { listenEvents :: (a -> IO ()) -> IO (), > closeStream :: IO () > } > > instance Functor EventSink where > fmap = undefined > > newtype TimeSeries a = TimeSeries {readTimeSeries :: IO (Maybe a)} > > instance Functor TimeSeries where > fmap = undefined > > ``` > > Now I'm clueless how to use the `withTypeable` trick to apply my polymorphic `hcHoldEvent` to `Dynamic`, naively written as in above, the error is: > > ```log > src/PoC/DynPoly.hs:20:49: error: > • Couldn't match expected type ‘EventSink a0’ with actual type ‘a’ > ‘a’ is a rigid type variable bound by > a pattern with constructor: > Dynamic :: forall a. > base-4.13.0.0:Data.Typeable.Internal.TypeRep a -> a -> Dynamic, > in an equation for ‘holdEvent’ > at src/PoC/DynPoly.hs:19:12-25 > • In the first argument of ‘hcHoldEvent’, namely ‘evs'’ > In the second argument of ‘Dynamic’, namely ‘(hcHoldEvent evs')’ > In the second argument of ‘($)’, namely > ‘Dynamic typeRep (hcHoldEvent evs')’ > • Relevant bindings include > evs' :: a (bound at src/PoC/DynPoly.hs:19:22) > t :: base-4.13.0.0:Data.Typeable.Internal.TypeRep a > (bound at src/PoC/DynPoly.hs:19:20) > | > 20 | withTypeable t $ Dynamic typeRep (hcHoldEvent evs') > | ^^^^ > > ``` > > Thanks with best regards, > Compl > > >> On 2021-04-12, at 22:04, Jaro Reinders > wrote: >> >> I have no experience in this area, but this compiles: >> >> ``` >> {-# LANGUAGE RankNTypes, ScopedTypeVariables #-} >> import Type.Reflection >> import Data.Dynamic >> >> appD :: forall f. Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic >> appD f (Dynamic rep (x :: a)) = withTypeable rep (toDyn (f x)) >> ``` >> >> Cheers, >> >> Jaro > > >> On 2021-04-12, at 21:06, Vladislav Zavialov > wrote: >> >> Would something like this work for you? >> >> import Type.Reflection >> import Data.Dynamic >> >> apD :: Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic >> apD f (Dynamic t a) = withTypeable t $ Dynamic typeRep (f a) >> >> - Vlad >> >>> On 12 Apr 2021, at 14:34, YueCompl via ghc-devs > wrote: >>> >>> Dear Cafe and GHC devs, >>> >>> >>> There used to be a "principled way with pattern match on the constructor": >>> >>> ```hs >>> data Dynamic where >>> Dynamic :: Typeable a => a -> Dynamic >>> >>> apD :: Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic >>> apD f (Dynamic a) = Dynamic $ f a >>> ``` >>> Source: https://www.reddit.com/r/haskell/comments/2kdcca/q_how_to_apply_a_polymorphic_function_to_a/ >>> >>> >>> But now with GHC 8.8 as in my case, `Dynamic` constructor has changed its signature to: >>> >>> ```hs >>> Dynamic :: forall a. TypeRep a -> a -> Dynamic >>> ``` >>> >>> Which renders the `apD` not working anymore. >>> >>> >>> And it seems missing dependencies now for an older solution Edward KMETT provides: >>> >>> ```hs >>> apD :: forall f. Typeable1 f => (forall a. a -> f a) -> Dynamic -> Dynamic >>> apD f a = dynApp df a >>> where t = dynTypeRep a >>> df = reify (mkFunTy t (typeOf1 (undefined :: f ()) `mkAppTy` t)) $ >>> \(_ :: Proxy s) -> toDyn (WithRep f :: WithRep s (() -> f ())) >>> ``` >>> Source: https://stackoverflow.com/questions/10889682/how-to-apply-a-polymorphic-function-to-a-dynamic-value >>> >>> >>> So, how can I do that nowadays? >>> >>> Thanks, >>> Compl >>> >>> _______________________________________________ >>> ghc-devs mailing list >>> ghc-devs at haskell.org >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs -------------- next part -------------- An HTML attachment was scrubbed... URL: From compl.yue at icloud.com Mon Apr 12 16:58:03 2021 From: compl.yue at icloud.com (YueCompl) Date: Tue, 13 Apr 2021 00:58:03 +0800 Subject: What's the modern way to apply a polymorphic function to a Dynamic value in GHC 8.8 and onwards? In-Reply-To: <34A44F73-E4D0-4F1D-BBC1-08A539FAC76A@icloud.com> References: <043B9A36-2014-4E02-9951-CBEC216C3CCA@icloud.com> <7F106DE5-7E92-4D21-BB0A-E7FC4EEE4484@serokell.io> <68E8C92A-9BB2-46FF-8747-C3DD07DA1084@icloud.com> <34A44F73-E4D0-4F1D-BBC1-08A539FAC76A@icloud.com> Message-ID: <15DE054A-5B61-4011-8D1D-9C344072F964@icloud.com> Oh, forgot to mention that there is a warning I also don't understand by far: ```log src/PoC/DynPoly.hs:40:3: warning: [-Woverlapping-patterns] Pattern match has inaccessible right hand side In a case alternative: Dynamic (App eventSink TypeRep) evs' -> ... | 40 | Dynamic (App eventSink TypeRep) evs' -> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... ``` I need to work out some extra stuff to test the solution in real case, meanwhile this warning seems worrying ... > On 2021-04-13, at 00:27, YueCompl via ghc-devs wrote: > > Thanks Erik, > > With the help from Iceland_jack via /r/haskell , I end up with a working solution like this: > > ```hs > data TypeableInstance a where > -- data TypeableInstance :: forall k. k -> Type where > TypeableInstance :: Typeable a => TypeableInstance a > > typeableInstance :: forall (k :: Type) (a :: k). TypeRep a -> TypeableInstance a > typeableInstance typeRep' = withTypeable typeRep' TypeableInstance > > pattern TypeRep :: forall k (a :: k). () => Typeable a => TypeRep a > pattern TypeRep <- > (typeableInstance -> TypeableInstance) > where > TypeRep = typeRep > > holdEvent :: Dynamic -> Dynamic > holdEvent !devs = case devs of > Dynamic (App eventSink TypeRep) evs' -> > case eqTypeRep (typeRep @EventSink) eventSink of > Just HRefl -> Dynamic TypeRep (hcHoldEvent evs') > Nothing -> error "not an EventSink" -- to be handled properly > _ -> error "even not a poly-type" -- to be handled properly > where > hcHoldEvent :: forall a. EventSink a -> IO (TimeSeries a) > hcHoldEvent !evs = do > !holder <- newIORef Nothing > listenEvents evs $ writeIORef holder . Just > return $ TimeSeries $ readIORef holder > > data EventSink a = EventSink > { listenEvents :: (a -> IO ()) -> IO (), > closeStream :: IO () > } > > instance Functor EventSink where > fmap = undefined > > newtype TimeSeries a = TimeSeries {readTimeSeries :: IO (Maybe a)} > > instance Functor TimeSeries where > fmap = undefined > > ``` > > I'm still wrapping my head around it, for how the `pattern TypeRep` works in this case. > > Or you think there exists a solution without using such a pattern? > > My function (hcHoldEvent) is polymorphic so not eligible to be wrapped as a Dynamic in the first place, or there also some way to specialize it at runtime? That'll be another interesting tool. > > Thanks with regards, > Compl > >> On 2021-04-12, at 22:50, Erik Hesselink > wrote: >> >> Your function is not `forall a. a -> f a`, as in your initial example, but requires its argument to be an `EventSink`. The value you unwrap from the `Dynamic` is any existential type, not necessarily an `EventSink`. You'll have to compare the TypeReps (with something like `eqTypeRep`[1], or wrap your function in a `Dynamic` and use `dynApply` [2], which does the comparison for you. >> >> Cheers, >> >> Erik >> >> [1] https://hackage.haskell.org/package/base-4.15.0.0/docs/Type-Reflection.html#v:eqTypeRep >> [2] https://hackage.haskell.org/package/base-4.15.0.0/docs/Data-Dynamic.html#v:dynApply >> On Mon, 12 Apr 2021 at 16:15, YueCompl via ghc-devs > wrote: >> Thanks to Vlad and Jaro, your solution of `apD` compiles, I think it should work. >> >> But unfortunately my real case is a little different / more complex, a MWE appears like this: >> >> ```hs >> holdEvent :: Dynamic -> Dynamic >> holdEvent (Dynamic t evs') = >> withTypeable t $ Dynamic typeRep (hcHoldEvent evs') >> where >> hcHoldEvent :: forall a. EventSink a -> IO (TimeSeries a) >> hcHoldEvent !evs = do >> !holder <- newIORef Nothing >> listenEvents evs $ writeIORef holder . Just >> return $ TimeSeries $ readIORef holder >> >> data EventSink a = EventSink >> { listenEvents :: (a -> IO ()) -> IO (), >> closeStream :: IO () >> } >> >> instance Functor EventSink where >> fmap = undefined >> >> newtype TimeSeries a = TimeSeries {readTimeSeries :: IO (Maybe a)} >> >> instance Functor TimeSeries where >> fmap = undefined >> >> ``` >> >> Now I'm clueless how to use the `withTypeable` trick to apply my polymorphic `hcHoldEvent` to `Dynamic`, naively written as in above, the error is: >> >> ```log >> src/PoC/DynPoly.hs:20:49: error: >> • Couldn't match expected type ‘EventSink a0’ with actual type ‘a’ >> ‘a’ is a rigid type variable bound by >> a pattern with constructor: >> Dynamic :: forall a. >> base-4.13.0.0:Data.Typeable.Internal.TypeRep a -> a -> Dynamic, >> in an equation for ‘holdEvent’ >> at src/PoC/DynPoly.hs:19:12-25 >> • In the first argument of ‘hcHoldEvent’, namely ‘evs'’ >> In the second argument of ‘Dynamic’, namely ‘(hcHoldEvent evs')’ >> In the second argument of ‘($)’, namely >> ‘Dynamic typeRep (hcHoldEvent evs')’ >> • Relevant bindings include >> evs' :: a (bound at src/PoC/DynPoly.hs:19:22) >> t :: base-4.13.0.0:Data.Typeable.Internal.TypeRep a >> (bound at src/PoC/DynPoly.hs:19:20) >> | >> 20 | withTypeable t $ Dynamic typeRep (hcHoldEvent evs') >> | ^^^^ >> >> ``` >> >> Thanks with best regards, >> Compl >> >> >>> On 2021-04-12, at 22:04, Jaro Reinders > wrote: >>> >>> I have no experience in this area, but this compiles: >>> >>> ``` >>> {-# LANGUAGE RankNTypes, ScopedTypeVariables #-} >>> import Type.Reflection >>> import Data.Dynamic >>> >>> appD :: forall f. Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic >>> appD f (Dynamic rep (x :: a)) = withTypeable rep (toDyn (f x)) >>> ``` >>> >>> Cheers, >>> >>> Jaro >> >> >>> On 2021-04-12, at 21:06, Vladislav Zavialov > wrote: >>> >>> Would something like this work for you? >>> >>> import Type.Reflection >>> import Data.Dynamic >>> >>> apD :: Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic >>> apD f (Dynamic t a) = withTypeable t $ Dynamic typeRep (f a) >>> >>> - Vlad >>> >>>> On 12 Apr 2021, at 14:34, YueCompl via ghc-devs > wrote: >>>> >>>> Dear Cafe and GHC devs, >>>> >>>> >>>> There used to be a "principled way with pattern match on the constructor": >>>> >>>> ```hs >>>> data Dynamic where >>>> Dynamic :: Typeable a => a -> Dynamic >>>> >>>> apD :: Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic >>>> apD f (Dynamic a) = Dynamic $ f a >>>> ``` >>>> Source: https://www.reddit.com/r/haskell/comments/2kdcca/q_how_to_apply_a_polymorphic_function_to_a/ >>>> >>>> >>>> But now with GHC 8.8 as in my case, `Dynamic` constructor has changed its signature to: >>>> >>>> ```hs >>>> Dynamic :: forall a. TypeRep a -> a -> Dynamic >>>> ``` >>>> >>>> Which renders the `apD` not working anymore. >>>> >>>> >>>> And it seems missing dependencies now for an older solution Edward KMETT provides: >>>> >>>> ```hs >>>> apD :: forall f. Typeable1 f => (forall a. a -> f a) -> Dynamic -> Dynamic >>>> apD f a = dynApp df a >>>> where t = dynTypeRep a >>>> df = reify (mkFunTy t (typeOf1 (undefined :: f ()) `mkAppTy` t)) $ >>>> \(_ :: Proxy s) -> toDyn (WithRep f :: WithRep s (() -> f ())) >>>> ``` >>>> Source: https://stackoverflow.com/questions/10889682/how-to-apply-a-polymorphic-function-to-a-dynamic-value >>>> >>>> >>>> So, how can I do that nowadays? >>>> >>>> Thanks, >>>> Compl >>>> >>>> _______________________________________________ >>>> ghc-devs mailing list >>>> ghc-devs at haskell.org >>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >>> >> >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs -------------- next part -------------- An HTML attachment was scrubbed... URL: From john.ericson at obsidian.systems Mon Apr 12 17:57:12 2021 From: john.ericson at obsidian.systems (John Ericson) Date: Mon, 12 Apr 2021 13:57:12 -0400 Subject: External STG Interpreter blog post In-Reply-To: References: Message-ID: Indeed it is! I also am very much hoping this can be the missing piece we need to allow Template Haskell to work with a stage 0 GHC, so that we can safely use TH in GHC itself even when the ABI is changing. See https://github.com/ghc-proposals/ghc-proposals/issues/162 for details, where I've also linked Csaba's blog post. (And maybe also https://gitlab.haskell.org/ghc/ghc/-/wikis/cross-compilation/roadmap for more background, and related things like https://github.com/ghc-proposals/ghc-proposals/pull/412.) TH could perhaps be used to replace some of the ad-hoc code gen we have for e.g. RTS constants and primops. This in turn would simplify the build system, allowing for `cabal install ghc` to work without shipping generated Haskell code in the sdist. John On 4/12/21 4:51 AM, Simon Peyton Jones via ghc-devs wrote: > > That’s extremely impressive, Csaba. > > Maybe of interest to folk who have been thinking about “fat interface > files”. > > > Simon > > *From:*ghc-devs *On Behalf Of *Csaba Hruska > *Sent:* 10 April 2021 11:49 > *To:* GHC developers > *Subject:* External STG Interpreter blog post > > Hello, > > I've written a blog post about GHC-WPC's external stg interpreter. > https://www.patreon.com/posts/external-stg-49857800 > > > Feedback is welcome. > > Cheers, > > Csaba > > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs -------------- next part -------------- An HTML attachment was scrubbed... URL: From hesselink at gmail.com Mon Apr 12 18:50:11 2021 From: hesselink at gmail.com (Erik Hesselink) Date: Mon, 12 Apr 2021 20:50:11 +0200 Subject: What's the modern way to apply a polymorphic function to a Dynamic value in GHC 8.8 and onwards? In-Reply-To: <15DE054A-5B61-4011-8D1D-9C344072F964@icloud.com> References: <043B9A36-2014-4E02-9951-CBEC216C3CCA@icloud.com> <7F106DE5-7E92-4D21-BB0A-E7FC4EEE4484@serokell.io> <68E8C92A-9BB2-46FF-8747-C3DD07DA1084@icloud.com> <34A44F73-E4D0-4F1D-BBC1-08A539FAC76A@icloud.com> <15DE054A-5B61-4011-8D1D-9C344072F964@icloud.com> Message-ID: That is a lot, I'm not sure I understand that pattern synonym. Using `withTypeable` instead works for me: holdEvent :: Dynamic -> Dynamic holdEvent (Dynamic tr x) = case tr of App ft at -> case ft `eqTypeRep` typeRep @EventSink of Just HRefl -> withTypeable at $ toDyn (hcHoldEvent x) Nothing -> error "to handle" _ -> error "to handle" Cheers, Erik On Mon, 12 Apr 2021 at 18:58, YueCompl wrote: > Oh, forgot to mention that there is a warning I also don't understand by > far: > > ```log > *src/PoC/DynPoly.hs:40:3: **warning:** [**-Woverlapping-patterns**]* > Pattern match has inaccessible right hand side > In a case alternative: Dynamic (App eventSink TypeRep) evs' -> ... > * |* > *40 |* *Dynamic (App eventSink TypeRep) evs' ->* > * |** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...* > ``` > I need to work out some extra stuff to test the solution in real case, > meanwhile this warning seems worrying ... > > On 2021-04-13, at 00:27, YueCompl via ghc-devs > wrote: > > Thanks Erik, > > With the help from Iceland_jack > via /r/haskell , I end up with a > working solution like this: > > ```hs > data TypeableInstance a where > -- data TypeableInstance :: forall k. k -> Type where > TypeableInstance :: Typeable a => TypeableInstance a > > typeableInstance :: forall (k :: Type) (a :: k). TypeRep a -> > TypeableInstance a > typeableInstance typeRep' = withTypeable typeRep' TypeableInstance > > pattern TypeRep :: forall k (a :: k). () => Typeable a => TypeRep a > pattern TypeRep <- > (typeableInstance -> TypeableInstance) > where > TypeRep = typeRep > > holdEvent :: Dynamic -> Dynamic > holdEvent !devs = case devs of > Dynamic (App eventSink TypeRep) evs' -> > case eqTypeRep (typeRep @EventSink) eventSink of > Just HRefl -> Dynamic TypeRep (hcHoldEvent evs') > Nothing -> error "not an EventSink" -- to be handled properly > _ -> error "even not a poly-type" -- to be handled properly > where > hcHoldEvent :: forall a. EventSink a -> IO (TimeSeries a) > hcHoldEvent !evs = do > !holder <- newIORef Nothing > listenEvents evs $ writeIORef holder . Just > return $ TimeSeries $ readIORef holder > > data EventSink a = EventSink > { listenEvents :: (a -> IO ()) -> IO (), > closeStream :: IO () > } > > instance Functor EventSink where > fmap = undefined > > newtype TimeSeries a = TimeSeries {readTimeSeries :: IO (Maybe a)} > > instance Functor TimeSeries where > fmap = undefined > > ``` > > I'm still wrapping my head around it, for how the `pattern TypeRep` works > in this case. > > Or you think there exists a solution without using such a pattern? > > My function (hcHoldEvent) is polymorphic so not eligible to be wrapped as > a Dynamic in the first place, or there also some way to specialize it at > runtime? That'll be another interesting tool. > > Thanks with regards, > Compl > > On 2021-04-12, at 22:50, Erik Hesselink wrote: > > Your function is not `forall a. a -> f a`, as in your initial example, but > requires its argument to be an `EventSink`. The value you unwrap from the > `Dynamic` is any existential type, not necessarily an `EventSink`. You'll > have to compare the TypeReps (with something like `eqTypeRep`[1], or wrap > your function in a `Dynamic` and use `dynApply` [2], which does the > comparison for you. > > Cheers, > > Erik > > [1] > https://hackage.haskell.org/package/base-4.15.0.0/docs/Type-Reflection.html#v:eqTypeRep > [2] > https://hackage.haskell.org/package/base-4.15.0.0/docs/Data-Dynamic.html#v:dynApply > > On Mon, 12 Apr 2021 at 16:15, YueCompl via ghc-devs > wrote: > >> Thanks to Vlad and Jaro, your solution of `apD` compiles, I think it >> should work. >> >> But unfortunately my real case is a little different / more complex, a >> MWE appears like this: >> >> ```hs >> holdEvent :: Dynamic -> Dynamic >> holdEvent (Dynamic t evs') = >> withTypeable t $ Dynamic typeRep (hcHoldEvent evs') >> where >> hcHoldEvent :: forall a. EventSink a -> IO (TimeSeries a) >> hcHoldEvent !evs = do >> !holder <- newIORef Nothing >> listenEvents evs $ writeIORef holder . Just >> return $ TimeSeries $ readIORef holder >> >> data EventSink a = EventSink >> { listenEvents :: (a -> IO ()) -> IO (), >> closeStream :: IO () >> } >> >> instance Functor EventSink where >> fmap = undefined >> >> newtype TimeSeries a = TimeSeries {readTimeSeries :: IO (Maybe a)} >> >> instance Functor TimeSeries where >> fmap = undefined >> >> ``` >> >> Now I'm clueless how to use the `withTypeable` trick to apply my >> polymorphic `hcHoldEvent` to `Dynamic`, naively written as in above, the >> error is: >> >> ```log >> *src/PoC/DynPoly.hs:20:49: **error:* >> • Couldn't match expected type ‘EventSink a0’ with actual type ‘a’ >> ‘a’ is a rigid type variable bound by >> a pattern with constructor: >> Dynamic :: forall a. >> base-4.13.0.0:Data.Typeable.Internal.TypeRep a -> a >> -> Dynamic, >> in an equation for ‘holdEvent’ >> at src/PoC/DynPoly.hs:19:12-25 >> • In the first argument of ‘hcHoldEvent’, namely ‘evs'’ >> In the second argument of ‘Dynamic’, namely ‘(hcHoldEvent evs')’ >> In the second argument of ‘($)’, namely >> ‘Dynamic typeRep (hcHoldEvent evs')’ >> • Relevant bindings include >> evs' :: a (bound at src/PoC/DynPoly.hs:19:22) >> t :: base-4.13.0.0:Data.Typeable.Internal.TypeRep a >> (bound at src/PoC/DynPoly.hs:19:20) >> * |* >> *20 |* withTypeable t $ Dynamic typeRep (hcHoldEvent *evs'*) >> * |** ^^^^* >> >> ``` >> >> Thanks with best regards, >> Compl >> >> >> On 2021-04-12, at 22:04, Jaro Reinders wrote: >> >> I have no experience in this area, but this compiles: >> >> ``` >> {-# LANGUAGE RankNTypes, ScopedTypeVariables #-} >> import Type.Reflection >> import Data.Dynamic >> >> appD :: forall f. Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic >> appD f (Dynamic rep (x :: a)) = withTypeable rep (toDyn (f x)) >> ``` >> >> Cheers, >> >> Jaro >> >> >> >> On 2021-04-12, at 21:06, Vladislav Zavialov >> wrote: >> >> Would something like this work for you? >> >> import Type.Reflection >> import Data.Dynamic >> >> apD :: Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic >> apD f (Dynamic t a) = withTypeable t $ Dynamic typeRep (f a) >> >> - Vlad >> >> On 12 Apr 2021, at 14:34, YueCompl via ghc-devs >> wrote: >> >> Dear Cafe and GHC devs, >> >> >> There used to be a "principled way with pattern match on the constructor": >> >> ```hs >> data Dynamic where >> Dynamic :: Typeable a => a -> Dynamic >> >> apD :: Typeable f => (forall a. a -> f a) -> Dynamic -> Dynamic >> apD f (Dynamic a) = Dynamic $ f a >> ``` >> Source: >> https://www.reddit.com/r/haskell/comments/2kdcca/q_how_to_apply_a_polymorphic_function_to_a/ >> >> >> But now with GHC 8.8 as in my case, `Dynamic` constructor has changed its >> signature to: >> >> ```hs >> Dynamic :: forall a. TypeRep a -> a -> Dynamic >> ``` >> >> Which renders the `apD` not working anymore. >> >> >> And it seems missing dependencies now for an older solution Edward KMETT >> provides: >> >> ```hs >> apD :: forall f. Typeable1 f => (forall a. a -> f a) -> Dynamic -> Dynamic >> apD f a = dynApp df a >> where t = dynTypeRep a >> df = reify (mkFunTy t (typeOf1 (undefined :: f ()) `mkAppTy` t)) $ >> \(_ :: Proxy s) -> toDyn (WithRep f :: WithRep s (() -> f >> ())) >> ``` >> Source: >> https://stackoverflow.com/questions/10889682/how-to-apply-a-polymorphic-function-to-a-dynamic-value >> >> >> So, how can I do that nowadays? >> >> Thanks, >> Compl >> >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> >> >> >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From compl.yue at icloud.com Tue Apr 13 14:07:32 2021 From: compl.yue at icloud.com (YueCompl) Date: Tue, 13 Apr 2021 22:07:32 +0800 Subject: What's the modern way to apply a polymorphic function to a Dynamic value in GHC 8.8 and onwards? In-Reply-To: References: <043B9A36-2014-4E02-9951-CBEC216C3CCA@icloud.com> <7F106DE5-7E92-4D21-BB0A-E7FC4EEE4484@serokell.io> <68E8C92A-9BB2-46FF-8747-C3DD07DA1084@icloud.com> <34A44F73-E4D0-4F1D-BBC1-08A539FAC76A@icloud.com> <15DE054A-5B61-4011-8D1D-9C344072F964@icloud.com> Message-ID: After struggled this far, I decide that I can neither trivially understand `pattern TypeRep`, nor the `withTypeable` at core. But this is what really amazing with Haskell, GHC and the community here - I can get my job done even without full understanding of what's going on under the hood, so long as the compiler says it's okay! The warning has gone due to unknown reason after I refactored the code a bit, surprisingly but well, I feel safe and comfort to use it now. Thanks to Erik, Vlad and Jaro again for your help. u/Iceland_jack made a ticket to [add pattern TypeRep to Type.Reflection](https://gitlab.haskell.org/ghc/ghc/-/issues/19691) and appears it's very welcomed. Though I don't expect it get shipped very soon or even could be back ported to GHC 8.8, so I end up with this shim: (there `PolyKinds` appears some unusual to be put into my `.cabal` due to its syntax change can break some of my existing code) ```hs {-# LANGUAGE PolyKinds #-} module Dyn.Shim ( pattern TypeRep, dynPerformIO, dynPerformSTM, dynContSTM, ) where import Control.Concurrent.STM (STM) import Data.Dynamic (Dynamic (..), Typeable) import Type.Reflection ( TypeRep, eqTypeRep, typeRep, withTypeable, pattern App, type (:~~:) (HRefl), ) import Prelude data TypeableInstance a where TypeableInstance :: Typeable a => TypeableInstance a typeableInstance :: TypeRep a -> TypeableInstance a typeableInstance tr = withTypeable tr TypeableInstance {- ORMOLU_DISABLE -} -- | Shim for the proposed one at: -- https://gitlab.haskell.org/ghc/ghc/-/issues/19691 pattern TypeRep :: forall k (a :: k). () => Typeable a => TypeRep a pattern TypeRep <- (typeableInstance -> TypeableInstance) where TypeRep = typeRep {- ORMOLU_ENABLE -} -- | Perform a polymorphic IO action which is wrapped in a 'Dynamic' -- -- The specified 'naAlt' action will be performed instead, if the wrapped -- computation is not applicable, i.e. not really an IO action. dynPerformIO :: IO Dynamic -> Dynamic -> IO Dynamic dynPerformIO naAlt (Dynamic trAct monotypedAct) = case trAct of App io TypeRep -> case io `eqTypeRep` typeRep @IO of Just HRefl -> Dynamic TypeRep <$> monotypedAct Nothing -> naAlt -- not an IO action _ -> naAlt -- not even a poly-type -- | Perform a polymorphic STM action which is wrapped in a 'Dynamic' -- -- The specified 'naAlt' action will be performed instead, if the wrapped -- computation is not applicable, i.e. not really an STM action. dynPerformSTM :: STM Dynamic -> Dynamic -> STM Dynamic dynPerformSTM naAlt (Dynamic trAct monotypedAct) = case trAct of App io TypeRep -> case io `eqTypeRep` typeRep @STM of Just HRefl -> Dynamic TypeRep <$> monotypedAct Nothing -> naAlt -- not an STM action _ -> naAlt -- not even a poly-type -- | Perform a polymorphic STM action which is wrapped in a 'Dynamic' -- -- The specified 'naAlt' action will be performed instead, if the wrapped -- computation is not applicable, i.e. not really an STM action. dynContSTM :: STM () -> Dynamic -> (Dynamic -> STM ()) -> STM () dynContSTM naAlt (Dynamic trAct monotypedAct) !exit = case trAct of App io TypeRep -> case io `eqTypeRep` typeRep @STM of Just HRefl -> exit . Dynamic TypeRep =<< monotypedAct Nothing -> naAlt -- not an STM action _ -> naAlt -- not even a poly-type ``` And my test case being a little more complex than the very first example, might be easier for others to grasp the usage, it runs like this: ```console λ> import PoC.DynPoly λ> testDynHold First got Nothing Then got Just 3 λ> ``` With the code: ```hs module PoC.DynPoly where import Control.Monad (void) import Data.Dynamic (Dynamic (..), fromDynamic, toDyn) import Data.IORef (modifyIORef', newIORef, readIORef, writeIORef) import Dyn.Shim import Type.Reflection (eqTypeRep, typeRep, pattern App, type (:~~:) (HRefl)) import Prelude dynHoldEvent :: Dynamic -> Dynamic dynHoldEvent (Dynamic trEvs monotypedEvs) = case trEvs of App trEs TypeRep -> case trEs `eqTypeRep` typeRep @EventSink of Just HRefl -> Dynamic TypeRep (holdEvent monotypedEvs) Nothing -> error "not an EventSink" -- to be handled properly _ -> error "even not a poly-type" -- to be handled properly where holdEvent :: forall a. EventSink a -> IO (TimeSeries a) holdEvent !evs = do !holder <- newIORef Nothing listenEvents evs $ writeIORef holder . Just return $ TimeSeries $ readIORef holder data EventSink a = EventSink { listenEvents :: (a -> IO ()) -> IO (), publishEvent :: a -> IO () } newtype TimeSeries a = TimeSeries {readTimeSeries :: IO (Maybe a)} newEventSink :: forall a. IO (EventSink a) newEventSink = do !listeners <- newIORef [] let listen listener = modifyIORef' listeners (listener :) publish a = readIORef listeners >>= void . mapM ($ a) return $ EventSink listen publish testDynHold :: IO () testDynHold = do (evs :: EventSink Int) <- newEventSink let !dynEvs = toDyn evs !dynHold = dynHoldEvent dynEvs !dynTs <- dynPerformIO (error "bug: dyn type mismatch?") dynHold case fromDynamic dynTs of Nothing -> error "bug: unexpected dyn result type" Just (ts :: TimeSeries Int) -> do v0 <- readTimeSeries ts putStrLn $ "First got " <> show v0 publishEvent evs 3 v1 <- readTimeSeries ts putStrLn $ "Then got " <> show v1 ``` Thanks with best regards, Compl > On 2021-04-13, at 02:50, Erik Hesselink wrote: > > That is a lot, I'm not sure I understand that pattern synonym. Using `withTypeable` instead works for me: > > holdEvent :: Dynamic -> Dynamic > holdEvent (Dynamic tr x) = > case tr of > App ft at -> > case ft `eqTypeRep` typeRep @EventSink of > Just HRefl -> withTypeable at $ toDyn (hcHoldEvent x) > Nothing -> error "to handle" > _ -> error "to handle" > > Cheers, > > Erik -------------- next part -------------- An HTML attachment was scrubbed... URL: From compl.yue at icloud.com Tue Apr 13 14:48:40 2021 From: compl.yue at icloud.com (YueCompl) Date: Tue, 13 Apr 2021 22:48:40 +0800 Subject: What's the modern way to apply a polymorphic function to a Dynamic value in GHC 8.8 and onwards? In-Reply-To: References: <043B9A36-2014-4E02-9951-CBEC216C3CCA@icloud.com> <7F106DE5-7E92-4D21-BB0A-E7FC4EEE4484@serokell.io> <68E8C92A-9BB2-46FF-8747-C3DD07DA1084@icloud.com> <34A44F73-E4D0-4F1D-BBC1-08A539FAC76A@icloud.com> <15DE054A-5B61-4011-8D1D-9C344072F964@icloud.com> Message-ID: <1CF43226-1D48-4411-8EC1-D0A6AC690CA4@icloud.com> A followup wish I have: ```hs case io `eqTypeRep` typeRep @IO of Just HRefl -> Dynamic TypeRep <$> monotypedAct Nothing -> naAlt -- not an IO action ``` The `Just HRefl` part as in above remains hard to understand for me, I had glanced it in doc of the 'Type.Reflection' module earlier, but had no chance to figure out the usage of `eqTypeRep` to be like this, at least on my own. The community is very helpful in this regards, in leading me to it. But may there can be better surface syntax / usage hints that more intuitive, i.e. costing less effort to reach the solution? I anticipate improvements but apparently lack expertise for progress, I tried `Just {}` and it won't compile already... I mean, things are already great as far, well, maybe the learning experience can be made even better. Best, Compl > On 2021-04-13, at 22:07, YueCompl via ghc-devs wrote: > > After struggled this far, I decide that I can neither trivially understand `pattern TypeRep`, nor the `withTypeable` at core. But this is what really amazing with Haskell, GHC and the community here - I can get my job done even without full understanding of what's going on under the hood, so long as the compiler says it's okay! The warning has gone due to unknown reason after I refactored the code a bit, surprisingly but well, I feel safe and comfort to use it now. > > Thanks to Erik, Vlad and Jaro again for your help. > > u/Iceland_jack made a ticket to [add pattern TypeRep to Type.Reflection](https://gitlab.haskell.org/ghc/ghc/-/issues/19691 ) and appears it's very welcomed. Though I don't expect it get shipped very soon or even could be back ported to GHC 8.8, so I end up with this shim: > > (there `PolyKinds` appears some unusual to be put into my `.cabal` due to its syntax change can break some of my existing code) > > ```hs > {-# LANGUAGE PolyKinds #-} > > module Dyn.Shim > ( pattern TypeRep, > dynPerformIO, > dynPerformSTM, > dynContSTM, > ) > where > > import Control.Concurrent.STM (STM) > import Data.Dynamic (Dynamic (..), Typeable) > import Type.Reflection > ( TypeRep, > eqTypeRep, > typeRep, > withTypeable, > pattern App, > type (:~~:) (HRefl), > ) > import Prelude > > data TypeableInstance a where > TypeableInstance :: Typeable a => TypeableInstance a > > typeableInstance :: TypeRep a -> TypeableInstance a > typeableInstance tr = withTypeable tr TypeableInstance > > {- ORMOLU_DISABLE -} > > -- | Shim for the proposed one at: > -- https://gitlab.haskell.org/ghc/ghc/-/issues/19691 > pattern TypeRep :: forall k (a :: k). () => Typeable a => TypeRep a > pattern TypeRep <- (typeableInstance -> TypeableInstance) > where TypeRep = typeRep > > {- ORMOLU_ENABLE -} > > -- | Perform a polymorphic IO action which is wrapped in a 'Dynamic' > -- > -- The specified 'naAlt' action will be performed instead, if the wrapped > -- computation is not applicable, i.e. not really an IO action. > dynPerformIO :: IO Dynamic -> Dynamic -> IO Dynamic > dynPerformIO naAlt (Dynamic trAct monotypedAct) = case trAct of > App io TypeRep -> > case io `eqTypeRep` typeRep @IO of > Just HRefl -> Dynamic TypeRep <$> monotypedAct > Nothing -> naAlt -- not an IO action > _ -> naAlt -- not even a poly-type > > -- | Perform a polymorphic STM action which is wrapped in a 'Dynamic' > -- > -- The specified 'naAlt' action will be performed instead, if the wrapped > -- computation is not applicable, i.e. not really an STM action. > dynPerformSTM :: STM Dynamic -> Dynamic -> STM Dynamic > dynPerformSTM naAlt (Dynamic trAct monotypedAct) = case trAct of > App io TypeRep -> > case io `eqTypeRep` typeRep @STM of > Just HRefl -> Dynamic TypeRep <$> monotypedAct > Nothing -> naAlt -- not an STM action > _ -> naAlt -- not even a poly-type > > -- | Perform a polymorphic STM action which is wrapped in a 'Dynamic' > -- > -- The specified 'naAlt' action will be performed instead, if the wrapped > -- computation is not applicable, i.e. not really an STM action. > dynContSTM :: STM () -> Dynamic -> (Dynamic -> STM ()) -> STM () > dynContSTM naAlt (Dynamic trAct monotypedAct) !exit = case trAct of > App io TypeRep -> > case io `eqTypeRep` typeRep @STM of > Just HRefl -> exit . Dynamic TypeRep =<< monotypedAct > Nothing -> naAlt -- not an STM action > _ -> naAlt -- not even a poly-type > > ``` > > And my test case being a little more complex than the very first example, might be easier for others to grasp the usage, it runs like this: > > ```console > λ> import PoC.DynPoly > λ> testDynHold > First got Nothing > Then got Just 3 > λ> > ``` > > With the code: > > ```hs > module PoC.DynPoly where > > import Control.Monad (void) > import Data.Dynamic (Dynamic (..), fromDynamic, toDyn) > import Data.IORef (modifyIORef', newIORef, readIORef, writeIORef) > import Dyn.Shim > import Type.Reflection (eqTypeRep, typeRep, pattern App, type (:~~:) (HRefl)) > import Prelude > > dynHoldEvent :: Dynamic -> Dynamic > dynHoldEvent (Dynamic trEvs monotypedEvs) = > case trEvs of > App trEs TypeRep -> > case trEs `eqTypeRep` typeRep @EventSink of > Just HRefl -> Dynamic TypeRep (holdEvent monotypedEvs) > Nothing -> error "not an EventSink" -- to be handled properly > _ -> error "even not a poly-type" -- to be handled properly > where > holdEvent :: forall a. EventSink a -> IO (TimeSeries a) > holdEvent !evs = do > !holder <- newIORef Nothing > listenEvents evs $ writeIORef holder . Just > return $ TimeSeries $ readIORef holder > > data EventSink a = EventSink > { listenEvents :: (a -> IO ()) -> IO (), > publishEvent :: a -> IO () > } > > newtype TimeSeries a = TimeSeries {readTimeSeries :: IO (Maybe a)} > > newEventSink :: forall a. IO (EventSink a) > newEventSink = do > !listeners <- newIORef [] > let listen listener = modifyIORef' listeners (listener :) > publish a = readIORef listeners >>= void . mapM ($ a) > return $ EventSink listen publish > > testDynHold :: IO () > testDynHold = do > (evs :: EventSink Int) <- newEventSink > let !dynEvs = toDyn evs > !dynHold = dynHoldEvent dynEvs > !dynTs <- dynPerformIO (error "bug: dyn type mismatch?") dynHold > case fromDynamic dynTs of > Nothing -> error "bug: unexpected dyn result type" > Just (ts :: TimeSeries Int) -> do > v0 <- readTimeSeries ts > putStrLn $ "First got " <> show v0 > publishEvent evs 3 > v1 <- readTimeSeries ts > putStrLn $ "Then got " <> show v1 > ``` > > Thanks with best regards, > Compl > > >> On 2021-04-13, at 02:50, Erik Hesselink > wrote: >> >> That is a lot, I'm not sure I understand that pattern synonym. Using `withTypeable` instead works for me: >> >> holdEvent :: Dynamic -> Dynamic >> holdEvent (Dynamic tr x) = >> case tr of >> App ft at -> >> case ft `eqTypeRep` typeRep @EventSink of >> Just HRefl -> withTypeable at $ toDyn (hcHoldEvent x) >> Nothing -> error "to handle" >> _ -> error "to handle" >> >> Cheers, >> >> Erik > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs -------------- next part -------------- An HTML attachment was scrubbed... URL: From chessai1996 at gmail.com Tue Apr 13 15:02:26 2021 From: chessai1996 at gmail.com (chessai) Date: Tue, 13 Apr 2021 10:02:26 -0500 Subject: What's the modern way to apply a polymorphic function to a Dynamic value in GHC 8.8 and onwards? In-Reply-To: <1CF43226-1D48-4411-8EC1-D0A6AC690CA4@icloud.com> References: <043B9A36-2014-4E02-9951-CBEC216C3CCA@icloud.com> <7F106DE5-7E92-4D21-BB0A-E7FC4EEE4484@serokell.io> <68E8C92A-9BB2-46FF-8747-C3DD07DA1084@icloud.com> <34A44F73-E4D0-4F1D-BBC1-08A539FAC76A@icloud.com> <15DE054A-5B61-4011-8D1D-9C344072F964@icloud.com> <1CF43226-1D48-4411-8EC1-D0A6AC690CA4@icloud.com> Message-ID: Having more examples and docs in the corresponding module might be the best first step toward that. On Tue, Apr 13, 2021, 10:00 YueCompl via ghc-devs wrote: > A followup wish I have: > > ```hs > case io `eqTypeRep` typeRep @IO of > Just HRefl -> Dynamic TypeRep <$> monotypedAct > Nothing -> naAlt -- not an IO action > ``` > > The `Just HRefl` part as in above remains hard to understand for me, I had > glanced it in doc of the 'Type.Reflection' module earlier, but had no > chance to figure out the usage of `eqTypeRep` to be like this, at least on > my own. The community is very helpful in this regards, in leading me to it. > But may there can be better surface syntax / usage hints that more > intuitive, i.e. costing less effort to reach the solution? I anticipate > improvements but apparently lack expertise for progress, I tried `Just {}` > and it won't compile already... > > I mean, things are already great as far, well, maybe the learning > experience can be made even better. > > Best, > Compl > > > On 2021-04-13, at 22:07, YueCompl via ghc-devs > wrote: > > After struggled this far, I decide that I can neither trivially understand > `pattern TypeRep`, nor the `withTypeable` at core. But this is what really > amazing with Haskell, GHC and the community here - I can get my job done > even without full understanding of what's going on under the hood, so long > as the compiler says it's okay! The warning has gone due to unknown reason > after I refactored the code a bit, surprisingly but well, I feel safe and > comfort to use it now. > > Thanks to Erik, Vlad and Jaro again for your help. > > u/Iceland_jack made a ticket to [add pattern TypeRep to Type.Reflection]( > https://gitlab.haskell.org/ghc/ghc/-/issues/19691) and appears it's very > welcomed. Though I don't expect it get shipped very soon or even could be > back ported to GHC 8.8, so I end up with this shim: > > (there `PolyKinds` appears some unusual to be put into my `.cabal` due to > its syntax change can break some of my existing code) > > ```hs > {-# LANGUAGE PolyKinds #-} > > module Dyn.Shim > ( pattern TypeRep, > dynPerformIO, > dynPerformSTM, > dynContSTM, > ) > where > > import Control.Concurrent.STM (STM) > import Data.Dynamic (Dynamic (..), Typeable) > import Type.Reflection > ( TypeRep, > eqTypeRep, > typeRep, > withTypeable, > pattern App, > type (:~~:) (HRefl), > ) > import Prelude > > data TypeableInstance a where > TypeableInstance :: Typeable a => TypeableInstance a > > typeableInstance :: TypeRep a -> TypeableInstance a > typeableInstance tr = withTypeable tr TypeableInstance > > {- ORMOLU_DISABLE -} > > -- | Shim for the proposed one at: > -- https://gitlab.haskell.org/ghc/ghc/-/issues/19691 > pattern TypeRep :: forall k (a :: k). () => Typeable a => TypeRep a > pattern TypeRep <- (typeableInstance -> TypeableInstance) > where TypeRep = typeRep > > {- ORMOLU_ENABLE -} > > -- | Perform a polymorphic IO action which is wrapped in a 'Dynamic' > -- > -- The specified 'naAlt' action will be performed instead, if the wrapped > -- computation is not applicable, i.e. not really an IO action. > dynPerformIO :: IO Dynamic -> Dynamic -> IO Dynamic > dynPerformIO naAlt (Dynamic trAct monotypedAct) = case trAct of > App io TypeRep -> > case io `eqTypeRep` typeRep @IO of > Just HRefl -> Dynamic TypeRep <$> monotypedAct > Nothing -> naAlt -- not an IO action > _ -> naAlt -- not even a poly-type > > -- | Perform a polymorphic STM action which is wrapped in a 'Dynamic' > -- > -- The specified 'naAlt' action will be performed instead, if the wrapped > -- computation is not applicable, i.e. not really an STM action. > dynPerformSTM :: STM Dynamic -> Dynamic -> STM Dynamic > dynPerformSTM naAlt (Dynamic trAct monotypedAct) = case trAct of > App io TypeRep -> > case io `eqTypeRep` typeRep @STM of > Just HRefl -> Dynamic TypeRep <$> monotypedAct > Nothing -> naAlt -- not an STM action > _ -> naAlt -- not even a poly-type > > -- | Perform a polymorphic STM action which is wrapped in a 'Dynamic' > -- > -- The specified 'naAlt' action will be performed instead, if the wrapped > -- computation is not applicable, i.e. not really an STM action. > dynContSTM :: STM () -> Dynamic -> (Dynamic -> STM ()) -> STM () > dynContSTM naAlt (Dynamic trAct monotypedAct) !exit = case trAct of > App io TypeRep -> > case io `eqTypeRep` typeRep @STM of > Just HRefl -> exit . Dynamic TypeRep =<< monotypedAct > Nothing -> naAlt -- not an STM action > _ -> naAlt -- not even a poly-type > > ``` > > And my test case being a little more complex than the very first example, > might be easier for others to grasp the usage, it runs like this: > > ```console > λ> import PoC.DynPoly > λ> testDynHold > First got Nothing > Then got Just 3 > λ> > ``` > > With the code: > > ```hs > module PoC.DynPoly where > > import Control.Monad (void) > import Data.Dynamic (Dynamic (..), fromDynamic, toDyn) > import Data.IORef (modifyIORef', newIORef, readIORef, writeIORef) > import Dyn.Shim > import Type.Reflection (eqTypeRep, typeRep, pattern App, type (:~~:) ( > HRefl)) > import Prelude > > dynHoldEvent :: Dynamic -> Dynamic > dynHoldEvent (Dynamic trEvs monotypedEvs) = > case trEvs of > App trEs TypeRep -> > case trEs `eqTypeRep` typeRep @EventSink of > Just HRefl -> Dynamic TypeRep (holdEvent monotypedEvs) > Nothing -> error "not an EventSink" -- to be handled properly > _ -> error "even not a poly-type" -- to be handled properly > where > holdEvent :: forall a. EventSink a -> IO (TimeSeries a) > holdEvent !evs = do > !holder <- newIORef Nothing > listenEvents evs $ writeIORef holder . Just > return $ TimeSeries $ readIORef holder > > data EventSink a = EventSink > { listenEvents :: (a -> IO ()) -> IO (), > publishEvent :: a -> IO () > } > > newtype TimeSeries a = TimeSeries {readTimeSeries :: IO (Maybe a)} > > newEventSink :: forall a. IO (EventSink a) > newEventSink = do > !listeners <- newIORef [] > let listen listener = modifyIORef' listeners (listener :) > publish a = readIORef listeners >>= void . mapM ($ a) > return $ EventSink listen publish > > testDynHold :: IO () > testDynHold = do > (evs :: EventSink Int) <- newEventSink > let !dynEvs = toDyn evs > !dynHold = dynHoldEvent dynEvs > !dynTs <- dynPerformIO (error "bug: dyn type mismatch?") dynHold > case fromDynamic dynTs of > Nothing -> error "bug: unexpected dyn result type" > Just (ts :: TimeSeries Int) -> do > v0 <- readTimeSeries ts > putStrLn $ "First got " <> show v0 > publishEvent evs 3 > v1 <- readTimeSeries ts > putStrLn $ "Then got " <> show v1 > ``` > > Thanks with best regards, > Compl > > > On 2021-04-13, at 02:50, Erik Hesselink wrote: > > That is a lot, I'm not sure I understand that pattern synonym. Using > `withTypeable` instead works for me: > > holdEvent :: Dynamic -> Dynamic > holdEvent (Dynamic tr x) = > case tr of > App ft at -> > case ft `eqTypeRep` typeRep @EventSink of > Just HRefl -> withTypeable at $ toDyn (hcHoldEvent x) > Nothing -> error "to handle" > _ -> error "to handle" > > Cheers, > > Erik > > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From rae at richarde.dev Wed Apr 14 18:26:38 2021 From: rae at richarde.dev (Richard Eisenberg) Date: Wed, 14 Apr 2021 18:26:38 +0000 Subject: instance {Semigroup, Monoid} (Bag a) ? Message-ID: <010f0178d1a29b9a-6b6402d0-f5bc-4f6c-80e2-db97b3b8a043-000000@us-east-2.amazonses.com> Hi devs, In the work on simplifying the error-message infrastructure (heavy lifting by Alfredo, in cc), I've been tempted (twice!) to add > instance Semigroup (Bag a) where > (<>) = unionBags > > instance Monoid (Bag a) where > mempty = emptyBag to GHC.Data.Bag. The downside to writing these is that users might be tempted to write e.g. mempty instead of emptyBag, while the latter gives more information to readers and induces less manual type inference (to a human reader). The upside is that it means Bags work well with Monoid-oriented functions, like foldMap. I favor adding them, and slipped them into !5509 (a big commit with lots of other stuff). Alfredo rightly wondered whether this decision deserved more scrutiny, and so I'm asking the question here. What do we think? Thanks, Richard From alan.zimm at gmail.com Wed Apr 14 19:06:13 2021 From: alan.zimm at gmail.com (Alan & Kim Zimmerman) Date: Wed, 14 Apr 2021 20:06:13 +0100 Subject: instance {Semigroup, Monoid} (Bag a) ? In-Reply-To: <010f0178d1a29b9a-6b6402d0-f5bc-4f6c-80e2-db97b3b8a043-000000@us-east-2.amazonses.com> References: <010f0178d1a29b9a-6b6402d0-f5bc-4f6c-80e2-db97b3b8a043-000000@us-east-2.amazonses.com> Message-ID: I wonder if it would be possible to have an hlint rule to check for mempty instead of emptyBag. On Wed, 14 Apr 2021 at 19:27, Richard Eisenberg wrote: > Hi devs, > > In the work on simplifying the error-message infrastructure (heavy lifting > by Alfredo, in cc), I've been tempted (twice!) to add > > > instance Semigroup (Bag a) where > > (<>) = unionBags > > > > instance Monoid (Bag a) where > > mempty = emptyBag > > to GHC.Data.Bag. > > The downside to writing these is that users might be tempted to write e.g. > mempty instead of emptyBag, while the latter gives more information to > readers and induces less manual type inference (to a human reader). The > upside is that it means Bags work well with Monoid-oriented functions, like > foldMap. > > I favor adding them, and slipped them into !5509 (a big commit with lots > of other stuff). Alfredo rightly wondered whether this decision deserved > more scrutiny, and so I'm asking the question here. > > What do we think? > > Thanks, > Richard > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From sgraf1337 at gmail.com Wed Apr 14 19:10:57 2021 From: sgraf1337 at gmail.com (Sebastian Graf) Date: Wed, 14 Apr 2021 21:10:57 +0200 Subject: instance {Semigroup, Monoid} (Bag a) ? In-Reply-To: <010f0178d1a29b9a-6b6402d0-f5bc-4f6c-80e2-db97b3b8a043-000000@us-east-2.amazonses.com> References: <010f0178d1a29b9a-6b6402d0-f5bc-4f6c-80e2-db97b3b8a043-000000@us-east-2.amazonses.com> Message-ID: Hi Richard, I've been guilty of slipping in similar instances myself. In fact, I like OrdList better than Bag precisely because it has more instances and thus a far better interface. Not being able to see whether mempty denotes a Bag should be as simple as a mouse hover with HLS set up. So a +99 from me. Cheers, Sebastian Am Mi., 14. Apr. 2021 um 20:28 Uhr schrieb Richard Eisenberg < rae at richarde.dev>: > Hi devs, > > In the work on simplifying the error-message infrastructure (heavy lifting > by Alfredo, in cc), I've been tempted (twice!) to add > > > instance Semigroup (Bag a) where > > (<>) = unionBags > > > > instance Monoid (Bag a) where > > mempty = emptyBag > > to GHC.Data.Bag. > > The downside to writing these is that users might be tempted to write e.g. > mempty instead of emptyBag, while the latter gives more information to > readers and induces less manual type inference (to a human reader). The > upside is that it means Bags work well with Monoid-oriented functions, like > foldMap. > > I favor adding them, and slipped them into !5509 (a big commit with lots > of other stuff). Alfredo rightly wondered whether this decision deserved > more scrutiny, and so I'm asking the question here. > > What do we think? > > Thanks, > Richard > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ietf-dane at dukhovni.org Wed Apr 14 19:29:44 2021 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Wed, 14 Apr 2021 15:29:44 -0400 Subject: instance {Semigroup, Monoid} (Bag a) ? In-Reply-To: <010f0178d1a29b9a-6b6402d0-f5bc-4f6c-80e2-db97b3b8a043-000000@us-east-2.amazonses.com> References: <010f0178d1a29b9a-6b6402d0-f5bc-4f6c-80e2-db97b3b8a043-000000@us-east-2.amazonses.com> Message-ID: On Wed, Apr 14, 2021 at 06:26:38PM +0000, Richard Eisenberg wrote: > In the work on simplifying the error-message infrastructure (heavy > lifting by Alfredo, in cc), I've been tempted (twice!) to add > > > instance Semigroup (Bag a) where > > (<>) = unionBags > > > > instance Monoid (Bag a) where > > mempty = emptyBag > > to GHC.Data.Bag. I agree that the new Monoid is appropriate. > The downside to writing these is that users might be tempted to write > e.g. mempty instead of emptyBag, while the latter gives more > information to readers and induces less manual type inference (to a > human reader). The upside is that it means Bags work well with > Monoid-oriented functions, like foldMap. I don't see the possibility of writing `mempty` as an issue. I find myself not infrequently writing `mempty` for, e.g., empty ByteStrings, rather than ByteString.empty, because while there are lots of type-specific "empties", they often need to be used qualified, while the polymorphic `mempty` is both clear and flexible. If anything, what's atypical here is that "emptyBag" has the type in its name. With many other types we have: empty :: ByteString empty :: ByteString.Builder empty :: Map k v empty :: Set a empty :: Seq a empty :: Text empty :: Vector a ... when the type is a Monoid, it is much simpler to just use mempty. -- Viktor. From chessai1996 at gmail.com Wed Apr 14 19:48:57 2021 From: chessai1996 at gmail.com (chessai) Date: Wed, 14 Apr 2021 14:48:57 -0500 Subject: instance {Semigroup, Monoid} (Bag a) ? In-Reply-To: References: <010f0178d1a29b9a-6b6402d0-f5bc-4f6c-80e2-db97b3b8a043-000000@us-east-2.amazonses.com> Message-ID: +1 to add from me, seems sensible On Wed, Apr 14, 2021, 14:31 Viktor Dukhovni wrote: > On Wed, Apr 14, 2021 at 06:26:38PM +0000, Richard Eisenberg wrote: > > > In the work on simplifying the error-message infrastructure (heavy > > lifting by Alfredo, in cc), I've been tempted (twice!) to add > > > > > instance Semigroup (Bag a) where > > > (<>) = unionBags > > > > > > instance Monoid (Bag a) where > > > mempty = emptyBag > > > > to GHC.Data.Bag. > > I agree that the new Monoid is appropriate. > > > The downside to writing these is that users might be tempted to write > > e.g. mempty instead of emptyBag, while the latter gives more > > information to readers and induces less manual type inference (to a > > human reader). The upside is that it means Bags work well with > > Monoid-oriented functions, like foldMap. > > I don't see the possibility of writing `mempty` as an issue. I find > myself not infrequently writing `mempty` for, e.g., empty ByteStrings, > rather than ByteString.empty, because while there are lots of > type-specific "empties", they often need to be used qualified, while the > polymorphic `mempty` is both clear and flexible. > > If anything, what's atypical here is that "emptyBag" has the type in its > name. With many other types we have: > > empty :: ByteString > empty :: ByteString.Builder > empty :: Map k v > empty :: Set a > empty :: Seq a > empty :: Text > empty :: Vector a > ... > > when the type is a Monoid, it is much simpler to just use mempty. > > -- > Viktor. > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ben at smart-cactus.org Thu Apr 15 00:17:22 2021 From: ben at smart-cactus.org (Ben Gamari) Date: Wed, 14 Apr 2021 20:17:22 -0400 Subject: instance {Semigroup, Monoid} (Bag a) ? In-Reply-To: References: <010f0178d1a29b9a-6b6402d0-f5bc-4f6c-80e2-db97b3b8a043-000000@us-east-2.amazonses.com> Message-ID: <878s5kqu40.fsf@smart-cactus.org> Viktor Dukhovni writes: > On Wed, Apr 14, 2021 at 06:26:38PM +0000, Richard Eisenberg wrote: > >> In the work on simplifying the error-message infrastructure (heavy >> lifting by Alfredo, in cc), I've been tempted (twice!) to add >> >> > instance Semigroup (Bag a) where >> > (<>) = unionBags >> > >> > instance Monoid (Bag a) where >> > mempty = emptyBag >> >> to GHC.Data.Bag. > > I agree that the new Monoid is appropriate. > >> The downside to writing these is that users might be tempted to write >> e.g. mempty instead of emptyBag, while the latter gives more >> information to readers and induces less manual type inference (to a >> human reader). The upside is that it means Bags work well with >> Monoid-oriented functions, like foldMap. > > I don't see the possibility of writing `mempty` as an issue. I find > myself not infrequently writing `mempty` for, e.g., empty ByteStrings, > rather than ByteString.empty, because while there are lots of > type-specific "empties", they often need to be used qualified, while the > polymorphic `mempty` is both clear and flexible. > I think the "clear" is where some might disagree. It has been argued in the past (fairly convincingly, in my opinion) that there is value in being explicit what concrete type an expression has. Afterall, understanding GHC is already hard enough; there's no reason to make it harder by forcing the reader to do type inference. This is why GHC has historically preferred concrete interfaces to using things like mempty. Cheers, - Ben -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: not available URL: From ben at smart-cactus.org Thu Apr 15 00:19:00 2021 From: ben at smart-cactus.org (Ben Gamari) Date: Wed, 14 Apr 2021 20:19:00 -0400 Subject: instance {Semigroup, Monoid} (Bag a) ? In-Reply-To: <010f0178d1a29b9a-6b6402d0-f5bc-4f6c-80e2-db97b3b8a043-000000@us-east-2.amazonses.com> References: <010f0178d1a29b9a-6b6402d0-f5bc-4f6c-80e2-db97b3b8a043-000000@us-east-2.amazonses.com> Message-ID: <875z0oqu18.fsf@smart-cactus.org> Richard Eisenberg writes: > Hi devs, > > In the work on simplifying the error-message infrastructure (heavy lifting by Alfredo, in cc), I've been tempted (twice!) to add > >> instance Semigroup (Bag a) where >> (<>) = unionBags >> >> instance Monoid (Bag a) where >> mempty = emptyBag > > to GHC.Data.Bag. > > The downside to writing these is that users might be tempted to write > e.g. mempty instead of emptyBag, while the latter gives more > information to readers and induces less manual type inference (to a > human reader). The upside is that it means Bags work well with > Monoid-oriented functions, like foldMap. > > I favor adding them, and slipped them into !5509 (a big commit with > lots of other stuff). Alfredo rightly wondered whether this decision > deserved more scrutiny, and so I'm asking the question here. > My sense is that adding the instances is a Good Thing. However, I do think that we probably ought to refrain from using (<>) and mempty where more specific functions would do. Adding a lint would be one way to accomplish this. Hiding the functions from GhcPrelude would be another. Cheers, - Ben -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: not available URL: From alfredo.dinapoli at gmail.com Thu Apr 15 06:30:30 2021 From: alfredo.dinapoli at gmail.com (Alfredo Di Napoli) Date: Thu, 15 Apr 2021 08:30:30 +0200 Subject: instance {Semigroup, Monoid} (Bag a) ? In-Reply-To: <875z0oqu18.fsf@smart-cactus.org> References: <010f0178d1a29b9a-6b6402d0-f5bc-4f6c-80e2-db97b3b8a043-000000@us-east-2.amazonses.com> <875z0oqu18.fsf@smart-cactus.org> Message-ID: Good morning all, I have now split Richard's commit in two, so that it's explicit in the commit history that we are adding those instances: https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5509/diffs?commit_id=2cbad0e7ced9de896eb9a1732631786a6adb676a *Ben*: I have briefly tried to add the Hlint annotations, but it turned out to be trickier than anticipated. I couldn't find any easy way in HLint to add a custom hint on a *typeclass instance*, and adding something like this into `compiler/.hlint.yaml` didn't change anything: - modules: - {name: GHC.Data.Bag, badidents: [mempty], message: "Use emptyBag as it's more descriptive"} - {name: GHC.Data.Bag, badidents: [(<>)], message: "Use unionBags as it's more descriptive"} (I suspect that's not what's the badidents syntax is for). I have also tried to add two `ANN` to the definitions, like this: {-# ANN (<>) ("HLint: use unionBags as it's more descriptive" :: String) #-} instance Semigroup (Bag a) where (<>) = unionBags However, this won't work as (<>) is imported qualified and there is no way in the ANN syntax to specify a fully qualified identifier. However, I suspect this is not the correct syntax either, as `(<>)` is really the *typeclass* method, but we want to target the particular instance implementation. *Having said that*, Richard carefully defined `(<>) = unionBags` and `mempty = emptyBag`, so I agree that using `(<>)` and `mempty` would be more opaque but at the end of the day it should have the asymptotic complexity than using `unionBags` and `emptyBag` (modulo dictionary passing, but I hope that won't each our lunch). A. On Thu, 15 Apr 2021 at 02:20, Ben Gamari wrote: > Richard Eisenberg writes: > > > Hi devs, > > > > In the work on simplifying the error-message infrastructure (heavy > lifting by Alfredo, in cc), I've been tempted (twice!) to add > > > >> instance Semigroup (Bag a) where > >> (<>) = unionBags > >> > >> instance Monoid (Bag a) where > >> mempty = emptyBag > > > > to GHC.Data.Bag. > > > > The downside to writing these is that users might be tempted to write > > e.g. mempty instead of emptyBag, while the latter gives more > > information to readers and induces less manual type inference (to a > > human reader). The upside is that it means Bags work well with > > Monoid-oriented functions, like foldMap. > > > > I favor adding them, and slipped them into !5509 (a big commit with > > lots of other stuff). Alfredo rightly wondered whether this decision > > deserved more scrutiny, and so I'm asking the question here. > > > My sense is that adding the instances is a Good Thing. However, I do > think that we probably ought to refrain from using (<>) and mempty where > more specific functions would do. Adding a lint would be one way to > accomplish this. Hiding the functions from GhcPrelude would be another. > > Cheers, > > - Ben > > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hecate at glitchbra.in Thu Apr 15 15:28:03 2021 From: hecate at glitchbra.in (=?UTF-8?Q?H=c3=a9cate?=) Date: Thu, 15 Apr 2021 17:28:03 +0200 Subject: Integrating more base Instances in the `stock` deriving strategy? Message-ID: Hi folks! I would like to start a discussion (if it hasn't already been done) around the idea of integrating the various type-classes that Base offers, that are hidden behind language extensions, in the `stock` deriving strategy. I wasn't around when it was all implemented, but I've always lived with it in my code bases, and I'd like to know if there are deeper issues pertaining to their exclusion from the `stock` deriving strategy. Here is the link to the discussion ticket: https://gitlab.haskell.org/ghc/ghc/-/issues/19707 Cheers, and have a nice week! -- Hécate ✨ 🐦: @TechnoEmpress IRC: Uniaika WWW: https://glitchbra.in RUN: BSD From csaba.hruska at gmail.com Tue Apr 20 21:38:00 2021 From: csaba.hruska at gmail.com (Csaba Hruska) Date: Tue, 20 Apr 2021 23:38:00 +0200 Subject: External STG Interpreter blog post In-Reply-To: References: Message-ID: Hello, In theory the ext-stg interpereter could be used to run TH, but it is not done yet. I'm interested in optimization much much more, but I deliberately designed the ext-stg ir/tooling to be simple and easy to use and understand for others so that an average Haskell programmer could implement his ideas or do his experiment. I'm also open for discussion about the possibilities. We can have a video meeting about this if you'd like to. Cheers, Csaba On Mon, Apr 12, 2021 at 7:57 PM John Ericson wrote: > Indeed it is! > > I also am very much hoping this can be the missing piece we need to allow > Template Haskell to work with a stage 0 GHC, so that we can safely use TH > in GHC itself even when the ABI is changing. See > https://github.com/ghc-proposals/ghc-proposals/issues/162 for details, > where I've also linked Csaba's blog post. (And maybe also > https://gitlab.haskell.org/ghc/ghc/-/wikis/cross-compilation/roadmap for > more background, and related things like > https://github.com/ghc-proposals/ghc-proposals/pull/412.) > > TH could perhaps be used to replace some of the ad-hoc code gen we have > for e.g. RTS constants and primops. This in turn would simplify the build > system, allowing for `cabal install ghc` to work without shipping generated > Haskell code in the sdist. > > John > On 4/12/21 4:51 AM, Simon Peyton Jones via ghc-devs wrote: > > That’s extremely impressive, Csaba. > > > > Maybe of interest to folk who have been thinking about “fat interface > files”. > > > Simon > > > > *From:* ghc-devs > *On Behalf Of *Csaba Hruska > *Sent:* 10 April 2021 11:49 > *To:* GHC developers > *Subject:* External STG Interpreter blog post > > > > Hello, > > > > I've written a blog post about GHC-WPC's external stg interpreter. > https://www.patreon.com/posts/external-stg-49857800 > > > Feedback is welcome. > > > > Cheers, > > Csaba > > _______________________________________________ > ghc-devs mailing listghc-devs at haskell.orghttp://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From simonpj at microsoft.com Thu Apr 22 10:39:11 2021 From: simonpj at microsoft.com (Simon Peyton Jones) Date: Thu, 22 Apr 2021 10:39:11 +0000 Subject: magicDict Message-ID: Ed, and other ghc-devs We are busy tidying up magicDict, and making it much more type-safe: see * https://gitlab.haskell.org/ghc/ghc/-/issues/16646 * https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5573 As part of that change we're think of changing its currently-rather-obscure name. I rather favour "reflectDict". Any other views? Simon -------------- next part -------------- An HTML attachment was scrubbed... URL: From arnaud.spiwack at tweag.io Thu Apr 22 13:26:06 2021 From: arnaud.spiwack at tweag.io (Spiwack, Arnaud) Date: Thu, 22 Apr 2021 15:26:06 +0200 Subject: magicDict In-Reply-To: References: Message-ID: Let me upvote `reflectDict`. On Thu, Apr 22, 2021 at 12:41 PM Simon Peyton Jones via ghc-devs < ghc-devs at haskell.org> wrote: > Ed, and other ghc-devs > > We are busy tidying up magicDict, and making it much more type-safe: see > > - https://gitlab.haskell.org/ghc/ghc/-/issues/16646 > - https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5573 > > As part of that change we’re think of changing its > currently-rather-obscure name. I rather favour “reflectDict”. Any other > views? > > Simon > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From krz.gogolewski at gmail.com Thu Apr 22 19:17:33 2021 From: krz.gogolewski at gmail.com (Krzysztof Gogolewski) Date: Thu, 22 Apr 2021 21:17:33 +0200 Subject: magicDict In-Reply-To: References: Message-ID: How about 'reifyDict'? The reflection library uses 'reify' to create a dictionary and 'reflect' to extract a value out of it. https://hackage.haskell.org/package/reflection-2.1.6/docs/Data-Reflection.html#v:reify On Thu, Apr 22, 2021 at 3:27 PM Spiwack, Arnaud wrote: > > Let me upvote `reflectDict`. > > On Thu, Apr 22, 2021 at 12:41 PM Simon Peyton Jones via ghc-devs wrote: >> >> Ed, and other ghc-devs >> >> We are busy tidying up magicDict, and making it much more type-safe: see >> >> https://gitlab.haskell.org/ghc/ghc/-/issues/16646 >> https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5573 >> >> As part of that change we’re think of changing its currently-rather-obscure name. I rather favour “reflectDict”. Any other views? >> >> Simon >> >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs From ekmett at gmail.com Thu Apr 22 20:17:11 2021 From: ekmett at gmail.com (Edward Kmett) Date: Thu, 22 Apr 2021 13:17:11 -0700 Subject: magicDict In-Reply-To: References: Message-ID: Happy to see progress being made here. I think Ryan and others have spoken to any issues I would otherwise raise with the implementation itself. Currently I find myself reaching for unsafeCoerce over magicDict in most situations, and I'd really like to be able to stop doing that! I'm +1 on the name being something `reify`-ish, to avoid flipping the direction on the vocabulary. It is reifying a value as a dictionary. Something like `reifyValue` or `reifyAsDict` would avoid confusion as the dict isn't being reified, the value is. Both are a little clunky, but it is a very rare operation. It is also worth considering possibly mangling the name with a # or an 'unsafe' in the name to give casual users pause. -Edward On Thu, Apr 22, 2021 at 12:18 PM Krzysztof Gogolewski < krz.gogolewski at gmail.com> wrote: > How about 'reifyDict'? The reflection library uses 'reify' to create a > dictionary and 'reflect' to extract a value out of it. > > > https://hackage.haskell.org/package/reflection-2.1.6/docs/Data-Reflection.html#v:reify > > On Thu, Apr 22, 2021 at 3:27 PM Spiwack, Arnaud > wrote: > > > > Let me upvote `reflectDict`. > > > > On Thu, Apr 22, 2021 at 12:41 PM Simon Peyton Jones via ghc-devs < > ghc-devs at haskell.org> wrote: > >> > >> Ed, and other ghc-devs > >> > >> We are busy tidying up magicDict, and making it much more type-safe: see > >> > >> https://gitlab.haskell.org/ghc/ghc/-/issues/16646 > >> https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5573 > >> > >> As part of that change we’re think of changing its > currently-rather-obscure name. I rather favour “reflectDict”. Any other > views? > >> > >> Simon > >> > >> _______________________________________________ > >> ghc-devs mailing list > >> ghc-devs at haskell.org > >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > > > _______________________________________________ > > ghc-devs mailing list > > ghc-devs at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From simonpj at microsoft.com Thu Apr 22 21:50:21 2021 From: simonpj at microsoft.com (Simon Peyton Jones) Date: Thu, 22 Apr 2021 21:50:21 +0000 Subject: magicDict In-Reply-To: References: Message-ID: Ah, yes... I can never remember which is reify and which is reflect. I'm fine either way. Maybe reifyDict is better. S | -----Original Message----- | From: Krzysztof Gogolewski | Sent: 22 April 2021 20:18 | To: Spiwack, Arnaud | Cc: Simon Peyton Jones ; GHC developers | Subject: Re: magicDict | | How about 'reifyDict'? The reflection library uses 'reify' to create a | dictionary and 'reflect' to extract a value out of it. | | https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fhack | age.haskell.org%2Fpackage%2Freflection-2.1.6%2Fdocs%2FData- | Reflection.html%23v%3Areify&data=04%7C01%7Csimonpj%40microsoft.com | %7C4c3a0fe8f1b2459d746308d905c34ed0%7C72f988bf86f141af91ab2d7cd011db47 | %7C1%7C0%7C637547159883839881%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAw | MDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sdata=bQ | RNfsZPQQ%2FxqVcJvVpRJSkBIEZojqmKyqhpv7gr9XU%3D&reserved=0 | | On Thu, Apr 22, 2021 at 3:27 PM Spiwack, Arnaud | wrote: | > | > Let me upvote `reflectDict`. | > | > On Thu, Apr 22, 2021 at 12:41 PM Simon Peyton Jones via ghc-devs | wrote: | >> | >> Ed, and other ghc-devs | >> | >> We are busy tidying up magicDict, and making it much more type- | safe: | >> see | >> | >> | https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit | >> lab.haskell.org%2Fghc%2Fghc%2F- | %2Fissues%2F16646&data=04%7C01%7Cs | >> | imonpj%40microsoft.com%7C4c3a0fe8f1b2459d746308d905c34ed0%7C72f988bf8 | >> | 6f141af91ab2d7cd011db47%7C1%7C0%7C637547159883839881%7CUnknown%7CTWFp | >> | bGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6M | >> | n0%3D%7C3000&sdata=6OX7dPWC2sVUeMKNaqZVGwH%2FJ9mGSWQRUEWuvUWq8uE% | >> 3D&reserved=0 | >> | https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit | >> lab.haskell.org%2Fghc%2Fghc%2F- | %2Fmerge_requests%2F5573&data=04%7 | >> | C01%7Csimonpj%40microsoft.com%7C4c3a0fe8f1b2459d746308d905c34ed0%7C72 | >> | f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637547159883839881%7CUnknown | >> | %7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLC | >> | JXVCI6Mn0%3D%7C3000&sdata=D2Q3wq74Y4RVnaAOjXQX6R9EuxuDplwmJ0zdk%2 | >> BAhN64%3D&reserved=0 | >> | >> As part of that change we're think of changing its currently- | rather-obscure name. I rather favour "reflectDict". Any other views? | >> | >> Simon | >> | >> _______________________________________________ | >> ghc-devs mailing list | >> ghc-devs at haskell.org | >> | https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail | >> .haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc- | devs&data=04%7C | >> | 01%7Csimonpj%40microsoft.com%7C4c3a0fe8f1b2459d746308d905c34ed0%7C72f | >> | 988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637547159883839881%7CUnknown% | >> | 7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJ | >> | XVCI6Mn0%3D%7C3000&sdata=%2BQHuwK50UdRQR0AQOuNGstDM%2BtDEv%2F75fs | >> Ia3mfqvIw%3D&reserved=0 | > | > _______________________________________________ | > ghc-devs mailing list | > ghc-devs at haskell.org | > | https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail. | > haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc- | devs&data=04%7C01 | > | %7Csimonpj%40microsoft.com%7C4c3a0fe8f1b2459d746308d905c34ed0%7C72f988 | > | bf86f141af91ab2d7cd011db47%7C1%7C0%7C637547159883839881%7CUnknown%7CTW | > | FpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6 | > | Mn0%3D%7C3000&sdata=%2BQHuwK50UdRQR0AQOuNGstDM%2BtDEv%2F75fsIa3mfq | > vIw%3D&reserved=0 From ben at well-typed.com Fri Apr 23 03:58:44 2021 From: ben at well-typed.com (Ben Gamari) Date: Thu, 22 Apr 2021 23:58:44 -0400 Subject: [ANNOUNCE] GHC 9.2.1-alpha2 released Message-ID: <874kfxps7i.fsf@smart-cactus.org> Hi all, The GHC developers are very happy to announce the availability of the second alpha release in the 9.2.1 series. Binary distributions, source distributions, and documentation are available at https://downloads.haskell.org/ghc/9.2.1-alpha2 GHC 9.2 will bring a number of exciting features including: * Many changes in the area of records, including the new `RecordDotSyntax` and `NoFieldSelectors` language extensions, as well as Support for `DuplicateRecordFields` with `PatternSynonyms`. * Introduction of the new `GHC2021` language extension set, giving users convenient access to a larger set of language extensions which have been long considered stable. * Merge of `ghc-exactprint` into the GHC tree, providing infrastructure for source-to-source program rewriting out-of-the-box. * Introduction of a `BoxedRep` `RuntimeRep`, allowing for polymorphism over levity of boxed objects (#17526) * Implementation of the `UnliftedDataTypes` extension, allowing users to define types which do not admit lazy evaluation ([proposal]) * The new [-hi profiling] mechanism which provides significantly improved insight into thunk leaks. * Support for the `ghc-debug` out-of-process heap inspection library [ghc-debug] * Support for profiling of pinned objects with the cost-centre profiler (#7275) * Introduction of Haddock documentation support in TemplateHaskell (#5467) * Proper support for impredicative types in the form of Quick-Look impredicativity. * A native code generator backend for AArch64. This pre-release brings nearly 50 fixes relative to the first alpha, although the long-awaited ARM NCG backend hasn't quite landed yet. As always, do give this a try and open a [ticket] if you see anything amiss. Happy testing, - Ben [proposal]: https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0265-unlifted-datatypes.rst [-hi profiling]: https://well-typed.com/blog/2021/01/first-look-at-hi-profiling-mode/ [ghc-debug]: http://ghc.gitlab.haskell.org/ghc-debug/ [ticket]: https://gitlab.haskell.org/ghc/ghc/-/issues/new -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: not available URL: From arnaud.spiwack at tweag.io Fri Apr 23 06:15:12 2021 From: arnaud.spiwack at tweag.io (Spiwack, Arnaud) Date: Fri, 23 Apr 2021 08:15:12 +0200 Subject: magicDict In-Reply-To: References: Message-ID: While I do value consistency, let me pet-peeve for a minute here (sorry in advance Edward for the rant). The word “reify” comes from the latin “res”, which means object/thing. It should always mean something along the line of “making more concrete”. In normalisation by evaluation, for instance, you reify a semantic value as syntax (an object of the language of study), and you reflect values of the language into the semantic domain. To me, the reflection library uses the terms inconsistently. For instance you have the type ReifiedMonoid for the concrete type representing a monoid instance. This is, in my opinion, the right terminology. However, a ReifiedMonoid should be the product of reification, but in the reflection library it actually gets reify-d further. This doesn’t seem to work at the grammar level. I contend that the function should have been reflect all along: you reflect a concrete dictionary object into the nebulous, untouchable world of type class instances. It’s probably too late to fix the reflection library, hence me never complaining about it (in public :-) ). But I vote we don’t perpetuate this situation, and still call the function reflectDict. -------------- next part -------------- An HTML attachment was scrubbed... URL: From carter.schonwald at gmail.com Fri Apr 23 16:17:56 2021 From: carter.schonwald at gmail.com (Carter Schonwald) Date: Fri, 23 Apr 2021 12:17:56 -0400 Subject: magicDict In-Reply-To: References: Message-ID: This makes sense to me, and provides a good explanation for why I mix up the terms. So usual parlance is reify brings stuff back down/ reflect bounces it up? On Fri, Apr 23, 2021 at 2:16 AM Spiwack, Arnaud wrote: > While I do value consistency, let me pet-peeve for a minute here (sorry in > advance Edward for the rant). The word “reify” comes from the latin “res”, > which means object/thing. It should always mean something along the line of > “making more concrete”. In normalisation by evaluation, for instance, you > reify a semantic value as syntax (an object of the language of study), and > you reflect values of the language into the semantic domain. > > To me, the reflection library uses the terms inconsistently. For instance > you have the type ReifiedMonoid for the concrete type representing a > monoid instance. This is, in my opinion, the right terminology. However, a > ReifiedMonoid should be the product of reification, but in the reflection > library it actually gets reify-d further. This doesn’t seem to work at > the grammar level. I contend that the function should have been reflect > all along: you reflect a concrete dictionary object into the nebulous, > untouchable world of type class instances. > > It’s probably too late to fix the reflection library, hence me never > complaining about it (in public :-) ). But I vote we don’t perpetuate this > situation, and still call the function reflectDict. > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ekmett at gmail.com Sun Apr 25 00:20:40 2021 From: ekmett at gmail.com (Edward Kmett) Date: Sat, 24 Apr 2021 17:20:40 -0700 Subject: magicDict In-Reply-To: References: Message-ID: I speak to much this same point in this old stack overflow response, though to exactly the opposite conclusion, and to exactly the opposite pet peeve. https://stackoverflow.com/a/5316014/34707 Let me see if I can try to explain why I think reasonable people can disagree here and why I ultimately adopted the "wrong" vocabulary from your perspective. To be explicit: Viewing a type as a space, 'reify' in the reflection library takes some space 'a' and splits it into individual fibers for each term in 'a', finding the appropriate one and handing it back to you as a fresh type 's' that captures just that singular value. The result is significantly less abstract, as we gained detail on the type, now every point in the original space 'a' is a new space. At the type level the fresh 's' in s `Reifies` a now concretely names exactly one inhabitant of 'a'. On the flip side, 'reflect' in the reflection library forgets this finer fibration / structure on space, losing the information about which fiber the answer came from, being forgetful is precisely the justification of it being the 'reflect' half of the reify -| reflect pairing. I confess I don't necessarily anticipate this changing your mind but it was not chosen blindly, reflect is the forgetful mapping here, reification is free and left adjoint to it, at least in the context of reflection-the-library, *where a quantifier is being injected to track the particular member*. This gets more muddled when you remove the quantifier, like here, now everything becomes the same size, nothing is being forgotten when you use "magicDict" to transform 5 :: Natural into dictionary for KnownNat (5 :: Nat) or use the single member of the dictionary to get your value back. If anything it goes the other way, because you _could_ evilly produce a dictionary from 6 :: Natural and nothing but your conscience stops you. But when used in a way that doesn't violate coherence of instance resolution, no finer fibration was introduced, reflect isn't forgetful, neither is reify, you produce singleton instances in a thin category from singleton types. In that framework, really neither term seems fully appropriate here -- or rather both do depending on your chosen perspective. This is where I believe the religious wars about which is concrete and which is abstract start up, because both uses satisfy that definition in this narrow case of isomorphism, no information is lost on either end. It is only when you actually introduce a quantifier to ensure 's' is fresh (as it is used in the reflection library to ensure this doesn't compromise instance resolution safety in general) that there is a bias introduced and 'reflect' forgets this hallucinated structure, finally forcing a 'handedness' on the terminology to use. I do not feel that I chose the vocabulary without due consideration of the precise meaning of the words used. -Edward On Thu, Apr 22, 2021 at 11:16 PM Spiwack, Arnaud wrote: > While I do value consistency, let me pet-peeve for a minute here (sorry in > advance Edward for the rant). The word “reify” comes from the latin “res”, > which means object/thing. It should always mean something along the line of > “making more concrete”. In normalisation by evaluation, for instance, you > reify a semantic value as syntax (an object of the language of study), and > you reflect values of the language into the semantic domain. > > To me, the reflection library uses the terms inconsistently. For instance > you have the type ReifiedMonoid for the concrete type representing a > monoid instance. This is, in my opinion, the right terminology. However, a > ReifiedMonoid should be the product of reification, but in the reflection > library it actually gets reify-d further. This doesn’t seem to work at > the grammar level. I contend that the function should have been reflect > all along: you reflect a concrete dictionary object into the nebulous, > untouchable world of type class instances. > > It’s probably too late to fix the reflection library, hence me never > complaining about it (in public :-) ). But I vote we don’t perpetuate this > situation, and still call the function reflectDict. > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From arnaud.spiwack at tweag.io Mon Apr 26 07:10:02 2021 From: arnaud.spiwack at tweag.io (Spiwack, Arnaud) Date: Mon, 26 Apr 2021 09:10:02 +0200 Subject: magicDict In-Reply-To: References: Message-ID: On Sun, Apr 25, 2021 at 2:20 AM Edward Kmett wrote: > I speak to much this same point in this old stack overflow response, > though to exactly the opposite conclusion, and to exactly the opposite pet > peeve. > > https://stackoverflow.com/a/5316014/34707 > :-) I do not feel that I chose the vocabulary without due consideration of the > precise meaning of the words used. > I didn't mean to imply that you did. Sorry if I did so: written communication is hard. For what it's worth, I didn't really think that I would change your mind, either. Though it still seems to me that the name `ReifiedMonoid` uses the word for a different thing than the `reifyMonoid` function does. To be explicit: > > Viewing a type as a space, 'reify' in the reflection library takes some > space 'a' and splits it into individual fibers for each term in 'a', > finding the appropriate one and handing it back to you as a fresh type 's' > that captures just that singular value. The result is significantly less > abstract, as we gained detail on the type, now every point in the original > space 'a' is a new space. At the type level the fresh 's' in s `Reifies` a > now concretely names exactly one inhabitant of 'a'. > > On the flip side, 'reflect' in the reflection library forgets this finer > fibration / structure on space, losing the information about which fiber > the answer came from, being forgetful is precisely the justification of it > being the 'reflect' half of the reify -| reflect pairing. > > I confess I don't necessarily anticipate this changing your mind but it > was not chosen blindly, reflect is the forgetful mapping here, reification > is free and left adjoint to it, at least in the context of > reflection-the-library, *where a quantifier is being injected to track > the particular member*. > I've got to admit that I have the hardest time seeing the `s` as representing an inhabitant of `a`. I'm probably missing something here. I also don't think that a free object construction embodies a reify/reflect pair completely. It's probably fair to see `reify` as being the natural mapping from the free object of X to X (the counit of the adjunction). But reification will not be the unit of the adjunction, because it's trivial. So there is still a piece missing in this story. Anyway… I've made my point, and I am not too willing to spend too much time proving Wadler's law correct. So I think I'll stop here, fascinating a conversation though it is. Best, Arnaud -------------- next part -------------- An HTML attachment was scrubbed... URL: From simonpj at microsoft.com Mon Apr 26 07:39:45 2021 From: simonpj at microsoft.com (Simon Peyton Jones) Date: Mon, 26 Apr 2021 07:39:45 +0000 Subject: magicDict In-Reply-To: References: Message-ID: Can we just agree a name, then? Please correct me if I'm wrong, but * I think Ed prefers 'reifyDict', * That is compatible with the existing reflection library * Arnaud disagrees but isn't going to die in the trenches for this one * Virtually anything is better than 'magicDict'. So: reifyDict it is? Simon From: Spiwack, Arnaud Sent: 26 April 2021 08:10 To: Edward Kmett Cc: Simon Peyton Jones ; GHC developers Subject: Re: magicDict On Sun, Apr 25, 2021 at 2:20 AM Edward Kmett > wrote: I speak to much this same point in this old stack overflow response, though to exactly the opposite conclusion, and to exactly the opposite pet peeve. https://stackoverflow.com/a/5316014/34707 :-) I do not feel that I chose the vocabulary without due consideration of the precise meaning of the words used. I didn't mean to imply that you did. Sorry if I did so: written communication is hard. For what it's worth, I didn't really think that I would change your mind, either. Though it still seems to me that the name `ReifiedMonoid` uses the word for a different thing than the `reifyMonoid` function does. To be explicit: Viewing a type as a space, 'reify' in the reflection library takes some space 'a' and splits it into individual fibers for each term in 'a', finding the appropriate one and handing it back to you as a fresh type 's' that captures just that singular value. The result is significantly less abstract, as we gained detail on the type, now every point in the original space 'a' is a new space. At the type level the fresh 's' in s `Reifies` a now concretely names exactly one inhabitant of 'a'. On the flip side, 'reflect' in the reflection library forgets this finer fibration / structure on space, losing the information about which fiber the answer came from, being forgetful is precisely the justification of it being the 'reflect' half of the reify -| reflect pairing. I confess I don't necessarily anticipate this changing your mind but it was not chosen blindly, reflect is the forgetful mapping here, reification is free and left adjoint to it, at least in the context of reflection-the-library, where a quantifier is being injected to track the particular member. I've got to admit that I have the hardest time seeing the `s` as representing an inhabitant of `a`. I'm probably missing something here. I also don't think that a free object construction embodies a reify/reflect pair completely. It's probably fair to see `reify` as being the natural mapping from the free object of X to X (the counit of the adjunction). But reification will not be the unit of the adjunction, because it's trivial. So there is still a piece missing in this story. Anyway... I've made my point, and I am not too willing to spend too much time proving Wadler's law correct. So I think I'll stop here, fascinating a conversation though it is. Best, Arnaud -------------- next part -------------- An HTML attachment was scrubbed... URL: From krz.gogolewski at gmail.com Mon Apr 26 14:34:37 2021 From: krz.gogolewski at gmail.com (Krzysztof Gogolewski) Date: Mon, 26 Apr 2021 16:34:37 +0200 Subject: magicDict In-Reply-To: References: Message-ID: I would like to propose one more option: withDict :: dt -> (ct => a) -> a 1. This is less symmetric than '(ct => a) -> dt -> a' but in existing applications magicDict gets the arguments in the reverse order. 2. Easier to chain 'withDict d1 (withDict d2 ...)'. 3. The name is similar to 'withTypeable' or 'withFile', and avoids arguing which is reify or reflect. On Mon, Apr 26, 2021 at 9:41 AM Simon Peyton Jones via ghc-devs wrote: > > Can we just agree a name, then? Please correct me if I’m wrong, but > > I think Ed prefers ‘reifyDict’, > That is compatible with the existing reflection library > Arnaud disagrees but isn’t going to die in the trenches for this one > Virtually anything is better than ‘magicDict’. > > > > > > So: reifyDict it is? > > > > Simon > > > > From: Spiwack, Arnaud > Sent: 26 April 2021 08:10 > To: Edward Kmett > Cc: Simon Peyton Jones ; GHC developers > Subject: Re: magicDict > > > > > > > > On Sun, Apr 25, 2021 at 2:20 AM Edward Kmett wrote: > > I speak to much this same point in this old stack overflow response, though to exactly the opposite conclusion, and to exactly the opposite pet peeve. > > > > https://stackoverflow.com/a/5316014/34707 > > > > :-) > > > > I do not feel that I chose the vocabulary without due consideration of the precise meaning of the words used. > > > > I didn't mean to imply that you did. Sorry if I did so: written communication is hard. For what it's worth, I didn't really think that I would change your mind, either. > > > > Though it still seems to me that the name `ReifiedMonoid` uses the word for a different thing than the `reifyMonoid` function does. > > > > To be explicit: > > > > Viewing a type as a space, 'reify' in the reflection library takes some space 'a' and splits it into individual fibers for each term in 'a', finding the appropriate one and handing it back to you as a fresh type 's' that captures just that singular value. The result is significantly less abstract, as we gained detail on the type, now every point in the original space 'a' is a new space. At the type level the fresh 's' in s `Reifies` a now concretely names exactly one inhabitant of 'a'. > > > > On the flip side, 'reflect' in the reflection library forgets this finer fibration / structure on space, losing the information about which fiber the answer came from, being forgetful is precisely the justification of it being the 'reflect' half of the reify -| reflect pairing. > > > > I confess I don't necessarily anticipate this changing your mind but it was not chosen blindly, reflect is the forgetful mapping here, reification is free and left adjoint to it, at least in the context of reflection-the-library, where a quantifier is being injected to track the particular member. > > > > I've got to admit that I have the hardest time seeing the `s` as representing an inhabitant of `a`. I'm probably missing something here. > > > > I also don't think that a free object construction embodies a reify/reflect pair completely. It's probably fair to see `reify` as being the natural mapping from the free object of X to X (the counit of the adjunction). But reification will not be the unit of the adjunction, because it's trivial. So there is still a piece missing in this story. > > > > Anyway… I've made my point, and I am not too willing to spend too much time proving Wadler's law correct. So I think I'll stop here, fascinating a conversation though it is. > > > > Best, > > Arnaud > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs From simonpj at microsoft.com Mon Apr 26 14:49:08 2021 From: simonpj at microsoft.com (Simon Peyton Jones) Date: Mon, 26 Apr 2021 14:49:08 +0000 Subject: magicDict In-Reply-To: References: Message-ID: | I would like to propose one more option: | | withDict :: dt -> (ct => a) -> a Ah, you mean simply: swap the argument order. I can see your logic about chaining etc. I'd be fine with this. Simon | -----Original Message----- | From: Krzysztof Gogolewski | Sent: 26 April 2021 15:35 | To: Simon Peyton Jones | Cc: Spiwack, Arnaud ; Edward Kmett | ; GHC developers | Subject: Re: magicDict | | I would like to propose one more option: | | withDict :: dt -> (ct => a) -> a | | 1. This is less symmetric than '(ct => a) -> dt -> a' | but in existing applications magicDict gets the arguments | in the reverse order. | 2. Easier to chain 'withDict d1 (withDict d2 ...)'. | 3. The name is similar to 'withTypeable' or 'withFile', | and avoids arguing which is reify or reflect. | | On Mon, Apr 26, 2021 at 9:41 AM Simon Peyton Jones via ghc-devs wrote: | > | > Can we just agree a name, then? Please correct me if I'm wrong, | but | > | > I think Ed prefers 'reifyDict', | > That is compatible with the existing reflection library Arnaud | > disagrees but isn't going to die in the trenches for this one | > Virtually anything is better than 'magicDict'. | > | > | > | > | > | > So: reifyDict it is? | > | > | > | > Simon | > | > | > | > From: Spiwack, Arnaud | > Sent: 26 April 2021 08:10 | > To: Edward Kmett | > Cc: Simon Peyton Jones ; GHC developers | > | > Subject: Re: magicDict | > | > | > | > | > | > | > | > On Sun, Apr 25, 2021 at 2:20 AM Edward Kmett | wrote: | > | > I speak to much this same point in this old stack overflow response, | though to exactly the opposite conclusion, and to exactly the opposite | pet peeve. | > | > | > | > | https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fstac | > | koverflow.com%2Fa%2F5316014%2F34707&data=04%7C01%7Csimonpj%40micro | > | soft.com%7C87da21fdcc8e4ed6bef508d908c071fb%7C72f988bf86f141af91ab2d7c | > | d011db47%7C1%7C0%7C637550444930791696%7CUnknown%7CTWFpbGZsb3d8eyJWIjoi | > | MC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000& | > | sdata=VlRrIEROGj%2BE6%2FuLXBEdfa%2BPWVlHh50dahgjIrw4tQU%3D&reserve | > d=0 | > | > | > | > :-) | > | > | > | > I do not feel that I chose the vocabulary without due consideration | of the precise meaning of the words used. | > | > | > | > I didn't mean to imply that you did. Sorry if I did so: written | communication is hard. For what it's worth, I didn't really think that | I would change your mind, either. | > | > | > | > Though it still seems to me that the name `ReifiedMonoid` uses the | word for a different thing than the `reifyMonoid` function does. | > | > | > | > To be explicit: | > | > | > | > Viewing a type as a space, 'reify' in the reflection library takes | some space 'a' and splits it into individual fibers for each term in | 'a', finding the appropriate one and handing it back to you as a fresh | type 's' that captures just that singular value. The result is | significantly less abstract, as we gained detail on the type, now | every point in the original space 'a' is a new space. At the type | level the fresh 's' in s `Reifies` a now concretely names exactly one | inhabitant of 'a'. | > | > | > | > On the flip side, 'reflect' in the reflection library forgets this | finer fibration / structure on space, losing the information about | which fiber the answer came from, being forgetful is precisely the | justification of it being the 'reflect' half of the reify -| reflect | pairing. | > | > | > | > I confess I don't necessarily anticipate this changing your mind but | it was not chosen blindly, reflect is the forgetful mapping here, | reification is free and left adjoint to it, at least in the context of | reflection-the-library, where a quantifier is being injected to track | the particular member. | > | > | > | > I've got to admit that I have the hardest time seeing the `s` as | representing an inhabitant of `a`. I'm probably missing something | here. | > | > | > | > I also don't think that a free object construction embodies a | reify/reflect pair completely. It's probably fair to see `reify` as | being the natural mapping from the free object of X to X (the counit | of the adjunction). But reification will not be the unit of the | adjunction, because it's trivial. So there is still a piece missing in | this story. | > | > | > | > Anyway... I've made my point, and I am not too willing to spend too | much time proving Wadler's law correct. So I think I'll stop here, | fascinating a conversation though it is. | > | > | > | > Best, | > | > Arnaud | > | > _______________________________________________ | > ghc-devs mailing list | > ghc-devs at haskell.org | > | https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail. | > haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc- | devs&data=04%7C01 | > | %7Csimonpj%40microsoft.com%7C87da21fdcc8e4ed6bef508d908c071fb%7C72f988 | > | bf86f141af91ab2d7cd011db47%7C1%7C0%7C637550444930791696%7CUnknown%7CTW | > | FpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6 | > | Mn0%3D%7C1000&sdata=4JfXyRNMjQKTSLqme2VJU9Dy0s6N4Y8t%2BINHYp38xJk% | > 3D&reserved=0 From ekmett at gmail.com Mon Apr 26 20:33:53 2021 From: ekmett at gmail.com (Edward Kmett) Date: Mon, 26 Apr 2021 13:33:53 -0700 Subject: magicDict In-Reply-To: References: Message-ID: I like withDict a lot. It is direct, easy to chain/use, avoids fighting about direction completely, and even matches the argument order used by reify in the reflection library. +1 from me. On Mon, Apr 26, 2021 at 7:49 AM Simon Peyton Jones wrote: > | I would like to propose one more option: > | > | withDict :: dt -> (ct => a) -> a > > Ah, you mean simply: swap the argument order. I can see your logic about > chaining etc. I'd be fine with this. > > Simon > > | -----Original Message----- > | From: Krzysztof Gogolewski > | Sent: 26 April 2021 15:35 > | To: Simon Peyton Jones > | Cc: Spiwack, Arnaud ; Edward Kmett > | ; GHC developers > | Subject: Re: magicDict > | > | I would like to propose one more option: > | > | withDict :: dt -> (ct => a) -> a > | > | 1. This is less symmetric than '(ct => a) -> dt -> a' > | but in existing applications magicDict gets the arguments > | in the reverse order. > | 2. Easier to chain 'withDict d1 (withDict d2 ...)'. > | 3. The name is similar to 'withTypeable' or 'withFile', > | and avoids arguing which is reify or reflect. > | > | On Mon, Apr 26, 2021 at 9:41 AM Simon Peyton Jones via ghc-devs | devs at haskell.org> wrote: > | > > | > Can we just agree a name, then? Please correct me if I'm wrong, > | but > | > > | > I think Ed prefers 'reifyDict', > | > That is compatible with the existing reflection library Arnaud > | > disagrees but isn't going to die in the trenches for this one > | > Virtually anything is better than 'magicDict'. > | > > | > > | > > | > > | > > | > So: reifyDict it is? > | > > | > > | > > | > Simon > | > > | > > | > > | > From: Spiwack, Arnaud > | > Sent: 26 April 2021 08:10 > | > To: Edward Kmett > | > Cc: Simon Peyton Jones ; GHC developers > | > > | > Subject: Re: magicDict > | > > | > > | > > | > > | > > | > > | > > | > On Sun, Apr 25, 2021 at 2:20 AM Edward Kmett > | wrote: > | > > | > I speak to much this same point in this old stack overflow response, > | though to exactly the opposite conclusion, and to exactly the opposite > | pet peeve. > | > > | > > | > > | > > | https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fstac > | > > | koverflow.com%2Fa%2F5316014%2F34707&data=04%7C01%7Csimonpj%40micro > | > > | soft.com%7C87da21fdcc8e4ed6bef508d908c071fb%7C72f988bf86f141af91ab2d7c > | > > | d011db47%7C1%7C0%7C637550444930791696%7CUnknown%7CTWFpbGZsb3d8eyJWIjoi > | > > | MC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000& > | > > | sdata=VlRrIEROGj%2BE6%2FuLXBEdfa%2BPWVlHh50dahgjIrw4tQU%3D&reserve > | > d=0 > | > > | > > | > > | > :-) > | > > | > > | > > | > I do not feel that I chose the vocabulary without due consideration > | of the precise meaning of the words used. > | > > | > > | > > | > I didn't mean to imply that you did. Sorry if I did so: written > | communication is hard. For what it's worth, I didn't really think that > | I would change your mind, either. > | > > | > > | > > | > Though it still seems to me that the name `ReifiedMonoid` uses the > | word for a different thing than the `reifyMonoid` function does. > | > > | > > | > > | > To be explicit: > | > > | > > | > > | > Viewing a type as a space, 'reify' in the reflection library takes > | some space 'a' and splits it into individual fibers for each term in > | 'a', finding the appropriate one and handing it back to you as a fresh > | type 's' that captures just that singular value. The result is > | significantly less abstract, as we gained detail on the type, now > | every point in the original space 'a' is a new space. At the type > | level the fresh 's' in s `Reifies` a now concretely names exactly one > | inhabitant of 'a'. > | > > | > > | > > | > On the flip side, 'reflect' in the reflection library forgets this > | finer fibration / structure on space, losing the information about > | which fiber the answer came from, being forgetful is precisely the > | justification of it being the 'reflect' half of the reify -| reflect > | pairing. > | > > | > > | > > | > I confess I don't necessarily anticipate this changing your mind but > | it was not chosen blindly, reflect is the forgetful mapping here, > | reification is free and left adjoint to it, at least in the context of > | reflection-the-library, where a quantifier is being injected to track > | the particular member. > | > > | > > | > > | > I've got to admit that I have the hardest time seeing the `s` as > | representing an inhabitant of `a`. I'm probably missing something > | here. > | > > | > > | > > | > I also don't think that a free object construction embodies a > | reify/reflect pair completely. It's probably fair to see `reify` as > | being the natural mapping from the free object of X to X (the counit > | of the adjunction). But reification will not be the unit of the > | adjunction, because it's trivial. So there is still a piece missing in > | this story. > | > > | > > | > > | > Anyway... I've made my point, and I am not too willing to spend too > | much time proving Wadler's law correct. So I think I'll stop here, > | fascinating a conversation though it is. > | > > | > > | > > | > Best, > | > > | > Arnaud > | > > | > _______________________________________________ > | > ghc-devs mailing list > | > ghc-devs at haskell.org > | > > | https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail. > | > haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc- > | devs&data=04%7C01 > | > > | %7Csimonpj%40microsoft.com%7C87da21fdcc8e4ed6bef508d908c071fb%7C72f988 > | > > | bf86f141af91ab2d7cd011db47%7C1%7C0%7C637550444930791696%7CUnknown%7CTW > | > > | FpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6 > | > > | Mn0%3D%7C1000&sdata=4JfXyRNMjQKTSLqme2VJU9Dy0s6N4Y8t%2BINHYp38xJk% > | > 3D&reserved=0 > -------------- next part -------------- An HTML attachment was scrubbed... URL: From simonpj at microsoft.com Mon Apr 26 21:21:58 2021 From: simonpj at microsoft.com (Simon Peyton Jones) Date: Mon, 26 Apr 2021 21:21:58 +0000 Subject: magicDict In-Reply-To: References: Message-ID: You mean you like 'withDict' with that name, as well as the argument order K suggests? i.e. not reifyDict? Simon From: Edward Kmett Sent: 26 April 2021 21:34 To: Simon Peyton Jones Cc: Krzysztof Gogolewski ; Spiwack, Arnaud ; GHC developers ; Ryan Scott Subject: Re: magicDict I like withDict a lot. It is direct, easy to chain/use, avoids fighting about direction completely, and even matches the argument order used by reify in the reflection library. +1 from me. On Mon, Apr 26, 2021 at 7:49 AM Simon Peyton Jones > wrote: | I would like to propose one more option: | | withDict :: dt -> (ct => a) -> a Ah, you mean simply: swap the argument order. I can see your logic about chaining etc. I'd be fine with this. Simon | -----Original Message----- | From: Krzysztof Gogolewski > | Sent: 26 April 2021 15:35 | To: Simon Peyton Jones > | Cc: Spiwack, Arnaud >; Edward Kmett | >; GHC developers > | Subject: Re: magicDict | | I would like to propose one more option: | | withDict :: dt -> (ct => a) -> a | | 1. This is less symmetric than '(ct => a) -> dt -> a' | but in existing applications magicDict gets the arguments | in the reverse order. | 2. Easier to chain 'withDict d1 (withDict d2 ...)'. | 3. The name is similar to 'withTypeable' or 'withFile', | and avoids arguing which is reify or reflect. | | On Mon, Apr 26, 2021 at 9:41 AM Simon Peyton Jones via ghc-devs > wrote: | > | > Can we just agree a name, then? Please correct me if I'm wrong, | but | > | > I think Ed prefers 'reifyDict', | > That is compatible with the existing reflection library Arnaud | > disagrees but isn't going to die in the trenches for this one | > Virtually anything is better than 'magicDict'. | > | > | > | > | > | > So: reifyDict it is? | > | > | > | > Simon | > | > | > | > From: Spiwack, Arnaud > | > Sent: 26 April 2021 08:10 | > To: Edward Kmett > | > Cc: Simon Peyton Jones >; GHC developers | > > | > Subject: Re: magicDict | > | > | > | > | > | > | > | > On Sun, Apr 25, 2021 at 2:20 AM Edward Kmett > | wrote: | > | > I speak to much this same point in this old stack overflow response, | though to exactly the opposite conclusion, and to exactly the opposite | pet peeve. | > | > | > | > | https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fstac | > | koverflow.com%2Fa%2F5316014%2F34707&data=04%7C01%7Csimonpj%40micro | > | soft.com%7C87da21fdcc8e4ed6bef508d908c071fb%7C72f988bf86f141af91ab2d7c | > | d011db47%7C1%7C0%7C637550444930791696%7CUnknown%7CTWFpbGZsb3d8eyJWIjoi | > | MC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000& | > | sdata=VlRrIEROGj%2BE6%2FuLXBEdfa%2BPWVlHh50dahgjIrw4tQU%3D&reserve | > d=0 | > | > | > | > :-) | > | > | > | > I do not feel that I chose the vocabulary without due consideration | of the precise meaning of the words used. | > | > | > | > I didn't mean to imply that you did. Sorry if I did so: written | communication is hard. For what it's worth, I didn't really think that | I would change your mind, either. | > | > | > | > Though it still seems to me that the name `ReifiedMonoid` uses the | word for a different thing than the `reifyMonoid` function does. | > | > | > | > To be explicit: | > | > | > | > Viewing a type as a space, 'reify' in the reflection library takes | some space 'a' and splits it into individual fibers for each term in | 'a', finding the appropriate one and handing it back to you as a fresh | type 's' that captures just that singular value. The result is | significantly less abstract, as we gained detail on the type, now | every point in the original space 'a' is a new space. At the type | level the fresh 's' in s `Reifies` a now concretely names exactly one | inhabitant of 'a'. | > | > | > | > On the flip side, 'reflect' in the reflection library forgets this | finer fibration / structure on space, losing the information about | which fiber the answer came from, being forgetful is precisely the | justification of it being the 'reflect' half of the reify -| reflect | pairing. | > | > | > | > I confess I don't necessarily anticipate this changing your mind but | it was not chosen blindly, reflect is the forgetful mapping here, | reification is free and left adjoint to it, at least in the context of | reflection-the-library, where a quantifier is being injected to track | the particular member. | > | > | > | > I've got to admit that I have the hardest time seeing the `s` as | representing an inhabitant of `a`. I'm probably missing something | here. | > | > | > | > I also don't think that a free object construction embodies a | reify/reflect pair completely. It's probably fair to see `reify` as | being the natural mapping from the free object of X to X (the counit | of the adjunction). But reification will not be the unit of the | adjunction, because it's trivial. So there is still a piece missing in | this story. | > | > | > | > Anyway... I've made my point, and I am not too willing to spend too | much time proving Wadler's law correct. So I think I'll stop here, | fascinating a conversation though it is. | > | > | > | > Best, | > | > Arnaud | > | > _______________________________________________ | > ghc-devs mailing list | > ghc-devs at haskell.org | > | https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail. | > haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc- | devs&data=04%7C01 | > | %7Csimonpj%40microsoft.com%7C87da21fdcc8e4ed6bef508d908c071fb%7C72f988 | > | bf86f141af91ab2d7cd011db47%7C1%7C0%7C637550444930791696%7CUnknown%7CTW | > | FpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6 | > | Mn0%3D%7C1000&sdata=4JfXyRNMjQKTSLqme2VJU9Dy0s6N4Y8t%2BINHYp38xJk% | > 3D&reserved=0 -------------- next part -------------- An HTML attachment was scrubbed... URL: From ekmett at gmail.com Mon Apr 26 21:22:23 2021 From: ekmett at gmail.com (Edward Kmett) Date: Mon, 26 Apr 2021 14:22:23 -0700 Subject: magicDict In-Reply-To: References: Message-ID: <9256C045-1BCA-49F0-A12B-310994DC2DA0@gmail.com> Indeed. Sent from my iPhone > On Apr 26, 2021, at 2:22 PM, Simon Peyton Jones wrote: > >  > You mean you like ‘withDict’ with that name, as well as the argument order K suggests? i.e. not reifyDict? > > Simon > > From: Edward Kmett > Sent: 26 April 2021 21:34 > To: Simon Peyton Jones > Cc: Krzysztof Gogolewski ; Spiwack, Arnaud ; GHC developers ; Ryan Scott > Subject: Re: magicDict > > I like withDict a lot. It is direct, easy to chain/use, avoids fighting about direction completely, and even matches the argument order used by reify in the reflection library. > > > > +1 from me. > > > > On Mon, Apr 26, 2021 at 7:49 AM Simon Peyton Jones wrote: > > | I would like to propose one more option: > | > | withDict :: dt -> (ct => a) -> a > > Ah, you mean simply: swap the argument order. I can see your logic about chaining etc. I'd be fine with this. > > Simon > > | -----Original Message----- > | From: Krzysztof Gogolewski > | Sent: 26 April 2021 15:35 > | To: Simon Peyton Jones > | Cc: Spiwack, Arnaud ; Edward Kmett > | ; GHC developers > | Subject: Re: magicDict > | > | I would like to propose one more option: > | > | withDict :: dt -> (ct => a) -> a > | > | 1. This is less symmetric than '(ct => a) -> dt -> a' > | but in existing applications magicDict gets the arguments > | in the reverse order. > | 2. Easier to chain 'withDict d1 (withDict d2 ...)'. > | 3. The name is similar to 'withTypeable' or 'withFile', > | and avoids arguing which is reify or reflect. > | > | On Mon, Apr 26, 2021 at 9:41 AM Simon Peyton Jones via ghc-devs | devs at haskell.org> wrote: > | > > | > Can we just agree a name, then? Please correct me if I'm wrong, > | but > | > > | > I think Ed prefers 'reifyDict', > | > That is compatible with the existing reflection library Arnaud > | > disagrees but isn't going to die in the trenches for this one > | > Virtually anything is better than 'magicDict'. > | > > | > > | > > | > > | > > | > So: reifyDict it is? > | > > | > > | > > | > Simon > | > > | > > | > > | > From: Spiwack, Arnaud > | > Sent: 26 April 2021 08:10 > | > To: Edward Kmett > | > Cc: Simon Peyton Jones ; GHC developers > | > > | > Subject: Re: magicDict > | > > | > > | > > | > > | > > | > > | > > | > On Sun, Apr 25, 2021 at 2:20 AM Edward Kmett > | wrote: > | > > | > I speak to much this same point in this old stack overflow response, > | though to exactly the opposite conclusion, and to exactly the opposite > | pet peeve. > | > > | > > | > > | > > | https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fstac > | > > | koverflow.com%2Fa%2F5316014%2F34707&data=04%7C01%7Csimonpj%40micro > | > > | soft.com%7C87da21fdcc8e4ed6bef508d908c071fb%7C72f988bf86f141af91ab2d7c > | > > | d011db47%7C1%7C0%7C637550444930791696%7CUnknown%7CTWFpbGZsb3d8eyJWIjoi > | > > | MC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000& > | > > | sdata=VlRrIEROGj%2BE6%2FuLXBEdfa%2BPWVlHh50dahgjIrw4tQU%3D&reserve > | > d=0 > | > > | > > | > > | > :-) > | > > | > > | > > | > I do not feel that I chose the vocabulary without due consideration > | of the precise meaning of the words used. > | > > | > > | > > | > I didn't mean to imply that you did. Sorry if I did so: written > | communication is hard. For what it's worth, I didn't really think that > | I would change your mind, either. > | > > | > > | > > | > Though it still seems to me that the name `ReifiedMonoid` uses the > | word for a different thing than the `reifyMonoid` function does. > | > > | > > | > > | > To be explicit: > | > > | > > | > > | > Viewing a type as a space, 'reify' in the reflection library takes > | some space 'a' and splits it into individual fibers for each term in > | 'a', finding the appropriate one and handing it back to you as a fresh > | type 's' that captures just that singular value. The result is > | significantly less abstract, as we gained detail on the type, now > | every point in the original space 'a' is a new space. At the type > | level the fresh 's' in s `Reifies` a now concretely names exactly one > | inhabitant of 'a'. > | > > | > > | > > | > On the flip side, 'reflect' in the reflection library forgets this > | finer fibration / structure on space, losing the information about > | which fiber the answer came from, being forgetful is precisely the > | justification of it being the 'reflect' half of the reify -| reflect > | pairing. > | > > | > > | > > | > I confess I don't necessarily anticipate this changing your mind but > | it was not chosen blindly, reflect is the forgetful mapping here, > | reification is free and left adjoint to it, at least in the context of > | reflection-the-library, where a quantifier is being injected to track > | the particular member. > | > > | > > | > > | > I've got to admit that I have the hardest time seeing the `s` as > | representing an inhabitant of `a`. I'm probably missing something > | here. > | > > | > > | > > | > I also don't think that a free object construction embodies a > | reify/reflect pair completely. It's probably fair to see `reify` as > | being the natural mapping from the free object of X to X (the counit > | of the adjunction). But reification will not be the unit of the > | adjunction, because it's trivial. So there is still a piece missing in > | this story. > | > > | > > | > > | > Anyway... I've made my point, and I am not too willing to spend too > | much time proving Wadler's law correct. So I think I'll stop here, > | fascinating a conversation though it is. > | > > | > > | > > | > Best, > | > > | > Arnaud > | > > | > _______________________________________________ > | > ghc-devs mailing list > | > ghc-devs at haskell.org > | > > | https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail. > | > haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc- > | devs&data=04%7C01 > | > > | %7Csimonpj%40microsoft.com%7C87da21fdcc8e4ed6bef508d908c071fb%7C72f988 > | > > | bf86f141af91ab2d7cd011db47%7C1%7C0%7C637550444930791696%7CUnknown%7CTW > | > > | FpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6 > | > > | Mn0%3D%7C1000&sdata=4JfXyRNMjQKTSLqme2VJU9Dy0s6N4Y8t%2BINHYp38xJk% > | > 3D&reserved=0 -------------- next part -------------- An HTML attachment was scrubbed... URL: From john.ericson at obsidian.systems Tue Apr 27 17:56:26 2021 From: john.ericson at obsidian.systems (John Ericson) Date: Tue, 27 Apr 2021 13:56:26 -0400 Subject: External STG Interpreter blog post In-Reply-To: References: Message-ID: Hi Csaba, Thanks for your interest. I'm not sure whether it would be better to do a call sooner or later, but certainly want to get to this at some point. Fendor and Sylvain (and occasionally I too) have been chipping away at multiple home packages, which I hope could help with these sorts of whole program things. I'm sort of thinking milestones like: 1. Proper Int64 => Single sdist for GHC the library that is truely target/configures-script-choice agnostic, but sdist contains vendored generated code 2. Multiple home packages => Maybe easier to rig up what you have with GHC's driver, though I suppose not needed for Hadrian since it uses one-shot mode. 3. Extensible interface directory => Can better upstream your work to save STG for later, needed for Hadrian / one-shot mode. 4. Matthew's proposal => can get whole program closure for just for TH, pruning away runtime stuff. 5. Put it all together => single sdist that is much more minimally processed, with TH instead of including generated code (no vendoring or Setup.hs evils necessary). Easier to work on IDE stuff with either sdist or fresh checkout of GHC. So it's quite a while before GHC is ready to fully leverage your work on the TH front, I think, but we could still talk through things in advance of that if people are interested. Also, included Sylvain Henry in the thread who's now back from paternity leave, John On 4/20/21 5:38 PM, Csaba Hruska wrote: > Hello, > > In theory the ext-stg interpereter could be used to run TH, but it is > not done yet. > I'm interested in optimization much much more, but I deliberately > designed the ext-stg ir/tooling to be simple and easy to use and > understand for others so that an average Haskell programmer could > implement his ideas or do his experiment. > I'm also open for discussion about the possibilities. We can have a > video meeting about this if you'd like to. > > Cheers, > Csaba > > On Mon, Apr 12, 2021 at 7:57 PM John Ericson > wrote: > > Indeed it is! > > I also am very much hoping this can be the missing piece we need > to allow Template Haskell to work with a stage 0 GHC, so that we > can safely use TH in GHC itself even when the ABI is changing. See > https://github.com/ghc-proposals/ghc-proposals/issues/162 > for > details, where I've also linked Csaba's blog post. (And maybe also > https://gitlab.haskell.org/ghc/ghc/-/wikis/cross-compilation/roadmap > > for more background, and related things like > https://github.com/ghc-proposals/ghc-proposals/pull/412 > .) > > TH could perhaps be used to replace some of the ad-hoc code gen we > have for e.g. RTS constants and primops. This in turn would > simplify the build system, allowing for `cabal install ghc` to > work without shipping generated Haskell code in the sdist. > > John > > On 4/12/21 4:51 AM, Simon Peyton Jones via ghc-devs wrote: >> >> That’s extremely impressive, Csaba. >> >> Maybe of interest to folk who have been thinking about “fat >> interface files”. >> >> >> Simon >> >> *From:*ghc-devs >> *On Behalf Of *Csaba Hruska >> *Sent:* 10 April 2021 11:49 >> *To:* GHC developers >> >> *Subject:* External STG Interpreter blog post >> >> Hello, >> >> I've written a blog post about GHC-WPC's external stg interpreter. >> https://www.patreon.com/posts/external-stg-49857800 >> >> >> Feedback is welcome. >> >> Cheers, >> >> Csaba >> >> >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From rae at richarde.dev Tue Apr 27 19:04:16 2021 From: rae at richarde.dev (Richard Eisenberg) Date: Tue, 27 Apr 2021 19:04:16 +0000 Subject: simple Haskell help needed on #19746 Message-ID: <010f017914b7bc69-0ebb4b75-ff53-4f76-ac13-dbe6ac1ce175-000000@us-east-2.amazonses.com> Hi devs, tl;dr: Is there any (efficient) way to get the String consumed by a `reads`? I'm stuck in thinking about a fix for #19746. Happily, the problem is simple enough that I could assign it in the first few weeks of a Haskell course... and yet I can't find a good solution! So I pose it here for inspiration. The high-level problem: Assign correct source spans to options within a OPTIONS_GHC pragma. Current approach: The payload of an OPTIONS_GHC pragma gets turned into a String and then processed by GHC.Utils.Misc.toArgs :: String -> Either String [String]. The result of toArgs is either an error string (the Left result) or a list of lexed options (the Right result). A little-known fact is that Haskell strings can be put in a OPTIONS_GHC pragma. So I can write both {-# OPTIONS_GHC -funbox-strict-fields #-} and {-# OPTIONS_GHC "-funbox-strict-fieds" #-}. Even stranger, I can write {-# OPTIONS_GHC ["-funbox-strict-fields"] #-}, where GHC will understand a list of strings. While I don't really understand the motivation for this last feature (I posted #19750 about this), the middle option, with the quotes, seems like it might be useful. Desired approach: change toArgs to have this type: RealSrcLoc -> String -> Either String [Located String], where the input RealSrcLoc is the location of the first character of the input String. Then, as toArgs processes the input, it advances the RealSrcLoc (with advanceSrcLoc), allowing us to create correct SrcSpans for each String. Annoying fact: Not all characters advance the source location by one character. Tabs and newlines don't. Perhaps some other characters don't, too. Central stumbling block: toArgs uses `reads` to parse strings. This makes great sense, because `reads` already knows how to convert Haskell String syntax into a proper String. The problem is that we have no idea what characters were consumed by `reads`. And, short of looking at the length of the remainder string in `reads` and comparing it to the length of the input string, there seems to be no way to recreate this lost information. Note that comparing lengths is slow, because we're dealing with Strings here. Once we know what was consumed by `reads`, then we can just repeatedly call advancedSrcLoc, and away we go. Ideas to get unblocked: 1. Just do the slow (quadratic in the number of options) thing, looking at the lengths of strings often. 2. Reimplement reading of strings to return both the result and the characters consumed 3. Incorporate the parsing of OPTIONS_GHC right into the lexer It boggles me that there isn't a better solution here. Do you see one? Thanks, Richard From sgraf1337 at gmail.com Tue Apr 27 19:32:57 2021 From: sgraf1337 at gmail.com (Sebastian Graf) Date: Tue, 27 Apr 2021 21:32:57 +0200 Subject: simple Haskell help needed on #19746 In-Reply-To: <010f017914b7bc69-0ebb4b75-ff53-4f76-ac13-dbe6ac1ce175-000000@us-east-2.amazonses.com> References: <010f017914b7bc69-0ebb4b75-ff53-4f76-ac13-dbe6ac1ce175-000000@us-east-2.amazonses.com> Message-ID: Hi Richard, Maybe I lack a bit of context, but I don't see why you wouldn't choose (3). Extending the lexer/parser will yield a declarative specification of what exactly constitutes a GHC_OPTIONS pragma (albeit in a language that isn't Haskell) and should be more efficient than `reads`, even if you fix it to scale linearly. Plus, it seems that's what we do for other pragmas such as RULE already. That's my opinion anyway. Cheers, Sebastian Am Di., 27. Apr. 2021 um 21:06 Uhr schrieb Richard Eisenberg < rae at richarde.dev>: > Hi devs, > > tl;dr: Is there any (efficient) way to get the String consumed by a > `reads`? > > I'm stuck in thinking about a fix for #19746. Happily, the problem is > simple enough that I could assign it in the first few weeks of a Haskell > course... and yet I can't find a good solution! So I pose it here for > inspiration. > > The high-level problem: Assign correct source spans to options within a > OPTIONS_GHC pragma. > > Current approach: The payload of an OPTIONS_GHC pragma gets turned into a > String and then processed by GHC.Utils.Misc.toArgs :: String -> Either > String [String]. The result of toArgs is either an error string (the Left > result) or a list of lexed options (the Right result). > > A little-known fact is that Haskell strings can be put in a OPTIONS_GHC > pragma. So I can write both {-# OPTIONS_GHC -funbox-strict-fields #-} and > {-# OPTIONS_GHC "-funbox-strict-fieds" #-}. Even stranger, I can write {-# > OPTIONS_GHC ["-funbox-strict-fields"] #-}, where GHC will understand a list > of strings. While I don't really understand the motivation for this last > feature (I posted #19750 about this), the middle option, with the quotes, > seems like it might be useful. > > Desired approach: change toArgs to have this type: RealSrcLoc -> String -> > Either String [Located String], where the input RealSrcLoc is the location > of the first character of the input String. Then, as toArgs processes the > input, it advances the RealSrcLoc (with advanceSrcLoc), allowing us to > create correct SrcSpans for each String. > > Annoying fact: Not all characters advance the source location by one > character. Tabs and newlines don't. Perhaps some other characters don't, > too. > > Central stumbling block: toArgs uses `reads` to parse strings. This makes > great sense, because `reads` already knows how to convert Haskell String > syntax into a proper String. The problem is that we have no idea what > characters were consumed by `reads`. And, short of looking at the length of > the remainder string in `reads` and comparing it to the length of the input > string, there seems to be no way to recreate this lost information. Note > that comparing lengths is slow, because we're dealing with Strings here. > Once we know what was consumed by `reads`, then we can just repeatedly call > advancedSrcLoc, and away we go. > > Ideas to get unblocked: > 1. Just do the slow (quadratic in the number of options) thing, looking at > the lengths of strings often. > 2. Reimplement reading of strings to return both the result and the > characters consumed > 3. Incorporate the parsing of OPTIONS_GHC right into the lexer > > It boggles me that there isn't a better solution here. Do you see one? > > Thanks, > Richard > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From iavor.diatchki at gmail.com Tue Apr 27 20:28:52 2021 From: iavor.diatchki at gmail.com (Iavor Diatchki) Date: Tue, 27 Apr 2021 13:28:52 -0700 Subject: simple Haskell help needed on #19746 In-Reply-To: <010f017914b7bc69-0ebb4b75-ff53-4f76-ac13-dbe6ac1ce175-000000@us-east-2.amazonses.com> References: <010f017914b7bc69-0ebb4b75-ff53-4f76-ac13-dbe6ac1ce175-000000@us-east-2.amazonses.com> Message-ID: Hi Richard, perhaps something like this would work: ```Haskell import Text.ParserCombinators.ReadP(readP_to_S, gather) import qualified Text.Read.Lex as L example :: ReadS (Int,String) example input = do ((xs,L.String t), rest) <- readP_to_S (gather L.lex) input pure ((length xs, t), rest) ``` -Iavor On Tue, Apr 27, 2021 at 12:05 PM Richard Eisenberg wrote: > Hi devs, > > tl;dr: Is there any (efficient) way to get the String consumed by a > `reads`? > > I'm stuck in thinking about a fix for #19746. Happily, the problem is > simple enough that I could assign it in the first few weeks of a Haskell > course... and yet I can't find a good solution! So I pose it here for > inspiration. > > The high-level problem: Assign correct source spans to options within a > OPTIONS_GHC pragma. > > Current approach: The payload of an OPTIONS_GHC pragma gets turned into a > String and then processed by GHC.Utils.Misc.toArgs :: String -> Either > String [String]. The result of toArgs is either an error string (the Left > result) or a list of lexed options (the Right result). > > A little-known fact is that Haskell strings can be put in a OPTIONS_GHC > pragma. So I can write both {-# OPTIONS_GHC -funbox-strict-fields #-} and > {-# OPTIONS_GHC "-funbox-strict-fieds" #-}. Even stranger, I can write {-# > OPTIONS_GHC ["-funbox-strict-fields"] #-}, where GHC will understand a list > of strings. While I don't really understand the motivation for this last > feature (I posted #19750 about this), the middle option, with the quotes, > seems like it might be useful. > > Desired approach: change toArgs to have this type: RealSrcLoc -> String -> > Either String [Located String], where the input RealSrcLoc is the location > of the first character of the input String. Then, as toArgs processes the > input, it advances the RealSrcLoc (with advanceSrcLoc), allowing us to > create correct SrcSpans for each String. > > Annoying fact: Not all characters advance the source location by one > character. Tabs and newlines don't. Perhaps some other characters don't, > too. > > Central stumbling block: toArgs uses `reads` to parse strings. This makes > great sense, because `reads` already knows how to convert Haskell String > syntax into a proper String. The problem is that we have no idea what > characters were consumed by `reads`. And, short of looking at the length of > the remainder string in `reads` and comparing it to the length of the input > string, there seems to be no way to recreate this lost information. Note > that comparing lengths is slow, because we're dealing with Strings here. > Once we know what was consumed by `reads`, then we can just repeatedly call > advancedSrcLoc, and away we go. > > Ideas to get unblocked: > 1. Just do the slow (quadratic in the number of options) thing, looking at > the lengths of strings often. > 2. Reimplement reading of strings to return both the result and the > characters consumed > 3. Incorporate the parsing of OPTIONS_GHC right into the lexer > > It boggles me that there isn't a better solution here. Do you see one? > > Thanks, > Richard > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From rae at richarde.dev Wed Apr 28 02:12:49 2021 From: rae at richarde.dev (Richard Eisenberg) Date: Wed, 28 Apr 2021 02:12:49 +0000 Subject: simple Haskell help needed on #19746 In-Reply-To: References: <010f017914b7bc69-0ebb4b75-ff53-4f76-ac13-dbe6ac1ce175-000000@us-east-2.amazonses.com> Message-ID: <010f017916401797-a6a49590-b9dd-4f74-8206-3ffbf0f227ea-000000@us-east-2.amazonses.com> > On Apr 27, 2021, at 3:32 PM, Sebastian Graf wrote: > > Hi Richard, > > Maybe I lack a bit of context, but I don't see why you wouldn't choose (3). > Extending the lexer/parser will yield a declarative specification of what exactly constitutes a GHC_OPTIONS pragma (albeit in a language that isn't Haskell) and should be more efficient than `reads`, even if you fix it to scale linearly. Plus, it seems that's what we do for other pragmas such as RULE already. (3) is tempting indeed. There are two problems: A. The code that parses strings isn't actually declarative. See https://gitlab.haskell.org/ghc/ghc/-/blob/d2399a46a01a6e46c831c19e797e656a0b8ca16d/compiler/GHC/Parser/Lexer.x#L1965. In particular note the comment: "This stuff is horrible. I hates it." Evidently written by Simon M in 2003 with the introduction of alex. B. We need this code outside the lexer, to deal with e.g. :set in GHCi. > On Apr 27, 2021, at 4:28 PM, Iavor Diatchki wrote: > > ... gather ... Aha! That was the magic incantation I needed but did not have. Many thanks, Iavor. The curious can see https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5509/diffs?commit_id=a560fcbbc7d4e37c4909385c55839f793b570e68#c1078a9741c11d1e15d4c678b107092790295bb3_308_317 for the final result. Thanks! Richard From iavor.diatchki at gmail.com Wed Apr 28 16:24:52 2021 From: iavor.diatchki at gmail.com (Iavor Diatchki) Date: Wed, 28 Apr 2021 09:24:52 -0700 Subject: simple Haskell help needed on #19746 In-Reply-To: <010f017916401797-a6a49590-b9dd-4f74-8206-3ffbf0f227ea-000000@us-east-2.amazonses.com> References: <010f017914b7bc69-0ebb4b75-ff53-4f76-ac13-dbe6ac1ce175-000000@us-east-2.amazonses.com> <010f017916401797-a6a49590-b9dd-4f74-8206-3ffbf0f227ea-000000@us-east-2.amazonses.com> Message-ID: Hello Richard, Just FYI `gather` doesn't work with `readS_to_P` (throws an error), so you'll have to stick to ReadP parsers but, hopefully, that's OK. -Iavor On Tue, Apr 27, 2021 at 7:14 PM Richard Eisenberg wrote: > > > > On Apr 27, 2021, at 3:32 PM, Sebastian Graf wrote: > > > > Hi Richard, > > > > Maybe I lack a bit of context, but I don't see why you wouldn't choose > (3). > > Extending the lexer/parser will yield a declarative specification of > what exactly constitutes a GHC_OPTIONS pragma (albeit in a language that > isn't Haskell) and should be more efficient than `reads`, even if you fix > it to scale linearly. Plus, it seems that's what we do for other pragmas > such as RULE already. > > (3) is tempting indeed. There are two problems: > > A. The code that parses strings isn't actually declarative. See > https://gitlab.haskell.org/ghc/ghc/-/blob/d2399a46a01a6e46c831c19e797e656a0b8ca16d/compiler/GHC/Parser/Lexer.x#L1965. > In particular note the comment: "This stuff is horrible. I hates it." > Evidently written by Simon M in 2003 with the introduction of alex. > > B. We need this code outside the lexer, to deal with e.g. :set in GHCi. > > > On Apr 27, 2021, at 4:28 PM, Iavor Diatchki > wrote: > > > > ... gather ... > > Aha! That was the magic incantation I needed but did not have. Many > thanks, Iavor. > > The curious can see > https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5509/diffs?commit_id=a560fcbbc7d4e37c4909385c55839f793b570e68#c1078a9741c11d1e15d4c678b107092790295bb3_308_317 > for the final result. > > Thanks! > Richard > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From kyrab at mail.ru Thu Apr 29 05:09:19 2021 From: kyrab at mail.ru (kyra) Date: Thu, 29 Apr 2021 08:09:19 +0300 Subject: [ANNOUNCE] Experimental Windows GHC 8.10.5 binary release. Supports Haskell DLLs. Message-ID: <7d8270dd-bf09-12c9-0180-dcdd8f6c3908@mail.ru> An experimental Windows GHC 8.10.5 64-bit Visual C/Native Windows SDK binary compatible distribution is released. Features: Supports Haskell DLLs. Both static and dynamic compilers are shipped. Uses LLVM tools exclusively, hence linking is blazing fast compared to the stock distro. Is position-independent (can be loaded to any address, not only the lower 2GBs) and generates position-independent code. Based on and targets Microsoft Visual C runtime and native Windows SDK. The "full" variant of distro contains 438 extra prebuilt packages and a set utilities, including not only the mandatory cabal, stack, Happy and Alex, but also linters, formatters, preprocessors, and even beasts like pandoc, haskell-language-server and even Agda compiler. Distribution site: https://awson.github.io/ghc-nw/. Cheers, K. Briantsev (aka awson) From simonpj at microsoft.com Thu Apr 29 08:22:35 2021 From: simonpj at microsoft.com (Simon Peyton Jones) Date: Thu, 29 Apr 2021 08:22:35 +0000 Subject: Compiling libraries Message-ID: Ben and other friends What is the approved way to build libraries with (and for) a compiler that I've just built? I tried this: bash$ cabal v2-install --with-ghc=/home/simonpj/code/ghc-9.2-branch/inplace/bin/ghc-stage2 streamly --allow-newer but it failed with Data/Primitive/Types.hs:273:844: error: * Couldn't match expected type 'Word#' with actual type 'Word8#' * In the fourth argument of 'shimmedSetWord8Array#', namely 'x#' (This was for a compiler built from the ghc-9.2 branch.) I'd like to be able to do the same for HEAD. I need to do this to help with the numerous tickets asking about library regressions. For example, I want to be able repoduce @harendra's example, but I can't because I can't build streamly. Thanks! Simon -------------- next part -------------- An HTML attachment was scrubbed... URL: From carter.schonwald at gmail.com Thu Apr 29 19:19:22 2021 From: carter.schonwald at gmail.com (Carter Schonwald) Date: Thu, 29 Apr 2021 15:19:22 -0400 Subject: Compiling libraries In-Reply-To: References: Message-ID: There’s hackage head, which has some docs on the gitlab instance. Though I’m not up to date on how to use it. On Thu, Apr 29, 2021 at 4:24 AM Simon Peyton Jones via ghc-devs < ghc-devs at haskell.org> wrote: > Ben and other friends > > What is the approved way to build libraries with (and for) a compiler that > I’ve just built? > > I tried this: > > bash$ cabal v2-install > --with-ghc=/home/simonpj/code/ghc-9.2-branch/inplace/bin/ghc-stage2 > streamly --allow-newer > > but it failed with > > Data/Primitive/Types.hs:273:844: error: > > • Couldn't match expected type ‘Word#’ with actual type ‘Word8#’ > > • In the fourth argument of ‘shimmedSetWord8Array#’, namely ‘x#’ > > (This was for a compiler built from the ghc-9.2 branch.) > > I’d like to be able to do the same for HEAD. > > I need to do this to help with the numerous tickets asking about library > regressions. For example, I want to be able repoduce @harendra’s example > , but I > can’t because I can’t build streamly. > > Thanks! > > Simon > > > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From a.pelenitsyn at gmail.com Thu Apr 29 21:43:42 2021 From: a.pelenitsyn at gmail.com (Artem Pelenitsyn) Date: Thu, 29 Apr 2021 17:43:42 -0400 Subject: Compiling libraries In-Reply-To: References: Message-ID: Yes, in particular, this: https://gitlab.haskell.org/ghc/head.hackage Readme there has some documentation… On Thu, Apr 29, 2021 at 3:19 PM Carter Schonwald wrote: > There’s hackage head, which has some docs on the gitlab instance. Though > I’m not up to date on how to use it. > > On Thu, Apr 29, 2021 at 4:24 AM Simon Peyton Jones via ghc-devs < > ghc-devs at haskell.org> wrote: > >> Ben and other friends >> >> What is the approved way to build libraries with (and for) a compiler >> that I’ve just built? >> >> I tried this: >> >> bash$ cabal v2-install >> --with-ghc=/home/simonpj/code/ghc-9.2-branch/inplace/bin/ghc-stage2 >> streamly --allow-newer >> >> but it failed with >> >> Data/Primitive/Types.hs:273:844: error: >> >> • Couldn't match expected type ‘Word#’ with actual type ‘Word8#’ >> >> • In the fourth argument of ‘shimmedSetWord8Array#’, namely ‘x#’ >> >> (This was for a compiler built from the ghc-9.2 branch.) >> >> I’d like to be able to do the same for HEAD. >> >> I need to do this to help with the numerous tickets asking about library >> regressions. For example, I want to be able repoduce @harendra’s example >> , but I >> can’t because I can’t build streamly. >> >> Thanks! >> >> Simon >> >> >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > -------------- next part -------------- An HTML attachment was scrubbed... URL: From carter.schonwald at gmail.com Fri Apr 30 01:53:41 2021 From: carter.schonwald at gmail.com (Carter Schonwald) Date: Thu, 29 Apr 2021 21:53:41 -0400 Subject: Compiling libraries In-Reply-To: References: Message-ID: Thanks for pulling that up! I was doing errands away from my desktop all day On Thu, Apr 29, 2021 at 5:43 PM Artem Pelenitsyn wrote: > Yes, in particular, this: > https://gitlab.haskell.org/ghc/head.hackage > > Readme there has some documentation… > > On Thu, Apr 29, 2021 at 3:19 PM Carter Schonwald < > carter.schonwald at gmail.com> wrote: > >> There’s hackage head, which has some docs on the gitlab instance. Though >> I’m not up to date on how to use it. >> >> On Thu, Apr 29, 2021 at 4:24 AM Simon Peyton Jones via ghc-devs < >> ghc-devs at haskell.org> wrote: >> >>> Ben and other friends >>> >>> What is the approved way to build libraries with (and for) a compiler >>> that I’ve just built? >>> >>> I tried this: >>> >>> bash$ cabal v2-install >>> --with-ghc=/home/simonpj/code/ghc-9.2-branch/inplace/bin/ghc-stage2 >>> streamly --allow-newer >>> >>> but it failed with >>> >>> Data/Primitive/Types.hs:273:844: error: >>> >>> • Couldn't match expected type ‘Word#’ with actual type ‘Word8#’ >>> >>> • In the fourth argument of ‘shimmedSetWord8Array#’, namely ‘x#’ >>> >>> (This was for a compiler built from the ghc-9.2 branch.) >>> >>> I’d like to be able to do the same for HEAD. >>> >>> I need to do this to help with the numerous tickets asking about library >>> regressions. For example, I want to be able repoduce @harendra’s >>> example , >>> but I can’t because I can’t build streamly. >>> >>> Thanks! >>> >>> Simon >>> >>> >>> _______________________________________________ >>> ghc-devs mailing list >>> ghc-devs at haskell.org >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >>> >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ben at smart-cactus.org Fri Apr 30 02:26:54 2021 From: ben at smart-cactus.org (Ben Gamari) Date: Thu, 29 Apr 2021 22:26:54 -0400 Subject: Compiling libraries In-Reply-To: References: Message-ID: <87v984jyms.fsf@smart-cactus.org> Simon Peyton Jones via ghc-devs writes: > Ben and other friends > What is the approved way to build libraries with (and for) a compiler that I've just built? > I tried this: > > bash$ cabal v2-install --with-ghc=/home/simonpj/code/ghc-9.2-branch/inplace/bin/ghc-stage2 streamly --allow-newer > but it failed with > > Data/Primitive/Types.hs:273:844: error: > > * Couldn't match expected type 'Word#' with actual type 'Word8#' > > * In the fourth argument of 'shimmedSetWord8Array#', namely 'x#' As noted by others, we maintain head.hackage for precisely this reason. It's not perfect, but I use it regularly to build Hackage packages with pre-releases. I have a draft blog post (which sadly has run into technical challenges which have prevented publishing) which describes usage [1]. Cheers, - Ben [1] https://gitlab.haskell.org/ghc/homepage/-/merge_requests/29 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: not available URL: From rae at richarde.dev Fri Apr 30 20:12:35 2021 From: rae at richarde.dev (Richard Eisenberg) Date: Fri, 30 Apr 2021 20:12:35 +0000 Subject: linting GHC Message-ID: <010f017924695d1f-ff64315f-b708-4cb9-b851-aa7c13f588ee-000000@us-east-2.amazonses.com> Hi devs, I see in CI that we're now linting the GHC source code. In order to avoid CI failure, I would like to lint locally, and I somehow know (though I forget where I learned it) that hadrian/build lint:compiler is the way to do this. After building hlint, I am able to do this. But the output is surprising; here is the tail: # hlint (for lint:compiler) compiler/GHC/Tc/Utils/Unify.hs:2:1-36: Warning: Unused LANGUAGE pragma Found: {-# LANGUAGE MultiWayIf #-} Perhaps you should remove it. compiler/stage1/build/GHC/Parser.hs:6:1-29: Warning: Unused LANGUAGE pragma Found: {-# LANGUAGE ViewPatterns #-} Perhaps you should remove it. compiler/stage1/build/GHC/Parser.hs:8:1-27: Warning: Unused LANGUAGE pragma Found: {-# LANGUAGE LambdaCase #-} Perhaps you should remove it. compiler/stage1/build/GHC/Parser.hs:38:1-54: Warning: Use fewer imports Found: import Control.Monad ( unless, liftM, when, (<=<) ) import Control.Monad ( ap ) Perhaps: import Control.Monad ( unless, liftM, when, (<=<), ap ) compiler/stage1/build/GHC/Parser.hs:43:1-18: Warning: Use fewer imports Found: import GHC.Prelude import GHC.Prelude Perhaps: import GHC.Prelude compiler/stage1/build/GHC/Cmm/Parser.hs:17:1-24: Warning: Use fewer imports Found: import GHC.StgToCmm.Prof import GHC.StgToCmm.Prof Perhaps: import GHC.StgToCmm.Prof compiler/stage1/build/GHC/Cmm/Parser.hs:71:1-20: Warning: Use fewer imports Found: import Control.Monad import Control.Monad ( ap ) Perhaps: import Control.Monad compiler/stage2/build/GHC/Parser.hs:6:1-29: Warning: Unused LANGUAGE pragma Found: {-# LANGUAGE ViewPatterns #-} Perhaps you should remove it. compiler/stage2/build/GHC/Parser.hs:8:1-27: Warning: Unused LANGUAGE pragma Found: {-# LANGUAGE LambdaCase #-} Perhaps you should remove it. compiler/stage2/build/GHC/Parser.hs:38:1-54: Warning: Use fewer imports Found: import Control.Monad ( unless, liftM, when, (<=<) ) import Control.Monad ( ap ) Perhaps: import Control.Monad ( unless, liftM, when, (<=<), ap ) compiler/stage2/build/GHC/Parser.hs:43:1-18: Warning: Use fewer imports Found: import GHC.Prelude import GHC.Prelude Perhaps: import GHC.Prelude compiler/stage2/build/GHC/Cmm/Parser.hs:17:1-24: Warning: Use fewer imports Found: import GHC.StgToCmm.Prof import GHC.StgToCmm.Prof Perhaps: import GHC.StgToCmm.Prof compiler/stage2/build/GHC/Cmm/Parser.hs:71:1-20: Warning: Use fewer imports Found: import Control.Monad import Control.Monad ( ap ) Perhaps: import Control.Monad 13 hints Error when running Shake build system: at want, called at src/Main.hs:104:30 in main:Main * Depends on: lint:compiler at cmd_, called at src/Rules/Lint.hs:70:3 in main:Rules.Lint * Raised the exception: Development.Shake.cmd, system command failed Command line: hlint -j --cpp-define x86_64_HOST_ARCH --cpp-include=includes --cpp-include=_build/stage1/lib --cpp-include=compiler --cpp-include=_build/stage1/lib/ghcplatform.h --cpp-include=_build/stage1/compiler/build -h compiler/.hlint.yaml compiler Exit code: 1 Stderr: There are several curiosities here: * I introduced one of these errors, in GHC.Tc.Utils.Unify; the other errors are in files I have not modified. Will these affect CI? * Hadrian crashes at the end. Is that expected? It says "system command failed" with a bunch of gobbledegook. Is this an error within Hadrian? Or is this just Hadrian's way of saying that it encountered an error when linting? If it's the latter, the current message is hard to read. * As you may be able to see, I use a dark-background terminal window. The colors output by the hlint process are nigh impossible to read when describing redundant LANGUAGE pragmas. Are these colors configurable? Thanks! Richard -------------- next part -------------- An HTML attachment was scrubbed... URL: