Re: [Haskell-cafe] Why Kleisli composition is not in the Monad signature?

2012-11-30 Thread Ben Franksen
Gershom Bazerman wrote:
 On 11/30/12 10:44 AM, Dan Doel wrote:

 Lists! The finite kind.

 This could mean Seq for instance.

 On Nov 30, 2012 9:53 AM, Brent Yorgey byor...@seas.upenn.edu 
 mailto:byor...@seas.upenn.edu wrote:


 Any data type which admits structures of arbitrary but *only finite*
 size has a natural zippy Apply instance but no Applicative (since
 pure would have to be an infinite structure).  The Map instance I
 mentioned above falls in this category.  Though I guess I'm having
 trouble coming up with other examples, but I'm sure some exist.  
Maybe
 Edward knows of other examples.

 
 Another common case would be an embedded DSL representing code in a 
 different language, targeting a different platform (or even an FPGA or 
 the like), etc. You can apply `OtherLang (a - b)` to an `OtherLang a` 
 and get an `OtherLang b`, but you clearly can't promote (or lower, I 
 guess) an arbitrary Haskell function into a function in your target 
 language. This is the same reason that GArrows remove the `arr` function 
 (http://www.cs.berkeley.edu/~megacz/garrows/).

A fine example! And I am getting the drift... yes, this could be a useful 
abstraction.

Now, on to Bind: the standard finite structure example for Bind is most 
probably the substitution thingy, i.e. if m :: m a, f :: a - m b, then m 
= f means replace all elements x :: a in m with f x and then flatten the 
result so it's an m b again. Like concatMap for lists, right? So, there is 
no return for that in the Map case for exactly the same reason as with 
Apply: the unit would have have value id for every possible key, so cannot 
be finite.

So what about an example for Bind\\Monad that is not yet another variation 
of the finite structure theme?

Cheers
-- 
Ben Franksen
()  ascii ribbon campaign - against html e-mail 
/\  www.asciiribbon.org   - against proprietary attachments


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


Re: [Haskell-cafe] Why Kleisli composition is not in the Monad signature?

2012-11-29 Thread Ben Franksen
Brent Yorgey wrote:
 On Thu, Nov 29, 2012 at 03:52:58AM +0100, Ben Franksen wrote:
 Tony Morris wrote:
  As a side note, I think a direct superclass of Functor for Monad is not
  a good idea, just sayin'
  
  class Functor f where
fmap :: (a - b) - f a - f b
  
  class Functor f = Apply f where
(*) :: f (a - b) - f a - f b
  
  class Apply f = Bind f where
(=) :: (a - f b) - f a - f b
  
  class Apply f = Applicative f where
unit :: a - f a
  
  class (Applicative f, Bind f) = Monad f where
  
  Same goes for Comonad (e.g. [] has (=) but not counit)
  ... and again for Monoid, Category, I could go on...
 
 Hi Tony
 
 even though I dismissed your mentioning this on the Haskell' list, I do 
have 
 to admit that the proposal has a certain elegance. However, before I buy 
 into this scheme, I'd like to see some striking examples for types with 
 natural (or at least useful) Apply and Bind instances that cannot be made 
 Applicative resp. Monad. 
 
 Try writing an Applicative instances for (Data.Map.Map k).  It can't
 be done, but the Apply instance is (I would argue) both natural and 
useful.

I see. So there is one example. Are there more? I'd like to get a feeling 
for the abstraction and this is hard if there is only a single example.

 Also, it is not clear to me what laws should hold 
 for them.
 
 http://hackage.haskell.org/package/semigroupoids defines all of these
 and specifies laws, presumably derived in a principled way.

Ok. I was not surprised to see that there are not many laws for the classes 
without unit.

Cheers
-- 
Ben Franksen
()  ascii ribbon campaign - against html e-mail 
/\  www.asciiribbon.org   - against proprietary attachments


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


[Haskell-cafe] A big hurray for lambda-case (and all the other good stuff)

2012-11-28 Thread Ben Franksen
Hi Everyone

just wanted to drop by to say how much I like the new lambda case extension. 
I use it all the time and I just *love* how it relieves me from conjuring up 
dummy variables, which makes teh code not only esier to write but also to 
read.

A big, huge thank you to the ghc developers. This has been so long on my 
wish list.

Also much appreciated and long awaited: tuple sections (though I use them 
not quite as often).

Both should *definitely* go into Haskell'13.

Of course, thank you also for all the other beautiful stuff in ghc-7.6.1, 
especially PolyKinds, DataKinds etc.

GHC is just simply amazing. You guys RULE THE WORLD!

Cheers
-- 
Ben Franksen
()  ascii ribbon campaign - against html e-mail 
/\  www.asciiribbon.org   - against proprietary attachments


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


Re: [Haskell-cafe] Why Kleisli composition is not in the Monad signature?

2012-11-28 Thread Ben Franksen
Tony Morris wrote:
 As a side note, I think a direct superclass of Functor for Monad is not
 a good idea, just sayin'
 
 class Functor f where
   fmap :: (a - b) - f a - f b
 
 class Functor f = Apply f where
   (*) :: f (a - b) - f a - f b
 
 class Apply f = Bind f where
   (=) :: (a - f b) - f a - f b
 
 class Apply f = Applicative f where
   unit :: a - f a
 
 class (Applicative f, Bind f) = Monad f where
 
 Same goes for Comonad (e.g. [] has (=) but not counit)
 ... and again for Monoid, Category, I could go on...

Hi Tony

even though I dismissed your mentioning this on the Haskell' list, I do have 
to admit that the proposal has a certain elegance. However, before I buy 
into this scheme, I'd like to see some striking examples for types with 
natural (or at least useful) Apply and Bind instances that cannot be made 
Applicative resp. Monad. Also, it is not clear to me what laws should hold 
for them.

Cheers
-- 
Ben Franksen
()  ascii ribbon campaign - against html e-mail 
/\  www.asciiribbon.org   - against proprietary attachments


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


Re: [Haskell-cafe] Why Kleisli composition is not in the Monad signature?

2012-11-28 Thread Ben Franksen
Dan Doel wrote:
 On Tue, Oct 16, 2012 at 10:37 AM, AUGER Cédric sedri...@gmail.com wrote:
 join IS the most important from the categorical point of view.
 In a way it is natural to define 'bind' from 'join', but in Haskell, it
 is not always possible (see the Monad/Functor problem).

 As I said, from the mathematical point of view, join (often noted μ in
 category theory) is the (natural) transformation which with return (η
 that I may have erroneously written ε in some previous mail) defines a
 monad (and requires some additionnal law).
 
 This is the way it's typically presented. Can you demonstrate that it
 is the most important presentation?
 
 I'd urge caution in doing so, too. For instance, there is a paper,
 Monads Need Not Be Endofunctors, that describes a generalization of
 monads to monads relative to another functor. And there, bind is
 necessarily primary, because join isn't even well typed. I don't think
 it's written by mathematicians per se (rather, computer
 scientists/type theorists). But mathematicians have their own
 particular interests that affect the way they frame things, and that
 doesn't mean those ways are better for everyone.

Right. Mathematical /conventions/ can and should be questioned. Sometimes 
they are not appropriate to the application domain. Sometimes the 
conventions are just stupid or obsolete even in a purely mathematical 
context (a well-known example is the extra syntax sugar for binomial 
coefficients, but there are worse ones), and you still find them in modern 
text books. Talk about backwards compatibility...

My preference for Kleisli composition is because it makes the monad laws so 
much easier to write down and understand. Everywhere it is said that = 
must be associative and then the laws are written down for = and return 
and it is very hard to see what this lambda grave has to do with 
associativity or units. When I started with Haskell, this was all I could 
find. It was years later that I stumbled over a text that explained it with 
= and suddenly it all became simple and clear and I finally understood the 
monad laws!

So, maybe = is the better primitive operation w.r.t. implementation, but 
IMO = is *much* more efficient w.r.t. understanding the monad laws. Since 
it is natural to explain the laws of a class using only class methods, I 
would prefer if = was added to the class with default implementations for 
= in terms of = and vice versa, so that you can still use = as the 
primitive operation when implementing an instance.

Cheers
-- 
Ben Franksen
()  ascii ribbon campaign - against html e-mail 
/\  www.asciiribbon.org   - against proprietary attachments


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


[Haskell-cafe] Serializing with alignment

2012-11-06 Thread Ben Franksen
Hi Everyone

I want to implement a binary protocol that, unfortunately, has some 
alignment restrictions. In order to fulfill these, I need access to the 
current offset in the bytestring. The binary package does provide a 
function

  bytesRead :: Get Int64

but only for the Get monad; there is no equivalent for the Put monad.

So my first question: is there a serialization library that offers something 
like

  bytesWritten :: PutM Int64

Failing that, would you think adding it to binary is a reasonable feature 
request? I have taken a cursory look at the implementation and it looks like 
this is not a matter of simply adding a missing function, but would probably 
need an addition to internal data structures.

I could also try and wrap the PutM from binary with a StateT transformer and 
count the bytes myself. I will probably have to use at least a ReaderT 
wrapper anyway, since I have to pass the byte order as a parameter (byte 
order gets negotiated between client and server, it is not fixed).

I was really hoping that there is some library that has built-in support for 
stateful serialization (alignment, byte-order, etc).

Any pointers, hints, etc are much appreciated.

Cheers
-- 
Ben Franksen
()  ascii ribbon campaign - against html e-mail 
/\  www.asciiribbon.org   - against proprietary attachments


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


Re: [Haskell-cafe] Correspondence between libraries and modules

2012-05-07 Thread Ben Franksen
Alvaro Gutierrez wrote:
 I've only dabbled in Haskell, so please excuse my ignorance: why isn't
 there a 1-to-1 mapping between libraries and modules?
 
 As I understand it, a library can provide any number of unrelated modules,
 and conversely, a single module could be provided by more than one
 library. I can see how this affords library authors more flexibility, but
 at a cost: there is no longer a single, unified view of the library
 universe. (The alternative would be for every module to be its own,
 hermetic library.) So I'm very interested in the rationale behind that
 aspect of the library system.

I am probably repeating arguments brought forward by others, but I really 
like that the Haskell module name space is ordered along functionality 
rather than authorship. If I ever manage to complete an implementaton of the 
EPICS pvData project in Haskell, it will certainly inherit the Java module 
naming convention and thus will contain modules named Org.Epics.PvData.XXX, 
*but* if I need to add utility functions to the API that are generic list 
processing functions they will certainly live in the Data.List.* name space 
and if I need to add type level stuff (which is likely) it will be published 
under Data.Type.* etc. This strikes me as promoting re-use: makes it far 
easier and more likely to factor out these things into a separate general 
purpose library or maybe even integrate them into a widely known standard 
library. It also gives you a much better idea what the thing you export is 
doing than if it is from, say, Org.Epics.PvData.Util. Finally, it gives the 
package author an incentive to actually do the refactoring that makes it 
obvious where the function belongs to, functionally.

Cheers
Ben


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


Re: [Haskell-cafe] ANNOUNCE: pipes-core 0.1.0

2012-04-17 Thread Ben Franksen
Paolo Capriotti wrote:
 On Mon, Apr 16, 2012 at 10:13 PM, Ben Franksen ben.frank...@online.de
 wrote:
 (1) What is the reason for the asymmetry in

 type Producer b m = Pipe () b m
 type Consumer a m = Pipe a Void m

 i.e. why does Producer use () for the input? I would expect it to use
 Void, like Consumer does for its output. Calling await in a Producer
 resulting in an immediate 'return ()' as you say is allowed (in the
 tutorial) strikes me as not very useful.
 
 The underlying reason for the asymmetry is the fact that '()' is a
 terminal object in the category of haskell types and *total*
 functions, while 'Void' is an initial object.
 
 Here's a property that uniquely determines the definitions of
 'Producer' above. Let 'X' be the type such that 'Producer b m = Pipe X
 b m'. For all producers 'p' there should be a unique (total) pipe
 'alpha :: forall a r. Pipe a X m r' such that 'alpha + p' and 'p'
 are observationally equal. In other words, since a producer never
 uses values of its input type 'a', there should be a unique way to
 make it into a pipe which is polymorphic in 'a'. It's easy to see that
 this property immediately implies that 'X' should be a terminal
 object, i.e. '()', and 'alpha' is therefore 'pipe (const ())'.
 
 Dually, you obtain that 'Consumer a m' is necessarily 'Pipe a Void m',
 and 'alpha = pipe absurd'.

Ok, thanks for the explanation. Makes sense...

 (2) The $$ operator is poorly named. I would intuitively expect an
 operator that looks so similar to the standard $ to have the same
 direction of data flow (i.e. right to left, like function application and
 composition) but your is left to right. You could use e.g. $ instead,
 which has the additional advantage of allowing a symmetric variant for
 the other direction i.e. $.
 
 '$$' is inspired by iteratees. Similarly to its iteratee counterpart,
 it discards upstream result values and only returns the output of the
 last pipe. That said, '$' looks like a clearer alternative, so I
 could consider changing it.

(...or maybe use a plain function instead of an operator...)

Cheers
Ben


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


Re: [Haskell-cafe] ANNOUNCE: pipes-core 0.1.0

2012-04-16 Thread Ben Franksen
Paolo Capriotti wrote:
 I'm pleased to announce the release of version 0.1.0 of pipes-core, a
 library for efficient, safe and compositional IO, similar in scope to
 iteratee and conduits.
 
 http://hackage.haskell.org/package/pipes-core

I like your pipes package. This is very similar to what Mario Blažević wrote 
about his Coroutines in the Monad.Reader (can't remember which issue; great 
article, BTW, many thanks Mario for making me understand the iteratee 
business (and also generators) for the first time). Your pipes-core looks 
even simpler to use, maybe due to avoiding to make a type distinction 
between consumer/producer/pipe (except the natural one i.e. through the 
input/output types), even though the parameterization by a functor (as in 
Monad.Coroutine) has its own beauty.


Two issues:

(1) What is the reason for the asymmetry in
 
  type Producer b m = Pipe () b m
  type Consumer a m = Pipe a Void m

i.e. why does Producer use () for the input? I would expect it to use Void, 
like Consumer does for its output. Calling await in a Producer resulting in 
an immediate 'return ()' as you say is allowed (in the tutorial) strikes me 
as not very useful.

If the idea is simply to flag nonsense like

  consumer + producer

with a type error, then it might be a better idea to introduce two different 
Void types:

  data NoOutput
  data NoInput

  type Producer b m = Pipe NoInput b m
  type Consumer a m = Pipe a NoOutput m
  type Pipeline m = Pipe NoInput NoOutput m

(and isn't this nicely self-explaining?)

(2) The $$ operator is poorly named. I would intuitively expect an operator 
that looks so similar to the standard $ to have the same direction of data 
flow (i.e. right to left, like function application and composition) but 
your is left to right. You could use e.g. $ instead, which has the 
additional advantage of allowing a symmetric variant for the other direction 
i.e. $.

Cheers
Ben


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


Re: [Haskell-cafe] Deduce problem.

2011-11-21 Thread Ben Franksen
Magicloud Magiclouds wrote:
 So I think I got what you guys meant, I limited ClassB to only H.
 Then how to archive my requirement, that from and to only return items
 that instanced ClassB?

If you are willing to go beyond Haskell98 (or Haskell2010), you can use a 
multi-parameter class. Enable the extension:

{-# LANGUAGE MultiParamTypeClasses #-}

An then, instead of

class (ClassA a) = ClassC a where
  from :: (ClassB b) = a - [b]
  to :: (ClassB c) = a - [c]

you say

class (ClassA a, ClassB b) = ClassC a b c where
  from :: c - [b]
  to :: c - [a]

This means that for each triple of concrete types (a,b,c) that you wish to 
be an instance of ClassC, you must provide an instance declaration, e.g.

instance ClassC Test H H where
  from = ...whatever...
  to = ...whatever...

Now you have the fixed type H in the instance declaration and not a 
universally quantified type variable.

Cheers
Ben


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


Re: [Haskell-cafe] Interpreter with Cont

2011-11-21 Thread Ben Franksen
You'll probably get answers from people who are more proficient with this, 
but here's what I learned over the years.

Tim Baumgartner wrote:
 Is Cont free as well?

No. In fact, free monads are quite a special case, many monads are not free, 
e.g. the list monad. I believe what David Menendez said was meant to mean 
'modulo some equivalence relation' i.e. you can define/implement many monads 
as 'quotients' of a free monad. But you cannot do this with Cont (though I 
am not able to give a proof).

 I guess so because I heard it's sometimes called the
 mother of all monads.

It is, in the sense that you can implement all monads in terms of Cont.

Cheers
Ben


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


Re: [Haskell-cafe] A Mascot

2011-11-21 Thread Ben Franksen
heathmatlock wrote:
 Cute! I like it!

Yea, it's cute. I don't like the formula, though: \x - x + x is just too 
trivial and not very Haskellish. Something higher order is the minimum 
requirement, IMO. The original (lambda knights) formula was cool: the fixed 
point operator is directly related to recursion, which is reflected in the 
picture that contains itself; note also that defining this operator requires 
an untyped language, so this fits LISP quite well (but not Haskell).

What about the formula for function composition

  (f . g) x = f (g x)

maybe together with its type (or maybe only the type)

  (.) :: (b - c) - (a - b) - a - c

Extremely cool are GADTs, such as

  data Eq a b where Refl :: Eq a a

Or, if you'd like something more obscure but still at the center of what 
Haskell is about, take the mother of all monads

  m = f = \k - m (\a - (f a) k)

This is a formula I can spend a day contemplating and still wonder if I have 
_really_ understood it. And doesn't that properly reflect the depth and 
richness of Haskell?

Cheers
Ben

 On Mon, Nov 21, 2011 at 7:52 AM, Karol Samborski
 edv.ka...@gmail.comwrote:
 
 2011/11/21 Karol Samborski edv.ka...@gmail.com:
  Hi all,
 
  This is my sister's proposition:
  http://origami.bieszczady.pl/images/The_Lamb_Da.png
 
  What do you think?
 

 Second version: http://origami.bieszczady.pl/images/The_Lamb_Da2.png

 Best,
 Karol Samborski

 ___
 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] Efficient mutable arrays in STM

2011-10-30 Thread Ben Franksen
Benjamin Franksen wrote:
 David Barbour wrote:
 Create an extra TVar Int for every `chunk` in the array (e.g every 256
 elements, tuned to your update patterns). Read-write it (increment it, be
 sure to force evaluation) just before every time you write an element or
 slice it or slice the array element.
 
 Incrementing and forcing evaluation should not be necessary, a  TVar ()
 should be enough. 

I was wrong, though not completely.

 I would be very much surprised if the internal STM
 machinery compares the actual _values_ of what is inside a TVar, I guess
 it just notes that a read or a write happened. 

According to the original STM paper the implementation does an equality 
test, albeit only for pointer equality. So, one should make sure that 
whatever is written to the TVar is a new object. An incremented integer 
would probably be ok, (no need to evaluate it, since the closure is newly 
allocated, thus a new object), a little more on the safe side is a new TVar 
i.e. use TVar (TVar ()).

Cheers
Ben


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


[Haskell-cafe] Efficient mutable arrays in STM

2011-10-25 Thread Ben Franksen
I have an application in mind where concurrent access to large arrays (up to 
millions of elements) of mostly small elements (Int or Double) is common. 
Typical access patterns would be chunk-wise, i.e. reads or writes from index 
n up to index m. Imagine stuff like images, scientific data, etc.

All this suggests that Control.Concurrent.STM.TArray, in its current 
implementation, is not appropriate. Quoting the docs:

It is currently implemented as Array ix (TVar e), but it may be replaced by 
a more efficient implementation in the future (the interface will remain the 
same, however).

An array of TVars is certainly *much* too inefficient for what I have in 
mind w.r.t. both memory and cpu time. In fact I had already decided to use 
Data.Vector.Unboxed from the vector package.

I see that Data.Vector.Unboxed.Mutable provides

  slice :: Unbox a = Int - Int - MVector s a - MVector s a
Yield a part of the mutable vector without copying it.

which is almost what I need... Can I use this together with unsafeIOToSTM 
internally inside a library to provide shared transactional access to an 
IOArray? The docs warn that using unsafeIOToSTM is (obviously) highly 
dangerous, but for what I have in mind the listed problems are not an 
issue:

 * running the IO code multiple times is ok
 * aborting is ok, too
 * inconsistent views are ok, too

The main question is: does the STM transaction actually see that I changed 
part of the underlying array, so that the transaction gets re-tried? Or do I 
have to implement this manually, and if yes: how?

Has anyone done something like that before? (If you tried this and found it 
doesn't work, please tell me, it would save me a lot of work repeating the 
effort).

Is someone working on providing a more efficient version of TArray?

Would it help if I said I'd be a happy user of a better TArray? ;-)

If what I sketched above is infeasible (I would not be surprised if it was, 
I haven't yet spent much effort trying it out), what other options do I 
have? Is there an internal API for the STM stuff, i.e. a C header file or 
something which would make it possible to add efficient TArrays?

Or should I use a high-level approach, something like a Data.Sequence.Seq of 
medium sized chunks (TVar (IOVector e))?

Any comments are highly appreciated!

Cheers
Ben


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


Re: [Haskell-cafe] Efficient mutable arrays in STM

2011-10-25 Thread Ben Franksen
David Barbour wrote:
 On Tue, Oct 25, 2011 at 10:47 AM, Ben Franksen
 ben.frank...@online.dewrote:
 
 The main question is: does the STM transaction actually see that I
 changed
 
 part of the underlying array, so that the transaction gets re-tried? Or do
 I
 have to implement this manually, and if yes: how?

 
 Create an extra TVar Int for every `chunk` in the array (e.g every 256
 elements, tuned to your update patterns). Read-write it (increment it, be
 sure to force evaluation) just before every time you write an element or
 slice it or slice the array element. The IO mutable array is then adjusted
 unsafely, but there is enough transactional context to restart
 transactions that see an inconsistent state. You will have extra
 read/write and write/write conflicts relative to a pure STM solution, but
 only within each chunk.

Your idea is quite similar to what I had in mind, and it encourages me that 
you think it should be possible to do it like that. My idea was to use 
variable-size chunks, based on which slices are currently in use and how 
they overlap, i.e. calculate the maximal non-overlapping index intervals. 
Such a solution would automatically adapt to the usage pattern, but is 
harder to implement efficiently.

 A cleaner alternative is to create a `chunked` TArray, i.e. that works
 with fixed-width immutable chunks in a spine. This should have good
 performance characteristics, and would be a lot safer for general purpose
 use.

This is also an interesting idea, probably much easier to implement, too.

Thanks for the feedback

Cheers
Ben


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


Re: [Haskell-cafe] Efficient mutable arrays in STM

2011-10-25 Thread Ben Franksen
Ketil Malde wrote:

 Ben Franksen ben.frank...@online.de writes:
 
 An array of TVars is certainly *much* too inefficient for what I have in
 mind w.r.t. both memory and cpu time.
 
 You must be a lot more confident than I if you say this without
 benchmarking first. :-) 

Ok, not science, but an informed guess based on what I read about how STM is 
implemented in ghc. Cache locality is one of the main reasons why unboxed 
arrays perform so much better in practice than boxed ones, and TVars are 
most certainly boxed...

 IME, there are (at least) two possible problems
 here, 1) transactions scale (quadratically, I think) with the number of
 TVars touched, 

Ouch! What would be the reason for that? I thought it would be linear... I 
mean what happens is that the transaction log gets built when the 
transaction runs, which should take a constant time per TVar, and then on 
commit we have to traverse the log, which is again linear in the number of 
TVars...

 so if any transaction touch a large part of the array,
 it's going to cost you, and 2) every element of your array will have a
 pointer to it, making GC potentially expensive.  Perhaps you can get
 around the latter by tuning GC, e.g. +RTS -A100M might help.
 
 Or should I use a high-level approach, something like a Data.Sequence.Seq
 of medium sized chunks (TVar (IOVector e))?
 
 I'm not sure exactly what you mean here, but if you're going to touch
 contigous segments of the array, why not TArray (Vector e) or similar?

Yes, that was what David suggested, too. Have to think about it.

Cheers
Ben


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


[Haskell-cafe] Re: Proving stuff about IORefs

2010-10-17 Thread Ben Franksen
Derek Elkins wrote:
 On Sun, Oct 17, 2010 at 6:49 AM, Miguel Mitrofanov
 miguelim...@yandex.ru wrote:

 On 17 Oct 2010, at 05:21, Ben Franksen wrote:

 I want to prove that

 f r == do
 s1 - readIORef r
 r' - newIORef s1
 x - f r'
 s3 - readIORef r'
 writeIORef r s3
 return x

 That is not true. Consider the following function:

 g r1 r2 = writeIORef r1 0  writeIORef r2 1  readIORef r1

 This function behaves differently depending on whether r1 and r2 are the
 same IORef or not. Therefore, the property you want to prove doesn't hold
 for the partially-applied function

 f = g r1
 
 I originally was thinking along these lines, and this is an important
 case, but there is an even more trivial example.
 
 Let f be return.

Oh, my god. Of course.

Thanks for pointing me to the obvious ;-)

This means I either have to give up on the second law

  callback . embed  =  id

or find another implementation. Maybe IORef is too powerful. Hmm.

The second law was inspired by the instance for ReaderT:

  instance Embed m (ReaderT r m) where
type Content m (ReaderT r m) = r
embed = ReaderT
callback = runReaderT

which is much more general (it does not depend on the inner monad being IO),
and where indeed the second law holds.

Cheers
Ben

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


[Haskell-cafe] Re: Re: Proving stuff about IORefs

2010-10-17 Thread Ben Franksen
Ben Millwood wrote:
 On Sun, Oct 17, 2010 at 11:15 AM, Malcolm Wallace
 malcolm.wall...@me.com wrote:

 The problem with the code you originally posted was that it looked like
 this:

 f r = do r' - something
 f r'
 something else -- this is dead code

 That is, the computation is non-terminating, because f simply calls
 itself recursively, with no base case.

 Regards,
 Malcolm
 
 He was using ==, not =, it was a statement of equality not a definition :)
 
 Much like one might say that sort xs == sort (reverse xs).

Yes, I thought that was obvious from the context. A different layout i.e.

  f r
= 
  do r' - something
 f r'

would have made that clearer.

Cheers
Ben

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


[Haskell-cafe] Re: Proving stuff about IORefs

2010-10-17 Thread Ben Franksen
Hi Mathew

Matthew Brecknell wrote:
 Ben Franksen wrote:
 Suppose we have a function
 
   f :: IORef a - IO b
 
 I want to prove that
 
   f r == do
 s1 - readIORef r
 r' - newIORef s1
 x - f r'
 s3 - readIORef r'
 writeIORef r s3
 return x
 
 I'm not sure where in your question the quantifiers for types a and b
 are intended to be.
 
 If you really do mean:
 
 Given an arbitrary function f with polymorphic type
 f :: forall a b. IORef a - IO b
 prove that...
 
 then you might be able to appeal to parametricity. I wouldn't know how
 to apply parametricity to IO actions, though.

No, I would have written this explicitly as

  f :: forall a b. IORef a - IO b .

I thought it is the generally accepted convention that free variables
appearing in a proposition are understood to be universally quantified (at
the outermost level). If we had to always explicitly write down all the
quantifiers, formulas would quickly become unwieldy.

 On the other hand, Miguel and Derek seem to be interpreting these as
 meta-variables which are quantified over the whole question; in other
 words, that you mean:
 
 Given arbitrary types A and B, and a function
 f :: IORef A - IO B
 prove that...
 
 Derek's counter-example is then, more explicitly:
 
 type A = ()
 type B = IORef ()
 f = return
 
 If I had time to digest your second post, I might be able to figure out
 which of these (plus a couple of other possibilities) is required. So my
 point is just that if you don't think about these things explicitly,
 it's easy to unwittingly make an assumption, possibly to the detriment
 of whatever you're trying to achieve.

Right, in general. That wasn't my mistake, though. I just wanted the law to
hold so badly I forgot that IORefs have an identity separate from what
their content is, so even if what the do-block returns has the same
content, it is still a different IORef.

However, I have the notion now that it suffices to prove something much
weaker, namely

  callback . embed . const = id

Note that this is a special case of the original law

  callback . embed = id

It means that the IO action does not get passed a reference and thus I need
only prove

  a
=
  do
s1 - readIORef r
r' - newIORef s1
x - a
s3 - readIORef r'
writeIORef r s3
return x

and this goes through w/o problems, as I can now safely move the first two
lines past the x - a.

Thanks for all the help.

Ben

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


[Haskell-cafe] Re: A rant against the blurb on the Haskell front page

2010-10-16 Thread Ben Franksen
Don Stewart wrote:
 ben.franksen:
  Haskell is an advanced purely functional programming language.
  
  Good start, if only the advanced were replaced with something more
  characteristic, like lazy, or statically typed. Which, BTW, both
  do not
 
 lazy and statically typed don't mean much to other people. They are
 buzz words that mean nothing to many people.

I imagine a list of 'bullet points' following the blurb, listing the main
features with a small explanation and a link to further details.

  appear in the whole blurb, even though they are *the*
  characteristics of Haskell, lazyness being even something that sets
  it apart from most other languages. I hear the marketeers crying
  but the average visitor has no idea what lazyness means. So what?
  Give them a link to the wiki with an explanation. So, a better
  introductory sentence would be
  
  - Haskell is a lazily evaluated, purely functional programming
  language with a very flexible and powerful static type system.
 
 What are the benefits of laziness?

It is difficult to explain lazy evaluation and why it helps to make programs
more concise in one sentence. But it still is *the* most distinguishing
feature.

And let us be honest: it has benefits and it also has disadvantages. The
most prominent disadvantage being that it makes reasoning about runtime
behaviour, i.e. performance, much more difficult.

  Next sentence:
  
  An open source product of more than twenty years of cutting edge
  research, it allows rapid development of robust, concise, correct
  software.
 
 It is open source, and was born open source. It is the product of
 research.

How can a language be open source, or rather, how can it *not* be open
source? The point of a (programming) language is that it has a published
('open') definition. Nothing prevents anyone from creating a proprietary
compiler or interpreter for Haskell, AFAIK.

I do not dispute that Haskell is a reasult of research and I agree that this
should be stated. It is still not a 'product'. Have you ever heard someone
characterising TCP/IP as a 'product'? Or HTML? Or even C? The
term 'product', as it is used in the blurb, implies or at least suggests
some specific implementation, not a written and published standard.

  This really gets me every time I read it. How can anyone write such
  a nonsense? Haskell is not an open source product! It is no
  product at all. That most (maybe all) implementations are opens
  source is certainly an interesting fact, but IMO not something that
  should appear at the top of the page right under the header The
  Haskell Programming Language. The second and third sentences
  deliberately conflate language and implementation(s). This is a well
  known falacy and I am ashamed that it
 
 As Python, Ruby, C and every other language do.

Exactly my point. They all have only one relevant implementation. And in
practice this implementation has a great tendency to be taken as the
*definition* of the language, at least w.r.t. its semantics.

Do I really have to explain why this is bad and why specification of a
language should be clearly separate from its implementation? (Hint: how can
you ever hope to prove something about a piece of code if all the semantics
you have is whatever the implementation does?)

I *love* it that there *do* exist other implementations for Haskell, and I
dearly hope UHC, JHC etc will soon get to the point where they can be used
and recommended for practical programming.

  That cutting edge research is done for Haskell as well as for its
  implementations is of course good to know, but just stating it is
  not nearly enough: such a statement must be corroberated with
  evidence, otherwise it is just idle marketing. (Not that there
  wouldn't be evidence amass, it's just that none is given.)
 
 You literally want evidence that research played a part in Haskell, in
 its opening statement? Why??

I reject this objection. I let myself get carried away here. Still I think
that further down some links can be given to papers about Haskell and its
implementation.

  On we go:
  
  With strong support for integration with other languages, built-in
  concurrency and parallelism, debuggers, profilers, rich libraries
  and an active community, Haskell makes it easier to produce
  flexible, maintainable high-quality software.
  
  Let us take that apart:
  
  (1) Fact: Haskell has a good and very easy to use FFI. To the C
  language. I have never heard of integration with any other langauge
  being directly supported.
 
 It is OK to contest these, but consider the FFI of our competition:
 Python, Ruby, Erlang. Woeful FFIs. You are not at risk using Haskell, as
 you can always call out to your favorite $language library.

You misunderstand: I *love* Haskells FFI. It is the best I have ever 

[Haskell-cafe] Re: A rant against the blurb on the Haskell front page

2010-10-16 Thread Ben Franksen
Donn Cave wrote:
 Quoth Ben Franksen ben.frank...@online.de,
 Enough. I think I have made my point.
 
 Yes, though possibly a little overstated it.  While it's easy to share
 your distaste for the blurb, if you take a generous attitude towards it,
 most of it is true enough.

Sorry. I was not in a generous mood, when I wrote this yesterday night. I am
more so now, and I agree that I have overstated soem points. It was not my
intention to attack the people who wrote the blurb, though it may have
sounded like I did. Again, sorry for that.

I agree with the most of it is true enough. Certainly, but that is not my
problem with it.

My problem with it is how it is expressed and that it misses out on
important characteristics.

 The implementation specific features are at least widely available to
 anyone who wants to use the language on the most popular computing
 platforms, so it's expedient, if a little cheesy, to say that Haskell
 supports those features.

I hate this sort of expediency. And it doesn't become the front page of a
language that excells in being principled. Haskell did *not* give in to
expedience when it came to IO and side effects. And what would we have now
it it had done so? Something far inferior and less interesting, I am sure.

That said, I have no problem with mentioning the excellent properties of
existing implementations, even in the first (or maybe second) paragraph.
But I want the text to be explicit and honest about this.

 We agree about strong support for integration with other languages,
 but I wouldn't like to say strong support for integration with C,
 either.  The FFI is mostly independent of C, per se - outside of the
 hsc macros, it just addresses a sort of platform standard for exposed
 library functionality, which happens to be commonly implemented in C.
 Someone might be able to think of a better way to put that.

Yes, this is difficult to state w/o going into details. Maybe talk
about 'binding to system libraries' or something like that.

 The point I liked best is the one you started with:
 
 This blurb should, IMO, give a concise description of what Haskell, the
 programming language, is, what makes it different from other languages,
 and why I should be interested in it.
 
 ... and, we understand, you don't find that in this blurb.  Lazy and
 statically typed may not be universally understood, but they aren't
 buzz words.  Whether that's the right way to shed some light on what
 Haskell is like, it sure says a lot more on a technical level than
 advanced purely functional programming language.  And while that
 phrase is linked to a longer exposition of Functional programming,
 the latter is set in language-independent terms and is at best ambiguous
 about whether it's talking about Haskell or not.

Yes, we have to be careful what we directly link to from the front page, and
especially from the blurb. These documents are almost as important as the
blurb itself.

They should concisely explain the main features for someone unfamiliar with
them, maybe contain some small examples. They definitely should be about
Haskell, not something more general, and also not something more specific,
like ghc, except if explicitly stated.

 I'm trying to picture someone who might find Haskell useful, but would
 be spooked by description of the language in unfamiliar technical
 terms.  Forget Python, this is a little different proposition.  A couple
 days ago I was talking to a friend about Haskell, turned out he hadn't
 heard of it.  I suppose he may have found this blurb.  I hope he
 found the blurb that appears at the top of the Introduction page:
 
  Haskell is a computer programming language. In particular, it is a
   polymorphically statically typed, lazy, purely functional language,
   quite different from most other programming languages. The language
   is named for Haskell Brooks Curry, whose work in mathematical logic
   serves as a foundation for functional languages. Haskell is based
   on the lambda calculus, hence the lambda we use as a logo.
 
 This most succinctly expresses the points I tried to convey to him
 about Haskell, and I don't think it would be out of place on the
 main page.

Much better. Though I *do* think mentioning the main implementations and
their qualities is a good thing to o, right after this:

Haskell can be interpreted or compiled. It has high quality, mature
implementations [link to a list of implementations], including optimizing
compilers, interactive interpreters, profilers and tools for debugging, and
a large and rapidly growing body of libraries [link to hackage]. The most
important Haskell implementation, ghc [like to ghc page], has served as a
test bed for practical application of cutting egde research into the
language as well as its compilation to efficiently executable code.

The text should go on and mention concurrency, parallelism, ffi, and
whatnot.

Cheers
Ben

___
Haskell-Cafe mailing list

[Haskell-cafe] Re: A rant against the blurb on the Haskell front page

2010-10-16 Thread Ben Franksen
Christopher Done wrote:
 On 16 October 2010 05:52, Ben Franksen ben.frank...@online.de wrote:
 what marketing idiot has written this inclonclusive mumble-jumble of
 buzz-words?
 [...]
 How can anyone write such a
 nonsense? Haskell is not an open source product!
 [...]
 I am ashamed that it appears on the front page of my favourite
 programming language.
 [...]
 But no, I forgot, we don't want to explain anything or even be
 logical, dear reader, we want to pound slogans into your head!
 
 Stand back everyone, Bill Hicks is back and he's got an axe to grind,
 and it looks rusty!

I am sorry about the wording of these sentences, especially teh first one. I
let myself get carried away.

I stand by the critique, though. The blurb mixes up too many things that
should be clearly separated.

 On 16 October 2010 07:49, Donn Cave d...@avvanta.com wrote:
  Haskell is a computer programming language. In particular, it is a
 polymorphically statically typed, lazy, purely functional language,
 quite different from most other programming languages. The language
 is named for Haskell Brooks Curry, whose work in mathematical logic
 serves as a foundation for functional languages. Haskell is based
 on the lambda calculus, hence the lambda we use as a logo.

 This most succinctly expresses the points I tried to convey to him
 about Haskell, and I don't think it would be out of place on the
 main page.
 
 This description is similar to Wikipedia's description of the Joy
 language, with samples from the blurb above spliced in:
 
 The Joy programming language is a purely functional programming
 language[, quite different from other programming languages.] It
 was produced by Manfred von Thun of La Trobe University in
 Melbourne, Australia. Joy is based on composition of functions
 rather than lambda calculus[, hence the composition operator
 we use as a logo.]
 
 These descriptions are fine, but they don't note how Haskell really is
 any different from other languages, like Joy.

It states very clearly how Haskell is very different from Java, C, C++,
Perl, Python, Ruby, etc.

Distinguishing it from exotic languages like Joy is important but can be
done in a later paragraph.

 It doesn't include the
 fact that Haskell is a very serious language: it has a comprehensive
 and stable implementation, growing community, growing and already
 large library set, is being used seriously in industry, is the focus
 of cutting edge parallelism and concurrency research, has many yearly
 conferences, hackathons, etc. The original blurb does mention these
 things.

All these things should be mentioned, but not before we say what Haskell
actually *is*.

 On 16 October 2010 09:09, Colin Paul Adams co...@colina.demon.co.uk
 wrote:
 And purely functional programming language?

 If they mean anything to many people, it's that the language works
 (i.e. functions). What language wouldn't work?

 I think Ben has a strong point here.
 
 To solve this ambiguity that phrase is a link that people can click to
 find out what it means. Object oriented, dynamically typed,
 stack-based are about as meaningful.

The difference may be that everyone thinks he knows what 'object oriented'
means. But 'lazyness', 'polymorphic type system', what the heck is that?

I just think there is nothing we can do about that. These concepts are not
as well known as others. We can link to an explanation and we should, but
let's face it, if someone come to Haskell and expects to see only stuff he
already knows about he will be disappointed, no matter how well we hide
these things on the front page.

Cheers
Ben

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


[Haskell-cafe] Re: A rant against the blurb on the Haskell front page

2010-10-16 Thread Ben Franksen
Ben Franksen wrote:
  That cutting edge research is done for Haskell as well as for its
  implementations is of course good to know, but just stating it is
  not nearly enough: such a statement must be corroberated with
  evidence, otherwise it is just idle marketing. (Not that there
  wouldn't be evidence amass, it's just that none is given.)
 
 You literally want evidence that research played a part in Haskell, in
 its opening statement? Why??
 
 I reject this objection. 

Oops, translation error. I wanted to say: I withdraw this objection.

Cheers
Ben

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


[Haskell-cafe] Proving stuff about IORefs

2010-10-16 Thread Ben Franksen
I have a formal proof where I am stuck at a certain point.

Suppose we have a function

  f :: IORef a - IO b

I want to prove that

  f r == do
s1 - readIORef r
r' - newIORef s1
x - f r'
s3 - readIORef r'
writeIORef r s3
return x

What happens here is that the temporary IORef r' takes the place of the
argument r, and after we apply f to it we take its content and store it in
the original r. This should be the same as using r as argument to f in the
first place.

How can I prove this formally?

Cheers
Ben

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


[Haskell-cafe] Re: Re: A rant against the blurb on the Haskell front page

2010-10-16 Thread Ben Franksen
wren ng thornton wrote:
 On 10/16/10 10:48 AM, Ben Franksen wrote:
 Don Stewart wrote:
 It is open source, and was born open source. It is the product of
 research.

 How can a language be open source, or rather, how can it *not* be open
 source? The point of a (programming) language is that it has a published
 ('open') definition. Nothing prevents anyone from creating a proprietary
 compiler or interpreter for Haskell, AFAIK.
 
 Miranda[TM] is/was a proprietary language, quite definitively so. If
 nothing else, this should be apparent by the fact that every reference
 to it in research papers of the era (a) included the TM sigil, and (b)
 had footnotes indicating who the IP holders are. That was before my
 time, but I was under the impression that Haskell was open from the
 beginning ---by express intention--- in order to enable work on lazy
 functional languages without being encumbered by Miranda[TM]'s closed
 nature.
 
 For that matter, until rather recently Java was very much a closed
 language defined by the runtime system provided by Sun Microsystems and
 not defined by the sequence of characters accepted by that system, nor
 by the behavior of the system when it accepts them. Sun even went
 through some trouble to try to shut out competitive development of
 runtime systems such as SoyLatte, IcedTea, and the like.
 
 Even the venerable C language has a long history of companies making
 proprietary extensions to the language in order to require you to buy
 their compiler, and they would most certainly pursue legal action if
 someone else copied the features. This is why GCC is as big a coup for
 the free/open-source movement as Linux is--- long before GCC changed its
 name and focus to being a compiler collection.
 
 The languages which are open-source are in close correspondence with the
 languages which have a free/open-source implementation. There are a lot
 of them, including the vast majority of recent languages. But don't be
 seduced into thinking that a language is a predicate on acceptable
 strings, a transducer from those strings into computer behaviors, or
 that such predicates and transducers are public domain.

Sigh. Yes, you are right, of course. All this is true, sadly. There are
stupid people who think that they can own a programming language. I hope
they will go the way all the other mis-adapted creatures have gone and just
die out.

Still, Haskell is an open source product doesn't sound right to me.
Even Haskell is open source (without the product) has a bad ring
because source is short for source code and source code is not
something a programming language has.

I agree that non-proprietary is a valid and important characterization of
the language. This should be mentioned where we speak about libraries and
community, since the active and friendly community is the motor behind the
growing set of libraries, and you get this sort of participation only with
a free/non-proprietary language. This applies not only to individuals but
to companies as well, maybe even more.

I anticipate the objection that potential commercial users might be scared
off by the terms non-proprietary or free, whereas the term open
source has been coined to (and probably actually does) sound more commerce
friendly. To countermand such an effect, we can point out that most
libraries have non-copyleft licenses and that there are a number of
companies who have done and still do a lot to support and advance Haskell.

Cheers
Ben

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


[Haskell-cafe] Re: Re: A rant against the blurb on the Haskell front page

2010-10-16 Thread Ben Franksen
wren ng thornton wrote:
 On 10/16/10 11:22 AM, Ben Franksen wrote:
 Much better. Though I *do* think mentioning the main implementations and
 their qualities is a good thing to o, right after this:

 [...]The most
 important Haskell implementation, ghc [like to ghc page], has served as a
 test bed for practical application of cutting egde research into the
 language as well as its compilation to efficiently executable code.
 
 Objection to calling GHC the most important. The most mature, most
 fully featured, most common, or even the standard implementation,, sure.
 But saying GHC is more important than the rest implies that (among
 others) the work on JHC and UHC is unimportant. To the contrary, I
 think JHC and UHC are, perhaps, more important than GHC precisely
 because they are treading new waters that the standard implementation
 cannot afford to explore.

Right on all accounts. Can one say most mature and full-featured ?

Cheers
Ben

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


[Haskell-cafe] Re: Proving stuff about IORefs

2010-10-16 Thread Ben Franksen
Derek Elkins wrote:
 On Sat, Oct 16, 2010 at 9:21 PM, Ben Franksen ben.frank...@online.de
 wrote:
 I have a formal proof where I am stuck at a certain point.

 Suppose we have a function

 f :: IORef a - IO b

 I want to prove that

 f r == do
 s1 - readIORef r
 r' - newIORef s1
 x - f r'
 s3 - readIORef r'
 writeIORef r s3
 return x

 What happens here is that the temporary IORef r' takes the place of the
 argument r, and after we apply f to it we take its content and store it
 in the original r. This should be the same as using r as argument to f in
 the first place.

 How can I prove this formally?
 
 You haven't provided us with any information about the formal model
 you are using and your question is somewhat ambiguously phrased, hence
 Thomas' response where, I'm pretty sure, he misunderstood what you
 were asking.

I don't have a model. Up to this point I can make do with equational
reasoning.

This is the context. I have this class

  class Embed i o where
type Content i o
embed :: (Content i o - i a) - o a
callback :: o a - Content i o - i a

which I _think_ should have these laws attached

  L1:embed . callback == id
  L2:callback . embed == id

and an instance

  newtype StateIO s a = StateIO { unStateIO :: StateT s IO a }

  instance Embed IO (StateIO s) where
type Content IO (StateIO s) = IORef s
embed f = StateIO $ StateT $ \s - do
  r - newIORef s
  x - f r
  s' - readIORef r
  return (x, s')
callback action r = do
  s - readIORef r
  (x, s') - runStateT (unStateIO action) s
  writeIORef r s'
  return x

The original idea comes from this message

  http://www.haskell.org/pipermail/haskell-cafe/2007-July/028501.html

but I have deviated somewhat from Jules' notation and generalised.

Now I want to prove the laws. L1 is straight forward:

embed (callback o)
  = { def embed }
StateIO $ StateT $ \s1 - do
  r - newIORef s1
  x - callback o r
  s4 - readIORef r
  return (x, s4)
  = { def callback }
StateIO $ StateT $ \s1 - do
  r - newIORef s1
  x - do
s2 - readIORef r
(x, s3) - runStateT (unStateIO o) s2
writeIORef r s3
return x
  s4 - readIORef r
  return (x, s4)
  = { Monad laws }
StateIO $ StateT $ \s1 - do
  r - newIORef s1
  s2 - readIORef r
  (x, s3) - runStateT (unStateIO o) s2
  writeIORef r s3
  s4 - readIORef r
  return (x, s4)
  = { IORef laws }
StateIO $ StateT $ \s1 - do
  r - newIORef s1
  (x, s3) - runStateT (unStateIO o) s1
  writeIORef r s3
  return (x, s3)
  = { reorder (r is unused in second stmt), Monad laws }
StateIO $ StateT $ \s1 - do
  (x, s3) - runStateT (unStateIO o) s1
  r - newIORef s1
  writeIORef r s3
  return (x, s3)
  = { IORef laws }
StateIO $ StateT $ \s1 - do
  (x, s3) - runStateT (unStateIO o) s1
  return (x, s3)
  = { Monad laws }
StateIO $ StateT $ \s1 - runStateT (unStateIO o) s1
  = {def StateIO, StateT }
o

You might question the step marked { IORef laws }. I don't know if this has
been formalized anywhere but I thought it safe to assume a law that states

  do
r - newIORef a
b - readIORef r
g b

  =

  do
r - newIORef a
g a

assuming that a is not used any further.

Similarly I have used the law

  do
writeIORef r a
b - readIORef r
g b

  =

  do
writeIORef r a
g a

Both of these are so obviously satisfied that I accept them as axioms.

Now, when I try to prove L2, I can reason similarly and get

callback (embed f) r
  = { def callback }
do
  s1 - readIORef r
  (x, s4) - runStateT (unStateIO (embed f)) s1
  writeIORef r s4
  return x
  = { def embed }
do
  s1 - readIORef r
  (x, s4) - runStateT (unStateIO $ StateIO $ StateT $ \s2 - do
  r' - newIORef s2
  x - f r'
  s3 - readIORef r'
  return (x, s3)
) s1
  writeIORef r s4
  return x
  = { def StateIO, StateT, beta reduce }
do
  s1 - readIORef r
  (x, s4) - do
  r' - newIORef s1
  x - f r'
  s3 - readIORef r'
  return (x, s3)
  writeIORef r s4
  return x
  = { Monad laws }
do
  s1 - readIORef r
  r' - newIORef s1
  x - f r'
  s3 - readIORef r'
  writeIORef r s3
  return x
  = { IORef laws }
do
  s1 - readIORef r
  r' - newIORef s1
  x - f r'
  s3 - readIORef r'
  writeIORef r s3
  return x
  = { ??? }
f r

and I would like to reduce the last step to the same level of obviosity as
in the previous proof.

 At any rate, if you intend to prove this for any arbitrary f, I can't
 tell you how to prove it formally because it's not true.

How do you know that? Can you give an example where it fails?

Cheers
Ben

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

[Haskell-cafe] A rant against the blurb on the Haskell front page

2010-10-15 Thread Ben Franksen
This is a critique of the current 'Haskell Blurb', the first paragraph on
www.haskell.org.

This blurb should, IMO, give a concise description of what Haskell, the
programming language, is, what makes it different from other languages, and
why I should be interested in it.

What it does, instead, is to make me scratch my head and ask myself: what
marketing idiot has written this inclonclusive mumble-jumble of buzz-words?

Let me explain.

Haskell is an advanced purely functional programming language.

Good start, if only the advanced were replaced with something more
characteristic, like lazy, or statically typed. Which, BTW, both do not
appear in the whole blurb, even though they are *the* characteristics of
Haskell, lazyness being even something that sets it apart from most other
languages. I hear the marketeers crying but the average visitor has no
idea what lazyness means. So what? Give them a link to the wiki with an
explanation. So, a better introductory sentence would be

- Haskell is a lazily evaluated, purely functional programming language
with a very flexible and powerful static type system.

Next sentence:

An open source product of more than twenty years of cutting edge research,
it allows rapid development of robust, concise, correct software.

This really gets me every time I read it. How can anyone write such a
nonsense? Haskell is not an open source product! It is no product at all.
That most (maybe all) implementations are opens source is certainly an
interesting fact, but IMO not something that should appear at the top of
the page right under the header The Haskell Programming Language. The
second and third sentences deliberately conflate language and
implementation(s). This is a well known falacy and I am ashamed that it
appears on the front page of my favourite programming language. The blurb
talks about robust, concise, correct software, but misses itself most of
these goals: it is imprecise, incorrect, and not robust (because
implementations vary), and therefore not a good advertisement, though quite
possibly rapidly developed.

The blurb promises rapid development of robust, concise, correct software
lest one think this were something akin to Perl which certainly allows
rapid development, yet typically neither robust nor correct, especially if
done rapidly. So, how does Haskell differ from that? Well, I'd say this is
where lazyness and a static yet flexible type system come into play. But
no, I forgot, we don't want to explain anything or even be logical, dear
reader, we want to pound slogans into your head!

That cutting edge research is done for Haskell as well as for its
implementations is of course good to know, but just stating it is not
nearly enough: such a statement must be corroberated with evidence,
otherwise it is just idle marketing. (Not that there wouldn't be evidence
amass, it's just that none is given.)

On we go:

With strong support for integration with other languages, built-in
concurrency and parallelism, debuggers, profilers, rich libraries and an
active community, Haskell makes it easier to produce flexible, maintainable
high-quality software.

Let us take that apart:

(1) Fact: Haskell has a good and very easy to use FFI. To the C language. I
have never heard of integration with any other langauge being directly
supported.

(2) Fact: Built-in concurrency and parallelism is not exactly part of the
langauage, although purity makes it possible to support them in a more
precise and less error-prone way; which is exploited by ghc's concurrency
and parallelism extensions.

(3) Fact: Traditional debuggers are practically useless in Haskell, due to
lazy evaluation. But, oh, we forgot to mention the small fact that Haskell
is lazy. Too bad. Profiling is supported by ghc only (AFAIK), but is
supposed to be very useful (never seriously used it, so I can't judge.)

(4) Fact: there are libraries. Some of them are good, others are not so
good. Most leave a lot to be desired, but I would be hard pressed to come
up with something better myself. What really distinguishes Haskell
libraries from what is found in other languages is the level of
abstraction. I know no other language where stuff like Monad, (Applicative)
Functor, Monoid, Category etc. is *at the heart* of all the libraries. But,
oh, I forgot, we don't want to scare people off, so better not talk about
this in public.

(5) Fact: Haskell has an active community. No question.

(6) Fact: Haskell makes certain things easier (than other languages). Other
things that are easy in other langauges are hard in Haskell. Or at least
very non-obvious. Whether Haskell programs are more flexible, when compared
with dynamically typed OO languages like Python, I seriously doubt.
Maintainable high-quality software is the real selling point, IMO; or
rather *reliably correct* software. However, I cannot see how this
dirtectly follows from the previous points, which is what the sentence is
saying. What has an FFI do to with high 

[Haskell-cafe] Re: Re: Re: Make your Darcs repositories hashed?

2010-10-13 Thread Ben Franksen
Jason Dagit wrote:
 On Tue, Oct 12, 2010 at 4:41 PM, Ben Franksen
 ben.frank...@online.dewrote:
 Seriously, the server is a debian etch (!) system. Also called debian
 old-stable. Of course I have long since installed newer version of
 darcs, but since I am not root there I cannot put it into /usr/local, so
 I cannot completely rule out the possibility that other users still use
 the ancient /usr/bin/darcs and will now have problems when they darcs
 get.
 
 Isn't debian etch a security liability at this point?

Certainly. But the admin (there is just one for a all our machines) can only
do so much at a time...

 I do _not_ expect that this will lead to any serious trouble, as the
 latest stable darcs is just a small addition to the PATH away. Still,
 users should be warned that darcs-2.x is required.
 
 Yes, sorry about that.  At the time I was having some trouble
 finding authoritative info on it so I went with my memory, which was
 wrong.

No problem. I thought you were still an active darcs developer, so I assumed
you must know ;-)

 As for your path, I'm reasonably confident that if you put your local
 darcs
 at the front of your path then you're good to go.  I know that works for
 local push, what I'm wondering about is push over ssh.

Works only if the remote user be default uses darcs-2, too.

  It seems easy for
 you to test in this case.  I know darcs finds the right executable by
 looking in PATH for 'darcs'.  What I can't know is whether the server
 you're
 using lets you set PATH over ssh invocations that are non-interactive. 
 It's entirely possible that has been disallowed by the sysadmins.

Yes, but it is no problem, since we abandoned a special user for the repos a
while ago and now share stuff using group memebership. This works really
well if each user has her own group by default, because then you can set
umask to 002 and share directories by giving them to the shared group and
setting the S-bit (so that all files and subdirectories created there
inherit the group).

Oops. How did we drift this far off-topic?

Cheers
Ben

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


[Haskell-cafe] Re: Make your Darcs repositories hashed?

2010-10-12 Thread Ben Franksen
One minor but important note: the hashed format is *not* readable with a
darcs-1 program:

(after a darcs optimize --upgrade
in /opt/repositories/controls/darcs/apps/HoBiCaT)

frank...@aragon:~/tmp  /usr/bin/darcs --version
1.0.9rc1 (release candidate 1)
frank...@aragon:~/tmp  /usr/bin/darcs
get /opt/repositories/controls/darcs/apps/HoBiCaT
Invalid repository:  /srv/csr/repositories/controls/darcs/apps/HoBiCaT
darcs: /srv/csr/repositories/controls/darcs/apps/HoBiCaT/_darcs/inventory:
openBinaryFile: does not exist (No such file or directory)
frank...@aragon:~/tmp  /opt/darcs/bin/darcs --version
2.0.2 (release)
frank...@aragon:~/tmp  /opt/darcs/bin/darcs
get /opt/repositories/controls/darcs/apps/HoBiCaT
Copying patches, to get lazy repository hit ctrl-C...
Finished getting.

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


[Haskell-cafe] Re: Re: A question regarding cmdargs package

2010-10-12 Thread Ben Franksen
Neil Mitchell wrote:
 This makes me curious.  What's the use case where you want to allow the
 user to pass arguments on the command line, but you don't want that user
 to be able
 to use '--help' to find out what arguments may be passed?

I wanted to create a clone of an existing program that had no help option
and instead gave the help output if it saw an invalid option.

 When you don't want to bother defining the help options/descriptions? :p

 (alternatively, you may wish to provide a more full-featured version
 like what darcs does by using a pager)
 
 You can already do this with CmdArgs. If you use cmdArgsMode/process
 it returns a structure populated to say what to do next (i.e. display
 a help message), but you are welcome to do something different, or do
 what it says in a different way. However, I can see some people might
 want to remove help entirely, so I'll try and find a balance.

The point here was not so much removing --help, but rather that I want to
have control over the 'standard' options (help,version,verbosity) in the
same way as for the rest. My program might not have a version, so why
offer --version? Or maybe I want a different name for it because the -V is
already used for something else, which I cannot change for backwards
compatibility. I might want another name for --help, for instance -h. The
standard -? does not work in all shells/configurations and --help might
look strange if all other options are of the one-dash-one-character sort. I
would also like to configure the help text for the standard options, for
instance for i18n or because I like starting with a lower case letter or...

Cheers
Ben

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


[Haskell-cafe] Re: Re: A question regarding cmdargs package

2010-10-12 Thread Ben Franksen
Joachim Breitner wrote:
 Am Dienstag, den 12.10.2010, 16:42 +1100 schrieb Ivan Lazar Miljenovic:
 On 12 October 2010 16:32, Magnus Therning mag...@therning.org wrote:
 
  This makes me curious.  What's the use case where you want to allow the
  user to pass arguments on the command line, but you don't want that
  user to be able
  to use '--help' to find out what arguments may be passed?
 
 When you don't want to bother defining the help options/descriptions? :p
 
 note that people expect cmd --help to at least do nothing. So if your
 program is called launchMissiles, please make it at least spit out a
 message like your evil dictator was too lazy to write a help message
 when it is called with --help.
 
 (That is if you are sharing your program. Not sure if you should share
 launchMissiles at all.)

launchMissiles = putStrLn Boom! (just kidding :)

BTW another cool feature of an auto-magic option parsing lib is the GNU
standard -- (arguments after this are not to be treated as options).

Cheers
Ben

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


[Haskell-cafe] Re: Haskellers.com recent changes (and I need some volunteers)

2010-10-12 Thread Ben Franksen
Roman Cheplyaka wrote:
 On Mon, 11 Oct 2010 13:09:00 +0200, Vo Minh Thu not...@gmail.com wrote:
 2010/10/11 Roman Cheplyaka r...@ro-che.info:
 On Mon, 11 Oct 2010 11:54:12 +0100, Magnus Therning
 mag...@therning.org
 wrote:
 On Mon, Oct 11, 2010 at 08:37, Michael Snoyman mich...@snoyman.com
 wrote:
 [...]
 Also, now 10 random profiles will be displayed on the homepage. Only
 verified users will be displayed here. I'm also considering adding a
 new status as well: real picture, so that only people with real images
 (not cartoons, not identicons) can show up on the homepage. I think
 this might give a more professional feel. Thoughts?

 I'd be weary of making that a requirement, there are good reasons for
 not putting your picture on the web, just like there are good reasons
 to not use your real name :-)

 ... just like there are good reasons not to publish yourself in a public
 catalogue (such as haskellers.com) at all.

 I have nothing against anonymity. I voted against requirement of real
 names
 on hackage.

 But in this particular case, the whole point to be in the listing is to
 present yourself. So I find the above proposal very reasonable.
 
 Hi,
 
 In the belgian law, an employer can (of course) request a faithful
 resume, but cannot request the resume to contain a picture of you.
 This is a clear example where you wish to advertise yourself, but not
 necessarily with a picture. Anyway, I don't think it is difficult to
 imagine situations where one doesn't wish to show a picture of his/her
 face.
 
 Agree. But then there should be no picture at all for a given person.
 As Michael said -- no cartoons, no identicons.

Why not? They can say more about a person than a picture (not some generic,
auto-chosen one, of course).

Cheers
Ben

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


[Haskell-cafe] Re: Re: Make your Darcs repositories hashed?

2010-10-12 Thread Ben Franksen
Jason Dagit wrote:
 On Tue, Oct 12, 2010 at 2:02 PM, Ben Franksen
 ben.frank...@online.dewrote:
 
 One minor but important note: the hashed format is *not* readable with a
 darcs-1 program:
 
 Sorry about that.  The support for hashed repos existed long before 2.0
 was released and so I misremembered the hashed support as appearing in a
 1.x release.
 
 It looks like you need at least 2.0 to read darcs 1 hashed repos.
 
 Upgrading to a modern darcs client is advised and is only a 'cabal install
 darcs' away.  I was under the impression that even debian stable has moved
 on to 2.x releases.  How is it that you have a 1.0.9 release candidate
 client still?

Have you ever worked at a public institution? I recommend the
experience... ;-)

Seriously, the server is a debian etch (!) system. Also called debian
old-stable. Of course I have long since installed newer version of darcs,
but since I am not root there I cannot put it into /usr/local, so I cannot
completely rule out the possibility that other users still use the
ancient /usr/bin/darcs and will now have problems when they darcs get.

I do _not_ expect that this will lead to any serious trouble, as the latest
stable darcs is just a small addition to the PATH away. Still, users should
be warned that darcs-2.x is required.

Cheers
Ben

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


[Haskell-cafe] Re: My knight's tour does not seem to end

2010-10-10 Thread Ben Franksen
Stephen Tetley wrote:
 On 10 October 2010 11:31, C K Kashyap ckkash...@gmail.com wrote:
 Did you mean this
 http://www.cs.tufts.edu/~nr/comp150fp/archive/richard-bird/sudoku.pdf?
 
 I was actually meaning these slides...
 http://icfp06.cs.uchicago.edu/bird-talk.pdf

But the paper is definitely worth reading, too! Though it requires only
elementary Haskell knowledge, it is still some piece of work if you try to
follow all the details.

C K Kashyap wrote:
 This is probably what I like (and dislike - in a nice way) - my quest
 to master Haskell has been like traversing through a ever expanding
 tree :)
 Very different from a bunch of learn over a weekend language!!!

Absolutely. And IME it never ends. I have studied Haskell for over 6 years
now and I still find lots of stuff out there that makes my brain hurt (like
Oleg's iteratee/enumerator code; though I feel like I am on the verge of
finally getting the hang of it).

Cheers
Ben

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


[Haskell-cafe] Re: Bulletproof resource management

2010-10-08 Thread Ben Franksen
Florian Weimer wrote:
 At least in my experience, in order to get proper resource management
 for things like file or database handles, you need both a close
 operation and a finalizer registered with the garbage collector.  The
 former is needed so that you can create resources faster than the
 garbage collector freeing them.  The latter is a safety net in cases
 where proper resource management is not follwoed (perhaps in GHCi).
 When the explicit close operation or the finalizer has been invoked,
 the object must somehow be disabled, so that further operations on it
 fail (otherwise, you might dereference a dangling pointer).
 
 What's the idom for implementing this in Haskell (or GHC)?  It seems
 that a ForeignPtr cannot be written to (otherwise I'd change it to a
 null pointer when the resource is freed).  It's also not possible to
 check if the finalizers have been run.
 
 Can the finalizers hold a reference to the object which in turn holds
 the ForeignPtr to be finalized?  Or would that prevent the finalizers
 from running at all?  Is there a way to avoid the extra level of
 indirection (or is GHC sufficiently smart to optimize it away)?

You might be interested in Lightweight Monadic Regions
 
  http://okmij.org/ftp/Haskell/regions.html#light-weight

which solve the problem (IMHO) in a much cleaner way, i.e. w/o explicit
closing and also w/o using finalizers.

Cheers
Ben

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


[Haskell-cafe] Re: Re: Bulletproof resource management

2010-10-08 Thread Ben Franksen
Florian Weimer wrote:
 * Ben Franksen:
 You might be interested in Lightweight Monadic Regions
  
   http://okmij.org/ftp/Haskell/regions.html#light-weight

 which solve the problem (IMHO) in a much cleaner way, i.e. w/o explicit
 closing and also w/o using finalizers.
 
 Is this approach composeable in the sense that you can combine code
 written in this code with code from another library?  I don't think
 so.

I see no reason why not.

 The other library might provide something like IORef, and then
 it's impossible to uphold static guarantees.

The way it is implemented for instance in the regions package, you can lift
IO actions into the Region monad, as there are

  instance MonadCatchIO pr = MonadCatchIO (RegionT s pr)   
  instance MonadIO pr = MonadIO (RegionT s pr)

Or maybe I don't understand your objection?

 IMHO, this rules out such an approach (until it's part of the standard
 library and forced upon everyone, which seems unlikely).

I don't think it is necessary or even desirable to enforce this, or any
other style of programming, especially not by standard library design.

Cheers
Ben

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


[Haskell-cafe] Re: Layered maps

2010-10-08 Thread Ben Franksen
Thomas DuBuisson wrote:
 On Fri, Oct 8, 2010 at 2:23 PM, Alex Rozenshteyn rpglove...@gmail.com
 wrote:
 Does there exist a library which allows me to have maps whose elements
 are maps whose elements ... with a convenient syntax.
 The containers library can do this already - there are no constraints
 on the elements of a Map.  For example:
 
 type TripleNestedMap a = Map Int (Map Char (Map String a))
 
 But this is rather silly as you can just do:
 
 type MapOfTriples a = Map (Int ,Char, String) a
 
 for most uses.

True, but I think this:

 Alternatively, does there exist a library like Data.Tree where forests
 are sets rather than lists?

suggests that the OP wants something different, rather like

import Data.Map

data MapTree a
  = Leaf
  | Node (Map a (MapTree a))

I don't know if somebody wrote a library around such a type.

Alex, could you give an example for what would be 'a convenient syntax' for
such a type?
What operations do you think should be available to make using it
convenient?

Cheers
Ben

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


[Haskell-cafe] Re: A question regarding cmdargs package

2010-10-04 Thread Ben Franksen
Arie Peterson wrote:
 On Sun, 03 Oct 2010 19:18:08 +0200, Ben Franksen
 ben.frank...@online.de wrote:
 How can I disable the standard arguments 'help' and 'version'?
 
 If you're not fully committed to the cmdargs package, you might try my
 package 'console-program' instead
 http://hackage.haskell.org/package/console-program. It does not have
 built-in --help or --version functionality. (There is a function
 'showUsage' that takes the description of the command/option structure
 of your program, and prints --help style usage information, but you
 use this at your own discretion.)

Thanks, looks good. I will certainly try it out.

Cheers
Ben

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


[Haskell-cafe] Re: A parsec question

2010-10-03 Thread Ben Franksen
Stephen Tetley wrote:
 Does this one give the expected error message for Parsec3.1 -
 unfortunately I can't test as I'm still using Parsec 2.1.0.1.
 
 parser = block (many digit ? digit)

Unfortunately, no.

Cheers
Ben

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


[Haskell-cafe] Re: Re: Non-existing types in existential quantification?

2010-10-03 Thread Ben Franksen
Henning Thielemann wrote:
 On Sun, 3 Oct 2010, Ben Franksen wrote:
 Christopher Done wrote:

 Consider the following program:

 main = putStrLn $ show $ length [undefined :: a,undefined :: b]

 A concrete type of the element in list doesn't need to be determined
 at runtime, or any time. a unifies with b, and that unifies with x in
 length :: [x] - Int.

 A simpler example is

  main = print Nothing
 
 This seems to be a different example, because GHCi -Wall says that the
 type variable defaults to (). Thus 'Nothing' has monomorphic type at
 runtime. The difference is certainly that 'print' requires a Show
 instance, whereas Christopher's example does not require a type
 constraint.

Right. I always forget about defaulting. This is an obscure feature of the
language.

Are there any programs that rely on defaulting and could not be easily
re-written so as not to?

Cheers
Ben

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


[Haskell-cafe] A question regarding cmdargs package

2010-10-03 Thread Ben Franksen
How can I disable the standard arguments 'help' and 'version'?

Cheers

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


[Haskell-cafe] Re: Haskell Helper

2010-10-03 Thread Ben Franksen
c8h10n4o2 wrote:
 No, it is not secret. I'm having trouble to define functions. Take a look
 at my code(please be gentle)
 http://haskell.1045720.n5.nabble.com/file/n3100036/hai1.hs hai1.hs

Can you explain in a few words what the Func constructor should represent
why it has three arguments? I ask because I am not sure whether it
represents function definition or function call.

Maybe yuou can give a small example for a function definition as well as a
function application (call) in your Hai language.

Cheers
Ben

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


[Haskell-cafe] Re: Haskell Helper

2010-10-03 Thread Ben Franksen
c8h10n4o2 wrote:
 The problem is there. A function in Hai would be function-name,
 arg1,argn=body.
 Func stores function name,arguments and body as Strings(I was thinking to
 put Func String String String).
 The parser func that I wrote so far try to parse a function definition,
 not a function call.
 But when I try to store the function on my Map I get a error with somthing
 called 'functional dependencies'(which I don't know what is).

You mean:

hai1.hs:41:6:
Couldn't match expected type `Hai' against inferred type `[Hai]'
  Expected type: Map.Map Hai Hai
  Inferred type: Map.Map [Hai] Hai
When using functional dependencies to combine
  MonadState (Map.Map [Hai] Hai) m,
arising from a use of `get' at hai1.hs:52:17-19
  MonadState (Map.Map Hai Hai) m,
arising from a use of `get' at hai1.hs:47:16-18
When generalising the type(s) for `w'

The type checker tells you that you are using the same Map with different
key types: at 52:17-19 the key has type [Hai], whereas at 47:16-18 it has
type Hai.

The latter is in your Func case:

  e -return $ Map.insert (a :[b]) c d

where you use  a :[b]  which is the same as  [a,b]  for the key.

Everywhere else, the key has type Hai. This in itself is questionable: do
you really want to use arbitrary expressions as keys? Usually one would
have a

  Map String Hai

representing a map from variable (or function) names to expressions.

For functions you then want

  data Hai = ... | Func [String] Hai | ...

so that

  Func args body

represents the (anonymous) function with the formal arguments  args  and the
resulting expression  body . The function gets a name by inserting it into
the variable map. This means that a definition

  function-name,arg1,...,argn=body

actually defines a variable named  function-name  which, when it gets
looked up in the environment, yields the value  Func [arg1,...,argn] body .

Cheers
Ben

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


[Haskell-cafe] Re: Re: A parsec question

2010-10-03 Thread Ben Franksen
Antoine Latter wrote:
 On Sun, Oct 3, 2010 at 11:55 AM, Ben Franksen ben.frank...@online.de
 wrote:
 Stephen Tetley wrote:
 Does this one give the expected error message for Parsec3.1 -
 unfortunately I can't test as I'm still using Parsec 2.1.0.1.

 parser = block (many digit ? digit)

 Unfortunately, no.

 Hey folks, sorry about this one - my changes to parsec in 3.1 made
 these error messages worse. I've sent a patch off to the maintainer
 which fixes the examples in this thread.

Thanks! I hope we get a new minor release with these fixes soon. I love
parsec-3 very much, especially since you fixed the speed problems.

Cheers
Ben

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


[Haskell-cafe] Re: Haskell Helper

2010-10-03 Thread Ben Franksen
Ben Franksen wrote:
 The type checker tells you that you are using the same Map with different
 key types: at 52:17-19 the key has type [Hai], whereas at 47:16-18 it has
 type Hai.
 
 The latter is in your Func case:

s/latter/former/

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


[Haskell-cafe] Re: Non-existing types in existential quantification?

2010-10-02 Thread Ben Franksen
Christopher Done wrote:
 On 1 October 2010 15:27, Henning Thielemann
 lemm...@henning-thielemann.de wrote:

 Given the following code, that is accepted by GHC:

 data Exist = forall a. Exist a

 exist :: Exist
 exist = Exist undefined

 What type has the 'undefined' ?
 
 I think its type is `a'.

 So far I assumed that at runtime all objects have a concrete type. This
 seems not to be true.

Haskell has a static type system. This means that the type is a property of
expressions in the source language, not (necessarily) something which
exists at runtime. Furthermore, polymorphic types (i.e. those which contain
type variables) such as

  Nothing :: forall a. Maybe a

are no less concrete than monomorphic ones (i.e. those which do not contain
type variables). It often happens that the 'same' expression has different
types in different contexts, and that some of them are monomorphic, even
though others are polymorphic. In this case the monomorphic type must be a
substitution instance of the polymorphic one (i.e. type variables have been
instatiated with (monomorphic) types). But I know of no rule that says
that /all/ type variables have to be instantiated eventually.  

 Consider the following program:
 
 main = putStrLn $ show $ length [undefined :: a,undefined :: b]
 
 A concrete type of the element in list doesn't need to be determined
 at runtime, or any time. a unifies with b, and that unifies with x in
 length :: [x] - Int.

A simpler example is

  main = print Nothing

Cheers
Ben

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


[Haskell-cafe] Re: A parsec question

2010-09-30 Thread Ben Franksen
Christian Maeder wrote:
 Am 29.09.2010 20:01, schrieb Daniel Fischer:
 On Wednesday 29 September 2010 19:10:22, Ben Franksen wrote:

 Note the last line mentions only '}'. I would rather like to see

   expecting } or digit

 since the parser could very well accept another digit here.
 
 parsec2 did that, I don't know whether that change is intentional or
 accidental.
 
 Right, parsec2 or parsec-2.1.0.1 still does so. (parsec-3 behaves
 differently wrt error messages.)
 
 Try ghc-pkg hide parsec so that parsec-2.1.0.1 will be taken:

I need parsec-3 since I use it as a monad transformer over IO so I can do IO
during parsing. And I want efficiency, too, so did not consider
parsec-3.0.*.

Cheers
Ben

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


[Haskell-cafe] A parsec question

2010-09-29 Thread Ben Franksen
I have a question about Parsec. The following program

 import Control.Applicative ((*),(*))
 import Text.Parsec
 import Text.Parsec.Char
 block p = char '{' * p * char '}'
 parser = block (many digit)
 main = parseTest parser {123a}

gives the output

  parse error at (line 1, column 5):
  unexpected a
  expecting }

Note the last line mentions only '}'. I would rather like to see

  expecting } or digit

since the parser could very well accept another digit here.

(1) What is the reason for this behaviour?
(2) Is there another combinator that behaves as I would like?
(3) Otherwise, how do I write one myself?

BTW, I am using parsec-3.1.0 and ghc-6.12.3.

Cheers
Ben

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


[Haskell-cafe] Re: A parsec question

2010-09-29 Thread Ben Franksen
Ben Franksen wrote:
 import Control.Applicative ((*),(*))
 import Text.Parsec
 import Text.Parsec.Char
 block p = char '{' * p * char '}'
 parser = block (many digit)
 main = parseTest parser {123a}
 
 gives the output
 
   parse error at (line 1, column 5):
   unexpected a
   expecting }
 
 Note the last line mentions only '}'. I would rather like to see
 
   expecting } or digit
 
 since the parser could very well accept another digit here.
 
 (1) What is the reason for this behaviour?
 (2) Is there another combinator that behaves as I would like?
 (3) Otherwise, how do I write one myself?

I just saw that Christian Maeder answered a similar question recently. I
tried his suggestion of using manyTill and bingo:

 {-# LANGUAGE NoMonomorphismRestriction #-}
 import Control.Applicative ((*),(*))
 import Text.Parsec
 block p = char '{' * p * char '}'
 parser = block (manyTill digit (char '}'))
 main = parseTest parser {123a}

gives

  parse error at (line 1, column 5):
  unexpected a
  expecting } or digit

So far so good. I wonder whether this parser is as efficient as the original
one. Also, this style is less modular, as I have to mention the terminator
in two places. Is there a non-greedy variant of 'many' so that modularity
gets restored and efficiency is not lost?

Cheers
Ben

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


[Haskell-cafe] Re: Re: A parsec question

2010-09-29 Thread Ben Franksen
Daniel Fischer wrote:
 On Wednesday 29 September 2010 19:10:22, Ben Franksen wrote:
 
  Note the last line mentions only '}'. I would rather like to see
 
expecting } or digit
 
  since the parser could very well accept another digit here.
 
 parsec2 did that, I don't know whether that change is intentional or
 accidental.

This looks more like a bug than a feature to me. I checked parsec-3.0.1 and
it behaves like parsec-2, i.e. behaves as I expected.

  (1) What is the reason for this behaviour?
  (2) Is there another combinator that behaves as I would like?
  (3) Otherwise, how do I write one myself?

 I just saw that Christian Maeder answered a similar question recently. I

 tried his suggestion of using manyTill and bingo:
  {-# LANGUAGE NoMonomorphismRestriction #-}
  import Control.Applicative ((*),(*))
  import Text.Parsec
  block p = char '{' * p * char '}'
  parser = block (manyTill digit (char '}'))
  main = parseTest parser {123a}
 You would need
 
 block (manyTill digit (lookAhead (char '}'))
 
 to replicate the behaviour of block (many digit).

Right, so it gets even more complicated.

 Is there a non-greedy variant of 'many' so
 that modularity gets restored and efficiency is not lost?

So many questions...

Cheers
Ben

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


[Haskell-cafe] Re: I still cannot seem to get a GUI working under Windows.

2010-09-29 Thread Ben Franksen
Andrew Coppin wrote:
   On 29/09/2010 07:33 PM, Steve Schafer wrote:
 The issue isn't that there aren't a lot of Windows developers who have
 an interest in Haskell+GUI development. The issue is that nearly every
 Windows developer who looks into Haskell+GUI says, This stuff sucks,
 and walks away, because they're interested in developing applications,
 not wrestling with GUI toolkits.
 
 Yep, that's the one.
 
 If you want to build a GUI application in Tcl, it's going to take a
 couple of minutes to throw together some Tk commands and you're done. 

Right.

 In
 Java, you'll have to write a mile of boilerplate, but there are wizzy
 tools that will write it for you. And I gather that if you've coding in
 C or C++ or C#, you can use VisualStudio to throw a complex GUI together
 in a couple of minutes.

Not so, at least with C++. I have used VS and C++, it is horrible. Never
again.

 How do you do that in Haskell? Well, you can either install and
 configure a complete Unix emulator and then compile wxHaskell from
 source (?!), or you can use Gtk2hs, which still requires you to manually
 install and configure GTK+ and compile the entire library from source
 code. And even then, your developed application will only run on Windows
 boxes that have GTK+ installed (i.e., none of them). 

Can you not statically link the gtk libraries?

 All of which is a
 far cry from install IDE, click some buttons, run the wizzard, job done.

I never found that this actually works. Yea, you can get *something* running
pretty fast, but as soon as you start to do stuff that is not 100% standard
off-the-shelf, you are screwed. *This* is when things become *really*
difficult. All this compiling and installing libraries stuff is harmless,
compared to the problems caused by stupidly broken APIs and crippled
languages.

Cheers
Ben

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


[Haskell-cafe] Re: Non-strict evaluation and concurrency (STM) : conflict?

2010-09-28 Thread Ben Franksen
Romain Demeyer wrote:
 Imagine this scenario : we have a set of threads (the workers) that have
 (each) a result to compute (purely). When finished, they try to save the
 result in an shared inbox, using STM. If the inbox is full, the thread
 waits until the inbox is empty.
 A specific thread is looking at the inbox: when it finds a value in the
 inbox, it prints the value on the screen (for example, it could be any
 processing based on the value) and then empty the inbox and wait that a
 remaining thread add a new value).

The technical reason this does not work as expected was given by others
(lazy evaluation, etc).

One additional remark: It seems you are using STM for parallelism, i.e. to
enhance performance, not for explicit concurrency. (Otherwise it would make
no difference to you which thread actually evaluates some expression). This
can be done much easier with the `par` combinator and friends
(http://hackage.haskell.org/package/parallel). The same caveat wrt lazyness
applies to this method, but your code will become a lot simpler: no need to
explicitly manage threads, pure functional (non-monadic) code.

Cheers
Ben

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


[Haskell-cafe] Re: Re: Re: Re: Do expression definition

2010-09-20 Thread Ben Franksen
wren ng thornton wrote:
 On 9/17/10 4:04 PM, Ben Franksen wrote:
 wren ng thornton wrote:
 Note that when compilers do CPS conversion, everything is
 converted into let-binding and continuations (i.e., longjump/goto with
 value passing). It's just dual to the everything-is-lambda world,
 nothing special.

 Do you know a good online introduction to CPS conversion that explains
 the kind of duality you mentioned?
 
 Not off hand. These papers[1] give a pretty good explanation of CPS
 conversion and the other stages of compilation, from the perspective of
 proving compiler correctness. But they don't say much about the duality
 aspect of it. For the duality side of things, Andrzej Filinski's masters
 thesis[2] is an excellent read; though it doesn't say much about
 compilation IIRC.

Thanks, I'll take a look.

 Basically the duality comes when decomposing a whole program. When we
 separate a term from its context, which part is in control? Control is
 just a perspective, so you could be outside the function looking in, or
 inside the function looking out. One person's push is another's pull.
 This is the same sort of thing as build/foldr vs unfoldr/destroy forms
 of list fusion: once we separate the F-algebra and F-coalgebra, which
 one should get the recursion?[3]

Ok, this gives me some vague intuition.

Cheers
Ben

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


[Haskell-cafe] Re: Re: Re: Do expression definition

2010-09-17 Thread Ben Franksen
wren ng thornton wrote:
 On 9/16/10 4:59 PM, Ben Franksen wrote:
 even though we always have

(\x -  e) y == let x = y in e

 which means that let can be translated to lambda, the converse is not
 true,
 
 Not exactly. Note that when compilers do CPS conversion, everything is
 converted into let-binding and continuations (i.e., longjump/goto with
 value passing). It's just dual to the everything-is-lambda world,
 nothing special.

I meant not possible as in by a source-to-source transformation in a
simple core-ML-like language (such as is used in most introductions to
HM-style type inference). If you translate to a language with mutable state
and/or built-in continuations then things are different, of course.

Do you know a good online introduction to CPS conversion that explains the
kind of duality you mentioned?

Cheers
Ben

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


[Haskell-cafe] Re: Re: Re: Full strict functor by abusing Haskell exceptions

2010-09-17 Thread Ben Franksen
Román González wrote:
 On Thu, Sep 16, 2010 at 2:12 PM, Ben Franksen
 ben.frank...@online.dewrote:
 
 Sjoerd Visscher wrote:
  But StrictIncl can't be a pointed functor, only endofunctors can be
  pointed.

 Could someone tell me what exactly a pointed functor is? I googled but
 did not find a definition.
 
 Here you will find what a Pointed Functor would be =
 http://haskell.org/sitewiki/images/8/85/TMR-Issue13.pdf
 
 Look up for the Typeclassopedia, start reading functor, next thing you
 will find is the Pointed typeclass

Thanks for the link. What I actually wanted was a mathematical definition,
though. From the TMR article I gather that a pointed functor could be
defined as an endo-functor

  F: C - C

together with a natural transformation

  pure: Id - F

where Id: C - C is the identity functor.

No additional laws (beside naturality of pure) are imposed.

Right so far?

Why is this an interesting structure?

Cheers
Ben

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


[Haskell-cafe] Re: Re: Do expression definition

2010-09-16 Thread Ben Franksen
wren ng thornton wrote:
 On 9/13/10 6:22 AM, Michael Lazarev wrote:
 Thanks for examples and pointers.

 Since I came from Lisp, it never occurred to me that let and lambda
 are different constructs in Haskell.
 I thought that
  let x = y in f
 is really
  (\x -  f) y
 It turns out that let is about declarations which are not the same as
 function applications above.
 
 Right. This is a common mistake for people coming from Lisp, Scheme, and
 other untyped lambda calculi. In the untyped world it's fine to conflate
 let and lambda, because they only differ in how they're typed (and if
 you have no types...).
 
 The difference is that, for let-bindings, once you've figured out a type
 of the variable being bound, then that type can be generalized. The
 exact process of generalization has some subtle details to watch out
 for, but suffice it to say that certain type variables are allowed to
 become universally quantified. Which means that you're allowed to use x
 at different types within f, provided all those different types are
 consistent with the generalized type.
 
 Whereas, lambda-bindings don't get generalized, and so they'll always be
 monomorphic (assuming Hindley--Milner inference without extensions like
 -XRankNTypes). This is necessary in order to catch numerous type errors,

Disclaimer: I am not a type system expert. Anyway, I thought the reason was
that type inference for rank-n types (n1) is undecidable. And therefore:

 though Haskell lets you override this behavior by giving an explicitly
 polymorphic type signature if you have -XRankNTypes enabled.

...so that polymorphic types for arguments don't have to be inferred.

I think it was in Milner's original paper where he tries to give some
intuition why let and lambda are treated differently: even though we always
have

  (\x - e) y == let x = y in e

which means that let can be translated to lambda, the converse is not true,
since a lambda expression can appear in contexts other than (as the left
hand side of) an application. Thus, let is syntactically more restrictive
than lambda, which means we can be more liberal when typing it. In
principle, the type-checker *could* be extended to infer polymorphic types
for those lambda-bound variables where the lambda expression immediately
gets applied to some other expression. In practice this would be of little
use as these are exactly the situations where a let can (and should!) be
used instead of a lambda.

Cheers
Ben

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


[Haskell-cafe] Re: Re: Full strict functor by abusing Haskell exceptions

2010-09-16 Thread Ben Franksen
Sjoerd Visscher wrote:
 But StrictIncl can't be a pointed functor, only endofunctors can be
 pointed.

Could someone tell me what exactly a pointed functor is? I googled but did
not find a definition.

Thanks
Ben

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


[Haskell-cafe] Haskell for control system [was: [reactive] A pong and integrate]

2010-05-19 Thread Ben Franksen
David Leimbach wrote:
 I find it's often the most practical chapter that I hit a lot during
 writes and changes to my server process I have in Haskell in our control
 system code :-)

Are you actually saying that you use Haskell for a control system server?
Thta would be very interesting to me.

Could you tell what kind of control system?

Cheers
Ben

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


[Haskell-cafe] Re: What do _you_ want to see in FGL?

2010-05-17 Thread Ben Franksen
Neil Brown wrote:
 Primarily I want to see in FGL: documentation, documentation and more
 documentation.  

+1

Cheers
Ben

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


[Haskell-cafe] Re: darcs 2.4 release candidate 2

2010-02-21 Thread Ben Franksen
And here are the numbers for record -lam:

b...@sarun[1]: .../rtems/rtems-4.9.0  darcs --version
2.3.1 (release)
b...@sarun[1]: .../rtems/rtems-4.9.0  time darcs record -lam'import release
4.9.0'
Finished recording patch 'import release 4.9.0'
darcs record -lam'import release 4.9.0'  143,33s user 6,57s system 69% cpu
3:34,22 total

vs.

b...@sarun[1]: .../rtems/rtems-4.9.0  /home/ben/.cabal/bin/darcs --version
2.3.99.2 (release candidate 2)
b...@sarun[1]: .../rtems/rtems-4.9.0  time /home/ben/.cabal/bin/darcs
record -lam'import release 4.9.0'
withSignalsHandled: Interrupted!

/home/ben/.cabal/bin/darcs record -lam'import release 4.9.0'  1549,45s user
11,81s system 94% cpu 27:40,50 total

(killed by me)

Re Petr Rockai:

No this isn't critical for us at the moment, so I don't need a workaround. I
still think regressions of such a scale should be considered a bug.

Cheers
Ben

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


[Haskell-cafe] Re: darcs 2.4 release candidate 2

2010-02-21 Thread Ben Franksen
Ben Franksen wrote:
 The situation with record is similar.
 
 I admit that the huge RTEMS tree with over 7000 changes between the two
 releases is challenging. However, earlier releases can do it (though it
 takes long, much longer than with, say, mercurial).

Just for comparison, here are the numbers for mercurial:

b...@sarun[1]: .../rtems/rtems-4.9.0  hg --version
Mercurial Distributed SCM (version 0.9.5)
b...@sarun[1]: .../rtems/rtems-4.9.0  hg log
changeset:   0:8b3cbc67b25f
user:b...@sarun
date:Sun Feb 21 21:29:10 2010 +0100
summary: import release 4.8.1

b...@sarun[1]: .../rtems/rtems-4.9.0  time (hg addremove  hg
commit -m'import release 4.9.0')
# ... long output elided ...
(; hg addremove  hg commit -m'import release 4.9.0'; )  9,20s user 1,15s
system 92% cpu 11,181 total

Cheers
Ben

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


[Haskell-cafe] Re: Re[2]: Threading and FFI

2010-02-21 Thread Ben Franksen
Yves Parès wrote:
 Just one last remark: when I moved all my OpenGL calls from the main
 thread to an unbound thread. I thought it'd not work -- because I assumed
 I would have to launch it in a bound thread -- and however it went
 right...

You were just lucky the RTS accidentally delegated all your OpenGL calls to
the same OS thread. It might turn out bad next time you run the program, or
on another machine, or after adding more threads. Been there...

Cheers
Ben

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


[Haskell-cafe] Re: darcs 2.4 release candidate 2

2010-02-19 Thread Ben Franksen
Hi All

This rc release is still notably slower on some operations than older
releases. My test case is a large project named RTEMS (a real-time OS),
that we wish to import into darcs (at work) to better track our own
additions and modifications.

To repeat, download two adjacent releases, e.g.

wget http://www.rtems.org/ftp/pub/rtems/4.9.0/rtems-4.8.1.tar.bz2
wget http://www.rtems.org/ftp/pub/rtems/4.9.0/rtems-4.9.0.tar.bz2

unpack, initialize darcs and record in the 4.8.1 tree, then copy _darcs to
the 4.9.0 version and try to record -l or whatsnew -l.

I have two darcs versions installed:

b...@sarun[1]: .../rtems/rtems-4.9.0  /usr/local/bin/darcs --version
2.2.1 (release)
b...@sarun[1]: .../rtems/rtems-4.9.0  darcs --version
2.3.99.2 (release candidate 2)

b...@sarun[1]: .../rtems/rtems-4.9.0  time /usr/local/bin/darcs whatsnew -l
# ...long output elided...
/usr/local/bin/darcs whatsnew -l  381,45s user 6,34s system 92% cpu 7:00,90
total

whereas with 2.3.99.2 it goes

b...@sarun[1]: .../rtems/rtems-4.9.0  time darcs whatsnew -l

Well, it is still running after 18 minutes! Top reports something like

  PID USER  PR  NI  VIRT  RES  SHR S %CPU %MEMTIME+  COMMAND   
 5702 ben   20   0 1112m 933m 3628 R 92.2 28.3  18:26.08 darcs  

One point to notice is that 2.3.99.2 has not yet reported any progress,
whereas 2.2.1 almost immediately starts reporting something about pristine
trees followed by the usual number/number stuff; and the numbers
continually rise.

The situation with record is similar.

I admit that the huge RTEMS tree with over 7000 changes between the two
releases is challenging. However, earlier releases can do it (though it
takes long, much longer than with, say, mercurial). At work I tried it with
2.3.1 (on a fast 4 processor machine) and it recorded all the changes in
about one minute.

I think this regression should be fixed before 2.4 is released.

Cheers
Ben

Reinier Lamers wrote:
 The darcs team would like to announce the immediate availability of darcs
 2.4 release candidate 2. darcs 2.4 will contain many improvements and
 bugfixes compared to darcs 2.3.1. Highlights are the faster operation of
 record, revert and related commands, and the experimental interactive hunk
 editing. This beta is your chance to test-drive these improvements and
 make darcs even better.

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


[Haskell-cafe] Re: darcs 2.4 release candidate 2

2010-02-19 Thread Ben Franksen
Ben Franksen wrote:
 b...@sarun[1]: .../rtems/rtems-4.9.0  time darcs whatsnew -l
 
 Well, it is still running after 18 minutes! Top reports something like
 
   PID USER  PR  NI  VIRT  RES  SHR S %CPU %MEMTIME+  COMMAND
  5702 ben   20   0 1112m 933m 3628 R 92.2 28.3  18:26.08 darcs

FYI, I finally killed it:

b...@sarun[1]: .../rtems/rtems-4.9.0  time darcs whatsnew -l 
withSignalsHandled: Interrupted!

darcs whatsnew -l  2307,92s user 17,33s system 88% cpu 43:49,89 total

Cheers
Ben

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


[Haskell-cafe] Re: darcs 2.4 release candidate 2

2010-02-19 Thread Ben Franksen
Ben Franksen wrote:
 b...@sarun[1]: .../rtems/rtems-4.9.0  /usr/local/bin/darcs --version
 2.2.1 (release)
 b...@sarun[1]: .../rtems/rtems-4.9.0  time /usr/local/bin/darcs whatsnew
 -l
 # ...long output elided...
 /usr/local/bin/darcs whatsnew -l  381,45s user 6,34s system 92% cpu
 7:00,90 total

Just installed 2.3.1 and tried the same:

b...@sarun[1]: .../rtems/rtems-4.9.0  darcs --version
2.3.1 (release)
b...@sarun[1]: .../rtems/rtems-4.9.0  time darcs whatsnew -l
# ...long output elided...
darcs whatsnew -l  239,41s user 4,74s system 85% cpu 4:44,33 total

Note the differences in user and system time. Darcs-2.3.1 is indeed faster
than 2.2.1 (but you already knew that).

Cheers
Ben

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


[Haskell-cafe] Re: Re[2]: Threading and FFI

2010-02-18 Thread Ben Franksen
Yves Parès wrote:
 But there are two things that remain obscure:
 First, there is my situation: int the main thread, I call to some C
 functions binded through FFI. All of them are marked 'unsafe', except one,
 which is internally supposed to make pauses with 'usleep'.
 I then execute in another haskell thread (with forkIO) some pure haskell
 actions.
 I then compile with the threaded RTS, and let at run the default behaviour
 which is to use one core.
 
 Question 1) What happens to the unsafe C functions? I that simply that
 the threaded RTS is unable to prevent them from blocking haskell threads
 (which in my case is a problem only for the function which pauses, since
 other C calls are fast)?

Yes. unsafe FFI calls are executed just as a Haskell function. Thta means
the underlying OS thread that happens to run the Haskell thread which
contains the unsafe FFI call will block and thus all other activity that is
scheduled to be run by this OS thread.

Note: With unbound threads (those created by forkIO) it might happen at any
time that the RTS choses to reschedule your Haskell thread onto another OS
thread.

 Or they could provoke a hazardous issue, so I
 have to mark all the C functions as safe (which will be much slower)
 because ?

You can leave them unsafe if you are sure that

1) they do not call (back) any function in your program
2) they do not block (or not long enough that it bothers you)

Otherwise they are no less safe that the safe calls. If (1) is not
fulfilled bad things might (that is, probably will) happen. Thus, if you
are not sure, chose safe.

 Question 2) In the Control.Concurrent documentation, I understood that
 forkIO creates unbound threads whereas forkOS creates bound threads, but
 what is not very clear is: when does GHC threaded runtime launches as
 bound instead of unbound if this one has been started with forkIO? 

Never. Bound thread are ONLY needed if you (that is, some foreign functions
you use) rely on thread-local storage.

 When it
 detects the thread calls to a C function? When it detects it calls to a
 safe C function (*)? When it detects another thread calls to a (safe) C
 function (which is my case)?

In no case will forkIO create a bounded thread. Period. Bound threads are
created with forkOS.

If runtime is threaded and FFI call is marked safe and Haskell thread is
unbound, then calls to such a function will be executed from SOME extra OS
thread that is managed completely behind the scenes.

 (*) according to documentation it would be this case. However as I said my
 C calls are done in the MAIN thread. 

This doesn't make a difference. Main thread in Haskell is treated as any
other thread (except with regard to program termination; imagine it has an
invisible exit() call at the end).

 The other thread just executes casual
 haskell operations, however it is not blocked, which makes me think that
 even if I launch it with forkIO, it is launched as an bound thread.

No. Bound thread means something different. It means that Haskell (green)
thread is BOUND (fixed) to an OS thread. This is very bad for performance
and only serves one purpose: to enable interoperation with broken C
libraries (i.e. those which use thread local storage, a bad, bad, bad thing
IMVHO).

Cheers
Ben

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


[Haskell-cafe] Re: Threading and FFI

2010-02-17 Thread Ben Franksen
Yves Parès wrote:
 I've also discovered something interesting: when I link with the
 'threaded' runtime, but let the program use only one core (with '+RTS
 -N1'), the problem disappears. How comes?
 The whole thing remains a mystery, because I think what I'm trying to do
 is quite common...
 
 
 Yves Parès wrote:
 
 There is a minimal code which produces this issue:
  http://old.nabble.com/file/p27613138/func.c func.c
  http://old.nabble.com/file/p27613138/main.hs main.hs
 
 
 Yves Parès wrote:
 
 Well I tried both 'unsafe' and 'safe', and actually I saw no
 difference...
 Even with 'safe', I see a huge difference between calling a C function
 which sleeps and another which doesn't. When there is a sleep, the other
 thread is really slower (it just prints numbers, and I look at which
 pace they're displayed).

This is to be expected. From the docs
(http://www.haskell.org/ghc/docs/latest/html/libraries/base-4.2.0.0/Control-Concurrent.html#10):

The downside of having lightweight threads is that only one can run at a
time, so if one thread blocks in a foreign call, for example, the other
threads cannot continue. The GHC runtime works around this by making use of
full OS threads where necessary. When the program is built with
the -threaded option (to link against the multithreaded version of the
runtime), a thread making a safe foreign call will not block the other
threads in the system; another OS thread will take over running Haskell
threads until the original call returns. The runtime maintains a pool of
these worker threads so that multiple Haskell threads can be involved in
external calls simultaneously.

IIRC, with -threaded, the RTS spawns a separate OS thread for 'safe' foreign
calls _in addition_ to the OS threads used for Haskell code (the number of
which you give with the +RTS -Nn option).

Cheers
Ben

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


[Haskell-cafe] Re: Pattern matching, and bugs

2009-12-21 Thread Ben Franksen
Jochem Berndsen wrote:
 András Mocsáry wrote:
 *My concern*
 is about predictable failure of sw written in Haskell.
 To illustrate it let's see a Haskell pattern matching example:
 
 And in Haskell pattern matching:
 
 switch 1 =  Unchecked
 
 switch 2 =  Checked
 
 switch 3 =  Unknown
 
 
 Let's say, these are clearly defined states of some objects.
 Then let's say something unexpected happens: x gets something else than 0
 1 2.
 Now we have a problem, which is most generally fixed in these ways:
 
 switch 1 =  Unchecked
 
 switch 2 =  Checked
 
 switch 3 =  Unknown
 
 switch x =  Nothing
 
 These general ways really avoid this particular crash, but does something
 real bad to the code in my opinion.
 
 Agreed. The real cause of the problem is that the programmer didn't
 prove that x is in {1,2,3} when calling switch.

I agree with most of what you say, just some clarification:

Well I'd say it depends on the function's specification. If it is specified
with 'precondition: parameter n must be one of 1,2,3', then yes. If it says
it works for all integers, then it is the function's fault. Such things
must be documented.

 Below are some cases x can go wrong:
 *1. The bad data we got as 'x', could have came from an another part of
 our very program, which is the REAL CAUSE of the crash, but we
 successfully hide it.*
 *
 Which makes it harder to fix later, and thus eventually means the death
 of the software product. Eventually someone has to rewrite it.
 Which is economically bad for the company, since rewriting implies
 increased costs.
 
 Yes.
 
 2. The bad data we got as 'x', could also could have come form a real
 word object,
 we have underestimated, or which changed in the meantime.
 
 You should not assume that your input is correct in fault-tolerant
 programs.
 
 3. This 'x' could have been corrupted over a network, or by 'mingling' or
 by other faulty software or something.
 
 Unlikely. There is nothing you can do about this, though.

I'd say this is exactly as point 2. Data you get over the network or from
other programs or from the file system should *never* be trusted. Data
integrity must be checked and bad data rejected.

 Point 1:
 If we allow ourself such general bugfixes, we eventually kill the ability
 of the project to 'evolve'.
 
 Point 2:
 Programmers eventually take up such 'arguably bad' habits, thus making
 harder to find such bugs.
 
 Thus it would be wiser to tell my people to never write Default cases,
 and such general pattern matching cases.

It depends, really. See above. Without a spec for the function in question
this cannot be decided.

 It is a better idea to use the type system to prevent this kind of bugs.
 In this particular case, it's better to try to have a datatype like
 data X = One | Two | Three

Yes. But there may be a place where you have to *generate* such data, e.g.
if you receive a byte from the network or user input or file, you need to
convert this to your type; and this is the point where bad data must be
cought.

As I said above, I think we basically agree, just wanted to stress the role
of the (hopefully documented) specification that should always explicitly
state any preconditions. It is then clear which side (caller or callee) is
to blame.

Cheers
Ben

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


[Haskell-cafe] Re: Re: Allowing hyphens in identifiers

2009-12-16 Thread Ben Franksen
Daniel Fischer wrote:
 Am Montag 14 Dezember 2009 01:44:16 schrieb Richard O'Keefe:
 Where is it written that aesthetic judgements are _entirely_ a
 matter of personal preference?
 
 I think you could find that written in many texts on aesthetic relativism.
 Doesn't matter, though.
 Of course, one's personal preferences aren't developed in a vacuum, they
 are strongly influenced by genes and society. So a lot of preferences are
 shared within a culture and even across cultures and aesthetic judgments
 aren't entirely *individual*. Nevertheless, I'm convinced that there is no
 Platonic idea Beauty (or Ugliness) and that if A says that van Gogh's
 Sunflowers is a beautiful picture while B says it's ugly, it's not the
 case that one is objectively right, the other wrong. Both are judgments
 based on their respective preferences and nothing else (unless: lying,
 acting, succumbing to social pressure, other reasons to not express one's
 actual opinion).

According to Robert Pirsig (Zen and the art of motorcycle maintenance) it
is neither objective nor subjective. It is (a facette of) something much
more fundamental than either subjects or objects, this something (a
difference in quality) being the reason why perception happens at all and
thus why a 'subject' becomes aware of an 'object' in the first place.

Cheers
Ben

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


[Haskell-cafe] Re: fgetc and fputc equivalents

2009-12-09 Thread Ben Franksen
John D. Earle wrote:
 Although much work has apparently gone into providing support for
 manipulation binary data I was unable to uncover a Haskell equivalent of
 the C fgetc and fputc functions. The Haskell equivalents work with Unicode
 character streams, not bytes words etcetera. I did find a library for
 handling arrays of bytes and such, but I did not find it to be convenient
 for the application I have in mind. I resolved myself to emitted Unicode
 0s and 1s that are later converted to binary 0s and 1s by means of a C
 program. Is this functionality missing in Haskell? or did I miss
 something?

It is not in the Standard, but (at least) GHC has hPutBuf and hGetBuf (see
http://haskell.org/ghc/docs/latest/html/libraries/base/System-IO.html).

Cheers
Ben

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


[Haskell-cafe] Re: ANN: hakyll-0.1

2009-12-08 Thread Ben Franksen
Ketil Malde wrote:
 minh thu not...@gmail.com writes:
 Why should your code be licensed under GPL?
 
 I think your code is covered by whatever license you wish.
 
 An aggregate work, on the other hand, would need to be covered by the
 GPL, and all source code would have to be available under GPL terms.  So
 if you distribute your code linked to or incorporating the GPL library,
 the whole must conform to the GPL license (source availability and
 redistributatbility, etc).
 
 Your contributions could still be licensed under a different license
 (e.g. BSD), as long as the licensing doesn't prevent somebody else to
 pick it up and relicense it under GPL.
 
 At least, that's how I understand things.

Right. So hakyll is absolutely fine with a BSD3 license, AFAICS.

Cheers
Ben

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


[Haskell-cafe] Re: The Transient monad

2009-12-08 Thread Ben Franksen
+1

Alberto G. Corona  wrote:
 Hi haskell cafe:
 
 concerning Stable Names
 

http://www.haskell.org/ghc/docs/6.10.4/html/libraries/base/System-Mem-StableName.html
 
 
 makeStableName :: a - IO (StableName a)
 
 I Did not test fully my proposal, and I´m thinking aloud, Just to inpire
 others and fish some ideas;
 
 The IO in makeStableName  suggest more side effects than makeStableName
 really do. But still the call isn't pure.
 
 For calls such are makeStableName that gives a different result the FIRST
 time they are called but return the same result every time in the same
 session,  I suggest to use a Transient monad:
 
 
 makeStableName :: a - Transient (StableName a)
 
 The key here is to maintain the programmer aware that it is not pure, but
 there are no IO and that  the results have no meaning from session to
 session.
 
 Instance Monad Transient where
  Transient x ↠ f =  f  x
  return x = Transient x
 
 We can Transient`ize IO calls by means of an implicit memoization:
 
 liftT:: IO a - Transient a
 liftT=  whatever memoization code
 liftT2=
 liftT3=
 
 Memorization then is embedded in the monad transformation
 This may be more elegant than  IO plus unsafePerformIO and is more
 informative for the programmer. The transition form IO to pure can be done
 in two steps, see below
 
   Instead of unsafePerformIO,  we can use:
 
 unsafePurifyTransient :: Transient a - a
 unsafePurifyTransient  (Transient x) = x
 
 for the inherently transient calls
 
 A safer version of unsafePerformIO using implicit memoization could be:
 unsafePerformIOT :: IO a - a
 unsafePerformIOT = unsafePurifyTransient  .  liftT
 
 unsafePerformIOT guatantee that it returns the same value in the same
 session.
 
 
 
 
 2009/12/8 Vladimir Zlatanov vl...@dikini.net
 
 jeanchristophe.min...@gmail.com wrote:
  I think lisp like symbols could be quite useful in the context of
 embedded
  DSL to create ... well... symbols that can be interpreted as variables
  in that DSL.

 Well for such use-case you could use either stable names, or recode
 them into a state monad- you will get either a global i.e. lisp like
 unique symbols, or their equivalent within a state context. Or some
 variation of the code posted previously in this thread.

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


[Haskell-cafe] Re: New Hackage category: Error Handling

2009-12-07 Thread Ben Franksen
Michael Snoyman wrote:
 On Mon, Dec 7, 2009 at 9:53 PM, Henning Thielemann 
 lemm...@henning-thielemann.de wrote:
 On Mon, 7 Dec 2009, Michael Snoyman wrote:
 I also think that in an earlier mail I answered, that errors can leave
 you with corrupt data, say invalid file handles, memory pointers, or data
 structures that violate invariants. You won't like to close files from
 invalid file handles and free memory from corrupt pointers or run into
 infinite loops by traversing the corrupt data structures. That's the
 reason why it is better to stop execution of the program and hand over
 control to the next higher level, say the shell or the web browser, that
 can free resources safely.

 Firstly: I'm really referring exclusively to non-FFI Haskell programs, to
 which most of the issues you mention don't really apply. Nonetheless, I
 think that for a language with exceptions, it still makes sense to use the
 exceptions in these cases.
 
 In all these cases, I think the correct thing is to have a specific
 exception type that is thrown that signals that it is such an
 unrecoverable error. This allows the programmer to do *whatever* they
 want. Perhaps they want to save some other data to a file before exiting?
 Perhaps they want to spawn a process to send in a bug report? Who knows.
 It doesn't matter. The point is, the user *might* want to do something,
 and exceptions let them do it if they wish, or they can completely ignore
 that specific exception type and let the program crash anyway.

Michael, Henning

There are two meanings to the word 'exception' in this context; both of you
tend to conflate these different meanings. One meaning is about a
*mechanism* for non-local control flow; the other is about certain classes
of un-desired program conditions.

Michael, you are above arguing that it is ok to use the same /mechanism/ to
signal errors and exceptions. That is ok with me. There are certainly good
use cases, you have presented a few. However, that does not mean it
is 'silly' or 'unnecessary' to distinguish between program(-mer) errors and
other kinds of expected exceptional conditions in general, as you claimed
in a previous message.

I agree with Henning insofar as I think it is important to make the
*conceptual* distinction -- regardless of whether we use the same mechanism
to signal (and, perhaps, after serious consideration, handle) them.

So, maybe it would help if we could agree to use different terms for those
two meanings of the word 'exception'. I think 'exception' is too strongly
associated with the non-local control flow mechanism to introduce a new
word for it.

Henning, what about calling an undesired  but expected condition a 'failure'
instead of an exception, so we could reserve this word for the language
mechanism? Calling something a 'failure' in this sense (i.e. in contrast
to 'error') would always include some judgement, as it needs to take the
different program levels into account.

Cheers
Ben

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


[Haskell-cafe] Re: Re: ANNOUNCE: Blueprint 0.1 -- PREVIEW

2009-12-06 Thread Ben Franksen
Gregory Crosswhite wrote:
 On Dec 4, 2009, at 11:02 AM, Ben Franksen wrote:
 Gregory Crosswhite wrote:
 I have posted Blueprint to Hackage so that people can see what I have
 done and possibly play with it.
 Very interesting, this. However, I could not build it. I get [...]
 At the moment you need to execute the setup script manually:
 
 runhaskell Setup.hs bootstrap
 ./Setup configure
 ./Setup build +RTS -N4 -RTS
 ./Setup install
 
 (The +RTS -N4 -RTS part is optional;  it just tells Setup to use up to 4
 threads to do building in parallel where possible.)

Thanks. I recommend adding a small readme.txt explaining stuff like that.

 Anyway, thank you for checking out Blueprint!  At this point it might be
 better to pull the sources directly from github (the Home Page link)

Will do.

 since I have made many improvements since that release (though I haven't
 fixed the cabal install problem yet).  And I do plan on thoroughly
 polishing and documenting Blueprint one of these days.  :-)

Thanks  Cheers
Ben

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


[Haskell-cafe] Re: New Hackage category: Error Handling

2009-12-06 Thread Ben Franksen
Michael Snoyman wrote:
 On Sun, Dec 6, 2009 at 12:55 AM, Henning Thielemann 
 lemm...@henning-thielemann.de wrote:
 On Sun, 6 Dec 2009, Michael Snoyman wrote:
  I think there are plenty of examples like web servers. A text editor
  with
 plugins? I
 don't want to lose three hours worth of work just because some plugin
 wasn't written
 correctly. For many classes of programs, the distinction between error
 and exception is
 not only blurred, it's fully irrelevant. Harping on people every time
 they use error in
 the wrong sense seems unhelpful.

 Hope my commenting on this subject doesn't become my own form of
 *pedantry*.

 In an earlier thread I have explained that one can consider a software
 architecture as divided into levels. What is an error in one level (text
 editor plugin, web server thread, operating system process) is an
 exception in the next higher level (text editor, web server, shell
 respectively). This doesn't reduce the importance to distinguish between
 errors and exceptions within one level. All approaches so far that I have
 seen in Haskell just mix exceptions and errors in an arbitrary way.

 I think we can all appreciate why it would be a bad thing is we treat
 exceptions as errors. For example, I don't want my program to crash on a
 file not found.
 
 On the other hand, what's so bad about treating errors as exceptions? If
 instead of the program crashing on an array-out-of-bound or pattern-match
 it throws an exception which can be caught, so what?

The error gets hidden instead of fixed?

Cheers
Ben

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


[Haskell-cafe] Re: ANNOUNCE: Blueprint 0.1 -- PREVIEW

2009-12-04 Thread Ben Franksen
Gregory Crosswhite wrote:
 I have posted Blueprint to Hackage so that people can see what I have done
 and possibly play with it.

Very interesting, this. However, I could not build it. I get

b...@sarun[2]: ~/tmp  cabal install blueprint
Resolving dependencies...
cabal: There is no installed version of base

Needless to say this is wrong:

b...@sarun[2]: ~/tmp  ghc-pkg list base  
/usr/local/lib/ghc-6.10.4/./package.conf:
base-3.0.3.1, base-4.1.0.0
/home/ben/.ghc/i386-linux-6.10.4/package.conf:

This has not happened to me with any other packages from hackage.

Cheers
Ben

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


[Haskell-cafe] Re: implementing recursive let

2009-11-28 Thread Ben Franksen
Hi Ryan,

first, to get this out of the way, you wrote:

 Also, your definition of Function seems to have problems with
 scoping; unless you intended to make a dynamically scoped language,

No, absolutely not! In fact, the whole exercise has been born out of
frustration with certain ad-hoc extensions to an already evil
domain-specific (macro substitution) language -- the extension being to add
dynamically scoped local variables; and the basic evilness to allow
substitution to occur in variable names (similar to make) as a poor man's
substitute for functional abstraction. This makes for extremely cryptic
programs whose result is very hard to predict. My aim is to show that there
is a better way.

 (Value - Eval Value) seems very likely to get evaluated in the
 context it is called in.

Fortunately, this is not the case, as I explicitly capture the evironment at
the definition site, ignoring the one at the call site:

eval (Lam parm body) = do
  env - ask
  return $ Function (\val - local (\_ - M.insert parm val env) (eval
body))

Now to the interesting part:

 Now the question is, what do you want to happen when given a malformed
 let expression?  I am pretty sure that you need more complicated
 flow-control here in order to get the result.  I believe you are on
 the right track with continuations.

My problem is that I have never really become comfortable with
continuations; just couldn't wrap my head around all the nested lambdas
involved. Is there a nice tutorial (preferably one of those functional
perls, I love them) that explains how CPS actually works to produce those
wonderful effects, like jumping around, fixing evaluation order and
whatnot? I tried to follow the recent explanations by Jacques Carette and
Oleg Kiselyov on this list but I must admit that I understood nought.

 Here is a question; what should these expressions do?
 let y = x; x = 1 in y
 let y = x x; x = 1 in x
 let x = x in x
 
 The last one is quite telling; I can see three possible behaviors here:
 
 1) Loop
 2) return some simple undefined value
 3) Give an error blackhole
 
 I will note that behavior (1) seems very difficult to achieve with
 your current monad stack; eval (Var x) terminates simply by looking up
 the value in the environment.
 
 I think you need to think hard about evaluation order and decide what
 you really want to happen.  The simplest answer, if you want to stay
 with strict evaluation, is probably to only allow recursive *function*
 definitions.  This way you can delay fully initializing the
 environment until after you've finished evaluating the functions
 themselves.

Thanks, Ryan. This got me thinking about the right questions. I found out
that what I really want is a mixture of lazy and strict evaluation: I want
variable definitions in a let expression to be lazy, but application of
functions to be strict. (I don't know whether this kind of mixture has been
used before.) Thus

 let y = x; x = 1 in y

should evaluate to  1 . I want the meaning of declarations on the same level
to be independent of their relative order. This is a purely functional
language, after all, so why should it matter in which order things are
defined?

 let y = x x; x = 1 in x

Here  y  is never used, so again this evaluates to  1 .

 let x = x in x

This should loop (or maybe better detected as a failure i.e. backhole), but
only if and when x is used, either in an application or as the final result
of the program. (In the former case it doesn't make a difference whether  x 
is used in function or in argument position.)

  ***

Thinking about how to make it _explicit_ in my code that application is
strict, whereas variables are lazy, I saw that this needs a change in the
type of environments. It used to be a map from variable names to _values_,
i.e. evaluated expressions. If I change this to a map from variable names
to either thunks (i.e. unevaluated expressions) or (evaluated) values, then
everything else falls smoothly into place; no need for mdo/mfix anymore,
thus no need for fiddling with ErrorT internals to convince it that
variable lookup always succeeds, and last not least all my examples behave
as I expect them to do (see attached code).

So, in a way I /have/ (finally) given up ;-) because variables are now
(internally) mutable cells: when a variable is demanded (e.g. by an
application) it gets mutated from thunk to value. Could as well revert to a
Reader monad and use STRefs for efficiency. (Or maybe I will finally try to
understand how to use continuations for stuff like this.)

I have learned (at least) this: The problem with using the host language's
lazyness for implementing lazyness in the defined language is that the
former is not directly observable. Thus it works fine as long as you buy
the whole package, i.e. either make sure that there can't be a failure, or
else use not only the built-in evaluation order but also the built-in
failure mode: error, pattern match failure, i.e. exceptions that can occur
in 

[Haskell-cafe] Re: Re: implementing recursive let

2009-11-27 Thread Ben Franksen
Ben Franksen wrote:
 Ok, it seems I have a version that does what I want. It is not very
 elegant, I have to manually wrap/unwrap the ErrorT stuff just for the Val
 case, but at least it seems to work. Here it goes:
 
 eval (Var x) = Eval $ ErrorT $ do
   env - get
   v - case M.lookup x env of
 Just v - return v
 Nothing - do
   warning (reference to undefined variable  ++ show x)
   let v = Data 
   modify (M.insert x v)
   return v
   return (Right v)
 
 warning s = tell $ [Warning:  ++ s]

While this works for simple var=constant declarations, it breaks down again
as soon as I add lambdas and application. Same symptoms as before: eval
loops; and it works again if I remove the ErrorT (but then I get a pattern
match failure if I apply a non-function which is of course what I wanted to
avoid with the ErrorT).

This is maddening! There must be some way to get mutual recursion to work
while still allowing for clean handling of failure. What galls me the most
is that it is so unpredictable whether the program will terminate with a
given input or not.

(The code is attached.)

Cheers
Ben
{-# LANGUAGE RecursiveDo, GeneralizedNewtypeDeriving,
TypeSynonymInstances, MultiParamTypeClasses #-}
import Control.Monad
import Control.Monad.State
import Control.Monad.Error
import Control.Monad.Writer
import Control.Monad.Reader
import Control.Monad.Fix
import qualified Data.Map as M

data Expr = Let [(String, Expr)] Expr | Const Int | Var String
  | Lam String Expr | App Expr Expr

data Value = Data String | Function (Value - Eval Value)

instance Show Value where
show (Data s) = s

type Env = M.Map String Value

eval :: Expr - Eval Value
eval (Const n) = return (Data (show n))
eval (Var x) = Eval $ noError $ do
  env - get
  case M.lookup x env of
Just v - return v
Nothing - do
  warning (reference to undefined variable  ++ show x)
  let v = Data 
  modify (M.insert x v)
  return v
eval (Let decls body) = mdo
  let (names,exprs) = unzip decls
  updateEnv env = foldr (uncurry M.insert) env $ zip names values
  (values,result) - local updateEnv $ liftM2 (,) (mapM eval exprs) (eval body)
  return result
eval (Lam parm body) = do
  env - ask
  return $ Function (\val - local (\_ - M.insert parm val env) (eval body))
eval (App fun arg) = do
  f - eval fun
  x - eval arg -- call-by-value, so evaluate the arg first
  case f of
Function f - f x

warning s = tell $ [Warning:  ++ s]

newtype Eval a = Eval {
unEval :: ErrorT String (StateT Env (Writer [String])) a
  } deriving (
Monad, MonadFix, MonadWriter [String],
MonadState Env, MonadError String
  )

runEval :: Eval Value - Either String Value
runEval = fst . runWriter . flip evalStateT M.empty . runErrorT . unEval

evaluate = runEval . eval

instance MonadReader Env Eval where
  ask = get
  local tr act = do
s - get
modify tr
r - act
put s
return r

noError ::  (Monad m, Error e) = ErrorT e m a - ErrorT e m a
noError m = ErrorT $ do
  ~(Right r) - runErrorT m
  return (Right r)

-- examples
good1 = Let [(x, Const 1)] (Var x)
good2 = Let [(y, Var x),(x, Const 1)] (Var y)
bad1 = Let [(x, Const 1)] (Var y)
letf = Let [(f,Lam x (Var x))] (App (Var f) (Const 1))
badapp = Let [(f,Lam x (Var x))] (App (Const 1) (Var f))

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


[Haskell-cafe] Re: Re: Re: implementing recursive let

2009-11-27 Thread Ben Franksen
Ryan Ingram wrote:
 The problem is that ErrorT makes any argument to mdo *much* more
 strict, and therefore much more likely to loop.
 
 This is because each action needs to know whether the previous action
 was successful before it can continue.

Thanks, you are confirming what I suspected. I just wasn't sure that I
didn't do something stupid that could easily be fixed.

 Notice that when you got it to work, you *always* return Right v;
 that is, you never actually have an error.

Yes, exactly. It helps in the simplest cases, but with function definitions
even this is not enough.

 If you want to avoid introducing bottoms into your code, I would avoid
 using fix/mdo except in cases where you can prove that the code is
 non-strict.  You keep running into cases where your code is more
 strict than you would like which is introducing the bottoms.
 
 To understand this better, consider the following function:
 
 fixEither :: (a - Either e a) - Either e a
 fixEither f = x where
 x = f a
 (Right a) = x
 
 Here, f *cannot* attempt to do anything with its argument until it is
 absolutely known that f is returning a Right value.

Interesting. I'll have to think about this one.

 Perhaps there is a different way to write this interpreter that avoids
 needing to tie the knot so tightly?  Can you split recursive-let into
 two stages, one where you construct the environment with dummy
 variables and a second where you populate them with the results of
 their evaluations?  You might need some sort of mutable thunk that you
 can store in the environment, which makes sense to me; in GHC Core,
 let means allocate a thunk on the heap.

Yea, this is how I would do it in an imperative language. I thought I could
avoid mtuable cells by exploiting lazyness. I am not yet ready to give up,
however. One thing I want to try is whether I can come up with a variation
of ErrorT that is less strict. Another idea I just had is that maybe
continuations might help, as they provide a possibility to 'jump' out of a
calculation.

Chers
Ben

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


[Haskell-cafe] Re: implementing recursive let

2009-11-26 Thread Ben Franksen
Ben Franksen wrote:
 My problem is that I still don't understand why this is so! I know of
 course that pattern matching is strict, but I thought this should be ok
 here, since I evaluate the declarations _before_ the body, so when
 evaluation of the body demands the variable, it will be defined.

Another data point: It /has/ something to do with ErrorT. If I remove the
ErrorT from the monad stack it works, even with the pattern matching in the
variable lookup:

newtype Eval a = Eval {
unEval :: {- ErrorT String -} (StateT Env (Writer [String])) a
  } deriving (
Monad,
MonadFix,
MonadWriter [String], -- for warnings  other messages
MonadState Env{- ,
MonadError String -}
  )

runEval :: Eval Value - {- Either String -} Value
runEval = fst . runWriter . flip evalStateT M.empty . {- runErrorT . -}
unEval

*Main evaluate example 
1

I am still lost as to how to make this work with ErrorT.

Cheers
Ben

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


[Haskell-cafe] Re: Re: implementing recursive let

2009-11-26 Thread Ben Franksen
Derek Elkins wrote:
 On Wed, Nov 25, 2009 at 3:48 PM, Ben Franksen ben.frank...@online.de
 What am I missing?
 
 The problem is the liftM2 in the Let branch of eval.  You are
 executing the body while making the bindings, so you are trying to
 look up x while you are still trying to bind it.  One solution is to
 move the execution of the body after the binding as in:
 
 eval (Let decls body) = mdo
  let (names,exprs) = unzip decls
  updateEnv env = foldr (uncurry M.insert) env $ zip names values
  values - local updateEnv $ mapM eval exprs
  local updateEnv $ eval body

I already tried that :( It works for non-recursive expressions
like 'example', but not for recursive ones; not even non-recursive ones
that merely use a variable before it is defined like this one

 example2 = Let [(y, Var x),(x, Const 1)] (Var y)

which again makes eval loop. However, if I use your lazy version

 eval (Var x)   = gets (fromJust . M.lookup x)

_or_ remove the ErrorT from the monad stack (see my other message) eval does
not loop, even with mutually recursive definitions.

*some time later*

Ok, it seems I have a version that does what I want. It is not very elegant,
I have to manually wrap/unwrap the ErrorT stuff just for the Val case, but
at least it seems to work. Here it goes:

 eval (Var x) = Eval $ ErrorT $ do
   env - get
   v - case M.lookup x env of
 Just v - return v
 Nothing - do
   warning (reference to undefined variable  ++ show x)
   let v = Data 
   modify (M.insert x v)
   return v
   return (Right v)
 
 warning s = tell $ [Warning:  ++ s]

I suspect what is needed to avoid this is a combinator that convinces ErrorT
that a computation is really going to succeed, no matter what. Hmm, now
that I think about it this should be possible using catchError. I will
investigate.

Cheers
Ben

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


[Haskell-cafe] Re: implementing recursive let

2009-11-25 Thread Ben Franksen
Derek Elkins wrote:
 The following code works fine for me, so it seems you are missing some
 details that may help.
 [...snip code...]

Thank you! Indeed I did simplify the code when writing the message --
because I thought that those other bits could not possibly be at
fault... ;-)

*trying out many changes to my own code and yours*

Ok, I finally found it. What actually made the difference was the case for
variables:

Your version is

 eval (Var x)   = gets (fromJust . M.lookup x)

which is suitably lazy, whereas mine was (more or less)

 eval e@(Var name) = do
   env - ask
   case M.lookup name env of
 Nothing  - do
   -- undefined variable reference
   warning (reference to undefined variable  ++ show name)
   let val = Data 
   modify (M.insert name val)
   return val
 Just val - return val

Note that whatever I do in the 'Nothing' case is irrelevant, your code with
the Var case replaced by

 eval e@(Var name) = do
   env - ask
   case M.lookup name env of
 Just val - return val

loops as well.

My problem is that I still don't understand why this is so! I know of course
that pattern matching is strict, but I thought this should be ok here,
since I evaluate the declarations _before_ the body, so when evaluation of
the body demands the variable, it will be defined.

What am I missing?

Cheers
Ben

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


[Haskell-cafe] Re: ANNOUNCE: feldspar-language

2009-11-25 Thread Ben Franksen
Emil Axelsson wrote:
 Henning Thielemann skrev:
 On Fri, 6 Nov 2009, Emil Axelsson wrote:
 
 Henning Thielemann skrev:
 I'm trying to get realtime signal processing with Haskell for long. I
 make progress, but slowly. Has Ericsson ever thought about using
 Haskell itself for signal processing? (But I think they already have
 Erlang?)
 No, using Haskell directly is not an option (at least with current
 compiler technology). Their performance requirements are very high, and
 the signal processors have quite limited memory, so putting a Haskell
 RTS on them wouldn't work.

 Yes, Erlang is used in some applications, but that's more for control
 programs, not for numerical computations.

 I hope you will succeed in making real-time signal processing in Haskell
 work!
 
 I'm currently testing JHC to that end. It produces relatively small C
 programs without a precompiled run-time system.
 
 Cool! I'd be very interested to see how that works out.

Me too!

Cheers
Ben

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


[Haskell-cafe] implementing recursive let

2009-11-24 Thread Ben Franksen
I am trying to write an interpreter for a very simple untyped functional
language. I have a problem with mutually recursive let expressions, for
which my interpreter loops :(

This is a code snippet from the eval function:

 eval :: Expr - Eval Value
 eval (Let decls body) = mdo
   let (names,exprs) = unzip decls
   let updateEnv env = foldr (uncurry M.insert) env $ zip names values
   (values,result) - local updateEnv $ liftM2 (,) (mapM eval exprs) (eval
body)
   return result

Module M is Data.Map, the environment is a simple map from strings to
values. Values are defined as

 data Value = Data String | Function (Value - Eval Value)

The Eval monad is defined as

 newtype Eval a = Eval {
 unEval :: ErrorT String (StateT Env (Writer [String])) a
   } deriving (
 Monad,
 MonadFix,
 MonadWriter [String], -- for warnings  other messages
 MonadState Env,
 MonadError String
   )

 instance MonadReader Env Eval where
   ask = get
   local tr act = do
 s - get
 modify tr
 r - act
 put s
 return r

When I test this with an extremely simple expression, something like let x
= 1 in x, the code above loops. I don't understand why, especially since
in a previous version it worked. In the previous version I had a simpler
monad stack that went

 newtype Eval a = Eval {
 unEval :: ReaderT Env (Writer [String])) a
   } deriving (
 Monad,
 MonadFix,
 MonadWriter [String],
 MonadReader Env
   )

(Replacing reader with state was done so I can add definitions to the
environment at runtime. The ErrorT provides for errors, such as application
of a non-function.)

Expressions not involving let work fine. Also, if I replace the above
definition by one which does not allow recursion (not using mdo, evaluating
the defining expressions before the variable gets added to the
environment), then non-recursive let-expressions (like the simple example
above) work just fine.

I am out of ideas as to what causes this problem. Does the addition of
ErrorT make my monad too strict? How else can I implement mutual recursion?

Cheers
Ben

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


[Haskell-cafe] Re: Re: cvs.haskell.org down? haskell-mode abandoned?

2009-10-22 Thread Ben Franksen
Johan Tibell wrote:
 I just wanted to say that I'd be really happy to see haskell-mode in
 code.haskell.org. I think it will make it easier for people to hack on
 it.

Another option is http://patch-tag.com/

Cheers
Ben

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


[Haskell-cafe] Re: is proof by testing possible?

2009-10-12 Thread Ben Franksen
Joe Fredette wrote:
 Really? How? That sounds very interesting, I've got a fair knowledge
 of basic topology, I'd love to see an application
 to programming...

Compactness is one of the most powerful concepts in mathematics, because on
the one hand it makes it possible to reduce many infinite problems to
finite ones (inherent in its definition: for every open cover there is a
finite subcover), on the other hand it is often easy to prove compactness
due to Tychonoff's theorem (any product of compact spaces is compact). The
connection to computing science is very nicely explained in 

 http://math.andrej.com/2007/09/28/seemingly-impossible-functional-programs/

I found this paragraph particularly enlightening:


 modulus :: (Cantor - Integer) - Natural
 modulus f = least(\n - forevery(\a - forevery(\b - eq n a b -- (f a ==
f b

 This [...] finds the modulus of uniform continuity, defined as the least
natural number `n` such that
 `forall alpha,beta. alpha =_n beta implies f(alpha)=f(beta),`
 where 
 `alpha =_n beta iff forall i n. alpha_i = beta_i.`

 What is going on here is that computable functionals are continuous, which
amounts to saying that finite amounts of the output depend only on finite
amounts of the input. But the Cantor space is compact, and in analysis and
topology there is a theorem that says that continuous functions defined on
a compact space are uniformly continuous. In this context, this amounts to
the existence of a single `n` such that for all inputs it is enough to look
at depth `n` to get the answer (which in this case is always finite,
because it is an integer).


Cheers

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


[Haskell-cafe] Re: Re: is proof by testing possible?

2009-10-12 Thread Ben Franksen
Joe Fredette wrote:
 That has got to be the single awesomest thing I have ever seen ever...

I was dumbfounded, too, when I first read about this.

BTW, and completely off-topic: if you like this, you might have fun too with
Conor McBride's discovery that data types can be differentiated, and the
result is even useful: it corresponds to what is known (to some) as a
Zipper:

 http://www.cs.nott.ac.uk/~ctm/diff.pdf

Moreover, we can also give a sensible and useful interpretation to finite
difference quotients of types:

 http://blog.sigfpe.com/2009/09/finite-differences-of-types.html

which McBride calls dissections and discusses in some depth here:

 http://strictlypositive.org/CJ.pdf

What is most astonishing to me is that these constructions work even though
there is neither subtraction nor division defined on data types, only
addition and multiplication (there are neutral elements for both, but not
necessarily inverses).

Cheers
Ben

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


[Haskell-cafe] Re: Re: What *is* a DSL?

2009-10-12 Thread Ben Franksen
S. Doaitse Swierstra wrote:
 This problem of dynamically transforming grammars and bulding parsers
 out of it is addressed in:
 
 @inproceedings{1411296,
   author = {Viera, Marcos and Swierstra, S. Doaitse and Lempsink,
 Eelco},
   title = {Haskell, do you read me?: constructing and composing
 efficient top-down parsers at runtime},
 [...]
   }

Indeed, it looks as if you solved exactly the problem that vexed me! I had
just found the presentation that corresponds to the paper you mention, and
I also found a preprint for Typed transformations of Typed Abstract
Syntax which I am studying at the moment. I must say your construction is,
well, involved...

Not that I want to belittle this really astounding and clever achievement...
but one disadvantage of your approach (which it shares with almost all
examples I have seen for dependently typed or heterogeneous collections) is
that (IIUC) the typed map from references to abstract syntactic terms is
operationally an association list, indexed by unary numbers. I would expect
this to scale poorly if the number of references (e.g. nonterminals) gets
large.

I think it would make for quite an interesting research project to study
whether it is possible to achieve the same level of precise static typing
with more efficient data structures. I imagine that using some 'fake
dependent type' variant of [Bit] for the key and the equivalent of a
patricia tree for the map could perhaps be made to work???

Cheers
Ben

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


[Haskell-cafe] Re: How do I get this done in constant mem?

2009-10-11 Thread Ben Franksen
mf-hcafe-15c311...@etc-network.de wrote:
 On Sat, Oct 10, 2009 at 11:11:24PM +0200, Daniel Fischer wrote:
 No, readFile reads the file lazily.
 
 hm?  oh, you are right, now that i fixed all the other problems in my
 code readFile isn't a problem any more either...  (-:
 
 (but then how does it know when to close the handle?  gotta go read
 the code i guess.)

It is somewhat documented, see
http://www.haskell.org/ghc/docs/latest/html/libraries/base/System-IO.html
or http://www.haskell.org/onlinelibrary/io.html, section 21.2.2 Semi-Closed
Handles:

[...] A semi-closed handle becomes closed:
 * if hClose is applied to it; 
 * if an I/O error occurs when reading an item from the handle; 
 * or once the entire contents of the handle has been read.

It is not stated here that the file /immediately/ gets closed after the last
byte has been read. Does that mean implementations are free to postpone
closing (e.g. until the next GC cycle)?

Cheers
Ben

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


[Haskell-cafe] Re: What *is* a DSL?

2009-10-11 Thread Ben Franksen
Ben Franksen wrote:
 Next thing I'll try is to transform such a grammar into an actual
 parser...

Which I also managed to get working. However, this exposed yet another
problem I am not sure how to solve.

The problem manifests itself with non-left-factored rules like

  Number ::= Digit Number | Digit

Translating such a grammar directly into a Parsec parser leads to parse
errors because Parsec's choice operator is predictive: if a production has
consumed any input the whole choice fails, even if alternative productions
would not:

*Main P.parseTest (parseGrammar myGrm) 2
parse error at (line 1, column 2):
unexpected end of input
expecting Number

Of course, one solution is to apply Parsec's try combinator to all choices
in a rule. But this rather defeats the purpose of using a (by default)
predictive parser in the first place which is to avoid unnecessary
backtracking.

So, a better solution is to left-factor the grammar before translating to
Parsec. Since we have a data representation of the grammar that we can
readily analyse and transform, this should be possible given some suitable
algorithm. But how is this transformation to be typed?

My first naive attempt was to define (recap: nt :: * - * is the type of
nonterminals, t :: * is the type of terminals a.k.a. tokens, and a is the
result type):

 leftFactor :: Grammar nt t a - Grammar nt t a

Of course, this is wrong:  Left-factoring is expected to introduce new
nonterminals, so on the right-hand side of the type we should not have the
same 'nt' as on the left. Instead we shoudl have some other type that
is 'nt' extended with new constructors. Moreover, we cannot statically
know how many new nonterminals are added, so we cannot simply apply a type
function to nt. Is this solvable at all in Haskell or do I need proper
dependent types to express this?

I have very vague ideas that revolve around setting up some recursive type
function that on each level adds one constructor, define a common interface
with a (multiparam) type class and then use existential quantification in
the result type to hide the resulting type of nonterminals.

The next question is: Even if this turns out to be possible, isn't it
overkill? Maybe it is better to use an infinite type for the nonterminals
in the first place and let the grammar be a partial function? OTOH, the
formulation of the grammar as a function that pattern matches on the
nonterminals is very elegant.

Cheers
Ben

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


Re: [Haskell-cafe] Haskell Weekly News: Issue 134 - October 10, 2009

2009-10-11 Thread Ben Franksen
Patrick LeBoutillier wrote:
 Could/should the Haskell Weekly News be posted to the beginners list as
 well?
 
 I normally don't follow haskell-cafe (too much traffic and generally above
 my level I must admit...), but I like to follow what's going on in the
 Haskell community.

I find reading the HWN is a lot is a lot more convenient with a web browser,
you don't have to jump up and down the document to find the links. There is
also an RSS feed (http://sequence.complete.org/node/feed) to keep you up to
date.

Cheers
Ben

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


[Haskell-cafe] Re: What *is* a DSL?

2009-10-11 Thread Ben Franksen
Ben Franksen wrote:
 Ben Franksen wrote:
 Next thing I'll try is to transform such a grammar into an actual
 parser...
 
 Which I also managed to get working.

First, before all this talking to myself here is boring you to death, please
shout and I'll go away. Anyway, at least one person has privately expressed
interest, so I'll post my code for the translation.(*)

 {-# LANGUAGE ExistentialQuantification, GADTs, Rank2Types #-}
 {-# LANGUAGE TypeSynonymInstances, MultiParamTypeClasses,
ImpredicativeTypes #-}
 import qualified Text.ParserCombinators.Parsec as P

Note that I have parameterized everything on the token (terminal) type. Here
are the data types, adapting the rest of the code is completely mechanical.

 data Production nt t a
 =   Stopa
 |   Terminalt  (Production nt t a)
 | forall b. NonTerminal (nt b) (Production nt t (b - a))

 newtype Rule nt t a = Rule [Production nt t a]

 type RuleSet nt t = forall a. nt a - Rule nt t a

 type Grammar nt t b = (nt b, RuleSet nt t)

I should probably turn this into a proper data type, which would BTW also
make the ImpredicativeTypes extension unnecessary.

Translation to Parsec
-

We restrict ourselves to Char as terminals for simplicity. The
generalization to arbitrary token types would need another three arguments:
showTok :: (tok - String), nextPos :: (SourcePos - tok - [tok] -
SourcePos), and testTok :: (tok - Maybe a), which are needed by
P.tokenPrim.

 parseGrammar :: Print nt = Grammar nt Char a - P.Parser a
 parseGrammar (start,rules) = parseNonTerminal rules start

 parseNonTerminal :: Print nt = RuleSet nt Char - nt a - P.Parser a
 parseNonTerminal rs nt = parseRule rs (rs nt) P.? pr nt

 parseRule :: Print nt = RuleSet nt Char - Rule nt Char a - P.Parser a
 parseRule rs (Rule ps) = P.choice (map ({- P.try . -} parseProduction rs)
ps)

 parseProduction :: Print nt = RuleSet nt Char - Production nt Char a -
P.Parser a
 parseProduction _  (Stop x) = return x
 parseProduction rs (Terminal c p) = P.char c  parseProduction rs p
 parseProduction rs (NonTerminal nt p) = do
   vnt - parseNonTerminal rs nt
   vp - parseProduction rs p
   return (vp vnt)

This is really not difficult, once you understand how the list-like
Production type works. The trick is that a NonTerminal forces the rest of
the production to return a function type, so you can apply its result to
the result of parsing the nonterminal. Whereas the result of parsing
terminals gets ignored by the rest of the production. You might wonder
how the code manages to return the correct integer values inside an ENum.
Well, I did, at least. I don't yet understand it completely but I think the
answer is in in the Functor and Applicative instances: all the code that
interprets syntactic elements (up to the abstract syntax) inside the myGrm
function gets pushed down through the elements of a production until it
ends up at a Stop, where we can finally pull it out (see the first clause
of parseProduction).

Note also the (commented-out) use of P.try in function parseRule. Let's try
it:

*Main putStrLn (printGrammar myGrm)
*Start ::= Sum
Sum ::= Product '+' Sum | Product
Product ::= Value '*' Product | Value
Value ::= Number | '(' Sum ')'
Number ::= Digit Number | Digit
Digit ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
*Main P.parseTest (parseGrammar myGrm) 2*(2+52)
parse error at (line 1, column 2):
unexpected *
expecting Number

After re-inserting the P.try call, I can actually parse expressions (yay!):

*Main :r
[1 of 1] Compiling Main ( Grammar.lhs, interpreted )
Ok, modules loaded: Main.
*Main P.parseTest (parseGrammar myGrm) 2*(2+52)
EProduct (ENum 2) (ESum (ENum 2) (ENum 52))

BTW, does anyone know a source (books, papers, blogs, whatever) about
algorithms for automatic left-factoring? I searched with google and found
some interesting papers on eliminating left recursion but nothing so far on
left-factoring. Have these problems all been solved before the internet
age?

Cheers
Ben

(*) One of these days I really should get my hands dirty and set up a
weblog; suggestions for how to proceed are appreciated. I would especially
like something where I can just upload a literate Haskell file and it gets
formatted automagically. Bonus points for beautifying operator symbols a la
lhs2tex ;-)

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


[Haskell-cafe] Re: What *is* a DSL?

2009-10-10 Thread Ben Franksen
Robert Atkey wrote:
 A deep embedding of a parsing DSL (really a context-sensitive grammar
 DSL) would look something like the following. I think I saw something
 like this in the Agda2 code somewhere, but I stumbled across it when I
 was trying to work out what free applicative functors were.

 [snip code  explanation]

This is extremely cool. I tried to understand in my head how this all works
but it just didn't click. It all seemed like magic.

Then I went ahead and tried to write a printer for your example grammar and
now everything is much clearer. Although I had to fight the type checker
quite a bit. This is the generic part:

 class Print f where
 pr :: f a - String

 instance Print nt = Print (Production nt) where
 pr = printProduction

 printProduction :: Print nt = Production nt a - String
 printProduction (Stop _) = 
 printProduction (Terminal t (Stop _)) = show t
 printProduction (Terminal t p) = show t ++   ++ printProduction p
 printProduction (NonTerminal nt (Stop _)) = pr nt
 printProduction (NonTerminal nt p) = pr nt ++   ++ printProduction p

 instance Print nt = Print (Rule nt) where
 pr (Rule ps) = printPs ps where
   printPs [] = 
   printPs [p]= printProduction p
   printPs (p:ps) = printProduction p ++  |  ++ printPs ps

 data Any f = forall a. Any (f a)

 class Enumerable f where
 enumeration :: [Any f]

 printRule :: Print nt = (nt a - Rule nt a) - nt a - String
 printRule g nt = pr nt ++  ::=  ++ pr (g nt)

 printGrammar :: (Print nt, Enumerable nt) = Grammar nt - String
 printGrammar g = foldr (++)  (intersperse \n rules) where
 rules = map printAnyRule enumeration
 printAnyRule (Any nt) = printRule g nt

We must also provide instances for the concrete types:

 instance Enumerable NT where
 enumeration = [Any Sum, Any Product, Any Value]

 instance Print NT where
 pr Value   = Value
 pr Product = Product
 pr Sum = Sum

So far so good. This even works... almost ;-)

*Main putStrLn $ printGrammar myGrm
Sum ::= Product '+' Sum | Product
Product ::= Value '*' Product | Value
Value ::= Interrupted. -- had to hit Ctrl-C here

When I replace 'posInt' with 'digit' in the rule for Value

 myGrm Value   = ENum $ digit
 | id   $  char '(' * nt Sum * char ')'

then the printer terminates just fine:

*Main putStrLn $ printGrammar myGrm
Sum ::= Product '+' Sum | Product
Product ::= Value '*' Product | Value
Value ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '('
Sum ')'

I found that the problem is the use of function 'some' from
Control.Applicative in

 posInt :: Rule nt Int
 posInt = fix 1 . reverse $ some digit where
   fix n [] = 0
   fix n (d:ds) = d*n + fix (n*10) ds

Since 'some' is defined recursively, this creates an infinite production for
numbers that you can neither print nor otherwise analyse in finite time.

I can see at least two solutions: One is to parameterize everything over the
type of terminals, too. A type suitable for the example would be

 data T = TNum Int | TPlus | TMult | TOParen | TCParen

and leave token recognition to a separate scanner.

The second solution (which I followed) is to break the recursion by adding
another nonterminal to the NT type:

 data NT a where
 Sum :: NT Expr
 Product :: NT Expr
 Value   :: NT Expr
 Number  :: NT [Int]
 Digit   :: NT Int

 instance Enumerable NT where
 enumeration = [Any Sum, Any Product, Any Value, Any Number, Any Digit]

 instance Print NT where
 pr Sum = Sum
 pr Product = Product
 pr Value   = Value
 pr Number  = Number
 pr Digit   = Digit

(Adding Digit /and/ Number is not strictly necessary, but it makes for a
nicer presentation.)

 myGrm :: Grammar NT
 myGrm Sum = ESum $ nt Product * char '+' * nt Sum
 | id   $ nt Product
 
 myGrm Product = EProduct $ nt Value * char '*' * nt Product
 | id   $ nt Value
 
 myGrm Value   = (ENum . toNat) $ nt Number
 | id   $  char '(' * nt Sum * char ')'
 
 myGrm Number  = extend   $ nt Digit * optional (nt Number)
 
 myGrm Digit   = digit

 extend d Nothing = [d]
 extend d (Just ds) = d:ds

 toNat :: [Int] - Int
 toNat = fix 1 . reverse where
   fix n [] = 0
   fix n (d:ds) = d*n + fix (n*10) ds

With this I get

*Main putStrLn $ printGrammar myGrm
Sum ::= Product '+' Sum | Product
Product ::= Value '*' Product | Value
Value ::= Number | '(' Sum ')'
Number ::= Digit Number | Digit
Digit ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'

Morale: Be careful with recursive functions when constructing a data
representation (e.g. for a deep DSL). You might get an infinite
representation which isn't what you want in this case.

Oh, and another point: there should be a distinguished start nonterminal,
otherwise this is not really a grammar. This suggests something like

 type Grammar nt a = (nt a, forall b. nt b - Rule nt b)


[Haskell-cafe] Re: Num instances for 2-dimensional types

2009-10-09 Thread Ben Franksen
Joe Fredette wrote:
 A ring is an abelian group in addition, with the added operation (*)
 being distributive over addition, and 0 annihilating under
 multiplication. (*) is also associative. Rings don't necessarily need
 _multiplicative_ id, only _additive_ id.

Yes, this is how I learned it in my Algebra course(*). Though I can imagine
that this is not universally agreed upon; indeed most of the more
interesting results need a multiplicative unit, IIRC, so there's a
justification for authors to include it in the basic definition (so they
don't have to say let-R-be-a-ring-with-multiplicative-unit all the time ;-)

Cheers
Ben

(*) As an aside, this was given by one Gernot Stroth, back then still at the
FU Berlin, of whom I later learned that he took part in the grand effort to
classify the simple finite groups. The course was extremely tight but it
was fun and I never again learned so much in one semester.

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


[Haskell-cafe] Re: Re: What *is* a DSL?

2009-10-09 Thread Ben Franksen
Emil Axelsson wrote:
 Ben Franksen skrev:
 minh thu wrote:
 2009/10/7 Günther Schmidt gue.schm...@web.de:
 I've informally argued that a true DSL -- separate from a good API --
 should have semantic characteristics of a language: binding forms,
 control structures, abstraction, composition. Some have type systems.

 That is one requirement that confuses me, abstraction.

 I thought of DSLs as special purpose languages, ie. you give your DSL
 everything it needs for that purpose.

 Why would it also need the ability to express even further
 abstractions, it is supposed to *be* the abstraction.
 Programming abstractions at the DSL level, not to further abstract
 what the DSL covers.

 Functions, for instance, are typical abstraction means offered by
 programming languages. Even if your language is specific to some
 domain, being able to create your own functions, and not only rely on
 those provided by the DSL implementation, is important.

 Imagine a (E)DSL for 3D programming (e.g. shading language): the
 language is designed to fit well the problem (e.g. in this case, 3D
 linear algebra, color operations, ...) but you'll agree it would be a
 shame to not be able to provide your own functions.
 
 But isn't one of the advantages of an _E_DSL that we can use the host
 language (Haskell) as a meta or macro language for the DSL? I would think
 that this greatly reduces the need to provide abstraction
 facilities /inside/ the DSL. In fact most existing (and often cited
 examples of) EDSLs in Haskell do not provide abstraction.
 
 I would say that the DSL is what the user sees. In this view, I think
 it's correct to say that many (or most) DSLs need function abstraction.
 Whether or not the internal data structure has function abstraction is
 an implementation detail.

If it is a stand-alone DSL (i.e. with its own parser), then yes. But I was
referring to Embedded DSLs, i.e. DSL as a library in a host language (eg
Haskell). In this case the user sees the host language by construction,
which means she has less need of function abstraction /inside/ the DSL.

Cheers
Ben

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


[Haskell-cafe] Re: Num instances for 2-dimensional types

2009-10-07 Thread Ben Franksen
Daniel Fischer wrote:
 Am Montag 05 Oktober 2009 16:29:02 schrieb Job Vranish:
 In what way is it not a number?
 
 If there's a natural[1] implementation of fromInteger, good.
 If there isn't, *don't provide one*.
 fromInteger _ = error Not sensible is better than doing something
 strange.
 
 [1] In the case of residue class rings, you may choose between restricting
 [the range of
 legitimate arguments for fromInteger or doing a modulo operation on the
 argument, both ways are natural and meet expectations sufficiently well.

More generally, any ring with multiplicative unit (let's call it 'one') will
do. If there were 'one' and 'zero' methods in class Num, we could even give
a default implementation (however inefficient) as

  fromInteger n | n  0 = negate (fromInteger n)
  fromInteger n | n  0 = one + fromInteger (n-1)
  fromInteger _ = zero

In fact, I'd argue that the existence of fromInteger in class Num morally
implies a unit for multiplication (namely 'fromInteger 1'), otherwise
fromInteger isn't even a ring morphism.

Cheers
Ben

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


[Haskell-cafe] Re: better way to do this?

2009-10-07 Thread Ben Franksen
Eugene Kirpichov wrote:
 Or you can use an effect system (however that doesn't give you the
 opportunity of overriding IO functions, but I think that providing
 such an opportunity with the means you suggest (splitting IO into many
 sub-monads) is not going to be usable in the large scale)
 
 By the way, I am surprised that there seems to not exist any
 non-purely-academic language at all that supports effect systems!
 (except for Java's checked exceptions being a poor analogue). The only
 language with an effect system *and* a compiler that I know of is DDC,
 but it seems to be purely experimental.

What about ATS (http://www.ats-lang.org/)?

Ben

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


[Haskell-cafe] Re: What *is* a DSL?

2009-10-07 Thread Ben Franksen
minh thu wrote:
 2009/10/7 Günther Schmidt gue.schm...@web.de:
 I've informally argued that a true DSL -- separate from a good API --
 should have semantic characteristics of a language: binding forms,
 control structures, abstraction, composition. Some have type systems.


 That is one requirement that confuses me, abstraction.

 I thought of DSLs as special purpose languages, ie. you give your DSL
 everything it needs for that purpose.

 Why would it also need the ability to express even further abstractions,
 it is supposed to *be* the abstraction.

 Programming abstractions at the DSL level, not to further abstract
 what the DSL covers.
 
 Functions, for instance, are typical abstraction means offered by
 programming languages. Even if your language is specific to some
 domain, being able to create your own functions, and not only rely on
 those provided by the DSL implementation, is important.
 
 Imagine a (E)DSL for 3D programming (e.g. shading language): the
 language is designed to fit well the problem (e.g. in this case, 3D
 linear algebra, color operations, ...) but you'll agree it would be a
 shame to not be able to provide your own functions.

But isn't one of the advantages of an _E_DSL that we can use the host
language (Haskell) as a meta or macro language for the DSL? I would think
that this greatly reduces the need to provide abstraction
facilities /inside/ the DSL. In fact most existing (and often cited
examples of) EDSLs in Haskell do not provide abstraction.

Cheers
Ben

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


[Haskell-cafe] Re: Cal, Clojure, Groovy, Haskell, OCaml, etc.

2009-10-02 Thread Ben Franksen
Hong Yang wrote:
 Good libraries are not enough for a language to go beyond mere existence.
 There must exist good documents, i.e., good tutorials, good books, and
 good explanations and examples in the libraries, etc, that are easy for
 people to learn and use. In my humble opinion, Haskell has a lot of
 libraries, but most of them offer few examples of how to use the modules.
 In this regards, Perl is much much better.

I wouldn't say 'better' as many, if not most, Perl libraries offer not much
beyond example usage as documentation. Even if they do, the docs are often
ambiguous, corner cases left to the user's imagination -- which is (at
least in my case) regularly different from the library author's -- etc. IMO
this is just the other extreme of the spectrum. It sure gets you started
quite cheaply, but in the long run you pay an ugly amount of interest as
you spend more and more time with debugging due to said ambiguities and
corner cases.

BTW, apparently, Perl library authors like to model their APIs after their
mother language Perl itself, of which one could justly say that its only
exact definition /is/ its implementation.

Which doesn't mean that documentation of many Haskell libs couldn't be
greatly improved...

Cheers
Ben

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


  1   2   3   >