Re: [Haskell-cafe] Why Kleisli composition is not in the Monad signature?
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?
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)
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?
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?
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
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
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
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
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.
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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?
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?
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
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
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)
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?
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
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
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
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
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
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
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?
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
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
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
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
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
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?
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
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
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
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
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.
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?
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
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
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
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
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
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]
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?
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
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
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
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
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
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
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
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
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
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
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
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
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
+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
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
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
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
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
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
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
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
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
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
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
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
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?
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?
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?
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?
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?
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?
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
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?
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?
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
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?
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
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?
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?
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.
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