From me at willsewell.com Thu Oct 1 12:19:56 2015 From: me at willsewell.com (Will Sewell) Date: Thu, 1 Oct 2015 13:19:56 +0100 Subject: Removing latency spikes. Garbage collector related? In-Reply-To: References: Message-ID: Thanks you for the suggestions both of you. After some more profiling, I've come to realise that most of the garbage is created from allocations when serialising messages to write to the socket. I am going to try and reduce this next. If that does not help reduce the latency spikes, I will work through each of your suggestions. On 29 September 2015 at 16:47, John Lato wrote: > By dumping metrics, I mean essentially the same as the ghc-events-analyze > annotations but with any more information that is useful for the > investigation. In particular, if you have a message id, include that. You > may also want to annotate thread names with GHC.Conc.labelThread. You may > also want to add more annotations to drill down if you uncover a problem > area. > > If I were investigating, I would take e.g. the five largest outliers, then > look in the (text) eventlog for those message ids, and see what happened > between the start and stop. You'll likely want to track the thread states > (which is why I suggested you annotate the thread names). > > I'm not convinced it's entirely the GC, the latencies are larger than I > would expect from a GC pause (although lots of factors can affect that). I > suspect that either you have something causing abnormal GC spikes, or > there's a different cause. > > > On 04:15, Tue, Sep 29, 2015 Will Sewell wrote: >> >> Thanks for the reply John. I will have a go at doing that. What do you >> mean exactly by dumping metrics, do you mean measuring the latency >> within the program, and dumping it if it exceeds a certain threshold? >> >> And from the answers I'm assuming you believe it is the GC that is >> most likely causing these spikes. I've never profiled Haskell code, so >> I'm not used to seeing what the effects of the GC actually are. >> >> On 28 September 2015 at 19:31, John Lato wrote: >> > Try Greg's recommendations first. If you still need to do more >> > investigation, I'd recommend that you look at some samples with either >> > threadscope or dumping the eventlog to text. I really like >> > ghc-events-analyze, but it doesn't provide quite the same level of >> > detail. >> > You may also want to dump some of your metrics into the eventlog, >> > because >> > then you'll be able to see exactly how high latency episodes line up >> > with GC >> > pauses. >> > >> > On Mon, Sep 28, 2015 at 1:02 PM Gregory Collins >> > >> > wrote: >> >> >> >> >> >> On Mon, Sep 28, 2015 at 9:08 AM, Will Sewell wrote: >> >>> >> >>> If it is the GC, then is there anything that can be done about it? >> >> >> >> Increase value of -A (the default is too small) -- best value for this >> >> is >> >> L3 cache size of the chip >> >> Increase value of -H (total heap size) -- this will use more ram but >> >> you'll run GC less often >> >> This will sound flip, but: generate less garbage. Frequency of GC runs >> >> is >> >> proportional to the amount of garbage being produced, so if you can >> >> lower >> >> mutator allocation rate then you will also increase net productivity. >> >> Built-up thunks can transparently hide a lot of allocation so fire up >> >> the >> >> profiler and tighten those up (there's an 80-20 rule here). Reuse >> >> output >> >> buffers if you aren't already, etc. >> >> >> >> G >> >> >> >> -- >> >> Gregory Collins >> >> _______________________________________________ >> >> Glasgow-haskell-users mailing list >> >> Glasgow-haskell-users at haskell.org >> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users From qdunkan at gmail.com Fri Oct 2 02:02:08 2015 From: qdunkan at gmail.com (Evan Laforge) Date: Thu, 1 Oct 2015 19:02:08 -0700 Subject: using nmitchell's space leak detection technique Message-ID: Neil Mitchell wrote an article about finding space leaks by limiting the stack size: http://neilmitchell.blogspot.fr/2015/09/detecting-space-leaks.html I'm giving it a try, but the results don't make any sense to me. My understanding is that the too-deep stack indicates that someone created too many thunks, so when they get evaluated you have to descend too many times. And if the stack trace seems to be a reasonable size (say 100 stack frames somehow consuming 1mb of stack) then it means there is a recursive call in there somewhere that ghc is helpfully eliding. And lastly, that the thing about "Stack space overflow: current size 33568 bytes." always showing 33568 bytes is due to a ghc bug and it should actually be whatever limit I gave it. Is all this accurate? The stack trace jumps around a lot, to places which are not lexically present in the caller. I assume this is just lazy evaluation, so e.g. maybe 'f' doesn't call 'g', but if 'f' forces a value returned from 'g' which has not yet been forced, the stack will go to 'g'. Also sometimes things which seem like they should be run consecutively wind up as caller and callee... but perhaps this is due to using a monad with a success continuation, and without the SCCs would be eliminated since they are tail calls... or maybe they are always eliminated and I only see them in the stack when the elimination failed for some reason. At first I got a stack trace that ended in a function which is recursive, but should be productive guarded recursion: events_of :: [LEvent d] -> [d] events_of [] = [] events_of (Event e : rest) = e : events_of rest events_of (Log _ : rest) = events_of rest It's my understanding that while this isn't tail recursive, it should require only constant space. Of course the consumer could retain it all, but that wouldn't show up as too-deep recursion on that particular function, would it? Since ghc elides self-calls from the stack, the culprit could be one of the functions above, and the one immediately above was part of transforming a large list which could well be insufficiently strict somewhere. So I tried to break that out into its own call without the distraction of the continuation monad etc., just a function from a list to a list. The result is even more confusing: % build/profile/RunProfile-SpaceLeak +RTS -K2905K -xc -RTS ... force - *** Exception (reporting due to +RTS -xc): (THUNK_STATIC), stack trace: Derive.PSignal.signal, called from Derive.DeriveTest.mkevent_scale, called from Derive.DeriveTest.mkevent, called from Derive.SpaceLeak_profile.profile_cancel.make, called from Derive.SpaceLeak_profile.profile_cancel.f, called from Derive.SpaceLeak_profile.profile_cancel, called from Derive.SpaceLeak_profile.CAF Somehow these 7 calls are consuming almost 3mb of stack, so there must be a ton of elided recursion hiding in one of them. The confusing thing is that the profile_cancel function is basically just: rnf $ suspicious_function $ map make [0 .. 1024*50] So the stack is going into the 'make' function which is just a bunch of constructors to produce the values that suspicious_function will transform. As far as I can tell, the only recursion is in 'map', and the thunks from 'mkevent' down to 'PSignal.signal' only go 3 deep. But suspicious_function is definitely suspicious, because if I remove it, I no longer get an exception. But how does it manage to not be in the stack? If suspicious_function is not a good consumer and is accumulating thunks, how can I get 3 stack entries consuming 3mb? If I rnf the result of 'make' before running suspicious_function, I get a completely different stack trace, and this one with '--> evaluated by:' entries, and I don't really know what those mean. But this one at least has some recursive calls within suspicious_function. I can keep debugging via trial and error and successive rnf's as Neil describes in another article, but it would be nice to know what's going on with the stack. The stack seems fairly straightforward in strict languages, is there some documentation on how to understand the ghc version? Any clues appreciated! From ongy44 at gmail.com Wed Oct 7 07:49:16 2015 From: ongy44 at gmail.com (Markus Ongyerth) Date: Wed, 7 Oct 2015 09:49:16 +0200 Subject: Handling multiple fds with GHC Message-ID: Hi, the last few days, I tried to get an IO-Event system running with GHC i.e. trigger an IO action when there is data to read from a fd. I looked at a few different implementations, but all of them have some downside. * using select package - This uses the select syscall. select is rather limited (fd cannot be >1024) * using GHC.Event - GHC.Event is broken in 7.10.1 (unless unsafeCoerce and a hacky trick are used) - GHC.Event is GHC internal according to hackage - Both Network libraries I looked at (networking (Network.Socket) and socket (System.Socket)) crash the application with GHC.Event - with 7.8+ I didn't see a way to create your own EventManager, so it only works with -threaded * using forkIO and threadWaitRead for each fd in a loop - needs some kind of custom control structure around it - uses a separate thread for each fd - might become pretty awkward to handle multiple events * using poll package - blocks in a safe foreign call - needs some kind of wrapper >From the above list, GHC.Event isn't usable (for me) right now. It would require some work for my usecase. The select option is usable, but suffers from the same problems as poll + the limitation mentioned, so it is strictly worse. This leaves me with two options: poll and forkIO + blocking. Those are based on two completely different approaches to event handling.. poll can be used in a rather classic event handling system with a main loop that blocks until an event occurs (or a timeout triggers) and handles the event in the loop. forkIO + blocking is closer to registering an action later that should be triggered by an event. My main questions right now are: 1. How bad is it for the (non-threaded) runtime to be blocking in a foreign call most of the time? 2. How significant will the overhead be for the forkIO version? 3. Is there a *good* way to use something like threadWaitRead that allows to wake up on other events as well? 4. Is there a better way to handle multiple fds that may get readable data at any time, in Haskell/with GHC right now? Thanks in advance, Ongy -------------- next part -------------- An HTML attachment was scrubbed... URL: From dct25-561bs at mythic-beasts.com Wed Oct 7 16:30:01 2015 From: dct25-561bs at mythic-beasts.com (David Turner) Date: Wed, 7 Oct 2015 17:30:01 +0100 Subject: Handling multiple fds with GHC In-Reply-To: References: Message-ID: Hi, Why the non-threaded runtime, out of interest? Threads forked with forkIO are pretty lightweight, and although things look like blocking calls from the Haskell point of view, as I understand it under the hood it's all done with events of one form or another. Thus even with the non-threaded runtime you will see forkIO-threads behaving as if they're running concurrently. In particular, you have two threads blocked trying to read from two different Handles and each will be awoken just when there's data to read, and the rest of the runtime will carry on even while they're blocked. Try it! If you're dealing with FDs that you've acquired from elsewhere, the function unix:System.Posix.IO.ByteString.fdToHandle can be used to import them and then they work like normal Handles in terms of blocking operations etc. Whenever I've had to deal with waking up for one of a number of reasons (not all of which are FDs) I've found the simplicity of STM is hard to beat. Something like: atomically ((Left <$> waitForFirstThing) <|> (Right <$> waitForSecondThing)) where waitForFirstThing and waitForSecondThing are blocked waiting for something interesting to occur in a TVar that they're watching. It's so simple that I reckon it's worth doing it like that and only trying something more complicated if it turns out from experimentation that this has too much overhead for you - "make it right" precedes "make it fast". Hope that helps, David On 7 October 2015 at 08:49, Markus Ongyerth wrote: > Hi, > > the last few days, I tried to get an IO-Event system running with GHC i.e. > trigger an IO action when there is data to read from a fd. > I looked at a few different implementations, but all of them have some > downside. > > * using select package > - This uses the select syscall. select is rather limited (fd cannot be > >1024) > > * using GHC.Event > - GHC.Event is broken in 7.10.1 (unless unsafeCoerce and a hacky trick > are used) > - GHC.Event is GHC internal according to hackage > - Both Network libraries I looked at (networking (Network.Socket) and > socket (System.Socket)) crash the application with GHC.Event > - with 7.8+ I didn't see a way to create your own EventManager, so it > only works with -threaded > > * using forkIO and threadWaitRead for each fd in a loop > - needs some kind of custom control structure around it > - uses a separate thread for each fd > - might become pretty awkward to handle multiple events > > * using poll package > - blocks in a safe foreign call > - needs some kind of wrapper > > > From the above list, GHC.Event isn't usable (for me) right now. It would > require some work for my usecase. > The select option is usable, but suffers from the same problems as poll + > the limitation mentioned, so it is strictly worse. > > This leaves me with two options: poll and forkIO + blocking. > > Those are based on two completely different approaches to event handling.. > > poll can be used in a rather classic event handling system with a main > loop that blocks until an event occurs (or a timeout triggers) and handles > the event in the loop. > forkIO + blocking is closer to registering an action later that should be > triggered by an event. > > My main questions right now are: > 1. How bad is it for the (non-threaded) runtime to be blocking in a > foreign call most of the time? > 2. How significant will the overhead be for the forkIO version? > 3. Is there a *good* way to use something like threadWaitRead that allows > to wake up on other events as well? > 4. Is there a better way to handle multiple fds that may get readable data > at any time, in Haskell/with GHC right now? > > Thanks in advance, > Ongy > > _______________________________________________ > Glasgow-haskell-users mailing list > Glasgow-haskell-users at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ongy44 at gmail.com Wed Oct 7 17:16:02 2015 From: ongy44 at gmail.com (Markus Ongyerth) Date: Wed, 7 Oct 2015 19:16:02 +0200 Subject: Handling multiple fds with GHC In-Reply-To: References: Message-ID: 2015-10-07 18:30 GMT+02:00 David Turner : > Hi, > > Why the non-threaded runtime, out of interest? Mostly because i am used to the poll/select method I mentioned and that one works without any threading. I don't really mind using the threaded runtime though, it's more habit. > Threads forked with forkIO are pretty lightweight, and although things look > like blocking calls from the Haskell point of view, as I understand it under > the hood it's all done with events of one form or another. Thus even with > the non-threaded runtime you will see forkIO-threads behaving as if they're > running concurrently. In particular, you have two threads blocked trying to > read from two different Handles and each will be awoken just when there's > data to read, and the rest of the runtime will carry on even while they're > blocked. Try it! Yeah, I know and I tried that. As far as I can see, that's actually why things break with GHC.Event. The Event system tries to register the Fd while it was registered by me and encounters an EEXIST from epoll. > If you're dealing with FDs that you've acquired from elsewhere, the function > unix:System.Posix.IO.ByteString.fdToHandle can be used to import them and > then they work like normal Handles in terms of blocking operations etc. > > Whenever I've had to deal with waking up for one of a number of reasons (not > all of which are FDs) I've found the simplicity of STM is hard to beat. > Something like: > > atomically ((Left <$> waitForFirstThing) <|> (Right <$> waitForSecondThing)) Looks like I should look up STM. Does this scale easily? I don't really need huge amounts, but I don't have any knowledge about the number of Fds I will have. > where waitForFirstThing and waitForSecondThing are blocked waiting for > something interesting to occur in a TVar that they're watching. It's so > simple that I reckon it's worth doing it like that and only trying something > more complicated if it turns out from experimentation that this has too much > overhead for you - "make it right" precedes "make it fast". > > Hope that helps, > > David Thanks for the help, Ongy From greg at gregorycollins.net Wed Oct 7 18:32:22 2015 From: greg at gregorycollins.net (Gregory Collins) Date: Wed, 7 Oct 2015 11:32:22 -0700 Subject: Handling multiple fds with GHC In-Reply-To: References: Message-ID: On Wed, Oct 7, 2015 at 10:16 AM, Markus Ongyerth wrote: > Mostly because i am used to the poll/select method I mentioned and that > one works without any threading. > I don't really mind using the threaded runtime though, it's more habit. > The stock stuff in the threaded runtime uses epoll() out of the box. When you call hRead on a Handle, if the handle would block then you ultimately get a call to threadWaitRead or threadWaitWrite; these functions register interest in the given file descriptor, and the IO manager / GHC runtime scheduler will wake up your thread (GHC uses "green" threads) when the file descriptor becomes writable. G -- Gregory Collins -------------- next part -------------- An HTML attachment was scrubbed... URL: From dct25-561bs at mythic-beasts.com Wed Oct 7 19:17:12 2015 From: dct25-561bs at mythic-beasts.com (David Turner) Date: Wed, 7 Oct 2015 20:17:12 +0100 Subject: Handling multiple fds with GHC In-Reply-To: References: Message-ID: On 7 October 2015 at 18:16, Markus Ongyerth wrote: > 2015-10-07 18:30 GMT+02:00 David Turner : > > Hi, > > > > Why the non-threaded runtime, out of interest? > > Mostly because i am used to the poll/select method I mentioned and that > one works without any threading. > I don't really mind using the threaded runtime though, it's more habit. > > > Threads forked with forkIO are pretty lightweight, and although things > look > > like blocking calls from the Haskell point of view, as I understand it > under > > the hood it's all done with events of one form or another. Thus even with > > the non-threaded runtime you will see forkIO-threads behaving as if > they're > > running concurrently. In particular, you have two threads blocked trying > to > > read from two different Handles and each will be awoken just when there's > > data to read, and the rest of the runtime will carry on even while > they're > > blocked. Try it! > > Yeah, I know and I tried that. > As far as I can see, that's actually why things break with GHC.Event. > The Event system tries to register the Fd while it was registered by me > and encounters an EEXIST from epoll. > > Ah, ok, so you can either do your epolling through the Haskell runtime or with your bare hands but you can't do both on a single FD. > If you're dealing with FDs that you've acquired from elsewhere, the > function > > unix:System.Posix.IO.ByteString.fdToHandle can be used to import them and > > then they work like normal Handles in terms of blocking operations etc. > > > > Whenever I've had to deal with waking up for one of a number of reasons > (not > > all of which are FDs) I've found the simplicity of STM is hard to beat. > > Something like: > > > > atomically ((Left <$> waitForFirstThing) <|> (Right <$> > waitForSecondThing)) > > Looks like I should look up STM. Does this scale easily? > I don't really need huge amounts, but I don't have any knowledge about the > number of Fds I will have. > Waiting on arbitrarily many things is pretty much as simple (as long as they all have the same type so you can put them in a list): atomically (asum listOfWaitingThings) In terms of code complexity that scales just fine! I'm afraid I've no real idea what the performance characteristics of such a device would be without trying it out in your use case. Whenever I've been doing this kind of thing I've always found myself IO-bound rather than CPU-bound so I've never found myself worrying too much about the efficiency of the code itself. If you're used to doing select/poll things yourself then it may help to think of Haskell threads blocking on Handles as basically a way to do an epoll-based event loop on the underlying FDs but with a much nicer syntax and less mucking around with explicit continuations. Similarly, if you're used to dealing with task scheduling at a low level then it may help to think of STM transactions blocking as a way to muck around with the run queues in the scheduler but with a much nicer syntax and less mucking around with explicit continuations. Best wishes, David -------------- next part -------------- An HTML attachment was scrubbed... URL: From ongy44 at gmail.com Wed Oct 7 19:46:33 2015 From: ongy44 at gmail.com (Markus Ongyerth) Date: Wed, 7 Oct 2015 21:46:33 +0200 Subject: Handling multiple fds with GHC In-Reply-To: References: Message-ID: 2015-10-07 21:17 GMT+02:00 David Turner : > > > On 7 October 2015 at 18:16, Markus Ongyerth wrote: >> >> 2015-10-07 18:30 GMT+02:00 David Turner : >> > Hi, >> > >> > Why the non-threaded runtime, out of interest? >> >> Mostly because i am used to the poll/select method I mentioned and that >> one works without any threading. >> I don't really mind using the threaded runtime though, it's more habit. >> >> > Threads forked with forkIO are pretty lightweight, and although things >> > look >> > like blocking calls from the Haskell point of view, as I understand it >> > under >> > the hood it's all done with events of one form or another. Thus even >> > with >> > the non-threaded runtime you will see forkIO-threads behaving as if >> > they're >> > running concurrently. In particular, you have two threads blocked trying >> > to >> > read from two different Handles and each will be awoken just when >> > there's >> > data to read, and the rest of the runtime will carry on even while >> > they're >> > blocked. Try it! >> >> Yeah, I know and I tried that. >> As far as I can see, that's actually why things break with GHC.Event. >> The Event system tries to register the Fd while it was registered by me >> and encounters an EEXIST from epoll. >> > > Ah, ok, so you can either do your epolling through the Haskell runtime or > with your bare hands but you can't do both on a single FD. Ah, I didn't to it with bare hands, I did it with GHC.Event registerFd. Running my own epoll might work (according to the epoll man page), but I really don't want to do that. >> > If you're dealing with FDs that you've acquired from elsewhere, the >> > function >> > unix:System.Posix.IO.ByteString.fdToHandle can be used to import them >> > and >> > then they work like normal Handles in terms of blocking operations etc. >> > >> > Whenever I've had to deal with waking up for one of a number of reasons >> > (not >> > all of which are FDs) I've found the simplicity of STM is hard to beat. >> > Something like: >> > >> > atomically ((Left <$> waitForFirstThing) <|> (Right <$> >> > waitForSecondThing)) >> >> Looks like I should look up STM. Does this scale easily? >> I don't really need huge amounts, but I don't have any knowledge about the >> number of Fds I will have. > > > Waiting on arbitrarily many things is pretty much as simple (as long as they > all have the same type so you can put them in a list): > > atomically (asum listOfWaitingThings) Oh, I didn't see asum, but "came up" with the same implementation. > In terms of code complexity that scales just fine! I'm afraid I've no real > idea what the performance characteristics of such a device would be without > trying it out in your use case. Whenever I've been doing this kind of thing > I've always found myself IO-bound rather than CPU-bound so I've never found > myself worrying too much about the efficiency of the code itself. > > If you're used to doing select/poll things yourself then it may help to > think of Haskell threads blocking on Handles as basically a way to do an > epoll-based event loop on the underlying FDs but with a much nicer syntax > and less mucking around with explicit continuations. Similarly, if you're > used to dealing with task scheduling at a low level then it may help to > think of STM transactions blocking as a way to muck around with the run > queues in the scheduler but with a much nicer syntax and less mucking around > with explicit continuations. > For my current project the speed does not really matter, but I tend to do some research anyway, since I might get to a point where I need it. The one thing I am not sure about right now, is how to use threadWaitReadSTM. Can I reuse the STM? I have two Fds I can test it with right now, and one of them works, the other one doesn't seem to work for me. I looked into the source and to me it looks like the STM should not be reused, since the content of the TVar used internally will be set to True. Thanks for the help, ongy From paul at denknerd.org Fri Oct 16 08:21:33 2015 From: paul at denknerd.org (Paul van der Walt) Date: Fri, 16 Oct 2015 10:21:33 +0200 Subject: Core libraries Message-ID: <871tcvustu.fsf@denknerd.org> Hello GHC users, For various reasons i'm trying to package something which is compatible with/equivalent to the Haskell Platform. I've been looking at the list posted at [0], and it turns out that GHC 7.10.2 doesn't bundle all the packages that are promised. (Or it's a case of PEBKAC and i apologise!) When i do `ghc-pkg list`, the output under ../package.conf.d provided by GHC notably has the following differences with the website list: $ diff website-list <(ghc-pkg list | ..prettify..) 2a3,4 > binary > bin-package-db 10c12,14 < haddock --- > ghc-prim > haskeline > hoopl 12,13c16 < old-locale < old-time --- > integer-gmp 15a19 > rts 16a21 > terminfo What surprises me is the lack of haddock, old-time and old-locale. Is this intentional, or a glitch on the website? I notice that these "missing" libraries are repeated in the `Additional Platform Libraries' and `Programs and Tools' sections. I guess this means that as a GHC packager, i should add these items separately? I guess what i'm saying is that i believe there is a bug in that list [0], but i'm not sure enough that i understand the situation to report it as such :). Sorry about the verbiage, and kind regards, p. 0. From qdunkan at gmail.com Sat Oct 24 02:48:07 2015 From: qdunkan at gmail.com (Evan Laforge) Date: Fri, 23 Oct 2015 19:48:07 -0700 Subject: type error formatting Message-ID: Here's a typical simple type error from GHC: Derive/Call/India/Pakhawaj.hs:142:62: Couldn't match type ?Text? with ?(a1, Syllable)? Expected type: [([(a1, Syllable)], [Sequence Bol])] Actual type: [([Syllable], [Sequence Bol])] Relevant bindings include syllables :: [(a1, Syllable)] (bound at Derive/Call/India/Pakhawaj.hs:141:16) best_match :: [(a1, Syllable)] -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) (bound at Derive/Call/India/Pakhawaj.hs:141:5) In the second argument of ?mapMaybe?, namely ?all_bols? In the second argument of ?($)?, namely ?mapMaybe (match_bols syllables) all_bols? I've been having more trouble than usual reading GHC's errors, and I finally spent some time to think about it. The problem is that this new "relevant bindings include" section gets in between the expected and actual types (I still don't like that wording but I've gotten used to it), which is the most critical part, and the location context, which is second most critical. Notice the same effect in the previous sentence :) After I see a type error the next thing I want to see is the where it happened, so I have to skip over the bindings, which can be long and complicated. Then I usually know what to do, and only look into the bindings if something more complicated is going on, like wonky inference. So how about reordering the message: Derive/Call/India/Pakhawaj.hs:142:62: Couldn't match type ?Text? with ?(a1, Syllable)? Expected type: [([(a1, Syllable)], [Sequence Bol])] Actual type: [([Syllable], [Sequence Bol])] In the second argument of ?mapMaybe?, namely ?all_bols? In the second argument of ?($)?, namely ?mapMaybe (match_bols syllables) all_bols? Relevant bindings include syllables :: [(a1, Syllable)] (bound at Derive/Call/India/Pakhawaj.hs:141:16) best_match :: [(a1, Syllable)] -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) (bound at Derive/Call/India/Pakhawaj.hs:141:5) After this, why not go one step further and set off the various sections visibly to make it easier to scan. The context section can also be really long if it gets an entire do block or record: Derive/Call/India/Pakhawaj.hs:142:62: * Couldn't match type ?Text? with ?(a1, Syllable)? Expected type: [([(a1, Syllable)], [Sequence Bol])] Actual type: [([Syllable], [Sequence Bol])] * In the second argument of ?mapMaybe?, namely ?all_bols? In the second argument of ?($)?, namely ?mapMaybe (match_bols syllables) all_bols? * Relevant bindings include syllables :: [(a1, Syllable)] (bound at Derive/Call/India/Pakhawaj.hs:141:16) best_match :: [(a1, Syllable)] -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) (bound at Derive/Call/India/Pakhawaj.hs:141:5) Or alternately, taking up a bit more vertical space: Derive/Call/India/Pakhawaj.hs:142:62: Couldn't match type ?Text? with ?(a1, Syllable)? Expected type: [([(a1, Syllable)], [Sequence Bol])] Actual type: [([Syllable], [Sequence Bol])] ----------------------------- In the second argument of ?mapMaybe?, namely ?all_bols? In the second argument of ?($)?, namely ?mapMaybe (match_bols syllables) all_bols? ----------------------------- Relevant bindings include syllables :: [(a1, Syllable)] (bound at Derive/Call/India/Pakhawaj.hs:141:16) best_match :: [(a1, Syllable)] -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) (bound at Derive/Call/India/Pakhawaj.hs:141:5) Thoughts? It seems simple enough that I could do myself, but of course not without buy-in. -------------- next part -------------- An HTML attachment was scrubbed... URL: From ezyang at mit.edu Sat Oct 24 02:50:57 2015 From: ezyang at mit.edu (Edward Z. Yang) Date: Fri, 23 Oct 2015 19:50:57 -0700 Subject: type error formatting In-Reply-To: References: Message-ID: <1445655044-sup-1310@sabre> I think this is quite a reasonable suggestion. Edward Excerpts from Evan Laforge's message of 2015-10-23 19:48:07 -0700: > Here's a typical simple type error from GHC: > > Derive/Call/India/Pakhawaj.hs:142:62: > Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] > Relevant bindings include > syllables :: [(a1, Syllable)] > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > best_match :: [(a1, Syllable)] > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > In the second argument of ?mapMaybe?, namely ?all_bols? > In the second argument of ?($)?, namely > ?mapMaybe (match_bols syllables) all_bols? > > I've been having more trouble than usual reading GHC's errors, and I > finally spent some time to think about it. The problem is that this new > "relevant bindings include" section gets in between the expected and actual > types (I still don't like that wording but I've gotten used to it), which > is the most critical part, and the location context, which is second most > critical. Notice the same effect in the previous sentence :) After I see > a type error the next thing I want to see is the where it happened, so I > have to skip over the bindings, which can be long and complicated. Then I > usually know what to do, and only look into the bindings if something more > complicated is going on, like wonky inference. So how about reordering the > message: > > Derive/Call/India/Pakhawaj.hs:142:62: > Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] > In the second argument of ?mapMaybe?, namely ?all_bols? > In the second argument of ?($)?, namely > ?mapMaybe (match_bols syllables) all_bols? > Relevant bindings include > syllables :: [(a1, Syllable)] > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > best_match :: [(a1, Syllable)] > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > After this, why not go one step further and set off the various sections > visibly to make it easier to scan. The context section can also be really > long if it gets an entire do block or record: > > Derive/Call/India/Pakhawaj.hs:142:62: > * Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] > * In the second argument of ?mapMaybe?, namely ?all_bols? > In the second argument of ?($)?, namely > ?mapMaybe (match_bols syllables) all_bols? > * Relevant bindings include > syllables :: [(a1, Syllable)] > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > best_match :: [(a1, Syllable)] > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > Or alternately, taking up a bit more vertical space: > > Derive/Call/India/Pakhawaj.hs:142:62: > Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] From mail at joachim-breitner.de Sat Oct 24 08:17:49 2015 From: mail at joachim-breitner.de (Joachim Breitner) Date: Sat, 24 Oct 2015 10:17:49 +0200 Subject: type error formatting In-Reply-To: References: Message-ID: <1445674669.32229.4.camel@joachim-breitner.de> Hi, thanks for starting this discussion, and I agree with your suggestion. Maybe we can brainstorm some more fine refinements. Given that our error message are on the rather verbose side, maybe there is detail that can be omitted. For example in > ? ?Relevant bindings include > ? ? ? syllables :: [(a1, Syllable)] > ? ? ? ? (bound at Derive/Call/India/Pakhawaj.hs:141:16) > ? ? ? best_match :: [(a1, Syllable)] > ? ? ? ? ? ? ? ? ? ? -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) > ? ? ? ? (bound at Derive/Call/India/Pakhawaj.hs:141:5) do we really need to know what file these come from? I guess, in all but very obscure cases (or really all) they are from the same file. So why not omit the filename? Also, unless the programmer is doing weird things with shadowing, is the "bound at" information really valuable? I?d say no: Usually, the programmer knows his bindings, and even if not, she will not have any problems finding the right binding. So I suggest to drop the "bound at" line unless the binding is from a different file. > This would make this section much easier to parse and grasp visually. Greetings, Joachim -- Joachim ?nomeata? Breitner mail at joachim-breitner.de ? http://www.joachim-breitner.de/ Jabber: nomeata at joachim-breitner.de ? GPG-Key: 0xF0FBF51F Debian Developer: nomeata at debian.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: This is a digitally signed message part URL: From malcolm.wallace at me.com Sat Oct 24 09:08:32 2015 From: malcolm.wallace at me.com (Malcolm Wallace) Date: Sat, 24 Oct 2015 10:08:32 +0100 Subject: type error formatting In-Reply-To: <1445674669.32229.4.camel@joachim-breitner.de> References: <1445674669.32229.4.camel@joachim-breitner.de> Message-ID: <80C4AD54-D711-4191-960A-EF12EA6B5F28@me.com> On 24 Oct 2015, at 09:17, Joachim Breitner wrote: > For example in > >> Relevant bindings include >> syllables :: [(a1, Syllable)] >> (bound at Derive/Call/India/Pakhawaj.hs:141:16) >> best_match :: [(a1, Syllable)] >> -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) >> (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > Also, unless the programmer is doing weird things with shadowing, is > the "bound at" information really valuable? I?d say no: Usually, the > programmer knows his bindings, and even if not, she will not have any > problems finding the right binding. As someone who spends a lot of time maintaining code that I did not write, I have to say that it is not enough that the "programmer knows his bindings". She might, but I do not. This kind of helpful signposting of exactly what file + linenumber + character position to look at, is really useful for someone who is not familiar with the code. Regards, Malcolm From mail at joachim-breitner.de Sat Oct 24 09:29:52 2015 From: mail at joachim-breitner.de (Joachim Breitner) Date: Sat, 24 Oct 2015 11:29:52 +0200 Subject: type error formatting In-Reply-To: <80C4AD54-D711-4191-960A-EF12EA6B5F28@me.com> References: <1445674669.32229.4.camel@joachim-breitner.de> <80C4AD54-D711-4191-960A-EF12EA6B5F28@me.com> Message-ID: <1445678992.32229.6.camel@joachim-breitner.de> Hi, Am Samstag, den 24.10.2015, 10:08 +0100 schrieb Malcolm Wallace: > On 24 Oct 2015, at 09:17, Joachim Breitner wrote: > > > For example in > > > > > ???Relevant bindings include > > > ??????syllables :: [(a1, Syllable)] > > > ????????(bound at Derive/Call/India/Pakhawaj.hs:141:16) > > > ??????best_match :: [(a1, Syllable)] > > > ????????????????????-> Maybe (Int, ([(a1, Syllable)], [(a1, > > > Sequence Bol)])) > > > ????????(bound at Derive/Call/India/Pakhawaj.hs:141:5) > > > > Also, unless the programmer is doing weird things with shadowing, > > is > > the "bound at" information really valuable? I?d say no: Usually, > > the > > programmer knows his bindings, and even if not, she will not have > > any > > problems finding the right binding. > > As someone who spends a lot of time maintaining code that I did not > write, I have to say that it is not enough that the "programmer knows > his bindings".??She might, but I do not.??This kind of helpful > signposting of exactly what file + linenumber + character position to > look at, is really useful for someone who is not familiar with the > code. sure, there is a trade off. But the file can by default to be assumed to be the file of the error. And are you really going to note the line number and go to that line, instead of just issuing /syllables? When error messages reach the vertical size of a terminal window, the benefit of adding such details diminishes. Greetings, Joachim -- Joachim ?nomeata? Breitner mail at joachim-breitner.de ? http://www.joachim-breitner.de/ Jabber: nomeata at joachim-breitner.de ? GPG-Key: 0xF0FBF51F Debian Developer: nomeata at debian.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: This is a digitally signed message part URL: From roma at ro-che.info Sat Oct 24 10:07:14 2015 From: roma at ro-che.info (Roman Cheplyaka) Date: Sat, 24 Oct 2015 13:07:14 +0300 Subject: type error formatting In-Reply-To: References: Message-ID: <562B5852.8020609@ro-che.info> I have the same issue with the current error messages. I think these are all good ideas. On 10/24/2015 05:48 AM, Evan Laforge wrote: > Here's a typical simple type error from GHC: > > Derive/Call/India/Pakhawaj.hs:142:62: > Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] > Relevant bindings include > syllables :: [(a1, Syllable)] > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > best_match :: [(a1, Syllable)] > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > In the second argument of ?mapMaybe?, namely ?all_bols? > In the second argument of ?($)?, namely > ?mapMaybe (match_bols syllables) all_bols? > > I've been having more trouble than usual reading GHC's errors, and I > finally spent some time to think about it. The problem is that this new > "relevant bindings include" section gets in between the expected and > actual types (I still don't like that wording but I've gotten used to > it), which is the most critical part, and the location context, which is > second most critical. Notice the same effect in the previous sentence > :) After I see a type error the next thing I want to see is the where > it happened, so I have to skip over the bindings, which can be long and > complicated. Then I usually know what to do, and only look into the > bindings if something more complicated is going on, like wonky > inference. So how about reordering the message: > > Derive/Call/India/Pakhawaj.hs:142:62: > Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] > In the second argument of ?mapMaybe?, namely ?all_bols? > In the second argument of ?($)?, namely > ?mapMaybe (match_bols syllables) all_bols? > Relevant bindings include > syllables :: [(a1, Syllable)] > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > best_match :: [(a1, Syllable)] > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > After this, why not go one step further and set off the various sections > visibly to make it easier to scan. The context section can also be > really long if it gets an entire do block or record: > > Derive/Call/India/Pakhawaj.hs:142:62: > * Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] > * In the second argument of ?mapMaybe?, namely ?all_bols? > In the second argument of ?($)?, namely > ?mapMaybe (match_bols syllables) all_bols? > * Relevant bindings include > syllables :: [(a1, Syllable)] > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > best_match :: [(a1, Syllable)] > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > Or alternately, taking up a bit more vertical space: > > Derive/Call/India/Pakhawaj.hs:142:62: > Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] > ----------------------------- > In the second argument of ?mapMaybe?, namely ?all_bols? > In the second argument of ?($)?, namely > ?mapMaybe (match_bols syllables) all_bols? > ----------------------------- > Relevant bindings include > syllables :: [(a1, Syllable)] > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > best_match :: [(a1, Syllable)] > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > Thoughts? It seems simple enough that I could do myself, but of course > not without buy-in. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From ryan.trinkle at gmail.com Sat Oct 24 15:30:42 2015 From: ryan.trinkle at gmail.com (Ryan Trinkle) Date: Sat, 24 Oct 2015 11:30:42 -0400 Subject: type error formatting In-Reply-To: <562B5852.8020609@ro-che.info> References: <562B5852.8020609@ro-che.info> Message-ID: This looks like an improvement to me. I love the idea of a visual demarcation between sections, too; the bullets seem like a good choice there (the horizontal lines seem like they'd take up more space). Ryan On Sat, Oct 24, 2015 at 6:07 AM, Roman Cheplyaka wrote: > I have the same issue with the current error messages. I think these are > all good ideas. > > On 10/24/2015 05:48 AM, Evan Laforge wrote: > > Here's a typical simple type error from GHC: > > > > Derive/Call/India/Pakhawaj.hs:142:62: > > Couldn't match type ?Text? with ?(a1, Syllable)? > > Expected type: [([(a1, Syllable)], [Sequence Bol])] > > Actual type: [([Syllable], [Sequence Bol])] > > Relevant bindings include > > syllables :: [(a1, Syllable)] > > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > > best_match :: [(a1, Syllable)] > > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence > Bol)])) > > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > In the second argument of ?mapMaybe?, namely ?all_bols? > > In the second argument of ?($)?, namely > > ?mapMaybe (match_bols syllables) all_bols? > > > > I've been having more trouble than usual reading GHC's errors, and I > > finally spent some time to think about it. The problem is that this new > > "relevant bindings include" section gets in between the expected and > > actual types (I still don't like that wording but I've gotten used to > > it), which is the most critical part, and the location context, which is > > second most critical. Notice the same effect in the previous sentence > > :) After I see a type error the next thing I want to see is the where > > it happened, so I have to skip over the bindings, which can be long and > > complicated. Then I usually know what to do, and only look into the > > bindings if something more complicated is going on, like wonky > > inference. So how about reordering the message: > > > > Derive/Call/India/Pakhawaj.hs:142:62: > > Couldn't match type ?Text? with ?(a1, Syllable)? > > Expected type: [([(a1, Syllable)], [Sequence Bol])] > > Actual type: [([Syllable], [Sequence Bol])] > > In the second argument of ?mapMaybe?, namely ?all_bols? > > In the second argument of ?($)?, namely > > ?mapMaybe (match_bols syllables) all_bols? > > Relevant bindings include > > syllables :: [(a1, Syllable)] > > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > > best_match :: [(a1, Syllable)] > > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence > Bol)])) > > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > > > After this, why not go one step further and set off the various sections > > visibly to make it easier to scan. The context section can also be > > really long if it gets an entire do block or record: > > > > Derive/Call/India/Pakhawaj.hs:142:62: > > * Couldn't match type ?Text? with ?(a1, Syllable)? > > Expected type: [([(a1, Syllable)], [Sequence Bol])] > > Actual type: [([Syllable], [Sequence Bol])] > > * In the second argument of ?mapMaybe?, namely ?all_bols? > > In the second argument of ?($)?, namely > > ?mapMaybe (match_bols syllables) all_bols? > > * Relevant bindings include > > syllables :: [(a1, Syllable)] > > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > > best_match :: [(a1, Syllable)] > > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence > Bol)])) > > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > > > Or alternately, taking up a bit more vertical space: > > > > Derive/Call/India/Pakhawaj.hs:142:62: > > Couldn't match type ?Text? with ?(a1, Syllable)? > > Expected type: [([(a1, Syllable)], [Sequence Bol])] > > Actual type: [([Syllable], [Sequence Bol])] > > ----------------------------- > > In the second argument of ?mapMaybe?, namely ?all_bols? > > In the second argument of ?($)?, namely > > ?mapMaybe (match_bols syllables) all_bols? > > ----------------------------- > > Relevant bindings include > > syllables :: [(a1, Syllable)] > > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > > best_match :: [(a1, Syllable)] > > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence > Bol)])) > > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > > > Thoughts? It seems simple enough that I could do myself, but of course > > not without buy-in. > > > > _______________________________________________ > Glasgow-haskell-users mailing list > Glasgow-haskell-users at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From simonpj at microsoft.com Sat Oct 24 19:50:08 2015 From: simonpj at microsoft.com (Simon Peyton Jones) Date: Sat, 24 Oct 2015 19:50:08 +0000 Subject: type error formatting In-Reply-To: References: Message-ID: <3097b47964924f189f925cfc55575cfb@DB4PR30MB030.064d.mgd.msft.net> I?m all for it. Can advise. (Make a ticket.) Thanks! Simon From: Glasgow-haskell-users [mailto:glasgow-haskell-users-bounces at haskell.org] On Behalf Of Evan Laforge Sent: 24 October 2015 03:48 To: GHC users Subject: type error formatting Here's a typical simple type error from GHC: Derive/Call/India/Pakhawaj.hs:142:62: Couldn't match type ?Text? with ?(a1, Syllable)? Expected type: [([(a1, Syllable)], [Sequence Bol])] Actual type: [([Syllable], [Sequence Bol])] Relevant bindings include syllables :: [(a1, Syllable)] (bound at Derive/Call/India/Pakhawaj.hs:141:16) best_match :: [(a1, Syllable)] -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) (bound at Derive/Call/India/Pakhawaj.hs:141:5) In the second argument of ?mapMaybe?, namely ?all_bols? In the second argument of ?($)?, namely ?mapMaybe (match_bols syllables) all_bols? I've been having more trouble than usual reading GHC's errors, and I finally spent some time to think about it. The problem is that this new "relevant bindings include" section gets in between the expected and actual types (I still don't like that wording but I've gotten used to it), which is the most critical part, and the location context, which is second most critical. Notice the same effect in the previous sentence :) After I see a type error the next thing I want to see is the where it happened, so I have to skip over the bindings, which can be long and complicated. Then I usually know what to do, and only look into the bindings if something more complicated is going on, like wonky inference. So how about reordering the message: Derive/Call/India/Pakhawaj.hs:142:62: Couldn't match type ?Text? with ?(a1, Syllable)? Expected type: [([(a1, Syllable)], [Sequence Bol])] Actual type: [([Syllable], [Sequence Bol])] In the second argument of ?mapMaybe?, namely ?all_bols? In the second argument of ?($)?, namely ?mapMaybe (match_bols syllables) all_bols? Relevant bindings include syllables :: [(a1, Syllable)] (bound at Derive/Call/India/Pakhawaj.hs:141:16) best_match :: [(a1, Syllable)] -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) (bound at Derive/Call/India/Pakhawaj.hs:141:5) After this, why not go one step further and set off the various sections visibly to make it easier to scan. The context section can also be really long if it gets an entire do block or record: Derive/Call/India/Pakhawaj.hs:142:62: * Couldn't match type ?Text? with ?(a1, Syllable)? Expected type: [([(a1, Syllable)], [Sequence Bol])] Actual type: [([Syllable], [Sequence Bol])] * In the second argument of ?mapMaybe?, namely ?all_bols? In the second argument of ?($)?, namely ?mapMaybe (match_bols syllables) all_bols? * Relevant bindings include syllables :: [(a1, Syllable)] (bound at Derive/Call/India/Pakhawaj.hs:141:16) best_match :: [(a1, Syllable)] -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) (bound at Derive/Call/India/Pakhawaj.hs:141:5) Or alternately, taking up a bit more vertical space: Derive/Call/India/Pakhawaj.hs:142:62: Couldn't match type ?Text? with ?(a1, Syllable)? Expected type: [([(a1, Syllable)], [Sequence Bol])] Actual type: [([Syllable], [Sequence Bol])] ----------------------------- In the second argument of ?mapMaybe?, namely ?all_bols? In the second argument of ?($)?, namely ?mapMaybe (match_bols syllables) all_bols? ----------------------------- Relevant bindings include syllables :: [(a1, Syllable)] (bound at Derive/Call/India/Pakhawaj.hs:141:16) best_match :: [(a1, Syllable)] -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) (bound at Derive/Call/India/Pakhawaj.hs:141:5) Thoughts? It seems simple enough that I could do myself, but of course not without buy-in. -------------- next part -------------- An HTML attachment was scrubbed... URL: From qdunkan at gmail.com Sat Oct 24 20:14:21 2015 From: qdunkan at gmail.com (Evan Laforge) Date: Sat, 24 Oct 2015 13:14:21 -0700 Subject: type error formatting In-Reply-To: <3097b47964924f189f925cfc55575cfb@DB4PR30MB030.064d.mgd.msft.net> References: <3097b47964924f189f925cfc55575cfb@DB4PR30MB030.064d.mgd.msft.net> Message-ID: Ok, ticket created. I'll go see how much I can figure out on my own. https://ghc.haskell.org/trac/ghc/ticket/11014 WRT the "bound at" bits in "relevant bindings", I have no strong opinion. What about omitting them if they are in the same file as the main error? Or maybe they always are? I'm not totally clear how it chooses which bindings are relevant. On Sat, Oct 24, 2015 at 12:50 PM, Simon Peyton Jones wrote: > I?m all for it. Can advise. (Make a ticket.) > > > > Thanks! > > > > Simon > > > > *From:* Glasgow-haskell-users [mailto: > glasgow-haskell-users-bounces at haskell.org] *On Behalf Of *Evan Laforge > *Sent:* 24 October 2015 03:48 > *To:* GHC users > *Subject:* type error formatting > > > > Here's a typical simple type error from GHC: > > > > Derive/Call/India/Pakhawaj.hs:142:62: > Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] > Relevant bindings include > syllables :: [(a1, Syllable)] > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > best_match :: [(a1, Syllable)] > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence > Bol)])) > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > In the second argument of ?mapMaybe?, namely ?all_bols? > In the second argument of ?($)?, namely > ?mapMaybe (match_bols syllables) all_bols? > > I've been having more trouble than usual reading GHC's errors, and I > finally spent some time to think about it. The problem is that this new > "relevant bindings include" section gets in between the expected and actual > types (I still don't like that wording but I've gotten used to it), which > is the most critical part, and the location context, which is second most > critical. Notice the same effect in the previous sentence :) After I see > a type error the next thing I want to see is the where it happened, so I > have to skip over the bindings, which can be long and complicated. Then I > usually know what to do, and only look into the bindings if something more > complicated is going on, like wonky inference. So how about reordering the > message: > > Derive/Call/India/Pakhawaj.hs:142:62: > Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] > In the second argument of ?mapMaybe?, namely ?all_bols? > In the second argument of ?($)?, namely > ?mapMaybe (match_bols syllables) all_bols? > Relevant bindings include > syllables :: [(a1, Syllable)] > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > best_match :: [(a1, Syllable)] > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence > Bol)])) > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > After this, why not go one step further and set off the various sections > visibly to make it easier to scan. The context section can also be really > long if it gets an entire do block or record: > > Derive/Call/India/Pakhawaj.hs:142:62: > * Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] > * In the second argument of ?mapMaybe?, namely ?all_bols? > In the second argument of ?($)?, namely > ?mapMaybe (match_bols syllables) all_bols? > * Relevant bindings include > syllables :: [(a1, Syllable)] > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > best_match :: [(a1, Syllable)] > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence > Bol)])) > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > > > Or alternately, taking up a bit more vertical space: > > > > Derive/Call/India/Pakhawaj.hs:142:62: > Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] > > ----------------------------- > In the second argument of ?mapMaybe?, namely ?all_bols? > In the second argument of ?($)?, namely > ?mapMaybe (match_bols syllables) all_bols? > > ----------------------------- > Relevant bindings include > > syllables :: [(a1, Syllable)] > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > best_match :: [(a1, Syllable)] > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence > Bol)])) > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > > > Thoughts? It seems simple enough that I could do myself, but of course > not without buy-in. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From migmit at gmail.com Sat Oct 24 20:30:11 2015 From: migmit at gmail.com (MigMit) Date: Sat, 24 Oct 2015 22:30:11 +0200 Subject: type error formatting In-Reply-To: References: <3097b47964924f189f925cfc55575cfb@DB4PR30MB030.064d.mgd.msft.net> Message-ID: <518D92BA-6EB8-45A3-A367-97E260AE3984@gmail.com> At the very least, "bound at" should help IDEs (Emacs in particular) show exactly the right places. > On 24 Oct 2015, at 22:14, Evan Laforge wrote: > > Ok, ticket created. I'll go see how much I can figure out on my own. > > https://ghc.haskell.org/trac/ghc/ticket/11014 > > WRT the "bound at" bits in "relevant bindings", I have no strong opinion. What about omitting them if they are in the same file as the main error? Or maybe they always are? I'm not totally clear how it chooses which bindings are relevant. > > On Sat, Oct 24, 2015 at 12:50 PM, Simon Peyton Jones wrote: > I?m all for it. Can advise. (Make a ticket.) > > > > Thanks! > > > > Simon > > > > From: Glasgow-haskell-users [mailto:glasgow-haskell-users-bounces at haskell.org] On Behalf Of Evan Laforge > Sent: 24 October 2015 03:48 > To: GHC users > Subject: type error formatting > > > > Here's a typical simple type error from GHC: > > > > Derive/Call/India/Pakhawaj.hs:142:62: > Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] > Relevant bindings include > syllables :: [(a1, Syllable)] > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > best_match :: [(a1, Syllable)] > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > In the second argument of ?mapMaybe?, namely ?all_bols? > In the second argument of ?($)?, namely > ?mapMaybe (match_bols syllables) all_bols? > > I've been having more trouble than usual reading GHC's errors, and I finally spent some time to think about it. The problem is that this new "relevant bindings include" section gets in between the expected and actual types (I still don't like that wording but I've gotten used to it), which is the most critical part, and the location context, which is second most critical. Notice the same effect in the previous sentence :) After I see a type error the next thing I want to see is the where it happened, so I have to skip over the bindings, which can be long and complicated. Then I usually know what to do, and only look into the bindings if something more complicated is going on, like wonky inference. So how about reordering the message: > > Derive/Call/India/Pakhawaj.hs:142:62: > Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] > In the second argument of ?mapMaybe?, namely ?all_bols? > In the second argument of ?($)?, namely > ?mapMaybe (match_bols syllables) all_bols? > Relevant bindings include > syllables :: [(a1, Syllable)] > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > best_match :: [(a1, Syllable)] > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > After this, why not go one step further and set off the various sections visibly to make it easier to scan. The context section can also be really long if it gets an entire do block or record: > > Derive/Call/India/Pakhawaj.hs:142:62: > * Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] > * In the second argument of ?mapMaybe?, namely ?all_bols? > In the second argument of ?($)?, namely > ?mapMaybe (match_bols syllables) all_bols? > * Relevant bindings include > syllables :: [(a1, Syllable)] > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > best_match :: [(a1, Syllable)] > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > > > Or alternately, taking up a bit more vertical space: > > > > Derive/Call/India/Pakhawaj.hs:142:62: > Couldn't match type ?Text? with ?(a1, Syllable)? > Expected type: [([(a1, Syllable)], [Sequence Bol])] > Actual type: [([Syllable], [Sequence Bol])] > > ----------------------------- > In the second argument of ?mapMaybe?, namely ?all_bols? > In the second argument of ?($)?, namely > ?mapMaybe (match_bols syllables) all_bols? > > ----------------------------- > Relevant bindings include > > syllables :: [(a1, Syllable)] > (bound at Derive/Call/India/Pakhawaj.hs:141:16) > best_match :: [(a1, Syllable)] > -> Maybe (Int, ([(a1, Syllable)], [(a1, Sequence Bol)])) > (bound at Derive/Call/India/Pakhawaj.hs:141:5) > > > > Thoughts? It seems simple enough that I could do myself, but of course not without buy-in. > > > _______________________________________________ > Glasgow-haskell-users mailing list > Glasgow-haskell-users at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users From mail at joachim-breitner.de Sun Oct 25 20:21:38 2015 From: mail at joachim-breitner.de (Joachim Breitner) Date: Sun, 25 Oct 2015 21:21:38 +0100 Subject: type error formatting In-Reply-To: References: <3097b47964924f189f925cfc55575cfb@DB4PR30MB030.064d.mgd.msft.net> Message-ID: <1445804498.1720.5.camel@joachim-breitner.de> Hi, Am Samstag, den 24.10.2015, 13:14 -0700 schrieb Evan Laforge: > WRT the "bound at" bits in "relevant bindings", I have no strong > opinion.? What about omitting them if they are in the same file as > the main error?? Or maybe they always are?? I'm not totally clear how > it chooses which bindings are relevant. take one step at a time, and fix the issue you are having within #11014. Once that is through and merged, then (or in parallel to) trying to trim down the bound-at messages can be attempted. Am Samstag, den 24.10.2015, 22:30 +0200 schrieb MigMit: > At the very least, "bound at" should help IDEs (Emacs in particular) > show exactly the right places. an IDE that offers such a deep integration will hopefully not parse data meant for human consumption. We have had this discussion before (in the context of avoiding or merging multiple instances of the same error message, such as ?foo not in scope?), and I continue to argue that the error messages printed by default should be tailored for the human reader. IDEs should ideally make use of something based on the GHC API. If that is not possible, then I?d advocate a flag, say "-fverbose-error- messages" or similar that includes all detail that might be relevant for an IDE, and maybe even in a nicer-to-parse format. Greetings, Joachim -- Joachim ?nomeata? Breitner mail at joachim-breitner.de ? http://www.joachim-breitner.de/ Jabber: nomeata at joachim-breitner.de ? GPG-Key: 0xF0FBF51F Debian Developer: nomeata at debian.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: This is a digitally signed message part URL: From migmit at gmail.com Sun Oct 25 20:30:37 2015 From: migmit at gmail.com (MigMit) Date: Sun, 25 Oct 2015 21:30:37 +0100 Subject: type error formatting In-Reply-To: <1445804498.1720.5.camel@joachim-breitner.de> References: <3097b47964924f189f925cfc55575cfb@DB4PR30MB030.064d.mgd.msft.net> <1445804498.1720.5.camel@joachim-breitner.de> Message-ID: > On 25 Oct 2015, at 21:21, Joachim Breitner wrote: > > Am Samstag, den 24.10.2015, 22:30 +0200 schrieb MigMit: >> At the very least, "bound at" should help IDEs (Emacs in particular) >> show exactly the right places. > > an IDE that offers such a deep integration will hopefully not parse > data meant for human consumption. Hope is good. Reality, however, is different. At least haskell-mode in Emacs DOES parse such data, when you try to load your file in REPL. > IDEs should ideally make use of something based on the GHC API. I agree. But the key word here is "ideally". Second thought though ? do we really want to create a gap between error messages from the compiler and whatever IDE tells us? After all, text output from GHC is ALSO a kind of API. > If that > is not possible, then I?d advocate a flag, say "-fverbose-error- > messages" or similar that includes all detail that might be relevant > for an IDE, and maybe even in a nicer-to-parse format. Doesn't seem worth it to me. Current format is quite parseable, and not really bad for human eyes either. From mail at joachim-breitner.de Sun Oct 25 20:45:01 2015 From: mail at joachim-breitner.de (Joachim Breitner) Date: Sun, 25 Oct 2015 21:45:01 +0100 Subject: type error formatting In-Reply-To: References: <3097b47964924f189f925cfc55575cfb@DB4PR30MB030.064d.mgd.msft.net> <1445804498.1720.5.camel@joachim-breitner.de> Message-ID: <1445805901.1720.11.camel@joachim-breitner.de> Hi, Am Sonntag, den 25.10.2015, 21:30 +0100 schrieb MigMit: > Doesn't seem worth it to me. Current format is quite parseable, and > not really bad for human eyes either. I know that you meant this as a?litote, but let me ignore that I know that for a moment to reply, that ?not really bad? is definitely not good enough for me, and I want the compiler to print messages that are meant for my consumption to be in the _best_ possible format. Or at least try that. Obviously, there is no ?best? for every human. But things get easier if we do not have to overly worry about computers as well. It goes the other way as well. IDEs would tremendously benefit if the error location would not just be a position but a whole span. But clearly (I hope) we do not want to include this information in the output that we read. BTW, does Emacs really parse _this_ bit of information? Most GHC integrations that I have seen match on the first line to indicate the file and position of the overall error, and take the error verbatim. Greetings, Joachim -- Joachim ?nomeata? Breitner mail at joachim-breitner.de ? http://www.joachim-breitner.de/ Jabber: nomeata at joachim-breitner.de ? GPG-Key: 0xF0FBF51F Debian Developer: nomeata at debian.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: This is a digitally signed message part URL: From migmit at gmail.com Sun Oct 25 21:03:02 2015 From: migmit at gmail.com (MigMit) Date: Sun, 25 Oct 2015 22:03:02 +0100 Subject: type error formatting In-Reply-To: <1445805901.1720.11.camel@joachim-breitner.de> References: <3097b47964924f189f925cfc55575cfb@DB4PR30MB030.064d.mgd.msft.net> <1445804498.1720.5.camel@joachim-breitner.de> <1445805901.1720.11.camel@joachim-breitner.de> Message-ID: <3893CAFF-3D52-45EE-8C18-49B34CFEA453@gmail.com> > On 25 Oct 2015, at 21:45, Joachim Breitner wrote: > > Hi, > > Am Sonntag, den 25.10.2015, 21:30 +0100 schrieb MigMit: >> Doesn't seem worth it to me. Current format is quite parseable, and >> not really bad for human eyes either. > > I know that you meant this as a litote, Please, don't say "know" when you mean "assume". It's especially annoying when you assume wrong. > but let me ignore that I know > that for a moment to reply, that ?not really bad? is definitely not > good enough for me, and I want the compiler to print messages that are > meant for my consumption to be in the _best_ possible format. Or at > least try that. > > Obviously, there is no ?best? for every human. But things get easier if > we do not have to overly worry about computers as well. I think that's a wrong approach. My theory is that the concepts "easy to read for a human with some experience" and "easy to parse for a computer" are two closely related notions. Sure, they aren't identical ? a binary format might still be quite easy to parse, but completely unreadable for human ? but they go hand in hand. Even with binary formats ? if, for example, there is a clear notion of "statement" in this binary formats, and statements are separated by the byte "0xff", it's easier both for a human (equipped with binary editor) and for a computer than, for example, if the length of the statement is determined by the first byte. But! It's much easier to argue about "what's easier for a computer" than the same thing for humans. > BTW, does Emacs really parse _this_ bit of information? Most GHC > integrations that I have seen match on the first line to indicate the > file and position of the overall error, and take the error verbatim. Last time I checked, Emacs transformed such positions into hyperlinks. From wren at community.haskell.org Sat Oct 31 01:26:19 2015 From: wren at community.haskell.org (wren romano) Date: Fri, 30 Oct 2015 21:26:19 -0400 Subject: type error formatting In-Reply-To: References: Message-ID: On Fri, Oct 23, 2015 at 10:48 PM, Evan Laforge wrote: > Here's a typical simple type error from GHC: > > [...] > > I've been having more trouble than usual reading GHC's errors, and I finally > spent some time to think about it. The problem is that this new "relevant > bindings include" section gets in between the expected and actual types (I > still don't like that wording but I've gotten used to it), which is the most > critical part, and the location context, which is second most critical. +1 to reordering the presentation and to adding bullets (or whatever) to better demarcate the sections. I've been bit by this a lot recently. With "normal" type errors it's quick and easy to figure out what went wrong, but especially when the issue has to do with type equality constraints, it takes far too much time to sift through the error message to find the relevant information[1]. I also wonder whether we should add in some flags for controlling how much verbosity we get from error/warning messages. Sometimes we want all the info we can get, whereas other times it'd be nice to just get the bare minimum (e.g., when we're mainly interested in a yes/no response and a line number for where things broke) [1] perhaps type equality errors should be presented differently than other type errors? The most relevant bits here are (a) what equality do we need, (b) what equalities do we have, and (c) what are the local bindings and their types (so we know where the various indices came from). Which is a bit different from the relevant information for an "expected Foo, found Bar" type error -- Live well, ~wren From mateusz.p.kloczko at gmail.com Sat Oct 31 13:39:16 2015 From: mateusz.p.kloczko at gmail.com (=?UTF-8?Q?Mateusz_K=C5=82oczko?=) Date: Sat, 31 Oct 2015 14:39:16 +0100 Subject: Fwd: GHC 7.10.2 and 7.8.4 - optimization flags do not force recompilation. In-Reply-To: References: Message-ID: Hello I would like to ask one question about optimization flags. For different n, executing ghc --make -On MyCode.hs doesn't force recompilation for both GHC 7.10.2 and 7.8.4. Is this intended behaviour ? Or am I missing something ? Regards, Mateusz K?oczko -------------- next part -------------- An HTML attachment was scrubbed... URL: From thomasmiedema at gmail.com Sat Oct 31 14:20:39 2015 From: thomasmiedema at gmail.com (Thomas Miedema) Date: Sat, 31 Oct 2015 15:20:39 +0100 Subject: GHC 7.10.2 and 7.8.4 - optimization flags do not force recompilation. In-Reply-To: References: Message-ID: It's a bug, see http://ghc.haskell.org/trac/ghc/ticket/10923 Workaround: use `-fforce-recomp`. On Sat, Oct 31, 2015 at 2:39 PM, Mateusz K?oczko < mateusz.p.kloczko at gmail.com> wrote: > Hello > > I would like to ask one question about optimization flags. > For different n, executing ghc --make -On MyCode.hs doesn't force > recompilation for both GHC 7.10.2 and 7.8.4. > > Is this intended behaviour ? Or am I missing something ? > > Regards, > Mateusz K?oczko > > > _______________________________________________ > Glasgow-haskell-users mailing list > Glasgow-haskell-users at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users > > -------------- next part -------------- An HTML attachment was scrubbed... URL: