Re: Records in Haskell

2012-02-25 Thread Henrik Nilsson

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


Re: Records in Haskell

2012-02-25 Thread Gábor Lehel
2012/2/25 Gábor Lehel illiss...@gmail.com:
 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

2012-02-25 Thread Barney Hilken
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-02-25 Thread Gábor Lehel
On Sat, Feb 25, 2012 at 3:54 PM, Barney Hilken b.hil...@ntlworld.com 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


Understanding the -A and the -H flags

2012-02-25 Thread Johan Tibell
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


Increasing number of worker tasks in RTS (GHC 7.4.1) - how to debug?

2012-02-25 Thread Sanket Agrawal
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 other arguments time = run where run = do threadDelay time 
do some work  run where other variables defined for run function

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


Re: Increasing number of worker tasks in RTS (GHC 7.4.1) - how to debug?

2012-02-25 Thread Sanket Agrawal
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 sanket.agra...@gmail.comwrote:

 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 other arguments time = run where run = do threadDelay time 
 do some work  run where other variables defined for run function

 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).

___

Re: Records in Haskell

2012-02-25 Thread Isaac Dupree

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: Records in Haskell

2012-02-25 Thread Gábor Lehel
On Sat, Feb 25, 2012 at 10:09 PM, Isaac Dupree
m...@isaac.cedarswampstudios.org 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

2012-02-25 Thread Barney Hilken
 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

2012-02-25 Thread Isaac Dupree

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: Understanding the -A and the -H flags

2012-02-25 Thread wren ng thornton

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

2012-02-25 Thread wren ng thornton

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: Records in Haskell

2012-02-25 Thread wren ng thornton

On 2/25/12 10:18 AM, Gábor Lehel wrote:

On Sat, Feb 25, 2012 at 3:54 PM, Barney Hilkenb.hil...@ntlworld.com  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: Increasing number of worker tasks in RTS (GHC 7.4.1) - how to debug?

2012-02-25 Thread Sanket Agrawal
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 sanket.agra...@gmail.comwrote:

 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 
 sanket.agra...@gmail.comwrote:

 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 other arguments time = run where run = do threadDelay time
  do some work  run where other variables defined for run function

 I also wrote a simpler code using just timer event (fork one timer 

Re: Records in Haskell

2012-02-25 Thread Anthony Clayden
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: Records in Haskell

2012-02-25 Thread Anthony Clayden

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
 Hilkenb.hil...@ntlworld.com  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