
Good evening, So I’ve been working on Haskell user-facing tooling in general for some years. By that I mean the level of Emacs talking with Haskell tools. I wrote the interactive-haskell-mode (most functionality exists in this file https://github.com/haskell/haskell-mode/blob/master/haskell-process.el#L1 ). which launches a GHCi process in a pipe and tries very earnestly to handle input/output with the process reasonably. For Emacs fanciers: Written in Elisp, there’s a nice command queue that you put commands onto, they will all be run on a FIFO one-by-one order, and eventually you’ll get a result back. Initially it was just me using it, but with the help of Herbert Riedel it’s now a mode on equal footing with the venerable inferior-haskell-mode all ye Emacs users know and love. It’s part of haskell-mode and can be enabled by enabling the interactive-haskell-mode minor mode. For years I’ve been using GHCi as a base and it’s been very reliable for almost every project I’ve done (the only exceptions are things like SDL and OpenGL, which are well known to be difficult to load in GHCi, at least on Linux). I think we’ve built up a good set of functionality https://github.com/haskell/haskell-mode/wiki/Haskell-Interactive-Mode purely based on asking GHCi things and getting it to do things. I literally use GHCi for everything. For type-checking, type info, I even send “:!cabal build” to it. Everything goes through it. I love my GHCi. Now, I’m sort of at the end of the line of where I can take GHCi. Here are the problems as I see them today: 1. There is no programmatic means of communicating with the process. I can’t send a command and get a result cleanly, I have to regex match on the prompt, and that is only so reliable. At the moment we solve this by using \4 (aka ‘END OF TRANSMISSION’). Also messages (warnings, errors, etc.) need to be parsed which is also icky, especially in the REPL when e.g. a defaulted Integer warning will mix with the output. Don’t get me started on handling multi-line prompts! Hehe. 2. GHCi, as a REPL, does not distinguish between stdout, stderr and the result of your evaluation. This can be problematic for making a smooth REPL UI, your results can often (with threading) be interspersed in unkind ways. I cannot mitigate this with any kind of GHCi trickery. 3. It forgets information when you reload. (I know this is intentional.) 4. Not enough information is exposed to the user. (Is there ever? ;) 5. There is a time-to-market overhead of contributing to GHCi — if I want a cool feature, I can write it on a locally compiled version of GHC. But for the work projects I have, I’m restricted to given GHC versions, as are other people. They have to wait to get the good features. 6. This is just a personal point — I’ve like to talk to GHCi over a socket, so that I can run it on a remote machine. Those familiar with Common Lisp will be reminded of SLIME and Swank. Examples for point 4 are: - Type of sub-expressions. - Go to definition of thing at point (includes local scope). - Local-scope completion. - A hoogle-like query (as seen in Idris recently). - Documentation lookup. - Suggest imports for symbols. - Show core for the current module. - Show CMM for the current module, ASM, etc. SLIME can do this. - Expand the template-haskell at point. - The :i command is amazingly useful, but programmatic access would be even better.¹ - Case split anyone? - Etc. ¹I’ve integrated with it in Emacs so that I can C-c C-i any identifier and it’ll popup a buffer with the :i result and then within that buffer I can drill down further with C-c C-i again. It makes for very natural exploration of a type. You’ve seen some of these features in GHC Mod, in hdevtools, in the FP Haskell Center, maybe some are in Yi, possibly also in Leksah (?). So in light of point (5), I thought: I’ve used the GHC API before, it can do interactive evaluation, why not write a project like “ghc-server” which encodes all these above ideas as a “drop-in” replacement for GHCi? After all I could work on my own without anybody getting my way over architecture decisions, etc. And that’s what I did. It’s here https://github.com/chrisdone/ghc-server. Surprisingly, it kind of works. You run it in your directoy like you would do “cabal repl” and it sets up all the extensions and package dependencies and starts accepting connections. It will compile across three major GHC versions. Hurray! Rub our hands together and call it done, right? Sadly not, the trouble is twofold: 1. The first problem with this is that every three projects will segfault or panic when trying to load in a project that GHCi will load in happily. The reasons are mysterious to me and I’ve already lugged over the GHC API to get to this point, so that kind of thing happening means that I have to fall back to my old GHCi-based setup, and is disappointing. People have similar complaints of GHC Mod & co. “Getting it to work” is a deterrant. 2. While this would be super beneficial for me, and has been a good learning experience for “what works and what doesn’t”, we end up with yet another alternative tool, that only a few people are using. 3. There are just certain behaviours and fixes here and there that GHCi does that take time to reproduce. So let’s go back to the GHCi question: is there still a development overhead for adding features to GHCi? Yes, new ideas need acceptance and people have to wait (potentially a year) for a new feature that they could be using right now. An alternative method is to do what Herbert did which is to release a “ghci-ng” http://hackage.haskell.org/package/ghci-ng which sports new shiny features that people (with the right GHC version) will be able to compile and use as a drop-in for GHCi. It’s the same codebase, but with more stuff! An example is the “:complete” command, this lets IDE implementers do completion at least at the REPL level. Remember the list of features earlier? Why are they not in GHCi? So, of course, this got me thinking that I could instead make ghc-server be based off of GHCi’s actual codebase. I could rebase upon the latest GHC release and maintain 2-3 GHC versions backwards. That’s certainly doable, it would essentially give me “GHCi++”. Good for me, I just piggy back on the GHCi goodness and then use the GHC API for additional things as I’m doing now. But is there a way I can get any of this into the official repo? For example, could I hack on this (perhaps with Herbert) as “ghci-ng”, provide an alternative JSON communication layer (e.g. via some —use-json flag) and and socket listener (—listen-on ), a way to distinguish stdout/stderr (possibly by forking a process, unsure at this stage), and then any of the above features (point 4) listed. I make sure that I’m rebasing upon HEAD, as if to say ghci-ng is a kind of submodule, and then when release time comes we merge back in any new stuff since the last release. Early adopters can use ghci-ng, and everyone benefits from official GHC releases. The only snag there is that, personally speaking, it would be better if ghci-ng would compile on older GHC versions. So if GHC 7.10 is the latest release, it would still be nice (and it *seems* pretty feasible) that GHC 7.8 users could still cabal install it without issue. People shouldn’t have to wait if they don’t have to. Well, that’s everything. Thoughts? Ciao!

I think there is currently a more general interest in this, and the ghc-mod
guys are thinking on similar lines, see
https://github.com/kazu-yamamoto/ghc-mod/issues/349
Alan
On Sat, Oct 18, 2014 at 5:48 PM, Christopher Done
Good evening,
So I’ve been working on Haskell user-facing tooling in general for some years. By that I mean the level of Emacs talking with Haskell tools.
I wrote the interactive-haskell-mode (most functionality exists in this file https://github.com/haskell/haskell-mode/blob/master/haskell-process.el#L1 ). which launches a GHCi process in a pipe and tries very earnestly to handle input/output with the process reasonably.
For Emacs fanciers: Written in Elisp, there’s a nice command queue that you put commands onto, they will all be run on a FIFO one-by-one order, and eventually you’ll get a result back. Initially it was just me using it, but with the help of Herbert Riedel it’s now a mode on equal footing with the venerable inferior-haskell-mode all ye Emacs users know and love. It’s part of haskell-mode and can be enabled by enabling the interactive-haskell-mode minor mode.
For years I’ve been using GHCi as a base and it’s been very reliable for almost every project I’ve done (the only exceptions are things like SDL and OpenGL, which are well known to be difficult to load in GHCi, at least on Linux). I think we’ve built up a good set of functionality https://github.com/haskell/haskell-mode/wiki/Haskell-Interactive-Mode purely based on asking GHCi things and getting it to do things.
I literally use GHCi for everything. For type-checking, type info, I even send “:!cabal build” to it. Everything goes through it. I love my GHCi.
Now, I’m sort of at the end of the line of where I can take GHCi. Here are the problems as I see them today:
1. There is no programmatic means of communicating with the process. I can’t send a command and get a result cleanly, I have to regex match on the prompt, and that is only so reliable. At the moment we solve this by using \4 (aka ‘END OF TRANSMISSION’). Also messages (warnings, errors, etc.) need to be parsed which is also icky, especially in the REPL when e.g. a defaulted Integer warning will mix with the output. Don’t get me started on handling multi-line prompts! Hehe. 2. GHCi, as a REPL, does not distinguish between stdout, stderr and the result of your evaluation. This can be problematic for making a smooth REPL UI, your results can often (with threading) be interspersed in unkind ways. I cannot mitigate this with any kind of GHCi trickery. 3. It forgets information when you reload. (I know this is intentional.) 4. Not enough information is exposed to the user. (Is there ever? ;) 5. There is a time-to-market overhead of contributing to GHCi — if I want a cool feature, I can write it on a locally compiled version of GHC. But for the work projects I have, I’m restricted to given GHC versions, as are other people. They have to wait to get the good features. 6. This is just a personal point — I’ve like to talk to GHCi over a socket, so that I can run it on a remote machine. Those familiar with Common Lisp will be reminded of SLIME and Swank.
Examples for point 4 are:
- Type of sub-expressions. - Go to definition of thing at point (includes local scope). - Local-scope completion. - A hoogle-like query (as seen in Idris recently). - Documentation lookup. - Suggest imports for symbols. - Show core for the current module. - Show CMM for the current module, ASM, etc. SLIME can do this. - Expand the template-haskell at point. - The :i command is amazingly useful, but programmatic access would be even better.¹ - Case split anyone? - Etc.
¹I’ve integrated with it in Emacs so that I can C-c C-i any identifier and it’ll popup a buffer with the :i result and then within that buffer I can drill down further with C-c C-i again. It makes for very natural exploration of a type.
You’ve seen some of these features in GHC Mod, in hdevtools, in the FP Haskell Center, maybe some are in Yi, possibly also in Leksah (?).
So in light of point (5), I thought: I’ve used the GHC API before, it can do interactive evaluation, why not write a project like “ghc-server” which encodes all these above ideas as a “drop-in” replacement for GHCi? After all I could work on my own without anybody getting my way over architecture decisions, etc.
And that’s what I did. It’s here https://github.com/chrisdone/ghc-server. Surprisingly, it kind of works. You run it in your directoy like you would do “cabal repl” and it sets up all the extensions and package dependencies and starts accepting connections. It will compile across three major GHC versions. Hurray! Rub our hands together and call it done, right? Sadly not, the trouble is twofold:
1. The first problem with this is that every three projects will segfault or panic when trying to load in a project that GHCi will load in happily. The reasons are mysterious to me and I’ve already lugged over the GHC API to get to this point, so that kind of thing happening means that I have to fall back to my old GHCi-based setup, and is disappointing. People have similar complaints of GHC Mod & co. “Getting it to work” is a deterrant. 2. While this would be super beneficial for me, and has been a good learning experience for “what works and what doesn’t”, we end up with yet another alternative tool, that only a few people are using. 3. There are just certain behaviours and fixes here and there that GHCi does that take time to reproduce.
So let’s go back to the GHCi question: is there still a development overhead for adding features to GHCi? Yes, new ideas need acceptance and people have to wait (potentially a year) for a new feature that they could be using right now.
An alternative method is to do what Herbert did which is to release a “ghci-ng” http://hackage.haskell.org/package/ghci-ng which sports new shiny features that people (with the right GHC version) will be able to compile and use as a drop-in for GHCi. It’s the same codebase, but with more stuff! An example is the “:complete” command, this lets IDE implementers do completion at least at the REPL level. Remember the list of features earlier? Why are they not in GHCi?
So, of course, this got me thinking that I could instead make ghc-server be based off of GHCi’s actual codebase. I could rebase upon the latest GHC release and maintain 2-3 GHC versions backwards. That’s certainly doable, it would essentially give me “GHCi++”. Good for me, I just piggy back on the GHCi goodness and then use the GHC API for additional things as I’m doing now.
But is there a way I can get any of this into the official repo? For example, could I hack on this (perhaps with Herbert) as “ghci-ng”, provide an alternative JSON communication layer (e.g. via some —use-json flag) and and socket listener (—listen-on ), a way to distinguish stdout/stderr (possibly by forking a process, unsure at this stage), and then any of the above features (point 4) listed. I make sure that I’m rebasing upon HEAD, as if to say ghci-ng is a kind of submodule, and then when release time comes we merge back in any new stuff since the last release. Early adopters can use ghci-ng, and everyone benefits from official GHC releases.
The only snag there is that, personally speaking, it would be better if ghci-ng would compile on older GHC versions. So if GHC 7.10 is the latest release, it would still be nice (and it *seems* pretty feasible) that GHC 7.8 users could still cabal install it without issue. People shouldn’t have to wait if they don’t have to.
Well, that’s everything. Thoughts?
Ciao!
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://www.haskell.org/mailman/listinfo/ghc-devs

On 10/18/2014 04:48 PM, Christopher Done wrote:
Good evening,
So I’ve been working on Haskell user-facing tooling in general for some years. By that I mean the level of Emacs talking with Haskell tools.
[snip]
You’ve seen some of these features in GHC Mod, in hdevtools, in the FP Haskell Center, maybe some are in Yi, possibly also in Leksah (?).
Currently any Yi support for such things is either poor or not present. We currently also just talk to the REPL and parse stuff out. The upside is that it is possible for us to talk to any Haskell stuff natively (including GHC API/ghc-mod) so we don't need to depend as much on GHCi as emacs or other editors, at least in theory.
[snip]
Well, that’s everything. Thoughts?
Ciao!
Sounds interesting. My only request/comment is that I hope whatever conclusion you come to, the library part of it will be usable just as much (or even more) as the executable: if we can talk to the library natively then that's much easier than talking to some remote socket and parsing out data. -- Mateusz K.

From: Mateusz Kowalczyk
Sounds interesting. My only request/comment is that I hope whatever conclusion you come to, the library part of it will be usable just as much (or even more) as the executable: if we can talk to the library natively then that's much easier than talking to some remote socket and parsing out data.
I agree! We should factor out useful bits in ghci into a library that can be used by other tools too since there's quite a lot of logic and workarounds in ghci that tools have to copy otherwise. --Daniel

On 18 October 2014 19:05, Mateusz Kowalczyk
Sounds interesting. My only request/comment is that I hope whatever conclusion you come to, the library part of it will be usable just as much (or even more) as the executable: if we can talk to the library natively then that's much easier than talking to some remote socket and parsing out data.
I'm not sure what GHC HQ would think of GHCi exposing an API, but certainly I'm for it. Yi would have no reason to talk via JSON API if it could just call the functions in a type-safe way directly, or at least have an API that does the talking to the remote socket so that you don't have to.

From: Christopher Done
1. The first problem with this is that every three projects will segfault or panic when trying to load in a project that GHCi will load in happily. [...] People have similar complaints of GHC Mod & co. “Getting it to work” is a deterrant.
Do you have any examples of such projects, I've never seen any complaints about ghc-mod doing this.
So, of course, this got me thinking that I could instead make ghc-server be based off of GHCi’s actual codebase. I could rebase upon the latest GHC release and maintain 2-3 GHC versions backwards. That’s certainly doable, it would essentially give me “GHCi++”. Good for me, I just piggy back on the GHCi goodness and then use the GHC API for additional things as I’m doing now.
I had that idea too for ghc-mod unfortunately it's not so easy as ghci's internal API mostly consists of functions that only have side effects (i.e. don't return anything you can process further) :/
But is there a way I can get any of this into the official repo? For example, could I hack on this (perhaps with Herbert) as “ghci-ng”, provide an alternative JSON communication layer (e.g. via some ―use-json flag) and and socket listener (―listen-on ), a way to distinguish stdout/stderr (possibly by forking a process, unsure at this stage), and then any of the above features (point 4) listed. I make sure that I’m rebasing upon HEAD, as if to say ghci-ng is a kind of submodule, and then when release time comes we merge back in any new stuff since the last release. Early adopters can use ghci-ng, and everyone benefits from official GHC releases.
The only snag there is that, personally speaking, it would be better if ghci-ng would compile on older GHC versions. So if GHC 7.10 is the latest release, it would still be nice (and it *seems* pretty feasible) that GHC 7.8 users could still cabal install it without issue. People shouldn’t have to wait if they don’t have to.
Sounds awesome I'd love to get in on this :) --Daniel

On 18 October 2014 19:28, Daniel Gröber
Do you have any examples of such projects, I've never seen any complaints about ghc-mod doing this.
I haven't used ghc-mod enough to have a crash happen to me. I couldn't get it to work the times I'd tried it and others make this complaint. Whereas GHCi works for everyone!
Sounds awesome I'd love to get in on this :)
Herbert doesn't have time to hack on it, but was encouraging about continuing with ghci-ng. I'm thinking to try forward-porting ghci-ng to GHC 7.8, or otherwise extracting GHC 7.8's GHCi again and then backporting it to 7.6. (Under the assumption that current + past is a reasonable number of GHCs to support.) I'm going to experiment with the JSON interface and I'll report back with results.

From: Christopher Done
I haven't used ghc-mod enough to have a crash happen to me. I couldn't get it to work the times I'd tried it and others make this complaint. Whereas GHCi works for everyone!
I didn't mean ghc-mod specifically. I was wondering which projects caused this problem for you (or others) when using ghc-server (or something else) as I'd like to try if it happens with ghc-mod too.
Herbert doesn't have time to hack on it, but was encouraging about continuing with ghci-ng.
Yeah I saw that conversation on IRC.
I'm thinking to try forward-porting ghci-ng to GHC 7.8, or otherwise extracting GHC 7.8's GHCi again and then backporting it to 7.6. (Under the assumption that current + past is a reasonable number of GHCs to support.) I'm going to experiment with the JSON interface and I'll report back with results.
Cool :) --Daniel

On 2014-10-18 at 19:59:24 +0200, Christopher Done wrote: [...]
Herbert doesn't have time to hack on it, but was encouraging about continuing with ghci-ng.
Yeah, it's quite convenient to hack on GHCi that way as it's just an ordinary Cabal package (so it doesn't require to setup a GHC source-tree and wrangle with the GHC build-system), if you're lucky enough (which is most of the time) that the parts you want to tweak don't require changing the GHC API.
I'm thinking to try forward-porting ghci-ng to GHC 7.8,
Iirc all of the deltas in ghci-ng-7.6 relative to GHC 7.6.3 landed in GHC 7.8.1, so extracting the latest GHCi frontend code would be probably better.
or otherwise extracting GHC 7.8's GHCi again and then backporting it to 7.6.
Fwiw, I setup the ghci-ng .cabal's in such a way, that if you 'cabal install ghci-ng' with a GHC 7.4.x, you'd get a ghci-ng-7.4.2.1, while when on GHC 7.6.x, ghci-ng-7.6.3.5 would be selected. Supporting multiple major-versions of the GHC API simultanously in the same code-base could prove to be rather tedious (and make it more difficult to extract clean patches to merge back into GHC HEAD). But this is only speculation on my part, so your mileage may vary....
(Under the assumption that current + past is a reasonable number of GHCs to support.) I'm going to experiment with the JSON interface and I'll report back with results.
You may want to be careful with the build-deps though; e.g. if you use JSON and want this to be merged back into GHC HEAD at some point, we may need something lighter than the usual go-to JSON implementation `aeson` in terms of build-deps... PS: I've added you to http://hackage.haskell.org/package/ghci-ng/maintainers/, just in case...

On 18 October 2014 22:36, Herbert Valerio Riedel
ordinary Cabal package (so it doesn't require to setup a GHC source-tree and wrangle with the GHC build-system), if you're lucky enough (which is most of the time) that the parts you want to tweak don't require changing the GHC API.
Right, so far my work on ghc-server has all been doable as far back as GHC 7.2. Iirc all of the deltas in ghci-ng-7.6 relative to GHC 7.6.3 landed in
GHC 7.8.1, so extracting the latest GHCi frontend code would be probably better.
Okies! Supporting multiple major-versions of the GHC API simultanously in the
same code-base could prove to be rather tedious (and make it more
difficult to extract clean patches to merge back into GHC HEAD). But this is only speculation on my part, so your mileage may vary....
It hasn’t been too tedious to support old versions at least on ghc-server — I went back as far as 7.2, but GHC 7.6 for example is very similar to 7.8 so kind of comes “for free”. Makes sense, really. One major version bump to another is rather passable, it’s when going a few versions back that it becomes tedious. At least in my experience. I’ll see anyway. You may want to be careful with the build-deps though; e.g. if you use
JSON and want this to be merged back into GHC HEAD at some point, we may need something lighter than the usual go-to JSON implementation `aeson` in terms of build-deps...
Indeed, I was considering extracting and embedding a simple parser/printer from the old json package (remember that?). Served me well for years before aeson usurped it. :-) I think it can be reduced down to one module that operators on Strings. PS: I've added you to
http://hackage.haskell.org/package/ghci-ng/maintainers/, just in case...
Thanks!

Christopher You are doing very cool things. Thank you. What I’m puzzled about is this: the GHC API *is* a programmatic interface to GHC. Why not just use it? I can think of some reasons: · It’s not very clear just what’s in the GHC API and what isn’t, since you have access to all of GHC’s internals if you use –package ghc. And the API isn’t very well designed. (Answer: could you help make it better?) · You want some functionality that is currently in GHCi, rather than in the ‘ghc’ package. (Answer: maybe we should move that functionality into the ‘ghc’ package and make it part of the GHC API?) · You have to be writing in Haskell to use the GHC API, whereas you want a separate process you connect to via a socket. (Answer: Excellent: write a server wrapper around the GHC API that offers a JSON interface, or whatever the right vocabulary is. Sounds as if you have more or less done this.) · Moreover, the API changes pretty regularly, and you want multi-compiler support. (No answer: I don’t know how to simultaneously give access to new stuff without risking breaking old stuff.) My meta-point is this: GHC is wide open to people like you building a consensus about how GHC’s basic functionality should be wrapped up and exposed to clients. (Luite is another person who has led in this space, via GHCJS.) So please do go ahead and lay out the way it *should* be done, think about migration paths, build a consensus etc. Much better that than do fragile screen-scraping on GHCi’s textual output. Thanks for what you are doing here. Simon From: ghc-devs [mailto:ghc-devs-bounces@haskell.org] On Behalf Of Christopher Done Sent: 18 October 2014 16:49 To: ghc-devs@haskell.org Subject: Making GHCi awesomer? Good evening, So I’ve been working on Haskell user-facing tooling in general for some years. By that I mean the level of Emacs talking with Haskell tools. I wrote the interactive-haskell-mode (most functionality exists in this filehttps://github.com/haskell/haskell-mode/blob/master/haskell-process.el#L1). which launches a GHCi process in a pipe and tries very earnestly to handle input/output with the process reasonably. For Emacs fanciers: Written in Elisp, there’s a nice command queue that you put commands onto, they will all be run on a FIFO one-by-one order, and eventually you’ll get a result back. Initially it was just me using it, but with the help of Herbert Riedel it’s now a mode on equal footing with the venerable inferior-haskell-mode all ye Emacs users know and love. It’s part of haskell-mode and can be enabled by enabling the interactive-haskell-mode minor mode. For years I’ve been using GHCi as a base and it’s been very reliable for almost every project I’ve done (the only exceptions are things like SDL and OpenGL, which are well known to be difficult to load in GHCi, at least on Linux). I think we’ve built up a good set of functionalityhttps://github.com/haskell/haskell-mode/wiki/Haskell-Interactive-Mode purely based on asking GHCi things and getting it to do things. I literally use GHCi for everything. For type-checking, type info, I even send “:!cabal build” to it. Everything goes through it. I love my GHCi. Now, I’m sort of at the end of the line of where I can take GHCi. Here are the problems as I see them today: 1. There is no programmatic means of communicating with the process. I can’t send a command and get a result cleanly, I have to regex match on the prompt, and that is only so reliable. At the moment we solve this by using \4 (aka ‘END OF TRANSMISSION’). Also messages (warnings, errors, etc.) need to be parsed which is also icky, especially in the REPL when e.g. a defaulted Integer warning will mix with the output. Don’t get me started on handling multi-line prompts! Hehe. 2. GHCi, as a REPL, does not distinguish between stdout, stderr and the result of your evaluation. This can be problematic for making a smooth REPL UI, your results can often (with threading) be interspersed in unkind ways. I cannot mitigate this with any kind of GHCi trickery. 3. It forgets information when you reload. (I know this is intentional.) 4. Not enough information is exposed to the user. (Is there ever? ;) 5. There is a time-to-market overhead of contributing to GHCi — if I want a cool feature, I can write it on a locally compiled version of GHC. But for the work projects I have, I’m restricted to given GHC versions, as are other people. They have to wait to get the good features. 6. This is just a personal point — I’ve like to talk to GHCi over a socket, so that I can run it on a remote machine. Those familiar with Common Lisp will be reminded of SLIME and Swank. Examples for point 4 are: · Type of sub-expressions. · Go to definition of thing at point (includes local scope). · Local-scope completion. · A hoogle-like query (as seen in Idris recently). · Documentation lookup. · Suggest imports for symbols. · Show core for the current module. · Show CMM for the current module, ASM, etc. SLIME can do this. · Expand the template-haskell at point. · The :i command is amazingly useful, but programmatic access would be even better.¹ · Case split anyone? · Etc. ¹I’ve integrated with it in Emacs so that I can C-c C-i any identifier and it’ll popup a buffer with the :i result and then within that buffer I can drill down further with C-c C-i again. It makes for very natural exploration of a type. You’ve seen some of these features in GHC Mod, in hdevtools, in the FP Haskell Center, maybe some are in Yi, possibly also in Leksah (?). So in light of point (5), I thought: I’ve used the GHC API before, it can do interactive evaluation, why not write a project like “ghc-server” which encodes all these above ideas as a “drop-in” replacement for GHCi? After all I could work on my own without anybody getting my way over architecture decisions, etc. And that’s what I did. It’s herehttps://github.com/chrisdone/ghc-server. Surprisingly, it kind of works. You run it in your directoy like you would do “cabal repl” and it sets up all the extensions and package dependencies and starts accepting connections. It will compile across three major GHC versions. Hurray! Rub our hands together and call it done, right? Sadly not, the trouble is twofold: 1. The first problem with this is that every three projects will segfault or panic when trying to load in a project that GHCi will load in happily. The reasons are mysterious to me and I’ve already lugged over the GHC API to get to this point, so that kind of thing happening means that I have to fall back to my old GHCi-based setup, and is disappointing. People have similar complaints of GHC Mod & co. “Getting it to work” is a deterrant. 2. While this would be super beneficial for me, and has been a good learning experience for “what works and what doesn’t”, we end up with yet another alternative tool, that only a few people are using. 3. There are just certain behaviours and fixes here and there that GHCi does that take time to reproduce. So let’s go back to the GHCi question: is there still a development overhead for adding features to GHCi? Yes, new ideas need acceptance and people have to wait (potentially a year) for a new feature that they could be using right now. An alternative method is to do what Herbert did which is to release a “ghci-ng”http://hackage.haskell.org/package/ghci-ng which sports new shiny features that people (with the right GHC version) will be able to compile and use as a drop-in for GHCi. It’s the same codebase, but with more stuff! An example is the “:complete” command, this lets IDE implementers do completion at least at the REPL level. Remember the list of features earlier? Why are they not in GHCi? So, of course, this got me thinking that I could instead make ghc-server be based off of GHCi’s actual codebase. I could rebase upon the latest GHC release and maintain 2-3 GHC versions backwards. That’s certainly doable, it would essentially give me “GHCi++”. Good for me, I just piggy back on the GHCi goodness and then use the GHC API for additional things as I’m doing now. But is there a way I can get any of this into the official repo? For example, could I hack on this (perhaps with Herbert) as “ghci-ng”, provide an alternative JSON communication layer (e.g. via some —use-json flag) and and socket listener (—listen-on ), a way to distinguish stdout/stderr (possibly by forking a process, unsure at this stage), and then any of the above features (point 4) listed. I make sure that I’m rebasing upon HEAD, as if to say ghci-ng is a kind of submodule, and then when release time comes we merge back in any new stuff since the last release. Early adopters can use ghci-ng, and everyone benefits from official GHC releases. The only snag there is that, personally speaking, it would be better if ghci-ng would compile on older GHC versions. So if GHC 7.10 is the latest release, it would still be nice (and it seems pretty feasible) that GHC 7.8 users could still cabal install it without issue. People shouldn’t have to wait if they don’t have to. Well, that’s everything. Thoughts? Ciao!

Simon Peyton Jones
Christopher
You are doing very cool things. Thank you.
What I’m puzzled about is this: the GHC API *is* a programmatic interface to GHC. Why not just use it?
One issue that sometimes bites me when trying to compile against GHC is that of dependencies. When compiling against GHC you are bound to use whatever dependency versions GHC was compiled with. In some cases these can be a bit dated which can lead to Cabal hell. I'm not really sure what can be done about this short of making Cabal/GHC more robust in the face of multiple dependency versions within the same build. Cheers, - Ben

On Oct 20, 2014, at 09:14, Ben Gamari
wrote: Simon Peyton Jones
writes: Christopher
You are doing very cool things. Thank you.
What I’m puzzled about is this: the GHC API *is* a programmatic interface to GHC. Why not just use it?
One issue that sometimes bites me when trying to compile against GHC is that of dependencies. When compiling against GHC you are bound to use whatever dependency versions GHC was compiled with. In some cases these can be a bit dated which can lead to Cabal hell. I'm not really sure what can be done about this short of making Cabal/GHC more robust in the face of multiple dependency versions within the same build.
I read recently that Rust has some sort of symbol-mangling in place to allow multiple versions of the same library to co-exist within a single build. How feasible would it be to add this feature to GHC? At a first glance it seems like it would help substantially.

On Mon, Oct 20, 2014 at 12:32 PM, Eric Seidel
How feasible would it be to add this feature to GHC? At a first glance it seems like it would help substantially
Only until you need to hand off data between them, sadly. -- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

Sure, but how often does the API deal with types that aren't defined by `ghc` or `base`? ByteString is one case I can think of, if you want to muck about with FastStrings without the overhead of Strings.
On Oct 20, 2014, at 09:59, Brandon Allbery
wrote: On Mon, Oct 20, 2014 at 12:32 PM, Eric Seidel
wrote: How feasible would it be to add this feature to GHC? At a first glance it seems like it would help substantially Only until you need to hand off data between them, sadly.
-- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

Excerpts from Eric Seidel's message of 2014-10-20 09:32:41 -0700:
I read recently that Rust has some sort of symbol-mangling in place to allow multiple versions of the same library to co-exist within a single build.
How feasible would it be to add this feature to GHC? At a first glance it seems like it would help substantially.
GHC already has this feature (and in 7.10, it will be upgraded to allow multiple instances of the same version of a library, but with different dependencies). The problem here is that Cabal doesn't understand how to put dependencies together like this. Edward

Sorry to bother everybody, but where is this documented? What happens if
incompatible versions pass data between each other?
On Mon, Oct 20, 2014 at 1:22 PM, Edward Z. Yang
Excerpts from Eric Seidel's message of 2014-10-20 09:32:41 -0700:
I read recently that Rust has some sort of symbol-mangling in place to allow multiple versions of the same library to co-exist within a single build.
How feasible would it be to add this feature to GHC? At a first glance it seems like it would help substantially.
GHC already has this feature (and in 7.10, it will be upgraded to allow multiple instances of the same version of a library, but with different dependencies). The problem here is that Cabal doesn't understand how to put dependencies together like this.
Edward _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://www.haskell.org/mailman/listinfo/ghc-devs

different versions will be considered to have *different* types (albeit
with the same name)
On Mon, Oct 20, 2014 at 2:27 PM, Christopher Allen
Sorry to bother everybody, but where is this documented? What happens if incompatible versions pass data between each other?
On Mon, Oct 20, 2014 at 1:22 PM, Edward Z. Yang
wrote: Excerpts from Eric Seidel's message of 2014-10-20 09:32:41 -0700:
I read recently that Rust has some sort of symbol-mangling in place to allow multiple versions of the same library to co-exist within a single build.
How feasible would it be to add this feature to GHC? At a first glance it seems like it would help substantially.
GHC already has this feature (and in 7.10, it will be upgraded to allow multiple instances of the same version of a library, but with different dependencies). The problem here is that Cabal doesn't understand how to put dependencies together like this.
Edward _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://www.haskell.org/mailman/listinfo/ghc-devs
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://www.haskell.org/mailman/listinfo/ghc-devs

Sorry I'm a bit late to the party, I'm a bit snowed under with some GHCJS
refactoring work and the things I really need to do before the 7.10 merge
window closes.
I think that exposing GHC's front end functionality through the library
would be a good idea. Unfortunately it adds the haskeline dependency, so
adding it to the `ghc` package wouldn't be ideal. On the other hand, if we
exposed the GHC/GHCi modules as a library in a `ghc-bin` package, then we'd
avoid this, and also address ghc-mod's problem of the terminfo dependency.
Unfortunately this part of GHC has never been written with use as a library
in mind, so users would likely run into limitations at some point. For
example, GHCJS has a complete copy - with some modifications - of the
`ghc/Main.hs` module containing the command line parser and session setup
code. Even if this module was exposed through the library, I wouldn't be
able to use much of it, because of slight differences in command line
options.
My approach/plan so far has been to first copy code from GHC to the GHCJS
tree to make it work, and then make changes in the next major GHC version
that'd let me remove most of the lower level (and most likely to be version
specific) code from my copy. It would probably take a few iterations to
satisfy all the needs of ghc-mod/ghc-server/GHCJS and others, but the
result, a library, would be more flexible than a JSON API for GHCi (which
would still be useful by itself).
If stability/segfaults are a major factor in choosing to communicate with
the GHCi program, rather than using GHC as a library, then this really
should be addressed directly. Has anyone done investigation of the
situations that make ghc-mod/ghc-server, but not GHCi, crash?
On Mon, Oct 20, 2014 at 3:07 PM, Simon Peyton Jones
Christopher
You are doing very cool things. Thank you.
What I’m puzzled about is this: the GHC API **is** a programmatic interface to GHC. Why not just use it?
I can think of some reasons:
· It’s not very clear just what’s in the GHC API and what isn’t, since you have access to all of GHC’s internals if you use –package ghc. And the API isn’t very well designed. (Answer: could you help make it better?)
· You want some functionality that is currently in GHCi, rather than in the ‘ghc’ package. (Answer: maybe we should move that functionality into the ‘ghc’ package and make it part of the GHC API?)
· You have to be writing in Haskell to use the GHC API, whereas you want a separate process you connect to via a socket. (Answer: Excellent: write a server wrapper around the GHC API that offers a JSON interface, or whatever the right vocabulary is. Sounds as if you have more or less done this.)
· Moreover, the API changes pretty regularly, and you want multi-compiler support. (No answer: I don’t know how to simultaneously give access to new stuff without risking breaking old stuff.)
My meta-point is this: GHC is wide open to people like you building a consensus about how GHC’s basic functionality should be wrapped up and exposed to clients. (Luite is another person who has led in this space, via GHCJS.) So please do go ahead and lay out the way it **should** be done, think about migration paths, build a consensus etc. Much better that than do fragile screen-scraping on GHCi’s textual output.
Thanks for what you are doing here.
Simon
*From:* ghc-devs [mailto:ghc-devs-bounces@haskell.org] *On Behalf Of *Christopher Done *Sent:* 18 October 2014 16:49 *To:* ghc-devs@haskell.org *Subject:* Making GHCi awesomer?
Good evening,
So I’ve been working on Haskell user-facing tooling in general for some years. By that I mean the level of Emacs talking with Haskell tools.
I wrote the interactive-haskell-mode (most functionality exists in this file https://github.com/haskell/haskell-mode/blob/master/haskell-process.el#L1 ). which launches a GHCi process in a pipe and tries very earnestly to handle input/output with the process reasonably.
For Emacs fanciers: Written in Elisp, there’s a nice command queue that you put commands onto, they will all be run on a FIFO one-by-one order, and eventually you’ll get a result back. Initially it was just me using it, but with the help of Herbert Riedel it’s now a mode on equal footing with the venerable inferior-haskell-mode all ye Emacs users know and love. It’s part of haskell-mode and can be enabled by enabling the interactive-haskell-mode minor mode.
For years I’ve been using GHCi as a base and it’s been very reliable for almost every project I’ve done (the only exceptions are things like SDL and OpenGL, which are well known to be difficult to load in GHCi, at least on Linux). I think we’ve built up a good set of functionality https://github.com/haskell/haskell-mode/wiki/Haskell-Interactive-Mode purely based on asking GHCi things and getting it to do things.
I literally use GHCi for everything. For type-checking, type info, I even send “:!cabal build” to it. Everything goes through it. I love my GHCi.
Now, I’m sort of at the end of the line of where I can take GHCi. Here are the problems as I see them today:
1. There is no programmatic means of communicating with the process. I can’t send a command and get a result cleanly, I have to regex match on the prompt, and that is only so reliable. At the moment we solve this by using \4 (aka ‘END OF TRANSMISSION’). Also messages (warnings, errors, etc.) need to be parsed which is also icky, especially in the REPL when e.g. a defaulted Integer warning will mix with the output. Don’t get me started on handling multi-line prompts! Hehe.
2. GHCi, as a REPL, does not distinguish between stdout, stderr and the result of your evaluation. This can be problematic for making a smooth REPL UI, your results can often (with threading) be interspersed in unkind ways. I cannot mitigate this with any kind of GHCi trickery.
3. It forgets information when you reload. (I know this is intentional.)
4. Not enough information is exposed to the user. (Is there ever? ;)
5. There is a time-to-market overhead of contributing to GHCi — if I want a cool feature, I can write it on a locally compiled version of GHC. But for the work projects I have, I’m restricted to given GHC versions, as are other people. They have to wait to get the good features.
6. This is just a personal point — I’ve like to talk to GHCi over a
socket, so that I can run it on a remote machine. Those familiar with Common Lisp will be reminded of SLIME and Swank.
Examples for point 4 are:
· Type of sub-expressions.
· Go to definition of thing at point (includes local scope).
· Local-scope completion.
· A hoogle-like query (as seen in Idris recently).
· Documentation lookup.
· Suggest imports for symbols.
· Show core for the current module.
· Show CMM for the current module, ASM, etc. SLIME can do this.
· Expand the template-haskell at point.
· The :i command is amazingly useful, but programmatic access would be even better.¹
· Case split anyone?
· Etc.
¹I’ve integrated with it in Emacs so that I can C-c C-i any identifier and it’ll popup a buffer with the :i result and then within that buffer I can drill down further with C-c C-i again. It makes for very natural exploration of a type.
You’ve seen some of these features in GHC Mod, in hdevtools, in the FP Haskell Center, maybe some are in Yi, possibly also in Leksah (?).
So in light of point (5), I thought: I’ve used the GHC API before, it can do interactive evaluation, why not write a project like “ghc-server” which encodes all these above ideas as a “drop-in” replacement for GHCi? After all I could work on my own without anybody getting my way over architecture decisions, etc.
And that’s what I did. It’s here https://github.com/chrisdone/ghc-server. Surprisingly, it kind of works. You run it in your directoy like you would do “cabal repl” and it sets up all the extensions and package dependencies and starts accepting connections. It will compile across three major GHC versions. Hurray! Rub our hands together and call it done, right? Sadly not, the trouble is twofold:
1. The first problem with this is that every three projects will segfault or panic when trying to load in a project that GHCi will load in happily. The reasons are mysterious to me and I’ve already lugged over the GHC API to get to this point, so that kind of thing happening means that I have to fall back to my old GHCi-based setup, and is disappointing. People have similar complaints of GHC Mod & co. “Getting it to work” is a deterrant.
2. While this would be super beneficial for me, and has been a good learning experience for “what works and what doesn’t”, we end up with yet another alternative tool, that only a few people are using.
3. There are just certain behaviours and fixes here and there that
GHCi does that take time to reproduce.
So let’s go back to the GHCi question: is there still a development overhead for adding features to GHCi? Yes, new ideas need acceptance and people have to wait (potentially a year) for a new feature that they could be using right now.
An alternative method is to do what Herbert did which is to release a “ghci-ng” http://hackage.haskell.org/package/ghci-ng which sports new shiny features that people (with the right GHC version) will be able to compile and use as a drop-in for GHCi. It’s the same codebase, but with more stuff! An example is the “:complete” command, this lets IDE implementers do completion at least at the REPL level. Remember the list of features earlier? Why are they not in GHCi?
So, of course, this got me thinking that I could instead make ghc-server be based off of GHCi’s actual codebase. I could rebase upon the latest GHC release and maintain 2-3 GHC versions backwards. That’s certainly doable, it would essentially give me “GHCi++”. Good for me, I just piggy back on the GHCi goodness and then use the GHC API for additional things as I’m doing now.
But is there a way I can get any of this into the official repo? For example, could I hack on this (perhaps with Herbert) as “ghci-ng”, provide an alternative JSON communication layer (e.g. via some —use-json flag) and and socket listener (—listen-on ), a way to distinguish stdout/stderr (possibly by forking a process, unsure at this stage), and then any of the above features (point 4) listed. I make sure that I’m rebasing upon HEAD, as if to say ghci-ng is a kind of submodule, and then when release time comes we merge back in any new stuff since the last release. Early adopters can use ghci-ng, and everyone benefits from official GHC releases.
The only snag there is that, personally speaking, it would be better if ghci-ng would compile on older GHC versions. So if GHC 7.10 is the latest release, it would still be nice (and it *seems* pretty feasible) that GHC 7.8 users could still cabal install it without issue. People shouldn’t have to wait if they don’t have to.
Well, that’s everything. Thoughts?
Ciao!
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://www.haskell.org/mailman/listinfo/ghc-devs

2014-10-23 22:49 GMT+02:00 Luite Stegeman
If stability/segfaults are a major factor in choosing to communicate with the GHCi program, rather than using GHC as a library, then this really should be addressed directly. Has anyone done investigation of the situations that make ghc-mod/ghc-server, but not GHCi, crash?
The crashes tend to be related to linker problems (like duplicate symbols, often also in combination with TH) IME. I think the problem that projects like ghc-mod, hdevtools etc encounter is that the GHC API is quite lowlevel. For example, just look at the code for `:load`: https://github.com/ghc/ghc/blob/5bb73d79a83bca57dc431421ca1e022f34b8dec9/ghc... . - First, I have no idea what abandonAll is doing here (and hdevtools isn't using it). I guess it is related to GHCi debugger, so that might not be a problem. - We then unload the active program and call doLoad. doLoad just resets some debugging related things (note that it calls discardActiveBreakPoints again, even though loadModule' already did that) and then calls GHC.load. After that, it calls `afterLoad`, which uses a foreign function calling into the RTS (!) to reset CAFs. As this function is only foreign import'ed in GHCi itself, I'm sure neither ghc-mod nor hdevtools call it. Needing to call a RTS function just to safely load a new module, replacing the old program, doesn't feel right to me. The problem here is that this `loadModule` function is only inside GHCi, and not exported through the GHC API. This was just one example, I'm sure there are more. There is just no highlevel GHC API function for most of GHCi's commands. Another reason for the crashes might be that ghc-mod and hdevtools tend to do many, many more reloads than GHCi, because they reload on every file save (or even after 0.5s idle time). Crashes that only appear very infrequent are thus much more likely to occur in ghc-mod. -- Benno
participants (14)
-
Alan & Kim Zimmerman
-
Ben Gamari
-
Benno Fünfstück
-
Brandon Allbery
-
Carter Schonwald
-
Christopher Allen
-
Christopher Done
-
Daniel Gröber
-
Edward Z. Yang
-
Eric Seidel
-
Herbert Valerio Riedel
-
Luite Stegeman
-
Mateusz Kowalczyk
-
Simon Peyton Jones