Re: Records in Haskell
Wren/all Please remember SPJ's request on the Records wiki to stick to the namespace issue. We're trying to make something better that H98's name clash. We are not trying to build some ideal polymorphic record system. To take the field labelled "name": in H98 you have to declare each record in a different module and import every module into your application and always refer to "name" prefixed by the module. DORF doesn't stop you doing any of that. So if you think of each "name" being a different meaning, carry on using multiple modules and module prefixes. That's as easy (or difficult) as under H98. You can declare fieldLabel "name" in one module, import it unqualified into another and declare more records with a "name" label -- contrary to what somebody was claiming. Or you can import fieldLabel "name" qualified, and use it as a selector function on all record types declared using it. It's just a function like any other imported/qualified function, for crying out loud! So if there's 'your' "name" label and 'my' "name", then use the module/qualification system as you would for any other scoped name. Then trying to apply My.name to Your.record will get an instance failure, as usual. (And by the way, there's no "DORFistas", let's avoid personalising this. There are people who don't seem to understand DORF -- both those criticising and those supporting.) AntC - Original Message Follows - > On 2/25/12 10:18 AM, Gábor Lehel wrote: > > On Sat, Feb 25, 2012 at 3:54 PM, Barney > Hilken wrote: >> After more > pondering, I finally think I understand what the DORFistas > want. Here is an example: >> > >> You want to define records which describe people, and > include (among other things) a field called "name". There > might be several different record types with a name field, > depending on whether the record refers to a customer, an > employee, a business contact etc., but in each case "name" > is the name of the person to which the record refers. You > then write various functions which assume this, such as >> > >>>spam :: Has r "name" String => r -> String > >>>spam r = "Dear " ++ r.name ++ "\nHave you > heard..." >> > >> Now I want to define records which describe products, > and I also use a field "name" in the same way, except that > it is the brand name of the product. I also define > functions such as >> > >>>offer :: Has r "name" String => r -> String > >>>offer r = "Reduced! " ++ r.name ++ " 50% off!" > >> > >> It doesn't make any sense to apply your functions to my > records or vice-versa, but because we both chose the same > label, the compiler allows it. Putting the code in > separate modules makes no difference, since labels are > global. > > > Exactly! > > FWIW, this is the concern I alluded to earlier. Namely > that we may want to have two (or more), er, 'classes' of > records--- where a field is polymorphic over an > individual class, but we don't want those classes to > merge simply because they happened to choose the same name > and type for the field. > > I'm not sure it's a good proposal, but it seems like the > only way to handle this issue is to (1) introduce a new > kind for semantically-oriented field names, and (2) make > the Has class use that kind rather than a type-level > string. By (1), what I mean is that rather than referring > to the field as "name", we would declare PersonalName and > BrandName and then use those in lieu of the string. And if > we do that, then (2) demands that we must somehow make > explicit which one we mean, should we want the `name` > field to be polymorphic for some given record > declaration. > > -- > Live well, > ~wren > > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@haskell.org > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Records in Haskell
Whoa! suddenly a deluge over the DORF proposal. I don't have time to reply fully now, but I must say: Barney you have got it all wrong. No, DORF does not attach one class to each label. There is only one class 'Has', with methods get and set. Each record decl generates an instance for the combination of record/field. You can't mix declared and free-standing labels in the same record. The switch for DORF is at the module level: in a module either all records and labels use DORF, or none do (that is, they use H98 style with each field name being unique). AntC - Original Message Follows - > > My objection is that I'm not sure if there is ever a > > case where "you really want things to be polymorphic > over all records". > > Well, I don't have a simple, really convincing example, > but there are certainly things I want to play with. More > importantly, DORF automatically attaches one class to each > label, but this is often not what you want. For example, > if you have two fields "firstname" and "lastname" the > associated classes are less useful: what you really want > is > > > class (Has r "firstname" String, Has r "lastname" > String) => HasPersonalName r > > so that you can define > > >fullname :: HasPersonalName r => r -> String > >fullname r = r.firstname ++ " " ++ r.lastname > > You may also want to define subclasses to express more > specific conditions. In general, the compiler cannot > automatically deduce what is semantically important: you > need to define it yourself. The Has class is the base on > which you can build. > > > It doesn't seem like the > > Haskell way to have the less safe thing as the one > > that's default and convenient, and to allow the > > programmer to layer a more-safe thing on top of it if he > > or she wants to. It seems more like the Haskell way to > have the safer thing be the default and to require extra > > work if you want to do something less safe*. > > I think you are using the word "safe" in a slightly > misleading way. None of this is mathematically unsafe, > because projections are natural (truly polymorphic). The > "safety" that is broken here is nothing to do with the > semantics of the language, it is to do with the semantics > of the system being implemented, and that is something the > compiler cannot infer. As my example above shows, it > doesn't always correspond one to one with the labels. > > The Haskel way is to make things as polymorphic as is > mathematically safe, even when this goes beyond the > programmers original intention. You can then restrict this > polymorphism by giving explicit less general types in the > same way as in my examples. I think my approach is more > Haskel like. > > Another important Haskel design consideration is to reuse > parts of the language where possible, rather than > introduce new structures. Type classes were originally > introduced to deal with equality and numeric functions, > but were reused for many things including monads. My > approach achieves the same as DORF (and more), but using > existing language features instead of introducing new > ones. > > Barney. > > > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@haskell.org > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Increasing number of worker tasks in RTS (GHC 7.4.1) - how to debug?
I have to take back what I said about the increase in worker tasks being related to some Mac OS pthread bug. I can now reproduce the issue on Linux (Redhat x86_64) too (and cause a segmentation fault once in a while). So, now, it seems the issue might be due to either some kind of interaction between GHC RTS, and C pthread mutexes, or a bug in my code. What I have done is to create a simple test case that reproduces the increase in number of worker threads with each run of Haskell timer thread (that syncs with C pthreads). I have put up the code on github with documentation on how to reproduce the issue: https://github.com/sanketr/cffitest I will appreciate feedback on whether it is a bug in my code, or a GHC bug that needs to be reported. On Sat, Feb 25, 2012 at 3:41 PM, Sanket Agrawal wrote: > On further investigation, it seems to be very specific to Mac OS Lion (I > am running 10.7.3) - all tests were with -N3 option: > > - I can reliably crash the code with seg fault or bus error if I create > more than 8 threads in C FFI (each thread creates its own mutex, for 1-1 > coordination with Haskell timer thread). My iMac has 4 processors. In gdb, > I can see that the crash happened in __psynch_cvsignal () which seems to be > related to pthread mutex. > > - If I increase the number of C FFI threads (and hence, pthread mutexes) > to >=7, the number of tasks starts increasing. 8 is the max number of FFI > threads in my testing where the code runs without crashing. But, it seems > that there is some kind of pthread mutex related leak. What the timer > thread does is to fork 8 parallel haskell threads to acquire mutexes from > each of the C FFI thread. Though the function returns after acquiring, > collecting data, and releasing mutex, some of the threads seem to be marked > as active by GC, because of mutex memory leak. Exactly how, I don't know. > > - If I keep the number of C FFI threads to <=6, there is no memory leak. > The number of tasks stays steady. > > So, it seems to be pthread library issue (and not a GHC issue). Something > to keep in mind when developing code on Mac that involves mutex > coordination with C FFI. > > > On Sat, Feb 25, 2012 at 2:59 PM, Sanket Agrawal > wrote: > >> I wrote a program that uses a timed thread to collect data from a C >> producer (using FFI). The number of threads in C producer are fixed (and >> created at init). One haskell timer thread uses threadDelay to run itself >> on timed interval. When I look at RTS output after killing the program >> after couple of timer iterations, I see number of worker tasks increasing >> with time. >> >> For example, below is an output after 20 iterations of timer event: >> >> MUT time (elapsed) GC time (elapsed) >> Task 0 (worker) :0.00s( 0.00s) 0.00s( 0.00s) >> Task 1 (worker) :0.00s( 0.00s) 0.00s( 0.00s) >> ...output until task 37 snipped as it is same as task 1... >> Task 38 (worker) :0.07s( 0.09s) 0.00s( 0.00s) >> Task 39 (worker) :0.07s( 0.09s) 0.00s( 0.00s) >> Task 40 (worker) :0.18s( 10.20s) 0.00s( 0.00s) >> Task 41 (worker) :0.18s( 10.20s) 0.00s( 0.00s) >> Task 42 (worker) :0.18s( 10.20s) 0.00s( 0.00s) >> Task 43 (worker) :0.18s( 10.20s) 0.00s( 0.00s) >> Task 44 (worker) :0.52s( 10.74s) 0.00s( 0.00s) >> Task 45 (worker) :0.52s( 10.75s) 0.00s( 0.00s) >> Task 46 (worker) :0.52s( 10.75s) 0.00s( 0.00s) >> Task 47 (bound) :0.00s( 0.00s) 0.00s( 0.00s) >> >> >> After two iterations of timer event: >> >>MUT time (elapsed) GC time (elapsed) >> Task 0 (worker) :0.00s( 0.00s) 0.00s( 0.00s) >> Task 1 (worker) :0.00s( 0.00s) 0.00s( 0.00s) >> Task 2 (worker) :0.07s( 0.09s) 0.00s( 0.00s) >> Task 3 (worker) :0.07s( 0.09s) 0.00s( 0.00s) >> Task 4 (worker) :0.16s( 1.21s) 0.00s( 0.00s) >> Task 5 (worker) :0.16s( 1.21s) 0.00s( 0.00s) >> Task 6 (worker) :0.16s( 1.21s) 0.00s( 0.00s) >> Task 7 (worker) :0.16s( 1.21s) 0.00s( 0.00s) >> Task 8 (worker) :0.48s( 1.80s) 0.00s( 0.00s) >> Task 9 (worker) :0.48s( 1.81s) 0.00s( 0.00s) >> Task 10 (worker) :0.48s( 1.81s) 0.00s( 0.00s) >> Task 11 (bound) :0.00s( 0.00s) 0.00s( 0.00s) >> >> >> Haskell code has one forkIO call to kick off C FFI - C FFI creates 8 >> threads. Runtime options are "-N3 +RTS -s". timer event is kicked off after >> forkIO. It is for the form (pseudo-code): >> >> timerevent time = run where run = do threadDelay time >> >> do some work >> run where >> >> I also wrote a simpler code using just
Re: Records in Haskell
On 2/25/12 10:18 AM, Gábor Lehel wrote: On Sat, Feb 25, 2012 at 3:54 PM, Barney Hilken wrote: After more pondering, I finally think I understand what the DORFistas want. Here is an example: You want to define records which describe people, and include (among other things) a field called "name". There might be several different record types with a name field, depending on whether the record refers to a customer, an employee, a business contact etc., but in each case "name" is the name of the person to which the record refers. You then write various functions which assume this, such as spam :: Has r "name" String => r -> String spam r = "Dear " ++ r.name ++ "\nHave you heard..." Now I want to define records which describe products, and I also use a field "name" in the same way, except that it is the brand name of the product. I also define functions such as offer :: Has r "name" String => r -> String offer r = "Reduced! " ++ r.name ++ " 50% off!" It doesn't make any sense to apply your functions to my records or vice-versa, but because we both chose the same label, the compiler allows it. Putting the code in separate modules makes no difference, since labels are global. Exactly! FWIW, this is the concern I alluded to earlier. Namely that we may want to have two (or more), er, 'classes' of records--- where a field is polymorphic over an individual class, but we don't want those classes to merge simply because they happened to choose the same name and type for the field. I'm not sure it's a good proposal, but it seems like the only way to handle this issue is to (1) introduce a new kind for semantically-oriented field names, and (2) make the Has class use that kind rather than a type-level string. By (1), what I mean is that rather than referring to the field as "name", we would declare PersonalName and BrandName and then use those in lieu of the string. And if we do that, then (2) demands that we must somehow make explicit which one we mean, should we want the `name` field to be polymorphic for some given record declaration. -- Live well, ~wren ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Records in Haskell
On 2/24/12 5:40 PM, Johan Tibell wrote: I share Greg's concerns about polymorphic projections. For example, given a function sort :: Ord a => ... we don't allow any 'a' that happens to export a operator that's spelled<= to be passed to 'sort'. We have the user explicitly create an instance and thereby defining that their<= is e.g. a strict weak ordering and thus make sense when used with 'sort'. This explicitness is useful, it communicates the contract of the function to the reader and lets us catch mistakes in a way that automatically polymorphic projections don't. Automatically polymorphic projections feels like Go's structural polymorphism, C++'s templates or C's automatic numeric coercions, and I'm worried it'll lead to problems when used at scale. They're not required to solve the problem we're trying to solve, so lets hurry slowly and don't bake them in together with the namespacing problem. At the very least use two different LANGUAGE pragmas so users can have one without the other. +1. I'm not sure that I like the current proposals for how to control the non/automatic-ness of polymorphism (for reasons I can spell out later, if desired). But we definitely want to have something that's a bit more cultured than simply making all record projectors polymorphic over records. -- Live well, ~wren ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Understanding the -A and the -H flags
On 2/25/12 11:51 AM, Johan Tibell wrote: Perhaps it would make sense to document the actual algorithm used to set -A given -H (with and without argument.) +1. I've always been a bit hazy on how the two are related. -- Live well, ~wren ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Records in Haskell
On 02/25/2012 05:10 PM, Gábor Lehel wrote: Could you elaborate on this? (What's the way I don't want? What do you mean by field-name-prefixes versus new-style overloading?) With DORF I have control over which fields are polymorphic over which records, very much like how I have control over which classes are polymorphic over which types. That's what I want. Darn, I misinterpreted DORF. There was too much text and too many options. Tell me if I'm correct: A. Every declaration with record syntax creates Has instances for all fields [1]. B. "Has", "get" and "set" may not be written by users (guessing due to representation-hiding fail). C. You create functions using "fieldLabel name [...]" D. which have the magical effect of, when in scope unqualified, causing data types defined with record syntax to be accessible through that particular fieldLabel function (and no other way). E. (When two fieldLabels of the same name are in scope unqualified, declaring a record containing that name is an error.) F. So adding an import (for some other reason for your code) that happens to include a fieldLabel can make your records accidentally be more visible, rather than be compile-error or no-effect. I feel weird about record fields having an option that depends on whether something's in scope and cannot be controlled syntactically. Maybe we can fix that without making the syntax worse. G. It is possible (but rather ugly) to use dot-notation when there are multiple fieldNames of the same name in scope. [2] Hmm. Maybe this is Haskelly as well as convenient enough. Did I get everything right? What do you think about my concern about F? [1] http://hackage.haskell.org/trac/ghc/wiki/Records/DeclaredOverloadedRecordFields/ImplementorsView [2] http://hackage.haskell.org/trac/ghc/wiki/Records/DeclaredOverloadedRecordFields/DotPostfix#UsingDotnotationamongstqualifiednames ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Records in Haskell
> My objection is that I'm not sure if there is ever a case where "you > really want things to be polymorphic over all records". Well, I don't have a simple, really convincing example, but there are certainly things I want to play with. More importantly, DORF automatically attaches one class to each label, but this is often not what you want. For example, if you have two fields "firstname" and "lastname" the associated classes are less useful: what you really want is > class (Has r "firstname" String, Has r "lastname" String) => > HasPersonalName r so that you can define > fullname :: HasPersonalName r => r -> String > fullname r = r.firstname ++ " " ++ r.lastname You may also want to define subclasses to express more specific conditions. In general, the compiler cannot automatically deduce what is semantically important: you need to define it yourself. The Has class is the base on which you can build. > It doesn't seem like the > Haskell way to have the less safe thing as the one that's default and > convenient, and to allow the programmer to layer a more-safe thing on > top of it if he or she wants to. It seems more like the Haskell way to > have the safer thing be the default and to require extra work if you > want to do something less safe*. I think you are using the word "safe" in a slightly misleading way. None of this is mathematically unsafe, because projections are natural (truly polymorphic). The "safety" that is broken here is nothing to do with the semantics of the language, it is to do with the semantics of the system being implemented, and that is something the compiler cannot infer. As my example above shows, it doesn't always correspond one to one with the labels. The Haskel way is to make things as polymorphic as is mathematically safe, even when this goes beyond the programmers original intention. You can then restrict this polymorphism by giving explicit less general types in the same way as in my examples. I think my approach is more Haskel like. Another important Haskel design consideration is to reuse parts of the language where possible, rather than introduce new structures. Type classes were originally introduced to deal with equality and numeric functions, but were reused for many things including monads. My approach achieves the same as DORF (and more), but using existing language features instead of introducing new ones. Barney. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Records in Haskell
On Sat, Feb 25, 2012 at 10:09 PM, Isaac Dupree wrote: > On 02/25/2012 10:18 AM, Gábor Lehel wrote: >>> >>> This seems to me a much simpler approach than building the mechanism in >>> to the language as DORF does, and it's also more general, because it isn't >>> hard linked to the module system. Does it have any disadvantages? >> >> >> I can't tell offhand whether it has any drawbacks with respect to >> expressiveness. It seems to be a good solution to the stated problem, >> so thank you for proposing it. >> >> My objection is that I'm not sure if there is ever a case where "you >> really want things to be polymorphic over all records". There is >> nothing (as far as I know) analogous to this kind of implicit >> name-based polymorphism anywhere in Haskell. [...] > > > True enough. But DORF doesn't, IMHO, really solve this concern. If you > choose to use DORF, then your PersonalName and BrandNames will still be > overloaded in just the way you don't want. The only way to avoid this is a > pretty arbitrary stylistic decision whether to use Haskell98-style > field-name-prefixes or use new-style overloading. Could you elaborate on this? (What's the way I don't want? What do you mean by field-name-prefixes versus new-style overloading?) With DORF I have control over which fields are polymorphic over which records, very much like how I have control over which classes are polymorphic over which types. That's what I want. > > Even SORF is better than, say, C++ overloading in the sense that adding > another overload in SORF cannot cause code not to compile, nor change its > behaviour. Sure. > > Convince me otherwise. > Your position seems to be that unless there is some kind of grave blocking problem with SORF, then we should go with SORF. I don't really understand this. I think we should go with the best solution available. I think DORF is a better solution than SORF, so we should rather go with DORF than SORF. You've just admitted that there is no actual use case for the behaviour of SORF, as opposed to that of DORF. What am I missing? ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Records in Haskell
On 02/25/2012 10:18 AM, Gábor Lehel wrote: This seems to me a much simpler approach than building the mechanism in to the language as DORF does, and it's also more general, because it isn't hard linked to the module system. Does it have any disadvantages? I can't tell offhand whether it has any drawbacks with respect to expressiveness. It seems to be a good solution to the stated problem, so thank you for proposing it. My objection is that I'm not sure if there is ever a case where "you really want things to be polymorphic over all records". There is nothing (as far as I know) analogous to this kind of implicit name-based polymorphism anywhere in Haskell. [...] True enough. But DORF doesn't, IMHO, really solve this concern. If you choose to use DORF, then your PersonalName and BrandNames will still be overloaded in just the way you don't want. The only way to avoid this is a pretty arbitrary stylistic decision whether to use Haskell98-style field-name-prefixes or use new-style overloading. Even SORF is better than, say, C++ overloading in the sense that adding another overload in SORF cannot cause code not to compile, nor change its behaviour. Convince me otherwise. -Isaac ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Increasing number of worker tasks in RTS (GHC 7.4.1) - how to debug?
On further investigation, it seems to be very specific to Mac OS Lion (I am running 10.7.3) - all tests were with -N3 option: - I can reliably crash the code with seg fault or bus error if I create more than 8 threads in C FFI (each thread creates its own mutex, for 1-1 coordination with Haskell timer thread). My iMac has 4 processors. In gdb, I can see that the crash happened in __psynch_cvsignal () which seems to be related to pthread mutex. - If I increase the number of C FFI threads (and hence, pthread mutexes) to >=7, the number of tasks starts increasing. 8 is the max number of FFI threads in my testing where the code runs without crashing. But, it seems that there is some kind of pthread mutex related leak. What the timer thread does is to fork 8 parallel haskell threads to acquire mutexes from each of the C FFI thread. Though the function returns after acquiring, collecting data, and releasing mutex, some of the threads seem to be marked as active by GC, because of mutex memory leak. Exactly how, I don't know. - If I keep the number of C FFI threads to <=6, there is no memory leak. The number of tasks stays steady. So, it seems to be pthread library issue (and not a GHC issue). Something to keep in mind when developing code on Mac that involves mutex coordination with C FFI. On Sat, Feb 25, 2012 at 2:59 PM, Sanket Agrawal wrote: > I wrote a program that uses a timed thread to collect data from a C > producer (using FFI). The number of threads in C producer are fixed (and > created at init). One haskell timer thread uses threadDelay to run itself > on timed interval. When I look at RTS output after killing the program > after couple of timer iterations, I see number of worker tasks increasing > with time. > > For example, below is an output after 20 iterations of timer event: > > MUT time (elapsed) GC time (elapsed) > Task 0 (worker) :0.00s( 0.00s) 0.00s( 0.00s) > Task 1 (worker) :0.00s( 0.00s) 0.00s( 0.00s) > ...output until task 37 snipped as it is same as task 1... > Task 38 (worker) :0.07s( 0.09s) 0.00s( 0.00s) > Task 39 (worker) :0.07s( 0.09s) 0.00s( 0.00s) > Task 40 (worker) :0.18s( 10.20s) 0.00s( 0.00s) > Task 41 (worker) :0.18s( 10.20s) 0.00s( 0.00s) > Task 42 (worker) :0.18s( 10.20s) 0.00s( 0.00s) > Task 43 (worker) :0.18s( 10.20s) 0.00s( 0.00s) > Task 44 (worker) :0.52s( 10.74s) 0.00s( 0.00s) > Task 45 (worker) :0.52s( 10.75s) 0.00s( 0.00s) > Task 46 (worker) :0.52s( 10.75s) 0.00s( 0.00s) > Task 47 (bound) :0.00s( 0.00s) 0.00s( 0.00s) > > > After two iterations of timer event: > >MUT time (elapsed) GC time (elapsed) > Task 0 (worker) :0.00s( 0.00s) 0.00s( 0.00s) > Task 1 (worker) :0.00s( 0.00s) 0.00s( 0.00s) > Task 2 (worker) :0.07s( 0.09s) 0.00s( 0.00s) > Task 3 (worker) :0.07s( 0.09s) 0.00s( 0.00s) > Task 4 (worker) :0.16s( 1.21s) 0.00s( 0.00s) > Task 5 (worker) :0.16s( 1.21s) 0.00s( 0.00s) > Task 6 (worker) :0.16s( 1.21s) 0.00s( 0.00s) > Task 7 (worker) :0.16s( 1.21s) 0.00s( 0.00s) > Task 8 (worker) :0.48s( 1.80s) 0.00s( 0.00s) > Task 9 (worker) :0.48s( 1.81s) 0.00s( 0.00s) > Task 10 (worker) :0.48s( 1.81s) 0.00s( 0.00s) > Task 11 (bound) :0.00s( 0.00s) 0.00s( 0.00s) > > > Haskell code has one forkIO call to kick off C FFI - C FFI creates 8 > threads. Runtime options are "-N3 +RTS -s". timer event is kicked off after > forkIO. It is for the form (pseudo-code): > > timerevent time = run where run = do threadDelay time >> > do some work >> run where > > I also wrote a simpler code using just timer event (fork one timer event, > and run another timer event after that), but didn't see any tasks in RTS > output. > > I tried searching GHC page for documentation on RTS output, but didn't > find anything that could help me debug above issue. I suspect that timer > event is the root cause of increasing number of tasks (with all but last 9 > tasks idle - I guess 8 tasks belong to C FFI, and one task to timerevent > thread), and hence, memory leak. > > I will appreciate pointers on how to debug it. The timerevent does forkIO > a call to send collected data from C FFI to a db server, but disabling that > fork still results in the issue of increasing number of tasks. So, it seems > strongly correlated with timer event though I am unable to reproduce it > with a simpler version of timer event (which removes mvar sync/callback > from C FFI). > ___ Glasgo
Increasing number of worker tasks in RTS (GHC 7.4.1) - how to debug?
I wrote a program that uses a timed thread to collect data from a C producer (using FFI). The number of threads in C producer are fixed (and created at init). One haskell timer thread uses threadDelay to run itself on timed interval. When I look at RTS output after killing the program after couple of timer iterations, I see number of worker tasks increasing with time. For example, below is an output after 20 iterations of timer event: MUT time (elapsed) GC time (elapsed) Task 0 (worker) :0.00s( 0.00s) 0.00s( 0.00s) Task 1 (worker) :0.00s( 0.00s) 0.00s( 0.00s) ...output until task 37 snipped as it is same as task 1... Task 38 (worker) :0.07s( 0.09s) 0.00s( 0.00s) Task 39 (worker) :0.07s( 0.09s) 0.00s( 0.00s) Task 40 (worker) :0.18s( 10.20s) 0.00s( 0.00s) Task 41 (worker) :0.18s( 10.20s) 0.00s( 0.00s) Task 42 (worker) :0.18s( 10.20s) 0.00s( 0.00s) Task 43 (worker) :0.18s( 10.20s) 0.00s( 0.00s) Task 44 (worker) :0.52s( 10.74s) 0.00s( 0.00s) Task 45 (worker) :0.52s( 10.75s) 0.00s( 0.00s) Task 46 (worker) :0.52s( 10.75s) 0.00s( 0.00s) Task 47 (bound) :0.00s( 0.00s) 0.00s( 0.00s) After two iterations of timer event: MUT time (elapsed) GC time (elapsed) Task 0 (worker) :0.00s( 0.00s) 0.00s( 0.00s) Task 1 (worker) :0.00s( 0.00s) 0.00s( 0.00s) Task 2 (worker) :0.07s( 0.09s) 0.00s( 0.00s) Task 3 (worker) :0.07s( 0.09s) 0.00s( 0.00s) Task 4 (worker) :0.16s( 1.21s) 0.00s( 0.00s) Task 5 (worker) :0.16s( 1.21s) 0.00s( 0.00s) Task 6 (worker) :0.16s( 1.21s) 0.00s( 0.00s) Task 7 (worker) :0.16s( 1.21s) 0.00s( 0.00s) Task 8 (worker) :0.48s( 1.80s) 0.00s( 0.00s) Task 9 (worker) :0.48s( 1.81s) 0.00s( 0.00s) Task 10 (worker) :0.48s( 1.81s) 0.00s( 0.00s) Task 11 (bound) :0.00s( 0.00s) 0.00s( 0.00s) Haskell code has one forkIO call to kick off C FFI - C FFI creates 8 threads. Runtime options are "-N3 +RTS -s". timer event is kicked off after forkIO. It is for the form (pseudo-code): timerevent time = run where run = do threadDelay time >> do some work >> run where I also wrote a simpler code using just timer event (fork one timer event, and run another timer event after that), but didn't see any tasks in RTS output. I tried searching GHC page for documentation on RTS output, but didn't find anything that could help me debug above issue. I suspect that timer event is the root cause of increasing number of tasks (with all but last 9 tasks idle - I guess 8 tasks belong to C FFI, and one task to timerevent thread), and hence, memory leak. I will appreciate pointers on how to debug it. The timerevent does forkIO a call to send collected data from C FFI to a db server, but disabling that fork still results in the issue of increasing number of tasks. So, it seems strongly correlated with timer event though I am unable to reproduce it with a simpler version of timer event (which removes mvar sync/callback from C FFI). ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Understanding the -A and the -H flags
Hi! I'm trying to understand the interaction between the -A and -H RTS flags. The documentation at http://www.haskell.org/ghc/docs/7.4.1/html/users_guide/runtime-control.html says that if you use -H (with or without an argument) it implicitly implies some value of -A. However, it's not clear to me what value -A will get and how that value is related to the value of -H. For example, if I set the suggested heap size to 1G, using -H1G, surely the size of the nursery (-A) won't be "whatever is left over," but something more reasonable e.g. the size of the L2 cache? Perhaps it would make sense to document the actual algorithm used to set -A given -H (with and without argument.) Cheers, Johan ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Records in Haskell
On Sat, Feb 25, 2012 at 3:54 PM, Barney Hilken wrote: > After more pondering, I finally think I understand what the DORFistas want. > Here is an example: > > You want to define records which describe people, and include (among other > things) a field called "name". There might be several different record types > with a name field, depending on whether the record refers to a customer, an > employee, a business contact etc., but in each case "name" is the name of the > person to which the record refers. You then write various functions which > assume this, such as > >> spam :: Has r "name" String => r -> String >> spam r = "Dear " ++ r.name ++ "\nHave you heard..." > > Now I want to define records which describe products, and I also use a field > "name" in the same way, except that it is the brand name of the product. I > also define functions such as > >> offer :: Has r "name" String => r -> String >> offer r = "Reduced! " ++ r.name ++ " 50% off!" > > It doesn't make any sense to apply your functions to my records or > vice-versa, but because we both chose the same label, the compiler allows it. > Putting the code in separate modules makes no difference, since labels are > global. Exactly! > > > Here is a simple solution, using SORF: > > The real problem is that the polymorphism of spam and offer is too general. > We should each define new classes > >> class Has r "name" String => HasPersonalName r >> class Has r "name" String => HasBrandName r > > and make each of our record types an instance of this class > >> instance HasPersonalName EmployeeRecord >> instance HasPersonalName CustomerRecord >> instance HasBrandName FoodRecord > > then we can define functions with a more specific polymorphism > >> spam :: HasPersonalName r => r -> String >> spam r = "Dear " ++ r.name ++ "\nHave you heard..." > >> offer :: HasBrandName r => r -> String >> offer r = "Reduced! " ++ r.name ++ " 50% off!" > > Now there is no danger of confusing the two uses of "name", because my > records are not instances of HasPersonalName, they are instances of > HasBrandName. You only use the class Has if you really want things to be > polymorphic over all records, otherwise you use the more specific class. > > > This seems to me a much simpler approach than building the mechanism in to > the language as DORF does, and it's also more general, because it isn't hard > linked to the module system. Does it have any disadvantages? I can't tell offhand whether it has any drawbacks with respect to expressiveness. It seems to be a good solution to the stated problem, so thank you for proposing it. My objection is that I'm not sure if there is ever a case where "you really want things to be polymorphic over all records". There is nothing (as far as I know) analogous to this kind of implicit name-based polymorphism anywhere in Haskell. It doesn't seem like the Haskell way to have the less safe thing as the one that's default and convenient, and to allow the programmer to layer a more-safe thing on top of it if he or she wants to. It seems more like the Haskell way to have the safer thing be the default and to require extra work if you want to do something less safe*. In this specific case, is there any actual use case for global implicitly-polymorphic-by-name record fields, where that is actually what you want, and where the DORFish way which is analogous to classes-and-instances wouldn't be appropriate? * (Now granted, if pure code versus unsafePerformIO is white versus black, then this is shade-of-gray versus slightly-darker-shade-of-gray, but the principle is the same.) ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Records in Haskell
After more pondering, I finally think I understand what the DORFistas want. Here is an example: You want to define records which describe people, and include (among other things) a field called "name". There might be several different record types with a name field, depending on whether the record refers to a customer, an employee, a business contact etc., but in each case "name" is the name of the person to which the record refers. You then write various functions which assume this, such as > spam :: Has r "name" String => r -> String > spam r = "Dear " ++ r.name ++ "\nHave you heard..." Now I want to define records which describe products, and I also use a field "name" in the same way, except that it is the brand name of the product. I also define functions such as > offer :: Has r "name" String => r -> String > offer r = "Reduced! " ++ r.name ++ " 50% off!" It doesn't make any sense to apply your functions to my records or vice-versa, but because we both chose the same label, the compiler allows it. Putting the code in separate modules makes no difference, since labels are global. Here is a simple solution, using SORF: The real problem is that the polymorphism of spam and offer is too general. We should each define new classes > class Has r "name" String => HasPersonalName r > class Has r "name" String => HasBrandName r and make each of our record types an instance of this class > instance HasPersonalName EmployeeRecord > instance HasPersonalName CustomerRecord > instance HasBrandName FoodRecord then we can define functions with a more specific polymorphism > spam :: HasPersonalName r => r -> String > spam r = "Dear " ++ r.name ++ "\nHave you heard..." > offer :: HasBrandName r => r -> String > offer r = "Reduced! " ++ r.name ++ " 50% off!" Now there is no danger of confusing the two uses of "name", because my records are not instances of HasPersonalName, they are instances of HasBrandName. You only use the class Has if you really want things to be polymorphic over all records, otherwise you use the more specific class. This seems to me a much simpler approach than building the mechanism in to the language as DORF does, and it's also more general, because it isn't hard linked to the module system. Does it have any disadvantages? Barney. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Records in Haskell
2012/2/25 Gábor Lehel : > Please correct me if I've misunderstood or mischaracterized any aspect of > DORF. Okay, I did end up misunderstanding and mischaracterizing at least two aspects of DORF. Re-reading the wiki page: http://hackage.haskell.org/trac/ghc/wiki/Records/DeclaredOverloadedRecordFields it's clear that you would not have to write fieldLabel declarations for every single field of every single record, only for the ones you wish to be shared and usable polymorphically. By default, fields of individual records would be specific to that record (monomorphic in the type of the record), except if there is a fieldLabel declaration for them in scope in which case they would be considered instances of it. (I hope I have it right this time...) So the difference between DORF and my variant would be: DORF: Fields are record-specific (monomorphic in the record type) by default; having a field be polymorphic requires writing a fieldLabel declaration and having it in scope when the record is declared; if a matching fieldLabel is in scope the field is automatically considered shared and polymorphic in the record type. In other words, you have to write the "classes" explicitly, but the "instances" are inferred automatically. Me: Declaring a record always implies fieldLabel declarations for each of its fields (record-specific, monomorphic-in-the-record-type fields are not possible); these are always *new* fieldLabels, which are not considered to be the same as previous ones and cannot be used interchangeably with them; to re-use an existing fieldLabel for a field of your record you must use explicit syntax. In other words, here the "classes" are automatic, but the "instances" are explicit. It wasn't clear to me before that DORF retains record-monomorphic fields, while my variant does away with them. In DORF you can presumably still use a record-monomorphic field selector to help infer the concrete type of the record (whereas with polymorphic fields inference goes in the other direction). Also, while in both variants it is possible to avoid re-using an existing "field class" for your record, in my variant it's not possible to prevent a downstream record from re-using your "field class" (whereas record-monomorphic fields by definition can't have further instances). So in effect in DORF inside of record declarations you can have two types of fields, record-polymorphic and record-monomorphic, along with separate top-level fieldLabel declarations to declare which ones are the polymorphic fields; while in my variant inside of records you can have two types of fields, "classes" and "instances", with explicit syntax to indicate which ones are the instances. Retaining record-monomorphic fields seems like a flexibility-versus-consistency tradeoff: in DORF you have two types of fields with opposite behaviour with respect to type inference, whereas with my variant you only have one. One troubling consequence of DORF -- again, if I'm understanding things correctly -- is that due to implicit field instances a module import can change the meaning of your program: a record field which was considered record-monomorphic for lack of a matching fieldLabel declaration will be considered polymorphic is one is imported. My variant avoids this. The other aspect of DORF which I mischaracterized in my previous email is that fieldLabel declarations don't look like fieldLabel name :: Text rather, they look like fieldLabel name :: r -> Text where r stands for the type of the record. The implications of this are not clear to me. As Henrik's email helped me realize, I'm completely clueless with regards to how type variables are scoped and handled in DORF. I also don't know how my proposed modifications would affect it. So I'll go back to reading the wiki some more and let Anthony field Henrik's questions in the meantime, if he wants to. (One thing that's obvious is that universally quantified polymorphic fields *are* allowed in DORF, because a specific example is listed which uses one. It's completely inconceivable to me that any record system proposal could be adopted which required doing away with them. Complete show-stopper.) ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Records in Haskell
Hi, Just checking my understanding here as I have not followed this thread in all its details. Gabor Lehel wrote: > I agree completely. This is what I like about DORF: the D stands for > "Declared", which is referring to the fact that the contracts are > explicit. Record fields aren't automatically polymorphic based on > their name and type, as with SORF, rather they are scoped and > disambiguated in the same way as classes. So, with both DORF and your variant of it, am I correct in understanding that polymorphic fields, be it universally quantified as in data ARecordType a = C1 { ..., fieldX :: a, ..., fieldY :: a -> a, ... } or existentially quantified as in: data AnotherRecordType = forall a . C2 { ..., fieldU :: a, ..., fieldV :: a -> Int, ... } would no longer be possible? Note that the type variable a in both cases scope just over the constructor(s) of the data type in question. So any attempt at declaring the types of the fields outside of this context, be it explicitly with the fieldLabel notation, or implicitly as per your proposal, would not be possible. E.g. fieldLabel fieldY :: a -> a would presumably mean fieldLabel fieldY :: forall a . a -> a resulting in ARecordType becoming second-order polymorphic where the value of fieldY would *have* to be a polymorphic function, which is very different from the original definition. Similarly, the whole point with the existentially quantification is to allow a number of fields to share some specific but arbitrary type, which again means that any attempt to type these fields outside of the context of the datatype to which they belong would result in something different. Note that fieldU and fieldV cannot be used as projection functions due to escaped type variables, but that field selection by pattern matching is perfectly fine. Both constructions above are very useful and, I'd argue that a design that rules them out actually is a rather poor fit for a language like Haskell. To be completely honest, I, at least, would be much happier keeping working around the present limitations of Haskell's named fields by picking my field names carefully, than losing the above. Or am I missing something? E.g. is the idea that sharing of fields only applies to fields of monomorphic type, i.e. whose type can be declared globally? Best, /Henrik -- Henrik Nilsson School of Computer Science The University of Nottingham n...@cs.nott.ac.uk ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users