Re: [Haskell-cafe] strict version of Haskell - does it exist?
On Sun, 2012-01-29 at 23:47 +0100, Marc Weber wrote: So maybe also the JSON parsing library kept too many unevaluated things in memory. So I could start either writing my own JSON parsing library (being more strict) Jfyi, aeson has been added strict parser variants json' and value' [1] some time ago, so you shouldn't have to write your own stricter JSON parsing library... [1]: http://hackage.haskell.org/packages/archive/aeson/0.6.0.0/doc/html/Data-Aeson-Parser.html#g:2 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Some thoughts on Type-Directed Name Resolution
On 30/01/2012 07:09, Donn Cave wrote: ((separate . crack . .smallEnd) egg).yolk (f egg).yolk where f = separate . crack . .smallEnd Scary - that .smallEnd worries me. It's like a field is being referenced with some magical context from nowhere. Obviously I need to read that full proposal. Sorry for going on about it, but this wouldn't happen in my idea. If field access functions are just items in a module, the . separates the module identification from the item name, same as always. The only difference is how you identify the module. There's no special interactions with function composition, or whatever it is that's happening here. If you want to composite the function with some other function without knowing in advance which record value you're dealing with, just get the access function from the record-type module. If I'm correctly guessing what your code means, that reads as... (f egg).yolk where f = separate . crack . (eggModule.eggType.smallEnd) OK, in a sense specifying eggModule.eggType there is a bit redundant, but in general that isn't true - define f separately and it needs some clue for the type inference to decide where to look for smallEnd, and eggtype provides it. I'd prefer a notation that allows me to reference the field without needing type inference to determine which record type it relates to. But then again, I'm probably just not understanding the reason behind that wierdness - perhaps it wouldn't seem so wierd if I did. Or maybe it's just a familiarity issue. First thought - I've not addressed access from within a polymorphic function with type class constraints. The situation there would (without extra features) be the same as it is now, with no TDNR support. Field access functions would have to be provided as explicit operations within the type class. That said, it shouldn't be hard to handle. For example, a type class can explicitly state which field names it is interested in, and an instance can provide functions to access those fields. Alternatively, the instance might support using arbitrary functions (of the right type). This might allow some wierdness (fields that aren't really fields), but it may allow some useful flexibility (this particular type provides the field daddy, that type provides mummy, a third type has no named fields but has a function that works by pattern matching that can provide the positionally-defined field - either way, this type class will refer to parent) so that polymorphic functions can use the dot notation, but the relationship between fields in the type class and fields in the instance type are flexible. It's really just syntactic sugar for what type classes have to do now - providing a dot notation, but still using vtable references to field access functions to do the work. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] space leak when repeatedly calling Control.Monad.State.Strict.modify
Have you tried to compile your code with optimisations? I guess GHC's strictness analysis would find strict evaluation is better here. 2012/1/30 Joey Hess j...@kitenet.net Claude Heiland-Allen wrote: Control.Monad.State.Strict is strict in the actions, but the state itself is still lazy, so you end up building a huge thunk in the state containing all the updates that ever took place to the initial state. Using this should fix it: modify' :: MonadState s m = (s - s) - m () modify' f = do x - get put $! f x -- force the new state when storing it Thanks! So, why does Control.Monad.State.Strict.modify not do that? And, I still don't quite understand why this only happened when the updated value is obtained using IO. -- see shy jo ___ 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] strict version of Haskell - does it exist?
On Mon, Jan 30, 2012 at 6:21 AM, Herbert Valerio Riedel h...@gnu.org wrote: On Sun, 2012-01-29 at 23:47 +0100, Marc Weber wrote: So maybe also the JSON parsing library kept too many unevaluated things in memory. So I could start either writing my own JSON parsing library (being more strict) Jfyi, aeson has been added strict parser variants json' and value' some time ago, so you shouldn't have to write your own stricter JSON parsing library... Also, besides using those variants, you may also use the attoparsec-conduit library [1]. If you have processJson :: Value - IO X then you'd need just something like import Data.Aeson (Value, json') import Data.Attoparsec.Char8 (isSpace_w8) import qualified Data.ByteString as B import qualified Data.Conduit as C import qualified Data.Conduit.Attoparsec as CA import qualified Data.Conduit.Binary as CB import qualified Data.Conduit.List as CL main = do ... ret - forM_ fileList $ \fp - do C.runResourceT $ CB.sourceFile fp C.$= jsonLines C.$= CL.mapM processJson C.$$ CL.consume print ret jsonLines :: C.Resource m = C.Conduit B.ByteString m Value jsonLines = C.sequenceSink () $ do val - CA.sinkParser json' CB.dropWhile isSpace_w8 return $ C.Emit () [val] This code is extremely resource-friendly, since (a) you can't leak file descriptors and (b) you just have to make sure that processJson function isn't too lazy. It should be quite fast as well. Cheers! =) [1] http://hackage.haskell.org/package/attoparsec-conduit -- Felipe. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] strict version of Haskell - does it exist?
On Sun, Jan 29, 2012 at 11:25:09PM +0100, Ertugrul Söylemez wrote: First of all, /learning/ to optimize Haskell can be difficult. The optimizing itself is actually fairly easy in my experience, once you understand how the language works. Given the fact that you have obviously mastered the learning part of this, do you have any recommendations on what to read or on how to proceed in order to learn how to optimize Haskell code? I can imagine, it's not only about understanding the language itself, but also about understanding how your compiler and its switches work, being able to find the hot spots in your code, being able to measure the effects of your changes, developing a good sense for the tradeoffs, etc. So far, I have only stumpled upon chapter 25 of Real World Haskell. Anything else you might recommend? regards Alex signature.asc Description: Digital signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Some thoughts on Type-Directed Name Resolution
Steve Every programmer has their own favorite editor, usually using the same Steve one to work in many different languages. For the moment, you'd have Steve a hard job separating me from Notepad++. Main editors have very advanced customization features (though incredibly hacky most of the time). A type-directed (this word is what I like most in the proposal ;]) Haskell editing mode for them could be a good first step. Steve If you really want a semantic editor, I'd argue a rich visual Steve language with a file format that isn't intended to be read directly. Steve Something more like writing in Word than writing in TeX. But I don't Steve think most programmers are ready for this, for various reasons. Steve Version control tools and readable differences get a place near the Steve top of that list. Well, in the long term I don't know ... maybe plain text won't be a good representation of a program anymore. But in the short term that's not an option. However, I see no problem in just constructing this textual representation through a strictly type-directed (yeah!) syntax tree editor. Emacs, Vim, and a lot of others have snippet support. The workflow could be something like : - action to create a new top-level function - PROMPT : name (eg. map) - PROMPT : signature (eg. (a - b) - [a] - [b]) - PROMPT : parameters matching (eg. f (x:xs)) - a stub is inserted with name, signature, and undefined definition map :: (a - b) - [a] - [b] map f (x:xs) = undefined map f [] = undefined - now enters definition construction. You would start by adding to a 'pool' the bindings you want to combine. Some could be added to the pool automatically (function parameters, top-level definitions in the module, explicitly imported functions ...). Then you would pick one of them, and the type-directed system would offer type-correct completion. For example : - The pool state is { f :: a - b , x :: a, xs :: [a], map :: (a - b) - [a] - [b] } (the type variables scope over the entire pool) - The definition type must be [b] - I ask to use 'f'. It isn't [b] so I can't use it alone. The wonderful system would then reduce the pool to things that I can combine f with in order to keep the target [b] type. The result is { map f xs :: [b] }. I say ok. - The sub is now : map :: (a - b) - [a] - [b] map f (x:xs) = map f xs map f [] = undefined - Now I ask to use (:) :: c - [c] - [c] . They are plenty of places where it could be used in the definition, so let's narrow the choice by associating the 'c' type to something in our expression : c == b. So (:) :: b - [b] - [b] - we have no expression typing as 'b' in the definition, but we have a single expression that types as [b], and it is 'map f xs'. So the system can safely offer : map :: (a - b) - [a] - [b] map f (x:xs) = undefined : map f xs map f [] = undefined - now let's define the first 'undefined'. Its type is b. We ask this time to use the 'x' binding (x :: a). But we are looking for a 'b'. We have f :: a - b so the system can offer 'f x'. map :: (a - b) - [a] - [b] map f (x:xs) = f x : map f xs map f [] = undefined - The last undefined is trivial. The user interface would certainly matter much, to have a fast and pleasant experience. But the point is that as a pure language, haskell very looks well suited for this kind of incremental syntax-tree editing, with type-directed assistance. I wonder, even, if some rules could be defined to construct automatically a definition that typechecks and use all bindings in the pool :) Back to the point of the thread, it looks like we certainly can target type-directed editing with current haskell function notation, which has the advantage of being beautiful and consistent. -- Paul ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] strict version of Haskell - does it exist?
On 29 Jan 2012, at 22:25, Ertugrul Söylemez wrote: A strict-by-default Haskell comes with the implication that you can throw away most of the libraries, including the base library. So yes, a strict-by-default Haskell is very well possible, but the question is whether you actually want that. I wouldn't, because a lot of my code relies on the standard semantics. At work, we have a strict version of Haskell, and indeed we do not use the standard libraries, but have built up our own versions of the ones we use. However, our compiler is smart enough to transform and optimise the source code *as if* it were non-strict: it is only at runtime that things are evaluated strictly. This means that, in general, you can rely on the standard semantics to a surprisingly large extent. For instance, maybe (error foo) lines (Just hello\nworld) will succeed without calling error, just like in Haskell. Even if the final argument is supplied only at runtime, not statically, it will still do the right thing. However, the downside of being strict at runtime is frequently poorer performance. Stack overflows are common if you use explicit recursion: it is better to use higher-order functions (map, fold, until) that are implemented at a lower level in C (i.e. not directly using explicit recursion themselves). This is a good thing of course - thinking of data structures in the aggregate, rather than piecemeal. However, bulk operations do transform the entire data structure, not merely the fragments that are needed for the onward computation, so it can often be a net performance loss. The standard lazy computational paradigm of generate-and-test is therefore hideously expensive, on occasion. Regards, Malcolm ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Need advice: Haskell in Web Client
**Bardur Arantsson wrote: On 01/26/2012 11:16 AM, dokondr wrote: Ideally, I would be happy to be able to write in Haskell a complete front-end / GUI, so it could be compiled to different back-ends: Javascript to run in the Browser and also a standalone app. In Python world this is already done with Pyjamas (http://pyjs.org/) - a Rich Internet Application (RIA) Development Platform for both Web and Desktop. Also from Pyjamas site: Pyjamas ... contains a Python-to-Javascript compiler, an AJAX framework and a Widget Set API. Pyjamas Desktop is the Desktop version of Pyjamas Pyjamas Desktop allows the exact same python web application source code to be executed as a standalone desktop application (running under Python) instead of being stuck in a Web browser. Architecture diagram http://pyjs.org/wiki/pyjamasandpyjamasdesktop/ I wonder if somebody works on similar Haskell Rich Internet Application (RIA) Development Platform ? Any ideas, comments on implementation of such system in Haskell? What existing Haskell GUI libraries can be used for a desktop GUI, etc.? Well, it's basically just proof-of-concept at the moment, and it's not really usable for real applications at the moment, but there is http://hackage.haskell.org/package/dingo-core-0.1.0 http://hackage.haskell.org/package/dingo-widgets-0.1.0 http://hackage.haskell.org/package/dingo-example-0.1.0 The basic client-server communication, server-side state handling, etc. is there, but it's missing a couple of things before it could be used for real apps: There's no real security, and there are *very* few widgets. The few widgets that exist at the moment are also probably lacking a few operations. On the plus side, it's should be pretty easy to create new widgets. You can get a feel for how the thing looks from an application programmer's perspective by looking at the source for the example. Looks neat, thanks! If I got this write, in dingo all web page content is created by running Haskell on the server side in run-time and then sending generated html + js to the client (browser). I am looking for the opposite - when client does more work running Javascript generated by Haskell in advance, the approach that Pyjamas use ( http://pyjs.org/) with Python to Javascript compilation. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Stuck on HXT basics
I'm quite stuck on getting HXT working to do my xml parsing, can you help me to get started? Even in http://www.haskell.org/haskellwiki/HXT#Getting_started:_Hello_world_examples the basic filter example that's given there in section 6: import Text.XML.HXT.Core import Text.XML.HXT.DOM.XmlTreeFilter selectAllText :: ArrowXml a = a XmlTree XmlTree selectAllText = deep isXText fails with the following error message. What could I be doing wrong? Couldn't match expected type `Data.Tree.NTree.TypeDefs.NTree XNode' with actual type `hxt-8.5.4:Data.Tree.NTree.TypeDefs.NTree hxt-8.5.4:Text.XML.HXT.DOM.TypeDefs.XNode' Expected type: a (Data.Tree.NTree.TypeDefs.NTree XNode) XmlTree Actual type: Text.XML.HXT.DOM.XmlTreeTypes.XmlFilter In the first argument of `deep', namely `isXText' In the expression: deep isXText On the other hand, perhaps you can suggest something other than HXT - my needs would be taking heavy XML's (a lot of little-neccessary structure, but correctly validated), extracting text tokens from it and outputting them with some light tagsoup annotation. Regards, Peteris ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Stuck on HXT basics
On Mon, Jan 30, 2012 at 3:06 PM, Pēteris Paikens peter...@gmail.com wrote: I'm quite stuck on getting HXT working to do my xml parsing, can you help me to get started? Even in http://www.haskell.org/haskellwiki/HXT#Getting_started:_Hello_world_examples the basic filter example that's given there in section 6: import Text.XML.HXT.Core import Text.XML.HXT.DOM.XmlTreeFilter selectAllText :: ArrowXml a = a XmlTree XmlTree selectAllText = deep isXText fails with the following error message. What could I be doing wrong? Couldn't match expected type `Data.Tree.NTree.TypeDefs.NTree XNode' with actual type `hxt-8.5.4:Data.Tree.NTree.TypeDefs.NTree hxt-8.5.4:Text.XML.HXT.DOM.TypeDefs.XNode' Expected type: a (Data.Tree.NTree.TypeDefs.NTree XNode) XmlTree Actual type: Text.XML.HXT.DOM.XmlTreeTypes.XmlFilter In the first argument of `deep', namely `isXText' In the expression: deep isXText On the other hand, perhaps you can suggest something other than HXT - my needs would be taking heavy XML's (a lot of little-neccessary structure, but correctly validated), extracting text tokens from it and outputting them with some light tagsoup annotation. Regards, Peteris ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe You could try xml-conduit[1] instead. I use it extensively at work. There's an appendix in the Yesod book[2] covering basic usage. Michael [1] http://hackage.haskell.org/package/xml-conduit [2] http://www.yesodweb.com/book/xml-enumerator ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Exceeding OS limits for simultaneous socket connections
Hi, I'm experiencing the accept: resource exhausted (Too many open files) exception when trying to use sockets in my Haskell program. The situation: - Around a dozen Linux machines running my Haskell program, transmitting thousands of messages to each other, sometimes within a small period of time. - I'm using the Network.Socket.ByteString.Lazy module to send and receive lazy bytestrings - The socket sent to the getMsg is bound and is listening, and is not closed until the program exits. getMsg is called in a loop to receive lazy bytestring from remote nodes. The socket is initialized with: sock - Network.Socket.socket (addrFamily myAddr) Stream defaultProtocol bindSocket sock (addrAddress myAddr) listen sock 10 Here's the code: sendMsg :: Maybe HostName - Int - Lazy.ByteString - IO () sendMsg dest sckt msg = do result - try $ withSocketsDo $ do addrinfos - getAddrInfo Nothing dest (Just (show sckt)) let serveraddr = head addrinfos sock - socket (addrFamily serveraddr) Stream defaultProtocol connect sock (addrAddress serveraddr) sendAll sock msg sClose sock case result of Left (ex::IOException) - return () -- permit send failure Right _ - return () getMsg :: Socket - IO Lazy.ByteString getMsg sock = do result - try $ withSocketsDo $ do (conn, addr) - accept sock getContents conn case result of Left (ex::IOException) - putStrLn (show ex) getMsg sock Right msg - return msg The current topology is a master/slave setup. For some programs that use these functions above, `sendMsg' is called thousands of times in quick succession on the remote nodes, where the destination of the `sendAll' function is the master node. Here's the maximum number of simultaneous sockets I am permitted to have open on my Linux machines: $ ulimit -n 1024 Indeed, when I experience the accept: resource exhausted (Too many open files) exception, I check the number of open sockets, which exceeds 1024, by looking at the contents of the directory: ls -lah /proc/prod_id/fd It is within the getContents function that, once the lazy bytestring is fully received, the socket is shutdown http://goo.gl/B6XcV : shutdown sock ShutdownReceive There seems to be no way of limiting the number of permitted connection requests from remote nodes. What I am perhaps looking for is a mailbox implementation on top of sockets, or another way to avoid this error. I am looking to scale up to 100's of nodes, where the possibility of more than 1024 simultaneous socket connections to one node is increased. Merely increasing the ulimit feels like a temporary measure. Part of the dilemma is that the `connect' call in `sendMsg' does not throw an error, despite the fact that it does indeed cause an error on the receiving node, by pushing the number of open connections to the same socket on the master node, beyond the 1024 limit permitted by the OS. Am I missing something? One would have thought such a problem occurs frequently with Haskell web servers and the like.. ? -- Rob Stewart ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Stuck on HXT basics
Couldn't match expected type `Data.Tree.NTree.TypeDefs.NTree XNode' with actual type `hxt-8.5.4:Data.Tree.NTree.TypeDefs.NTree hxt-8.5.4:Text.XML.HXT.DOM.TypeDefs.XNode' perhaps you have installed several (conflicting) versions of packages. I use hxt = 9, and here is some example code: http://dfa.imn.htwk-leipzig.de/cgi-bin/gitweb.cgi?p=tpdb.git;a=tree;f=TPDB/XTC;hb=master Best - J.W. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Stuck on HXT basics
Yep, that does seem to be the case - cabal shows Versions installed: 8.5.4, 9.1.6. The module referenced in the website example - Text.XML.HXT.DOM.XmlTreeFilter and function isXText - has only old packages, so when installing hxt I got version 9.1.6, but from hxt-filter I got hxt 8.5.4, so that's why the example fails. Peteris On Mon, Jan 30, 2012 at 3:42 PM, Johannes Waldmann waldm...@imn.htwk-leipzig.de wrote: Couldn't match expected type `Data.Tree.NTree.TypeDefs.NTree XNode' with actual type `hxt-8.5.4:Data.Tree.NTree.TypeDefs.NTree hxt-8.5.4:Text.XML.HXT.DOM.TypeDefs.XNode' perhaps you have installed several (conflicting) versions of packages. I use hxt = 9, and here is some example code: http://dfa.imn.htwk-leipzig.de/cgi-bin/gitweb.cgi?p=tpdb.git;a=tree;f=TPDB/XTC;hb=master Best - J.W. ___ 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] strict version of Haskell - does it exist?
On Mon, Jan 30, 2012 at 6:24 AM, Malcolm Wallace malcolm.wall...@me.comwrote: On 29 Jan 2012, at 22:25, Ertugrul Söylemez wrote: A strict-by-default Haskell comes with the implication that you can throw away most of the libraries, including the base library. So yes, a strict-by-default Haskell is very well possible, but the question is whether you actually want that. I wouldn't, because a lot of my code relies on the standard semantics. At work, we have a strict version of Haskell, and indeed we do not use the standard libraries, but have built up our own versions of the ones we use. However, our compiler is smart enough to transform and optimise the source code *as if* it were non-strict: it is only at runtime that things are evaluated strictly. This means that, in general, you can rely on the standard semantics to a surprisingly large extent. I wanted to emphasize Malcolm's point here. Optimizing using the original Haskell semantics turned out to be pretty important back when I was working on Eager Haskell. For example, a lot of Haskell functions are written in the following style: f a b c | guard1 d = g h i | guard2 e = h | guard3 f = i | otherwise = j where d = ...expensive... e = ...expensive... f = ...expensive... g = ...expensive... h = ...expensive... i = ...expensive... j = ... expensive... An an ordinary procedural language, where function calls in g, h, i, and j might have side effects, we can't sink bindings down to the point of use. Even in the absence of side effects, we have to account for the fact that some of these computations are used in some -- but not all -- right-hand sides, and that often we need to do some inlining to discover that a value isn't going to be used. It turns out Haskell code relies on this sort of thing all over the place, and simply coding around it leads to deeply-nested let bindings that walk off the right-hand edge of the screen. It's not difficult to rewrite most of the prelude functions in this style, but it's no longer pretty, and it's recognizably not idiomatic Haskell. However, bulk operations do transform the entire data structure, not merely the fragments that are needed for the onward computation, so it can often be a net performance loss. The standard lazy computational paradigm of generate-and-test is therefore hideously expensive, on occasion. This was a huge issue in Eager Haskell. By far our worst performance was on stream-like programs that generated infinite lists of results, and then sliced away the useless tail. With completely strict evaluation, this of course doesn't work at all, but it can be tricky to bound the required sizes of inputs even if you know how much of the output you want (imagine a call to takeWhile or filter on an infinite list). -Jan-Willem Maessen Regards, Malcolm ___ 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] Exceeding OS limits for simultaneous socket connections
What you can try - reduce amount of threads running at the same time - thus accept less connections. AFAIK the OS has a buffer caching the connection request for a while - thus this may just work. Using STM it would be trivial to implement it: try incrementing a var, if it is 100 fail. It will only be retried if the vars change or such, correct? When you're done decrease the number. - increase limit (you said this is no option) - replace getContents conn by something strict and close the handle yourself? (not sure about this.) Eg yesod introduces conduits for that reason = http://www.yesodweb.com/blog/2011/12/conduits There are alternative implementations on hackage. - not sure how many apps are running at the same time. But instead of creating many connections from machine A to B you could try establishing a permanent connection sending binary streams or chunk the messages. Eg wait for 5 requests - then bundle them and send them all at once (depneds on your implementation whether this could be an option). That's all which comes to my mind. Probably more experienced users have additional ideas. Thus keep waiting and reading. Marc Weber ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] [Haskell] ANNOUNCE multiarg - parser combinators for command line parsing
On Sun, 29 Jan 2012, Simon Meier wrote: I'm currently using Neil Mitchell's cmdargs package [1]. How does your package compare to that? Last time I checked cmdargs it was not referential transparent. Is multiarg better in this respect? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] strict version of Haskell - does it exist?
Alexander Bernauer alex-hask...@copton.net wrote: On Sun, Jan 29, 2012 at 11:25:09PM +0100, Ertugrul Söylemez wrote: First of all, /learning/ to optimize Haskell can be difficult. The optimizing itself is actually fairly easy in my experience, once you understand how the language works. Given the fact that you have obviously mastered the learning part of this, do you have any recommendations on what to read or on how to proceed in order to learn how to optimize Haskell code? I can imagine, it's not only about understanding the language itself, but also about understanding how your compiler and its switches work, being able to find the hot spots in your code, being able to measure the effects of your changes, developing a good sense for the tradeoffs, etc. So far, I have only stumpled upon chapter 25 of Real World Haskell. Anything else you might recommend? That's the tricky part about this. Unfortunately the monad tutorial fallacy [1] applies here. At some point it makes click and suddenly you see all the data dependencies. If you were schizophrenic, you would probably see little arrows all over your code. What helped me a bit was to read the Wikibooks page about Haskell's denotational semantics [2], but other than that I pretty much learned it by myself. In any case it's helpful to use 'seq' explicitly instead of bang patterns. Personally I never use bang patterns, but always use seq, strict patterns or guards with strict functions. Example: add :: Integer - Integer - Integer add x 0 = x add x y = (add $! succ x) (pred y) Here the pattern forces the second argument, so there is no need to force it yourself. However, nothing forces the first argument, so it needs to be forced manually, in this case by using ($!). [1]: http://byorgey.wordpress.com/2009/01/12/ abstraction-intuition-and-the-monad-tutorial-fallacy/ [2]: http://en.wikibooks.org/wiki/Haskell/Denotational_semantics Greets, Ertugrul -- nightmare = unsafePerformIO (getWrongWife = sex) http://ertes.de/ signature.asc Description: PGP signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Some thoughts on Type-Directed Name Resolution
Quoth Steve Horne sh006d3...@blueyonder.co.uk, On 30/01/2012 07:09, Donn Cave wrote: ((separate . crack . .smallEnd) egg).yolk (f egg).yolk where f = separate . crack . .smallEnd Scary - that .smallEnd worries me. It's like a field is being referenced with some magical context from nowhere. Obviously I need to read that full proposal. As I said: (assuming for the sake of discussion a functional dot notation .field = \ r - r.field) By that, I meant to say that I just made that up. I am sure that various proposals have made some notational provision for `\ r - r.field', but it may or may not be `.field', I don't recall. But that's all the magic there is to it. Either you have a notational shorthand for it, or you're obliged to write out `\ r - r.field' Donn ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] strict version of Haskell - does it exist?
Replying to all replies at once: Malcolm Wallace At work, we have a strict version of Haskell :-) which proofs that it is worth thinking about it. Ertugrul If you want to save the time to learn how to write efficient Haskell programs, you may want to have a look into the Disciple language. Yes - I will. Its on my TODO list for at least 12 month :( Not sure whether there are parser combinator libraries yet. @ Herbert Valerio Riedel (suggesting aeson) I gave it yet another try - see below. It still fails. @ Felipe Almeida Lessa (suggesting conduits and atto parsec) I mentioned that I already tried it. Counting lines only was a lot slower than counting lines and parsing JSON using PHP. @ Chris Wong flag is that strictness isn't just something you turn on and off willy-nilly You're right. But those features are not required for all tasks :) Eg have a look at Data.Map. Would a strict implementation look that different? I came up with this now. Trying strict bytestrings and Aeson. note the LB.fromChunks usage below to turn a strict into a lazy bytestring. Result: PHP script doing the same runs in 33secs (using the AFindCheckoutsAndContacts branch) The haskell program below - I stopped it after 8 min. (At least it does no longer cause my system to swap .. You're right: I could start profiling. I could learn about how to optimize it.) But why? The conclusion is that if I ever use yesod - and if I ever want to analyse logs - I should call PHP from yesod as external process !? :-( Even if I had a core i7 (8 threads in parallel) I still would not be sure whether Haskell would be the right choice. I agree that I assume that all data fits into memory so that piecewise evaluation doesn't matter too much. Thanks for all your help - it proofs once again that the Haskell community is the most helpful I know about. Yet I think me being the programmer Haskell is the wrong choice for this task. Thanks Marc Weber my new attempt - now I should start profiling.. Looks like I haven't built all libs with profiling support .. import Data.Aeson.Types import Data.Aeson import Data.List import Control.Applicative import Debug.Trace import qualified Data.Map as M import Action import Data.Aeson.Parser as AP import qualified Data.ByteString.Lazy as LB import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as LBC8 data Action = ACountLine | AFindCheckoutsAndContacts -- lines look like this: -- {id:4ee535f01550c,r:,ua:Mozilla\/5.0 (compatible; bingbot\/2.0; +http:\/\/www.bing.com\/bingbot.htm),t:1323644400,k:XXX,v:YY} data Item = Item { id :: SB.ByteString, ua :: SB.ByteString, t :: Int, k :: SB.ByteString, v :: SB.ByteString } instance FromJSON Item where parseJSON (Object v) = Item $ v .: id * v .: ua * v .: t * v .: k * v .: v parseJSON _ = empty run :: Action - [FilePath] - IO () run AFindCheckoutsAndContacts files = do -- find all ids quering the server more than 100 times. -- do so by building a map counting queries (lines :: [BS.ByteString]) - fmap (concat . (map LBC8.lines) ) $ mapM BS.readFile files let processLine :: (M.Map BS.ByteString Int) - BS.ByteString - (M.Map BS.ByteString Int) processLine st line = case decode' (LB.fromChunks [line]) of Nothing - st -- traceShow (bad line ++ (LBC8.unpack line)) st Just (Item id ua t k v) - M.insertWith (+) k 1 st let count_by_id = foldl' processLine (M.empty) lines mapM_ print $ M.toList $ M.filter ( 100) count_by_id ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] strict version of Haskell - does it exist?
On Mon, Jan 30, 2012 at 2:12 PM, Marc Weber marco-owe...@gmx.de wrote: @ Felipe Almeida Lessa (suggesting conduits and atto parsec) I mentioned that I already tried it. Counting lines only was a lot slower than counting lines and parsing JSON using PHP. Then please take a deeper look into my code. What you said that you've tried is something else. Cheers, -- Felipe. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] strict version of Haskell - does it exist?
Marc Weber wrote: Replying to all replies at once: Malcolm Wallace At work, we have a strict version of Haskell :-) which proofs that it is worth thinking about it. But doesn't necessarily prove that it's a good idea. Just (Item id ua t k v) - M.insertWith (+) k 1 st Does replacing this by insertWith' help? Roman ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] [Haskell Cafe] strict version of Haskell - does it exist?
Is there any document describing why there is no ghc --strict flag making all code strict by default? Wouldn't such a '--strict' flag turn Haskell/GHC into a better C/gcc compiler? I agree that a strict flag would turn Haskell into C--but that's a perversion of Haskell. Almost all Haskell code I write depends critically on laziness. Sure, there are little bits here and there that would run faster if I carefully decorated them with strict flags. But the genius of Haskell is architectural clarity, achieved in no small part by relegating nasty issues of sequencing to the implementation. If you even have to think once about what needs to be strict or non-strict, then non-strict is the only viable default. I can't imagine writing any interesting Haskell code that will successfully run all strict. Doug McIlroy ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] strict version of Haskell - does it exist?
Marc Weber wrote: Replying to all replies at once: Malcolm Wallace At work, we have a strict version of Haskell :-) which proofs that it is worth thinking about it. But doesn't necessarily prove that it's a good idea. Just (Item id ua t k v) - M.insertWith (+) k 1 st Does replacing this by insertWith' help? Roman ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Some thoughts on Type-Directed Name
| What would really, really help me is for someone to have a look at the 'solution' I | posted to the difficulties SPJ saw with the SORF approach. (I ref'd it in my reply to In response to your plea, I took a look at your post http://www.haskell.org/pipermail/glasgow-haskell-users/2011-December/021298.html Some thoughts * I don't think you need GetTy at all. The attached version of your code gets rid of it. * Your trick with SetrTy does, I think, support type-changing update. Good. (Whether type-changing update is itself a valuable enough feature to be worth the extra complexity, I'm not certain, but perhaps that's a separate matter.) * Your trick with SetTy to support update of polymorphic fields is, I belive, an (ingenious) hack that does not scale. I think it works only for fields that are quantified over one type variable with no constraints. So, I think that update of polymorphic fields remains problematic. Simon | -Original Message- | From: glasgow-haskell-users-boun...@haskell.org [mailto:glasgow-haskell-users- | boun...@haskell.org] On Behalf Of Anthony Clayden | Sent: 28 January 2012 09:25 | To: Greg Weber; Steve Horne; Haskell Cafe | Cc: glasgow-haskell-us...@haskell.org | Subject: Re: [Haskell-cafe] Some thoughts on Type-Directed Name | | There is an effort underway to make Haskell's Records better. The | discussion is ongoing on the ghc-users mail list, ... | in the direction of making the most minimal changes possible to | achieve some simple record name-spacing. | | Thanks, | Greg Weber | | Thank you Greg, | | Yes I know, and I have been trying to follow along (intermittently). Thank you for | your attempts to marshall the discussion. | | What would really, really help me is for someone to have a look at the 'solution' I | posted to the difficulties SPJ saw with the SORF approach. (I ref'd it in my reply to | Steve.) | http://www.haskell.org/pipermail/glasgow-haskell-users/2011- | December/021298.html | | It seemed from my testing to address the needs. Since I got it working in GHC | 7.2.1, there's a good chance it will need only minimal changes to implement | (I'm thinking mostly syntactic sugar) -- providing of course that it is workable and | generalisable enough. | | It could possibly benefit from some of the new Kind-level stuff in 7.4.1 (that SPJ | used, but wasn't available to me at the time). | | I keep trying to make the time to write up the full proposal on the Wiki. I see it as | a 'tweak' to SORF. Given that I'm supposed to have a day job, I'm reluctant to | make time until/unless someone else double-checks whether I'm barking up the | wrong tree. | | Anthony | | | | | ___ | Glasgow-haskell-users mailing list | glasgow-haskell-us...@haskell.org | http://www.haskell.org/mailman/listinfo/glasgow-haskell-users ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] space leak when repeatedly calling Control.Monad.State.Strict.modify
Yves Parès wrote: Have you tried to compile your code with optimisations? I guess GHC's strictness analysis would find strict evaluation is better here. The original code I saw this happen to the wild was built with -O2. I didn't try building the test case with optimisations. -- see shy jo signature.asc Description: Digital signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceeding OS limits for simultaneous socketconnections
Quoth Marc Weber marco-owe...@gmx.de, ... - replace getContents conn by something strict and close the handle yourself? (not sure about this.) That's an easy one to try, right? Just force evaluation of the getContents return value, in getMsg. If lazy I/O is the culprit here, it wouldn't be the first time. But that will only reduce the magnitude of the problem (albeit perhaps vastly reduce), and as you say, the more reliable solution is to limit the number of concurrent accepts, and concurrent open-and-sends. It isn't like socket I/O really benefits from unlimited concurrency, as all the data is still serially pushed through a wire; you just need enough concurrent peer connections to keep the interface busy. Donn ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ANN: combinatorics
-- combinatorics 0.1.0 The combinatorics package offers efficient *exact* computation of common combinatorial functions like the binomial coefficients and factorial. (For fast *approximations*, see the math-functions package instead.) Shameless self-promotion: The combinat package (which deliberately does not try to own the valuable namespace Math.Combinatorics) is a more extensive combinatorics library: http://hackage.haskell.org/package/combinat While the main focus is the generation of combinatorial objects themselves, counting functions and common number sequences like the above are also offered. Even though the binomial and factorial definition in this package are the naive ones, a quick experiment imply that the differences start show themselves around 100,000 factorial, or choosing 50,000 elements out of 100,000, which is probably a rather specialized use case. The primes function in the combinat package is based on an old Cafe thread, and actually seems to be faster than the one in the combinatorics package. In any case, I may switch to the faster algorithms in the future :) Balazs ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Speculative Parallelism
Dear List, my question is in which cases, I could understand the speculative parallelism in parallel Haskell? Does the case in which all and the same number of created sparks are converted by both original and second generation strategies, speak of the speculative parallelism effect? If it does not, how can I prove the argument that indicating speculative parallelism could be exploited in second generation strategies while it is not possible to exploit when usages of original ones are in question? Kind regards, Burak. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] help with safecopy + acid-state
Felipe Almeida Lessa felipe.lessa at gmail.com writes: data T_orig = T_orig Foo $(deriveSafeCopy 0 'base ''T_orig) data T = T Foo Bar $(deriveSafeCopy 0 'extension ''T) instance Migrate T where type MigrateFrom T = T_Orig ... As you can read from deriveSafeCopy's documentation [1], you need to increase the version of your data type (e.g. change that zero to one). Thanks - which zero? (there are two of them.) and how does it play together with Data.Acid? Can I really rename old.T = new.T_orig ? It looks as if then tries to load the wrong acid-state snapshot. Best - J.W. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] help with safecopy + acid-state
On Mon, Jan 30, 2012 at 4:46 PM, Johannes Waldmann waldm...@imn.htwk-leipzig.de wrote: Thanks - which zero? (there are two of them.) You should not change the deriveSafeCopy of your old data type. The only allowed change is renaming your data type (see below). You should increment the version of the new version of your data type, akin to releasing a new version of a library. Can I really rename old.T = new.T_orig ? It looks as if then tries to load the wrong acid-state snapshot. The name of your data type doesn't matter as acid-state doesn't store that on the disk. HTH, -- Felipe. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] strict version of Haskell - does it exist?
Hi, Am Montag, den 30.01.2012, 10:52 +0100 schrieb Alexander Bernauer: On Sun, Jan 29, 2012 at 11:25:09PM +0100, Ertugrul Söylemez wrote: First of all, /learning/ to optimize Haskell can be difficult. The optimizing itself is actually fairly easy in my experience, once you understand how the language works. Given the fact that you have obviously mastered the learning part of this, do you have any recommendations on what to read or on how to proceed in order to learn how to optimize Haskell code? I can imagine, it's not only about understanding the language itself, but also about understanding how your compiler and its switches work, being able to find the hot spots in your code, being able to measure the effects of your changes, developing a good sense for the tradeoffs, etc. So far, I have only stumpled upon chapter 25 of Real World Haskell. Anything else you might recommend? Although I would not claim that I have mastered this, I did recently hold a talk that touched some of these issues, and also exhibits a case where you want something more fine-grained than just strictness or lazyness. From your name I think it is safe to point you to a German document: http://www.joachim-breitner.de/blog/archives/539-Guest-lecture-on-Haskell-performance.html Greetings, Joachim -- Joachim nomeata Breitner m...@joachim-breitner.de | nome...@debian.org | GPG: 0x4743206C xmpp: nome...@joachim-breitner.de | http://www.joachim-breitner.de/ signature.asc Description: This is a digitally signed message part ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] TCP Server
On 12-01-28 06:56 AM, Felipe Almeida Lessa wrote: On Sat, Jan 28, 2012 at 9:40 AM, Yves Parèsyves.pa...@gmail.com wrote: I think there is still no consensus on which iteratee library is the one to use. There are at least iteratee, enumerator, iterIO, conduit, and pipes. The reusability of your libary depends on the choice of iteratee-style library you select. Yes, and IMO this is a growing problem. Since iteratees were designed, a lot of different libraries providing this kind of service have appeared. Of course they all have advantages and inconvenients, but some libraries that could be compatible are not, because they rely on a different iteratee-ish package. For instance pipes (as its documentation states) is really like iteratee... but with more concrete names. Still it's sufficient to break compatibility. In principle it's possible to have some code that converts functions between these different iteratee packages -- at least between iteratee, enumerator and iterIO since these seem to have more or less the same implementation ideas. It's not only possible, it's done. The coroutine-enumerator and coroutine-iteratee packages convert to and from the enumerator and iteratee packages, using monad-coroutine as a bridge. The conversions are bare-bone, and I don't know if anybody has ever used them in practice. They still prove the concept. Converting from pipes may be possible, but to pipes seems pretty difficult since pipes sweeps IO under the rug. A Pipe appears to be just a specialized Coroutine from the monad-coroutine package with its type arguments expanded, so it would also be convertible. -- Mario Blazevic mblaze...@stilo.com Stilo International This message, including any attachments, is for the sole use of the intended recipient(s) and may contain confidential and privileged information. Any unauthorized review, use, disclosure, copying, or distribution is strictly prohibited. If you are not the intended recipient(s) please contact the sender by reply email and destroy all copies of the original message and any attachments. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ANN: combinatorics
* wren ng thornton w...@freegeek.org [2012-01-29 17:30:34-0500] On 1/29/12 5:48 AM, Roman Cheplyaka wrote: * wren ng thorntonw...@freegeek.org [2012-01-28 23:06:08-0500] * Math.Combinatorics.Primes: provides the prime numbers via Runciman's lazy wheel sieve algorithm. Provided here since efficient algorithms for combinatorial functions often require prime numbers. The current version memoizes the primes as an infinite list CAF, which could lead to memory leaks in long-running programs with irregular access to large primes. I'm looking into a GHC patch to allow resetting individual CAFs from within compiled programs so that you can explicitly decide when to un-memoize the primes. (In GHCi when you reload a module all the CAFs are reset. However, there's no way to access this feature from within compiled programs as yet.) Why not to make it more pure? That is, return a lazy list of Ints (but not a CAF), which user can throw away by the usual GC means? The functions from the other modules that use primes would have to be put in a Reader monad. That would make it a little bit more awkward to use, but personally I'd prefer that over memory leaks. I'd also prefer a more pure solution, but I don't think that the Reader monad is the right tool here. I played around with that approach, but it requires extremely invasive changes to client code, obfuscating what should be simple mathematical formulae. And, it's too fragile, exposing the implementation in a way that breaks client code should I change a non-prime-using algorithm to a prime-using one, or vice versa. The fragility could be partially avoided by providing both prime-using and non-prime-using algorithms, but then that forces users to decide which one they want--- and if their only concern is performance, then they'd have to go through the code-breaking refactoring anyways, just to determine which is faster for their application. Makes sense; but doesn't making the monad abstract and putting all functions in the monad address the fragility issue? -- Roman I. Cheplyaka :: http://ro-che.info/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] [Haskell Cafe] strict version of Haskell - does it exist?
On 31/01/2012, at 5:47 AM, Doug McIlroy wrote: Is there any document describing why there is no ghc --strict flag making all code strict by default? Wouldn't such a '--strict' flag turn Haskell/GHC into a better C/gcc compiler? I agree that a strict flag would turn Haskell into C--but that's a perversion of Haskell. On the other hand, a designed-to-be-strict language-and-libraries with close-to-Haskell *syntax* would be nice. I recently described F# as combining the beauty of Caml with the functional purity of C# -- both of course are like the snakes of Ireland. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] [Haskell Cafe] strict version of Haskell - doesit exist?
Quoth Richard O'Keefe o...@cs.otago.ac.nz, ... On the other hand, a designed-to-be-strict language-and-libraries with close-to-Haskell *syntax* would be nice. I recently described F# as combining the beauty of Caml with the functional purity of C# -- both of course are like the snakes of Ireland. Ouch, the beauty of Caml, tsk. I guess it may not have been a very lively project of late, but the Timber language, a descendant of O'Haskell, is supposed to be strict, I suppose because they were using it in real time controllers. Donn ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] [Haskell] ANNOUNCE multiarg - parser combinators for command line parsing
On Mon, Jan 30, 2012 at 03:19:47PM +0100, Henning Thielemann wrote: On Sun, 29 Jan 2012, Simon Meier wrote: I'm currently using Neil Mitchell's cmdargs package [1]. How does your package compare to that? Last time I checked cmdargs it was not referential transparent. Is multiarg better in this respect? Absolutely, multiarg is 100% referentially transparent. The main data type in multiarg is a monad transformer, so if the programmer really wants to write something that does IO or is otherwise not referentially transparent, then she can. Certainly there is no need to do this though. I'd expect one would usually put the transformer on top of Identity, as I have always done so far. But the option is there if you want it. --Omari ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Invitation to connect on LinkedIn
LinkedIn I'd like to add you to my professional network on LinkedIn. - Sunny Sunny Basi Software Development Engineer Intern at Amazon.com Greater Seattle Area Confirm that you know Sunny Basi: https://www.linkedin.com/e/uc6lxc-gy2lv1bv-z/isd/5727371010/HFPCz0eC/?hs=falsetok=09bkUGyiX_Kl41 -- You are receiving Invitation to Connect emails. Click to unsubscribe: http://www.linkedin.com/e/uc6lxc-gy2lv1bv-z/XvIdBwmueHfd6vFMPXXdLaqreCbl5oOSpPTFPU/goo/haskell-cafe%40haskell%2Eorg/20061/I1992906321_1/?hs=falsetok=3aJUMubkr_Kl41 (c) 2012 LinkedIn Corporation. 2029 Stierlin Ct, Mountain View, CA 94043, USA. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe