Re: [Haskell-cafe] stream interface vs string interface: references

2013-09-03 Thread Richard A. O'Keefe

On 3/09/2013, at 5:17 PM, damodar kulkarni wrote:
 I didn't want to clutter that thread so I am asking a question here.
 Where do I find foundational and/or other good references on the topic of 
 stream interface vs string interface to convert objects to text? I tried 
 google but failed. 

It has to do with the cost of string concatenation.

Let's take a simple thing.
A Set of Strings.

Smalltalk has

String
  printOn: aStream
aStream nextPut: $'.
self do: [:each |
  each = $' ifTrue: [aStream nextPut: $'].
  aStream nextPut: each].
aStream nextPut: $'.

(Smalltalk uses '' for strings with quote doubling for embedded
quotes and has no character escapes.  s nextPut: c writes character
c to stream s.  do: [:...] is a loop.)

Set
  printOn: aStream
|started|
started := false.
aStream nextPutAll: 'a Set ('.
self do: [:each |
  started ifTrue: [aStream space] ifFalse: [started := true].
  each printOn: aStream].
aStream nextPut: $'.

Object
  printString
|stream|
stream := WriteStream on: (String new: 40).
self printOn: stream.
^stream contents

(A WriteStream is an internal stream.  It starts with the
array-like object you give it and grows it, typically by
doubling, as needed.  `contents' returns the part actually
written to.)

Let's actually do something subtly different.
Each Set will contain the printString of a number
and also another set, so
   a Set('3' a Set('2' a Set('1' a Set(

s := Set new.
1 to: 1000*1000 do: [:i |
s := Set with: s with: i printString].
s printOn: Transcript.

The set having been created, how much allocation is done
by the output phase?   *NONE*.  And the time is *LINEAR*
in the size of the output.

To summarise: Smalltalk makes append print version to output stream
the basic form and obtain print version as a string a derived form.
The result is that printing (acyclic) objects of any size takes time
linear in the size of the output.

Now consider the Java version.
Java makes obtain print version as a string the basic form and
append print version to output stream a derived form.

There's a nasty little wrinkle which is that foo.toString() is
foo instead of the expected \foo\ in Java.  So the output
will be [3, [2, [1, []]] or something like that.

String {
String toString() {
return this;
}
}

HashSet {
String toString() {
StringBuilder b = new StringBuilder();
boolean started = false;
b.append([);
for (Object o: this) {
if (started) b.append(, ); else started = true;
b.append(o.toString());
}
b.append(]);
return b.toString();
}
}

This takes *QUADRATIC* time, but it's annoyingly hard to demonstrate
because it keeps crashing with a stack overflow for even quite small n.
Thankfully, the -Xss option comes to the rescue.

ntime (seconds)
  1000.16
  2000.18
  5000.22
 10000.30
 20000.62
 50002.58
1   12.08
2   51.54

Not only does it take an obscene amount of time to print a large
object, it turns over a totally unwarranted amount of space.

Now you might object that sets like this are not realistic.
If you are trying to write large circuits or abstract syntax
trees or the like to a file, or using this *style* even if
not this specific *interface* to write XML documents, the
example errs by being unrealistically *easy* for Java.
It's easy to understand what's going wrong.

Consider [2, [1, []]]
When visiting {}, we create [].  So far so good.
When visiting {1, {}}, we *copy* the [] into [1, []].
When visiting {2, {1, {}}}, we *copy* the [1, []] into
[2, [1, []]].
And so it goes.  This does an awful lot of copying and
*none* of it is needed given a sane interface.

What is the take of Haskell on this?
There is a *reason* 'shows' exists.

newtype Date = Date (Int,Int,Int)
instance Show Date
  where showsPrec _ (Date (y,m,d)) rest =
 Date ( ++ shows y (, ++ shows m (, ++ shows d () ++ rest)))

The only uses of ++ here are where the left operand is a short literal.
Using this approach, Haskell programs can produce strings in linear time
and linear space.

For lazy I/O, using shows in Haskell is a good analogue of using
#printOn: in Smalltalk.  The basic form is include this as PART of
a stream, with convert this to a whole string as a derived form.

What the equivalent of this would be for Iteratees I don't yet
understand.



___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] stream interface vs string interface: references

2013-09-03 Thread damodar kulkarni
Thank you very much for the detailed explanation. It surely was an
enlightenment for me. Especially the comments

Java makes obtain print version as a string the basic form and  append
 print version to output stream a derived form.

Smalltalk makes append print version to output stream
 the basic form and obtain print version as a string a derived form.


I wonder, this seems a good example of how such a seemingly 'small' design
decision can mean so much in terms of performance difference.

Surely, in Java I will have to take a detour to get around this handicap by
implementing something 'shows' on my own or may be use an equivalent
function from some library BUT in any case I will have to be aware of this.

Please give me a more general principle that can be learnt from this design
lesson, which you might think of. It doesn't quite seem to be the 'kiss'
principle i.e. keep it simple stupid.
What is really behind the Smalltalk's decision?

Thanks and regards,
-Damodar Kulkarni


On Tue, Sep 3, 2013 at 12:06 PM, Richard A. O'Keefe o...@cs.otago.ac.nzwrote:


 On 3/09/2013, at 5:17 PM, damodar kulkarni wrote:
  I didn't want to clutter that thread so I am asking a question here.
  Where do I find foundational and/or other good references on the topic
 of stream interface vs string interface to convert objects to text? I
 tried google but failed.

 It has to do with the cost of string concatenation.

 Let's take a simple thing.
 A Set of Strings.

 Smalltalk has

 String
   printOn: aStream
 aStream nextPut: $'.
 self do: [:each |
   each = $' ifTrue: [aStream nextPut: $'].
   aStream nextPut: each].
 aStream nextPut: $'.

 (Smalltalk uses '' for strings with quote doubling for embedded
 quotes and has no character escapes.  s nextPut: c writes character
 c to stream s.  do: [:...] is a loop.)

 Set
   printOn: aStream
 |started|
 started := false.
 aStream nextPutAll: 'a Set ('.
 self do: [:each |
   started ifTrue: [aStream space] ifFalse: [started := true].
   each printOn: aStream].
 aStream nextPut: $'.

 Object
   printString
 |stream|
 stream := WriteStream on: (String new: 40).
 self printOn: stream.
 ^stream contents

 (A WriteStream is an internal stream.  It starts with the
 array-like object you give it and grows it, typically by
 doubling, as needed.  `contents' returns the part actually
 written to.)

 Let's actually do something subtly different.
 Each Set will contain the printString of a number
 and also another set, so
a Set('3' a Set('2' a Set('1' a Set(

 s := Set new.
 1 to: 1000*1000 do: [:i |
 s := Set with: s with: i printString].
 s printOn: Transcript.

 The set having been created, how much allocation is done
 by the output phase?   *NONE*.  And the time is *LINEAR*
 in the size of the output.

 To summarise: Smalltalk makes append print version to output stream
 the basic form and obtain print version as a string a derived form.
 The result is that printing (acyclic) objects of any size takes time
 linear in the size of the output.

 Now consider the Java version.
 Java makes obtain print version as a string the basic form and
 append print version to output stream a derived form.

 There's a nasty little wrinkle which is that foo.toString() is
 foo instead of the expected \foo\ in Java.  So the output
 will be [3, [2, [1, []]] or something like that.

 String {
 String toString() {
 return this;
 }
 }

 HashSet {
 String toString() {
 StringBuilder b = new StringBuilder();
 boolean started = false;
 b.append([);
 for (Object o: this) {
 if (started) b.append(, ); else started = true;
 b.append(o.toString());
 }
 b.append(]);
 return b.toString();
 }
 }

 This takes *QUADRATIC* time, but it's annoyingly hard to demonstrate
 because it keeps crashing with a stack overflow for even quite small n.
 Thankfully, the -Xss option comes to the rescue.

 ntime (seconds)
   1000.16
   2000.18
   5000.22
  10000.30
  20000.62
  50002.58
 1   12.08
 2   51.54

 Not only does it take an obscene amount of time to print a large
 object, it turns over a totally unwarranted amount of space.

 Now you might object that sets like this are not realistic.
 If you are trying to write large circuits or abstract syntax
 trees or the like to a file, or using this *style* even if
 not this specific *interface* to write XML documents, the
 example errs by being unrealistically *easy* for Java.
 It's easy to understand what's going wrong.

 Consider [2, [1, []]]
 When visiting {}, we create [].  So far so good.
 When visiting {1, {}}, we *copy* the 

Re: [Haskell-cafe] stream interface vs string interface: references

2013-09-03 Thread oleg

 For lazy I/O, using shows in Haskell is a good analogue of using
 #printOn: in Smalltalk.  The basic form is include this as PART of
 a stream, with convert this to a whole string as a derived form.

 What the equivalent of this would be for Iteratees I don't yet
 understand.

Why not to try simple generators first, which are simpler, truly. It seems
generators reproduce the Smalltalk printing patterns pretty well --
even simpler since we don't have to specify any stream. The printing
takes linear time in input size. The same `printing' generator can be
used even if we don't actually want to see any output -- rather, we
only want the statistics (e.g., number of characters printed, or
number of lines, etc). Likewise, the same printing generator
print_yield can be used if we are to encode the output somehow (e.g.,
compress it). The entire pipeline can run in constant space (if
encoding is in constant space).

Here is the code

module PrintYield where

-- http://okmij.org/ftp/continuations/PPYield/
import GenT

import Data.Set as S
import Data.Foldable
import Control.Monad.State.Strict

type Producer m e= GenT e m ()

class PrintYield a where
print_yield :: Monad m = a - Producer m String

instance PrintYield Int where
print_yield = yield . show

instance (PrintYield a, PrintYield b) = PrintYield (Either a b) where
print_yield (Left x)  = yield Leftprint_yield x
print_yield (Right x) = yield Right   print_yield x

instance (PrintYield a) = PrintYield (Set a) where
print_yield x = do
  yield {
  let f True  x = print_yield x  return False
  f False x = yield ,   print_yield x  return False
  foldlM f True x 
  yield }

instance PrintYield ISet where
print_yield (ISet x) = print_yield x

newtype ISet = ISet (Either Int (Set ISet))
deriving (Eq, Ord)

set1 :: Set ISet
set1 = Prelude.foldr 
   (\e s - S.fromList [ISet (Left e), ISet (Right s)]) S.empty [1..20]

-- Real printing
print_set :: Set ISet - IO ()
print_set s = print_yield s `runGenT` putStr

t1 = print_set set1

-- Counting the number of characters
-- Could use Writer but the Writer is too lazy, may leak memory

count_printed :: Set ISet - Integer
count_printed s = (print_yield s `runGenT` counter) `execState` 0
 where
 counter _ = get = put . succ_strict
 succ_strict x = x `seq` succ x

-- According to GHCi statistics, counting is linear in time
-- (space is harder to estimate: it is not clear what GHCi prints
-- for memory statistics; we need max bytes allocated rather than
-- total bytes allocated)
t2 = count_printed set1

-- Doesn't do anything but ensures the set is constructed
t3 :: IO ()
t3 = print_yield set1 `runGenT` (\x - return ())




___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Fwd: MVar problem in acid-state?

2013-09-03 Thread Dag Odenhall
It's conceivable. It might help if you list what version of
acid-stateyou're using and what parts of it. And maybe file
a bug https://github.com/acid-state/acid-state/issues upstream even if
you're not sure it is acid-state.


On Mon, Sep 2, 2013 at 7:35 PM, Corentin Dupont
corentin.dup...@gmail.comwrote:

 Hi the list,
 I have compiled my application on my PC, it works fine, but when I copy it
 on my server (same architecture), I get:
 Nomyx: thread blocked indefinitely in an MVar operation

 I don't use MVars in my application, is it possible that it's coming from
 acid-state?
 Thanks,
 Corentin

 ___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Fwd: Can I use String without in ghci?

2013-09-03 Thread Rustom Mody
On Mon, Sep 2, 2013 at 10:43 AM, Richard A. O'Keefe o...@cs.otago.ac.nzwrote:


 On 2/09/2013, at 3:55 PM, Rustom Mody wrote:

  On Mon, Sep 2, 2013 at 5:43 AM, Richard A. O'Keefe  wrote:
 

  A slogan I have programmed by since I first met C and recognised
  how vastly superior to PL/I it was for text manipulation _because_
  it didn't have a proper string type is Strings are Wrong!.
 

 C rode to fame on the back of Unix. And Unix's innovation – one of many –
 is that at the OS level the string type was made common fare – a universal
 type.  So everything from file names to file contents to IPC is a string.

 The idea of file names being strings was no innovation.
 Yes, in crippled monstrosities like TOPS-10 file names were
 weird records -- I can still remember too much of the details --
 and every ruddy TOPS-10 program had to do its own file name
 parsing and it seemed as if they all did it differently.  But
 the B6700 MCP interfaces treated file names as strings before
 UNIX was dreamed of.

 File contents in UNIX are *not* strings and never have been --
 NUL termination is no part of files and binary files have been
 commonplace since the beginning (an a.out file is not a string!).
 They are *byte arrays*.

 As for IPC, since when have System V shared memory, semaphores,
 or message queues had anything to do with strings?
 (Hint: the 'name' of a System V shared memory segment is a
  key_t, and that's an integral type, not a string.
  Hint: the 'name' of a System V semaphore is also a key_t
  integer, not a string.
  Hint: the 'name' of a System V message queue is also a key_t
  integer, not a string.
  Hint: messages sent using msgsnd are not strings, they are
  byte arrays with a separate count parameter.
 )


Whoops! my bad -- I was *thinking* 'pipes' but ended up *writing* 'IPC'
:-)

So let me restate more explicitly what I intended -- pipes, FIFOs, sockets,
etc.
IOW read/write/send/recv calls and the mathematical model represented by
the (non-firstclass) pair of C data structures in those functions: buf,
len (or count).

As an aside: modern usage types the buf as void * .  The version 7 unix
manuals on which I grew up (and first edition of KR), there was no void;
buf would be just 'char *buf; '


 Classic UNIX uses strings for file names, and really, that's it.
 (The command line argv[] is not really an exception, because it
 was used for file names as well as options, and in fact mixing
 the two up caused endless problems.)
 Everything else in V7, S3, or SysV was identified by a *number*.
 Plan 9 has exit(string) but Unix has exit(byte).

 From the perspective of someone who used UNIX v6 in 1979,
 *POSIX* IPC -- with its IPC objects *might* be in the file
 system but then again might *not* be so their names are
 sorta-kinda-like file names but not really) -- and /proc are
 recent innovations.

 The idea that 'string' was even remotely like a universal type
 in UNIX is bizarre.

 Heck, UNIX never even used 'string' for *lines* in text files!

  Of course when instructing a beginning programmer your basic premise
 'Strings are Wrong!' is most likely right.

 No, I'm talking about experienced programmers writing high performance
 programs.

   However if programs are seen as entities interacting with an 'external'
 world, the currency at the portals is invariably string.

 - The currency at the portals is *not* invariably string.
   Learn PowerShell.
 - Text is one thing and string is another.  This was the
   B6700 lesson (well, really the B5500 lesson): for many purposes
   you want a text *stream* not a text *string* at the interface.
   It's also the what-Smalltalk-got-right-and-Java-got-wrong
   lesson: the right way to convert objects to text is via a
   *stream* interface, not a *string* interface.


I realize this is a terminology issue:

My usage of terminology like string/file are evidently more aligned to
http://en.wikipedia.org/wiki/Vienna_Development_Method#Collections:_Sets.2C_Mappings_and_Sequences
file(chap 4):
http://red.cs.nott.ac.uk/~rxq/files/SpecificationCaseStudies.pdf

Contrariwise 'file' can mean
http://en.wikipedia.org/wiki/Data_set_%28IBM_mainframe%29

So coming back from terminology to principles...

   And more than just noob programmers have got this wrong – think of the
 precious one-byte opcodes that Intel wastes on ascii and decimal arithmetic.

 Hang on, they are there in order to *support* the numbers are text model.
 You can't have it both ways.


So let me restate (actually I didn't state it earlier!) my point in this
example:

When Intel introduced these instructions in 8008 (or whatever) decades ago,
it seemed like a good idea to help programmers and reduce their burden by
allowing them to do some minimal arithmetic on data without burdensome
conversion-to-binary functions.

4 decades on and (Intel's very own Gordon) Moore's law ensuring our
machines and networks some 7 orders of magnitude larger, the cost-equations
look different.  printf and scanf are a 

[Haskell-cafe] type constructor section for (- Bool), _not_ ((-) Bool)

2013-09-03 Thread AntC
I'm probably being dumb, but Hoogle nor the wiki are helping me.

I want an instance and type improvement constraint of the form

instance (f ~ (- Bool)) = C Foo (f b) where ...

The first arg to C is driving type improvement, for example:

instance (f ~ []) = C Bar (f b) where ...

(The real instances are more complex, and involve overlap, of course.)

I'm trying to write a section to get the improved type (b - Bool), 
but (- Bool) or ((- Bool) b) is invalid syntax.

This is valid, but wrong: ((-) Bool) b  -- gives (Bool - b).

I could do:

data FlipFun b  -- abstract
instance (f ~ FlipFun) = C Foo (f b) where ...

And a type function inside the class to generate the type.
But then I'd have to apply the type function for all instances,
and in most places it'd be id.

??


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Fwd: MVar problem in acid-state?

2013-09-03 Thread Corentin Dupont
OK, my mistake: it's working now.
It was because I'm using an haskell interpreter in my program, and the
version of GHC was different on my PC (where I compile) and on the server
(where I run)...


On Tue, Sep 3, 2013 at 11:13 AM, Dag Odenhall dag.odenh...@gmail.comwrote:

 It's conceivable. It might help if you list what version of acid-stateyou're 
 using and what parts of it. And maybe file
 a bug https://github.com/acid-state/acid-state/issues upstream even if
 you're not sure it is acid-state.


 On Mon, Sep 2, 2013 at 7:35 PM, Corentin Dupont corentin.dup...@gmail.com
  wrote:

 Hi the list,
 I have compiled my application on my PC, it works fine, but when I copy
 it on my server (same architecture), I get:
 Nomyx: thread blocked indefinitely in an MVar operation

 I don't use MVars in my application, is it possible that it's coming from
 acid-state?
 Thanks,
 Corentin

 ___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe



___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] On Markdown in Haddock and why it's not going to happen

2013-09-03 Thread Niklas Hambüchen
On 30/08/13 10:30, Mateusz Kowalczyk wrote:
 I would also like to remind you that if there's something that you'd
 like to see in Haddock or something that you feel is broken, a good way
 express this is to make a ticket on the Haddock Trac[2].

I made one:

http://trac.haskell.org/haddock/ticket/257

This is very useful for us because haddock is broken by some TH issue.
This way, we can have most of our docs anyway.

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] type constructor section for (- Bool), _not_ ((-) Bool)

2013-09-03 Thread Brent Yorgey
On Tue, Sep 03, 2013 at 11:33:46AM +, AntC wrote:
 I'm probably being dumb, but Hoogle nor the wiki are helping me.
 
 I want an instance and type improvement constraint of the form
 
 instance (f ~ (- Bool)) = C Foo (f b) where ...
 
 The first arg to C is driving type improvement, for example:
 
 instance (f ~ []) = C Bar (f b) where ...
 
 (The real instances are more complex, and involve overlap, of course.)
 
 I'm trying to write a section to get the improved type (b - Bool), 
 but (- Bool) or ((- Bool) b) is invalid syntax.

There is no operator section syntax for types.  Moreover, this is not
just an issue of syntax: it is impossible to partially apply a type
constructor to anything other than its first argument, because there
is no type-level lambda.

 This is valid, but wrong: ((-) Bool) b  -- gives (Bool - b).
 
 I could do:
 
 data FlipFun b  -- abstract
 instance (f ~ FlipFun) = C Foo (f b) where ...
 
 And a type function inside the class to generate the type.
 But then I'd have to apply the type function for all instances,
 and in most places it'd be id.

That's the only way to do it that I know of.

-Brent

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] World's First Commercial Haskell IDE and Deployment Platform, FP Haskell Center Launches Today

2013-09-03 Thread Tommy Thorn
This is interesting and I wish them luck, but it seems surprising
that the below link doesn't have as much as a screenshot (for an IDE,
you kind of expect to see what it looks like).

After much browsing around on their website I finally found the Video Demo:
https://www.fpcomplete.com/business/haskell-center/video-walk-through/
but the there's no video for me on Firefox (Mac OS X). In Safari shows, but
when I try to play it, it reports An error occurred, please try again later.

Tommy




On Sep 3, 2013, at 11:16 , Natalia Muska nata...@fpcomplete.com wrote:

 FP Complete Has Officially Launched the World's First Commercial Haskell IDE!
 
 http://www.i-newswire.com/fp-complete-launches-fp-haskell/237230
 
 We greatly appreciate the support we've received from the Haskell community. 
 
 
 Natalia Muska
 Marketing Manager
 FP Complete, Inc.
 nata...@fpcomplete.com
 865-506-6513
 skype: natalia.s.muska
 
 
 
 
 -- 
 Natalia Muska
 Marketing Manager
 FP Complete, Inc.
 nata...@fpcomplete.com
 865-506-6513
 skype: natalia.s.muska
 Official Launch PR.docx___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] World's First Commercial Haskell IDE and Deployment Platform, FP Haskell Center Launches Today

2013-09-03 Thread MigMit
Confirm the issue. I have Firefox on Mac as well, and it does show for me, but 
says the same thing as Tommy's Safari

On Sep 3, 2013, at 11:25 PM, Tommy Thorn tt1...@yahoo.com wrote:

 This is interesting and I wish them luck, but it seems surprising
 that the below link doesn't have as much as a screenshot (for an IDE,
 you kind of expect to see what it looks like).
 
 After much browsing around on their website I finally found the Video Demo:
 https://www.fpcomplete.com/business/haskell-center/video-walk-through/
 but the there's no video for me on Firefox (Mac OS X). In Safari shows, but
 when I try to play it, it reports An error occurred, please try again later.
 
 Tommy
 
 
 
 
 On Sep 3, 2013, at 11:16 , Natalia Muska nata...@fpcomplete.com wrote:
 
 FP Complete Has Officially Launched the World's First Commercial Haskell IDE!
 
 http://www.i-newswire.com/fp-complete-launches-fp-haskell/237230
 
 We greatly appreciate the support we've received from the Haskell community. 
 
 
 Natalia Muska
 Marketing Manager
 FP Complete, Inc.
 nata...@fpcomplete.com
 865-506-6513
 skype: natalia.s.muska
 
 
 
 
 -- 
 Natalia Muska
 Marketing Manager
 FP Complete, Inc.
 nata...@fpcomplete.com
 865-506-6513
 skype: natalia.s.muska
 Official Launch PR.docx___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe
 
 
 ___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] World's First Commercial Haskell IDE and Deployment Platform, FP Haskell Center Launches Today

2013-09-03 Thread MigMit
OK, now video on 
http://www.i-newswire.com/fp-complete-launches-fp-haskell/237230 works. Seems 
like a youtube glitch

On Sep 3, 2013, at 11:37 PM, MigMit miguelim...@yandex.ru wrote:

 Confirm the issue. I have Firefox on Mac as well, and it does show for me, 
 but says the same thing as Tommy's Safari
 
 On Sep 3, 2013, at 11:25 PM, Tommy Thorn tt1...@yahoo.com wrote:
 
 This is interesting and I wish them luck, but it seems surprising
 that the below link doesn't have as much as a screenshot (for an IDE,
 you kind of expect to see what it looks like).
 
 After much browsing around on their website I finally found the Video Demo:
 https://www.fpcomplete.com/business/haskell-center/video-walk-through/
 but the there's no video for me on Firefox (Mac OS X). In Safari shows, but
 when I try to play it, it reports An error occurred, please try again 
 later.
 
 Tommy
 
 
 
 
 On Sep 3, 2013, at 11:16 , Natalia Muska nata...@fpcomplete.com wrote:
 
 FP Complete Has Officially Launched the World's First Commercial Haskell 
 IDE!
 
 http://www.i-newswire.com/fp-complete-launches-fp-haskell/237230
 
 We greatly appreciate the support we've received from the Haskell 
 community. 
 
 
 Natalia Muska
 Marketing Manager
 FP Complete, Inc.
 nata...@fpcomplete.com
 865-506-6513
 skype: natalia.s.muska
 
 
 
 
 -- 
 Natalia Muska
 Marketing Manager
 FP Complete, Inc.
 nata...@fpcomplete.com
 865-506-6513
 skype: natalia.s.muska
 Official Launch PR.docx___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe
 
 
 ___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe
 
 
 ___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Reasoning about performance

2013-09-03 Thread Scott Pakin

I'm a Haskell beginner, and I'm baffled trying to reason about code
performance, at least with GHC.  For a program I'm writing I needed to
find all pairs of elements of a list.  That is, given the list ABCD
I wanted to wind up with the list
[('A','B'),('A','C'),('A','D'),('B','C'),('B','D'),('C','D')], where
the order of elements in the resulting list is immaterial, but I don't
want both ('A', 'B') and ('B', 'A'), for example.

My first attempt looked like this:

allPairs1 :: [a] - [(a, a)]
allPairs1 [] = []
allPairs1 (x:xs) = map (\a  - (x, a)) xs ++ allPairs1 xs

Benchmarking with ghci's :set +s reveals the following performance
(median of three runs shown):

$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude :!ghc -c -O2 allpairs.hs
Prelude :load allpairs
Ok, modules loaded: AllPairs.
Prelude AllPairs :m +Control.DeepSeq
Prelude Control.DeepSeq AllPairs :show modules
AllPairs ( allpairs.hs, allpairs.o )
Prelude Control.DeepSeq AllPairs :set +s
Prelude Control.DeepSeq AllPairs deepseq (allPairs1 [1..1]) True
True
(4.85 secs, 4004173984 bytes)

A colleague suggested getting rid of the list append as follows:

allPairs2 :: [a] - [(a, a)]
allPairs2 [] = []
allPairs2 (x:xs) = allPairs2' x xs xs
  where allPairs2' x [] [] = []
allPairs2' x (y:ys) zs = (x,y) : allPairs2' x ys zs
allPairs2' x [] (z:zs) = allPairs2' z zs zs

Not surprisingly, that runs faster:

Prelude Control.DeepSeq AllPairs deepseq (allPairs2 [1..1]) True
True
(2.14 secs, 4403686376 bytes)

I then figured I could do even better by rewriting the code
tail-recursively:

allPairs3 :: [a] - [(a, a)]
allPairs3 [] = []
allPairs3 (x:xs) = allPairs3' x xs xs []
  where allPairs3' :: a - [a] - [a] - [(a, a)] - [(a, a)]
allPairs3' h (x:xs) ys result = allPairs3' h xs ys ((h, 
x):result)
allPairs3' _ [] (y:ys) result = allPairs3' y ys ys result
allPairs3' _ [] [] result = result

This takes half the memory as the above (yay!) but runs substantially
*slower* (and appears to be thrashing my computer's memory system):

Prelude Control.DeepSeq AllPairs deepseq (allPairs3 [1..1]) True
True
(10.58 secs, 2403820152 bytes)

What gives?  Why does my tail-recursive implementation run even slower
and presumably produce more garbage than my initial, naive
implementation?  Is there some optimization GHC is performing for
allPairs1 and allPairs2 that it can't apply to allPairs3?

Similarly, how should I, as a newcomer who wants to write efficient
Haskell code, reason about whether a code change is likely to improve
rather than degrade performance?  Guidelines like per-iteration
appends = bad and tail recursion = good are great, but the
preceding data indicate that something subtler is taking precedence
over those guidelines with respect to code performance.

Thanks in advance,
-- Scott

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Unexpected behaviour with send and send-buffer setting

2013-09-03 Thread Brandon Allbery
On Tue, Sep 3, 2013 at 6:56 PM, Simon Yarde simonya...@me.com wrote:

 I've found that setting the send buffer size causes send to truncate the
 ByteString to the buffer size, but that successive sends continue to
 succeed when the buffer should be full.


I see no actual flow control here. That the receiver is blocked does not
mean the receiver's *kernel* has not received the packets and buffered
them. Also note that send is not synchronous; it cannot know that the
receiver has hit its buffer limit --- and the kernel may well have already
sent the previous packet, so the send buffer is in fact empty at that
point, with the pending packet either in flight or in the receiving
kernel's (interrupt time or normal; they are usually distinct. Or, with a
sufficiently fancy network card, its own) network buffers.

In short, you have not thought through all the possible ramifications, nor
considered that the kernel handles packets and buffering independently of
your program, nor considered the effects of the non-instantaneous network
between sender and receiver. It may or not behave differently when sender
and receiver are on the same machine. Do not assume that the kernel will
short-circuit here and leave out all the intermediate buffering! The only
part you're guaranteed to avoid is the interface with the network hardware.

The crux of my line of enquiry is this;  how can my application know when
 to pause in generating its chunked output if send doesn't block and the
 current non-blocking send behaviour apparently succeeds when the send
 buffer should be full?


I would suggest reading a book on TCP/IP networking.

-- 
brandon s allbery kf8nh   sine nomine associates
allber...@gmail.com  ballb...@sinenomine.net
unix, openafs, kerberos, infrastructure, xmonadhttp://sinenomine.net
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] World's First Commercial Haskell IDE and Deployment Platform, FP Haskell Center Launches Today

2013-09-03 Thread Mike Meyer
On Tue, Sep 3, 2013 at 2:25 PM, Tommy Thorn tt1...@yahoo.com wrote:

 This is interesting and I wish them luck, but it seems surprising
 that the below link doesn't have as much as a screenshot (for an IDE,
 you kind of expect to see what it looks like).


If you follow the link that says Product Highlights, you get to
https://www.fpcomplete.com/business/haskell-center/fp-haskell-center-highlights/
,
which includes links to a PDF for each highlight, which have a number of
screenshots.They tend to be covered by  explanatory text, or only partial
shots of the window, etc.

The other option is to use the Free Trial link and just see it live.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] World's First Commercial Haskell IDE and Deployment Platform, FP Haskell Center Launches Today

2013-09-03 Thread Mathijs Kwik
You can always try the attached docx! :)

On Tue, Sep 3, 2013 at 9:25 PM, Tommy Thorn tt1...@yahoo.com wrote:
 This is interesting and I wish them luck, but it seems surprising
 that the below link doesn't have as much as a screenshot (for an IDE,
 you kind of expect to see what it looks like).

 After much browsing around on their website I finally found the Video Demo:
 https://www.fpcomplete.com/business/haskell-center/video-walk-through/
 but the there's no video for me on Firefox (Mac OS X). In Safari shows, but
 when I try to play it, it reports An error occurred, please try again later.

 Tommy




 On Sep 3, 2013, at 11:16 , Natalia Muska nata...@fpcomplete.com wrote:

 FP Complete Has Officially Launched the World's First Commercial Haskell IDE!

 http://www.i-newswire.com/fp-complete-launches-fp-haskell/237230

 We greatly appreciate the support we've received from the Haskell community.


 Natalia Muska
 Marketing Manager
 FP Complete, Inc.
 nata...@fpcomplete.com
 865-506-6513
 skype: natalia.s.muska




 --
 Natalia Muska
 Marketing Manager
 FP Complete, Inc.
 nata...@fpcomplete.com
 865-506-6513
 skype: natalia.s.muska
 Official Launch PR.docx___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe


 ___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Unexpected behaviour with send and send-buffer setting

2013-09-03 Thread Simon Yarde
I'm new to Haskell and have reached an impasse in understanding the behaviour 
of sockets. 

I see that under the hood Network.Socket sockets are set to non-blocking. 

Presumably, when a non-blocking socket's buffer is full it should immediately 
return 0 bytes. 

I've found that setting the send buffer size causes send to truncate the 
ByteString to the buffer size, but that successive sends continue to succeed 
when the buffer should be full. 

In the server code I set the send buffer to 1, then attempted to overflow it:

handleConnection conn = do
  setSocketOption conn SendBuffer 1
  s1 - send conn abc
  putStrLn $ Bytes sent:  ++ show s1
  s2 - send conn def
  putStrLn $ Bytes sent:  ++ show s2
  s3 - send conn ghi
  putStrLn $ Bytes sent:  ++ show s3
  close conn

And in the client I delay the recv by 1 second:

  setSocketOption sk RecvBuffer 1
  threadDelay (1 * 10^6)
  b1 - recv sk 1
  B8.putStrLn b1
  b2 - recv sk 1
  B8.putStrLn b2
  b3 - recv sk 1
  B8.putStrLn b3

The server immediately outputs:

Bytes sent: 1
Bytes sent: 1
Bytes sent: 1

The client waits a for second and then outputs:

a
d
g

What's going on?  I expected the second and third send operation to return 0 
bytes sent, because the send buffer can only hold 1 byte.

The crux of my line of enquiry is this;  how can my application know when to 
pause in generating its chunked output if send doesn't block and the current 
non-blocking send behaviour apparently succeeds when the send buffer should be 
full?   

More generally, isn't polling sockets using system calls to be avoided in 
favour of blocking and lightweight haskell threads?

Hope someone can help clear up the confusion. 
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] World's First Commercial Haskell IDE and Deployment Platform, FP Haskell Center Launches Today

2013-09-03 Thread Brandon Allbery
On Tue, Sep 3, 2013 at 3:35 PM, Mathijs Kwik math...@bluescreen303.nlwrote:

 You can always try the attached docx! :)


Which likewise showed nothing.

-- 
brandon s allbery kf8nh   sine nomine associates
allber...@gmail.com  ballb...@sinenomine.net
unix, openafs, kerberos, infrastructure, xmonadhttp://sinenomine.net
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Reasoning about performance

2013-09-03 Thread Bob Ippolito
Haskell's non-strict evaluation can often lead to unexpected results when
doing tail recursion if you're used to strict functional programming
languages. In order to get the desired behavior you will need to force the
accumulator (with something like Data.List's foldl', $!,
seq, BangPatterns, etc.).

One issue with the tail recursive version is that you're basically
sequencing it twice, forcing the result is going to force the whole spine
of the list, and then you're walking it again with deepseq. The overhead of
the deepseq call with that size list on my machine is 2.2 seconds, so
you're basically paying that cost twice with a tail recursive version.
allPairs2 only forces what is needed, so deepseq isn't traversing any data
structures that are already forced.

I think what's happening with allPairs2 is that GHC is throwing away the
the list during the traversal since the result of the computation isn't
used at all. I get very different timings (still fast, but no longer orders
of magnitude difference) for allPairs2 if the result is still around. You
could probably figure this out with the heap profiler.

h deepseq (allPairs2 [1..1]) True
True
(2.47 secs, 4403724176 bytes)
h let x = allPairs2 [1..1]
(0.00 secs, 510488 bytes)
h deepseq x True
True
(10.47 secs, 4401625192 bytes)
h deepseq x True
True
(2.21 secs, 1031864 bytes)

I'm no expert, but I think that allPairs2 is likely as good as you're going
to get with straightforward Haskell using lists. It doesn't build up a lot
of unevaluated computation, and if you only need to see the first n
elements it's not going to have to process the entire input. allPairs1 has
most of the good properties of allPairs2 but is a bit worse because of the
concatenation, though concatenating in this way isn't a disaster like it
would be in a strict functional programming language.

-bob



On Tue, Sep 3, 2013 at 3:28 PM, Scott Pakin pa...@lanl.gov wrote:

 I'm a Haskell beginner, and I'm baffled trying to reason about code
 performance, at least with GHC.  For a program I'm writing I needed to
 find all pairs of elements of a list.  That is, given the list ABCD
 I wanted to wind up with the list
 [('A','B'),('A','C'),('A','D')**,('B','C'),('B','D'),('C','D')**], where
 the order of elements in the resulting list is immaterial, but I don't
 want both ('A', 'B') and ('B', 'A'), for example.

 My first attempt looked like this:

 allPairs1 :: [a] - [(a, a)]
 allPairs1 [] = []
 allPairs1 (x:xs) = map (\a  - (x, a)) xs ++ allPairs1 xs

 Benchmarking with ghci's :set +s reveals the following performance
 (median of three runs shown):

 $ ghci
 GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
 Loading package ghc-prim ... linking ... done.
 Loading package integer-gmp ... linking ... done.
 Loading package base ... linking ... done.
 Prelude :!ghc -c -O2 allpairs.hs
 Prelude :load allpairs
 Ok, modules loaded: AllPairs.
 Prelude AllPairs :m +Control.DeepSeq
 Prelude Control.DeepSeq AllPairs :show modules
 AllPairs ( allpairs.hs, allpairs.o )
 Prelude Control.DeepSeq AllPairs :set +s
 Prelude Control.DeepSeq AllPairs deepseq (allPairs1 [1..1]) True
 True
 (4.85 secs, 4004173984 bytes)

 A colleague suggested getting rid of the list append as follows:

 allPairs2 :: [a] - [(a, a)]
 allPairs2 [] = []
 allPairs2 (x:xs) = allPairs2' x xs xs
   where allPairs2' x [] [] = []
 allPairs2' x (y:ys) zs = (x,y) : allPairs2' x ys zs
 allPairs2' x [] (z:zs) = allPairs2' z zs zs

 Not surprisingly, that runs faster:

 Prelude Control.DeepSeq AllPairs deepseq (allPairs2 [1..1]) True
 True
 (2.14 secs, 4403686376 bytes)

 I then figured I could do even better by rewriting the code
 tail-recursively:

 allPairs3 :: [a] - [(a, a)]
 allPairs3 [] = []
 allPairs3 (x:xs) = allPairs3' x xs xs []
   where allPairs3' :: a - [a] - [a] - [(a, a)] - [(a, a)]
 allPairs3' h (x:xs) ys result = allPairs3' h xs ys ((h,
 x):result)
 allPairs3' _ [] (y:ys) result = allPairs3' y ys ys result
 allPairs3' _ [] [] result = result

 This takes half the memory as the above (yay!) but runs substantially
 *slower* (and appears to be thrashing my computer's memory system):

 Prelude Control.DeepSeq AllPairs deepseq (allPairs3 [1..1]) True
 True
 (10.58 secs, 2403820152 bytes)

 What gives?  Why does my tail-recursive implementation run even slower
 and presumably produce more garbage than my initial, naive
 implementation?  Is there some optimization GHC is performing for
 allPairs1 and allPairs2 that it can't apply to allPairs3?

 Similarly, how should I, as a newcomer who wants to write efficient
 Haskell code, reason about whether a code change is likely to improve
 rather than degrade performance?  Guidelines like per-iteration
 appends = bad and tail recursion 

Re: [Haskell-cafe] Unexpected behaviour with send and send-buffer setting

2013-09-03 Thread Gregory Collins
On Wed, Sep 4, 2013 at 12:56 AM, Simon Yarde simonya...@me.com wrote:

 What's going on?  I expected the second and third send operation to return
 0 bytes sent, because the send buffer can only hold 1 byte.


If the underlying write operation returns EWOULDBLOCK then the send
function calls into the GHC IO manager with threadWaitWrite, which
registers interest in the file descriptor using epoll() and blocks the
calling Haskell thread until the socket is writable.

G
-- 
Gregory Collins g...@gregorycollins.net
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Unexpected behaviour with send and send-buffer setting

2013-09-03 Thread Joey Adams
On Tue, Sep 3, 2013 at 6:56 PM, Simon Yarde simonya...@me.com wrote:

 I'm new to Haskell and have reached an impasse in understanding the
 behaviour of sockets.

 The crux of my line of enquiry is this;  how can my application know when
 to pause in generating its chunked output if send doesn't block and the
 current non-blocking send behaviour apparently succeeds when the send
 buffer should be full?


'send' will eventually block after enough 'send's without matching
'recv's.  As Brandon explains, there is more buffering going on than the
send buffer.  In particular, the receiving host will accept segments until
its buffer fills up.  TCP implements flow control (i.e. keeps the sender
from flooding the receiver) by having the receiver tell the sender how many
more bytes it is currently willing to accept.  This is done with the
window size value in the TCP segment header [1].

 [1]:
http://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Reasoning about performance

2013-09-03 Thread Carter Schonwald
It's also worth adding that ghci does a lot less optimization than ghc.
Likewise, the best tool for doing performance benchmarking is the excellent
Criterion library.

To repeat: use compiled code for benchmarking, and use criterion.  Ghci is
not as performance tuned as compiled code, except when ghci is linking in
code that's already been compiled

On Tuesday, September 3, 2013, Bob Ippolito wrote:

 Haskell's non-strict evaluation can often lead to unexpected results when
 doing tail recursion if you're used to strict functional programming
 languages. In order to get the desired behavior you will need to force the
 accumulator (with something like Data.List's foldl', $!,
 seq, BangPatterns, etc.).

 One issue with the tail recursive version is that you're basically
 sequencing it twice, forcing the result is going to force the whole spine
 of the list, and then you're walking it again with deepseq. The overhead of
 the deepseq call with that size list on my machine is 2.2 seconds, so
 you're basically paying that cost twice with a tail recursive version.
 allPairs2 only forces what is needed, so deepseq isn't traversing any data
 structures that are already forced.

 I think what's happening with allPairs2 is that GHC is throwing away the
 the list during the traversal since the result of the computation isn't
 used at all. I get very different timings (still fast, but no longer orders
 of magnitude difference) for allPairs2 if the result is still around. You
 could probably figure this out with the heap profiler.

 h deepseq (allPairs2 [1..1]) True
 True
 (2.47 secs, 4403724176 bytes)
 h let x = allPairs2 [1..1]
 (0.00 secs, 510488 bytes)
 h deepseq x True
 True
 (10.47 secs, 4401625192 bytes)
 h deepseq x True
 True
 (2.21 secs, 1031864 bytes)

 I'm no expert, but I think that allPairs2 is likely as good as you're
 going to get with straightforward Haskell using lists. It doesn't build up
 a lot of unevaluated computation, and if you only need to see the first n
 elements it's not going to have to process the entire input. allPairs1 has
 most of the good properties of allPairs2 but is a bit worse because of the
 concatenation, though concatenating in this way isn't a disaster like it
 would be in a strict functional programming language.

 -bob



 On Tue, Sep 3, 2013 at 3:28 PM, Scott Pakin pa...@lanl.govjavascript:_e({}, 
 'cvml', 'pa...@lanl.gov');
  wrote:

 I'm a Haskell beginner, and I'm baffled trying to reason about code
 performance, at least with GHC.  For a program I'm writing I needed to
 find all pairs of elements of a list.  That is, given the list ABCD
 I wanted to wind up with the list
 [('A','B'),('A','C'),('A','D')**,('B','C'),('B','D'),('C','D')**], where
 the order of elements in the resulting list is immaterial, but I don't
 want both ('A', 'B') and ('B', 'A'), for example.

 My first attempt looked like this:

 allPairs1 :: [a] - [(a, a)]
 allPairs1 [] = []
 allPairs1 (x:xs) = map (\a  - (x, a)) xs ++ allPairs1 xs

 Benchmarking with ghci's :set +s reveals the following performance
 (median of three runs shown):

 $ ghci
 GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
 Loading package ghc-prim ... linking ... done.
 Loading package integer-gmp ... linking ... done.
 Loading package base ... linking ... done.
 Prelude :!ghc -c -O2 allpairs.hs
 Prelude :load allpairs
 Ok, modules loaded: AllPairs.
 Prelude AllPairs :m +Control.DeepSeq
 Prelude Control.DeepSeq AllPairs :show modules
 AllPairs ( allpairs.hs, allpairs.o )
 Prelude Control.DeepSeq AllPairs :set +s
 Prelude Control.DeepSeq AllPairs deepseq (allPairs1 [1..1]) True
 True
 (4.85 secs, 4004173984 bytes)

 A colleague suggested getting rid of the list append as follows:

 allPairs2 :: [a] - [(a, a)]
 allPairs2 [] = []
 allPairs2 (x:xs) = allPairs2' x xs xs
   where allPairs2' x [] [] = []
 allPairs2' x (y:ys) zs = (x,y) : allPairs2' x ys zs
 allPairs2' x [] (z:zs) = allPairs2' z zs zs

 Not surprisingly, that runs faster:

 Prelude Control.DeepSeq AllPairs deepseq (allPairs2 [1..1]) True
 True
 (2.14 secs, 4403686376 bytes)

 I then figured I could do even better by rewriting the code
 tail-recursively:

 allPairs3 :: [a] - [(a, a)]
 allPairs3 [] = []
 allPairs3 (x:xs) = allPairs3' x xs xs []
   where allPairs3' :: a - [a] - [a] - [(a, a)] - [(a, a)]
 allPairs3' h (x:xs) ys result = allPairs3' h xs ys ((h,
 x):result)
 allPairs3' _ [] (y:ys) result = allPairs3' y ys ys result
 allPairs3' _ [] [] result = result

 This takes half the memory as the above (yay!) but runs substantially
 *slower* (and appears to be thrashing my computer's memory system):

 Prelude Control.DeepSeq AllPairs deepseq (allPairs3 [1..1]) True
 True
 (10.58 secs, 2403820152 bytes)

 What 

Re: [Haskell-cafe] Unexpected behaviour with send and send-buffer setting

2013-09-03 Thread Brandon Allbery
On Tue, Sep 3, 2013 at 7:58 PM, Joey Adams joeyadams3.14...@gmail.comwrote:

 On Tue, Sep 3, 2013 at 6:56 PM, Simon Yarde simonya...@me.com wrote:

 I'm new to Haskell and have reached an impasse in understanding the
 behaviour of sockets.

 The crux of my line of enquiry is this;  how can my application know when
 to pause in generating its chunked output if send doesn't block and the
 current non-blocking send behaviour apparently succeeds when the send
 buffer should be full?


 'send' will eventually block after enough 'send's without matching
 'recv's.  As Brandon explains, there is more buffering going on than the
 send buffer.  In particular, the receiving host will accept segments until
 its buffer fills up.  TCP implements flow control (i.e. keeps the sender
 from flooding the receiver) by


Also note that, if you're using TCP, Nagle's algorithm will be turned on
unless you specifically turn it off; this is explicitly designed to avoid
sending very short packets, by buffering them into larger packets in the
kernel network stack up until some timeout or a minimum threshold size is
reached. (Protocols such as ssh and telnet turn it off for interactivity.)
And if you're using UDP, there's no flow control at all; while packets
won't be aggregated á la Nagle, the network stacks on the sending and
receiving ends can do pretty much whatever they want with the individual
packets. And in either case the socket buffer size is only the last mile:
there is no way to control what happens elsewhere, and in particular the
interrupt-time received packet handling usually won't know even what socket
is the target, much less what buffer size that socket has set.

-- 
brandon s allbery kf8nh   sine nomine associates
allber...@gmail.com  ballb...@sinenomine.net
unix, openafs, kerberos, infrastructure, xmonadhttp://sinenomine.net
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Reasoning about performance

2013-09-03 Thread Dan Burton
Well for one thing, note that allPairs3 produces the result in reverse
order:

 allPairs1 abc
[('a','b'),('a','c'),('b','c')]
 allPairs2 abc
[('a','b'),('a','c'),('b','c')]
 allPairs3 abc
[('b','c'),('a','c'),('a','b')]

allPairs2 uses guarded recursion which the optimizer probably likes,
although I don't quite see why that version would use twice as much memory
as allPairs3.

See also:
http://www.haskell.org/haskellwiki/Tail_recursion

Here's a fun alternative for you to benchmark, using an old trick. I kind
of doubt that this one will optimize as nicely as the others, but I am by
no means an optimization guru:

allPairsS :: [a] - [(a, a)]
allPairsS xs = go xs [] where
  go [] = id
  go (y:ys) = (map (\a - (y, a)) ys ++) . go xs

Further reading:
http://www.haskell.org/haskellwiki/Difference_list


-- Dan Burton


On Tue, Sep 3, 2013 at 3:28 PM, Scott Pakin pa...@lanl.gov wrote:

 I'm a Haskell beginner, and I'm baffled trying to reason about code
 performance, at least with GHC.  For a program I'm writing I needed to
 find all pairs of elements of a list.  That is, given the list ABCD
 I wanted to wind up with the list
 [('A','B'),('A','C'),('A','D')**,('B','C'),('B','D'),('C','D')**], where
 the order of elements in the resulting list is immaterial, but I don't
 want both ('A', 'B') and ('B', 'A'), for example.

 My first attempt looked like this:

 allPairs1 :: [a] - [(a, a)]
 allPairs1 [] = []
 allPairs1 (x:xs) = map (\a  - (x, a)) xs ++ allPairs1 xs

 Benchmarking with ghci's :set +s reveals the following performance
 (median of three runs shown):

 $ ghci
 GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
 Loading package ghc-prim ... linking ... done.
 Loading package integer-gmp ... linking ... done.
 Loading package base ... linking ... done.
 Prelude :!ghc -c -O2 allpairs.hs
 Prelude :load allpairs
 Ok, modules loaded: AllPairs.
 Prelude AllPairs :m +Control.DeepSeq
 Prelude Control.DeepSeq AllPairs :show modules
 AllPairs ( allpairs.hs, allpairs.o )
 Prelude Control.DeepSeq AllPairs :set +s
 Prelude Control.DeepSeq AllPairs deepseq (allPairs1 [1..1]) True
 True
 (4.85 secs, 4004173984 bytes)

 A colleague suggested getting rid of the list append as follows:

 allPairs2 :: [a] - [(a, a)]
 allPairs2 [] = []
 allPairs2 (x:xs) = allPairs2' x xs xs
   where allPairs2' x [] [] = []
 allPairs2' x (y:ys) zs = (x,y) : allPairs2' x ys zs
 allPairs2' x [] (z:zs) = allPairs2' z zs zs

 Not surprisingly, that runs faster:

 Prelude Control.DeepSeq AllPairs deepseq (allPairs2 [1..1]) True
 True
 (2.14 secs, 4403686376 bytes)

 I then figured I could do even better by rewriting the code
 tail-recursively:

 allPairs3 :: [a] - [(a, a)]
 allPairs3 [] = []
 allPairs3 (x:xs) = allPairs3' x xs xs []
   where allPairs3' :: a - [a] - [a] - [(a, a)] - [(a, a)]
 allPairs3' h (x:xs) ys result = allPairs3' h xs ys ((h,
 x):result)
 allPairs3' _ [] (y:ys) result = allPairs3' y ys ys result
 allPairs3' _ [] [] result = result

 This takes half the memory as the above (yay!) but runs substantially
 *slower* (and appears to be thrashing my computer's memory system):

 Prelude Control.DeepSeq AllPairs deepseq (allPairs3 [1..1]) True
 True
 (10.58 secs, 2403820152 bytes)

 What gives?  Why does my tail-recursive implementation run even slower
 and presumably produce more garbage than my initial, naive
 implementation?  Is there some optimization GHC is performing for
 allPairs1 and allPairs2 that it can't apply to allPairs3?

 Similarly, how should I, as a newcomer who wants to write efficient
 Haskell code, reason about whether a code change is likely to improve
 rather than degrade performance?  Guidelines like per-iteration
 appends = bad and tail recursion = good are great, but the
 preceding data indicate that something subtler is taking precedence
 over those guidelines with respect to code performance.

 Thanks in advance,
 -- Scott

 __**_
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/**mailman/listinfo/haskell-cafehttp://www.haskell.org/mailman/listinfo/haskell-cafe

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Reasoning about performance

2013-09-03 Thread Richard A. O'Keefe
allPairs2 can be simplified using a trick I wouldn't dare use in
any language but Haskell:

triangle4 xs = fused undefined [] xs
  where fused x (y:ys) zs = (x,y) : fused x ys zs
fused _ [] (z:zs) = fused z zs zs
fused _ [] [] = []

I submit this just for grins; it happens to be a touch faster but
not enough to bother about.

While the result _isn't_ all possible pairs of elements, making
the allPairs name a bit dodgy, it _does_ have O(|xs|**2) of them...

I would be surprised if the relative performance of two
approaches in ghci were always the same as their relative
performance in ghc.


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Unexpected behaviour with send and send-buffer setting

2013-09-03 Thread Simon Yarde
 On 4 Sep 2013, at 00:49, Gregory Collins g...@gregorycollins.net wrote:
 If the underlying write operation returns EWOULDBLOCK then the send 
 function calls into the GHC IO manager with threadWaitWrite, which 
 registers interest in the file descriptor using epoll() and blocks the 
 calling Haskell thread until the socket is writable.


If I'm following along correctly.. I was mistaken in thinking that send would 
never block because sockets are set to non-blocking, whereas the implementation 
of send re-introduces blocking behaviour through threadWaitWrite and efficient 
use of epoll (instead of continually polling with the attendant system call 
overhead).


 On Tue, Sep 3, 2013 at 6:56 PM, Simon Yarde simonya...@me.com wrote:
 The crux of my line of enquiry is this;  how can my application know when to 
 pause in generating its chunked output if send doesn't block and the current 
 non-blocking send behaviour apparently succeeds when the send buffer should 
 be full?

Now I've learned that send *can* block the current thread to avoid overwhelming 
the receiver (but uses different mechanisms than send()), I understand my app 
need simply wait for a send to proceed before generating the next chunk.

Does that sound anywhere close?


 On 4 Sep 2013, at 00:58, Joey Adams joeyadams3.14...@gmail.com wrote:
 'send' will eventually block after enough 'send's without matching 'recv's.  
 As Brandon explains, there is more buffering going on than the send buffer.  
 In particular, the receiving host will accept segments until its buffer fills 
 up.  TCP implements flow control (i.e. keeps the sender from flooding the 
 receiver) by having the receiver tell the sender how many more bytes it is 
 currently willing to accept.  This is done with the window size value in 
 the TCP segment header [1].
 
  [1]: 
 http://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure

If the receiver's buffer is full (reporting window size 0?), does send block 
until the receiver can accept more bytes, or return 0 bytes sent?  Put another 
way; is there a scenario in which send could return 0 bytes sent?


 On 4 Sep 2013, at 00:13, Brandon Allbery allber...@gmail.com wrote:
 I would suggest reading a book on TCP/IP networking.


I've studied Beej's Guide To Network Programming, Wikipedia entry, TCP spec, 
man pages.. I'll gladly take any recommendations that could help me understand 
system resource usage and configuration.


Many thanks Brandon, Gregory, Joey.



___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Traversals of monomorphic containers

2013-09-03 Thread Mario Blažević

On 09/02/13 06:53, Nicolas Trangez wrote:

# Redirected to haskell-cafe

On Sun, 2013-09-01 at 14:58 +0400, Artyom Kazak wrote:

Would this be an appropriate place to propose adding mapM_ (and then
possibly mapM) to bytestring library?

Was it suggested before? If yes, why was it rejected?


This got me wondering: there are several type-classes useful for
polymorphic container types, e.g. Functor, Foldable  Traversable which
all apply to some type of kind (* - *).

Are there related things for monomorphic containers, like ByteString,
Text or some newtype'd Vector with fixed element type, e.g.

class MFunctor f a where
 mfmap :: (a - a) - f - f

instance MFunctor ByteString Word8 where
 mfmap = ByteString.map



	I'm not aware of this particular class, but I have considered it. In 
the end I've chosen to generalize the class to FactorialMonoid instead:


class Monoid m = FactorialMonoid m where
   ...
   foldMap :: Monoid n = (m → n) → m → n

	ByteString and Text are instances of the class, and so are lists, maps, 
and other containers, and Sum and Product as well.



http://hackage.haskell.org/packages/archive/monoid-subclasses/0.3.2/doc/html/Data-Monoid-Factorial.html





or (maybe even better)

class MFunctor f where
 type Elem
 mfmap :: (Elem - Elem) - f - f

instance MFunctor ByteString where
 type Elem = Word8
 mfmap = ByteString.map

and similar for other classes.

Nicolas


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe




___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Traversals of monomorphic containers

2013-09-03 Thread Tony Morris
These questions are exactly what Control.Lens answers.
 On 04/09/2013 12:50 PM, Mario Blažević blama...@acanac.net wrote:

 On 09/02/13 06:53, Nicolas Trangez wrote:

 # Redirected to haskell-cafe

 On Sun, 2013-09-01 at 14:58 +0400, Artyom Kazak wrote:

 Would this be an appropriate place to propose adding mapM_ (and then
 possibly mapM) to bytestring library?

 Was it suggested before? If yes, why was it rejected?


 This got me wondering: there are several type-classes useful for
 polymorphic container types, e.g. Functor, Foldable  Traversable which
 all apply to some type of kind (* - *).

 Are there related things for monomorphic containers, like ByteString,
 Text or some newtype'd Vector with fixed element type, e.g.

 class MFunctor f a where
  mfmap :: (a - a) - f - f

 instance MFunctor ByteString Word8 where
  mfmap = ByteString.map



 I'm not aware of this particular class, but I have considered it.
 In the end I've chosen to generalize the class to FactorialMonoid instead:

 class Monoid m = FactorialMonoid m where
...
foldMap :: Monoid n = (m → n) → m → n

 ByteString and Text are instances of the class, and so are lists,
 maps, and other containers, and Sum and Product as well.


 http://hackage.haskell.org/**packages/archive/monoid-**
 subclasses/0.3.2/doc/html/**Data-Monoid-Factorial.htmlhttp://hackage.haskell.org/packages/archive/monoid-subclasses/0.3.2/doc/html/Data-Monoid-Factorial.html




 or (maybe even better)

 class MFunctor f where
  type Elem
  mfmap :: (Elem - Elem) - f - f

 instance MFunctor ByteString where
  type Elem = Word8
  mfmap = ByteString.map

 and similar for other classes.

 Nicolas


 __**_
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/**mailman/listinfo/haskell-cafehttp://www.haskell.org/mailman/listinfo/haskell-cafe



 __**_
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/**mailman/listinfo/haskell-cafehttp://www.haskell.org/mailman/listinfo/haskell-cafe

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe