[Haskell-cafe] how to force hackage to use ghc 6.12.3
Hi, I have been releasing packages on hackage that do not build with ghc 7.0.* due to a bug that will be fixed in ghc 7.2.1. (One of the packages is http://hackage.haskell.org/package/AERN-Basics) I was hoping hackage will try also ghc 6.12.3 but it does not. Is there some way I can change the cabal file to help hackage to compile it with 6.12.3 and generate haddock? The package requires base = 4 so I cannot try base 4. Michal -- |-| Dr. Michal Konecny, Computer Science, Aston University |-| Room MB212D | Tel +44 121 204 3462 | Fax +44 121 204 3681 |-| http://www.aston.ac.uk/~konecnym |-| OpenPGP key http://www.aston.ac.uk/~konecnym/ki.aston -- |o| Michal Konecny mikkone...@gmail.com |o|http://www-users.aston.ac.uk/~konecnym/ |o|office: (+42) (0)121 204 3462 |o| PGP key http://www-users.aston.ac.uk/~konecnym/ki.aston 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] trying to cabal install lambdabot, failure on 'random' package
On May 8, 2011, at 3:34 PM, Albert Y. C. Lai wrote: On 11-05-08 03:24 AM, Sean Perry wrote: package random-1.0.0.3 requires time-1.2.0.3 package random-1.0.0.3 requires time-1.2.0.4 In addition to unregistering --user random-1.0.0.3, also unregister --user time-1.2.0.4, the real culprit. The real culprit is why you are infected with a duplicate random-1.0.0.3. If you let time-1.2.0.4 live, the problem will just recur infinitely. See my http://www.vex.net/~trebla/haskell/sicp.xhtml for why this happens and what it costs you. And never upgrade packages piecemeal like this again. Thank you for the article. I went looking and had a 6. and two 7. releases of the haskell platform and a bunch of locally installed things that it turns out were migrated poorly. It would be nice if 'cabal upgrade' worked and was not deprecated. Also, installing a new haskell platform could comment on the fact that it is leaving a bunch of old most likely garbage behind and how to resolve it. Tonight I just did not bother and wiped Haskell completely and reinstalled. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ANN: Newt - command-line template instantiation tool library
2011/5/9 bri...@aracnet.com: On Sun, 8 May 2011 16:23:59 -0700 Rogan Creswick cresw...@gmail.com wrote: Newt scans the input (either a file, directory or stdin) for tags marked with tagName [1], then replaces those entries with values specified on the command line, producing either a new file, modifying the input template in place (--inplace), writing to stdout, or writing to a directory. This is a useful tool ! I would like to suggest allowing customization of the syntax to indicate a tag, e.g. {# #} instead of (You just knew someone was going to say that, right ? :-) Hello, Did you see his [1] footnote in his mail? Cheers, Thu ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Apache license, any drawbacks for Haskell packages?
On Sun, May 8, 2011 at 1:25 PM, Magnus Therning mag...@therning.org wrote: Are there any drawbacks to using the Apache license for Haskell packages? I don't think so. It looks to be almost identical to using BSD3, which is already quite popular for haskellers. This seems like a good write up of the apache license: http://www.oss-watch.ac.uk/resources/apache2.xml Jason ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Apache license, any drawbacks for Haskell packages?
On Mon, May 9, 2011 at 10:59, Jason Dagit dag...@gmail.com wrote: On Sun, May 8, 2011 at 1:25 PM, Magnus Therning mag...@therning.org wrote: Are there any drawbacks to using the Apache license for Haskell packages? I don't think so. It looks to be almost identical to using BSD3, which is already quite popular for haskellers. I would consider this, in itself, to be a small but significant disadvantage. Anyone who uses Haskell is going to know (and probably be comfortable with) the BSD3 license. If I find Apache-licensed code, I now have to look that up, determine the differences between it and BSD3, find out whether it's compatible with the GPL and BSD3. Basically, the cost of introducing *any* new license to a software ecosystem is non-zero. Of course, a widespread license like Apache is better than making up your own. --Max ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Apache license, any drawbacks for Haskell packages?
* Jason Dagit dag...@gmail.com [2011-05-09 01:59:46-0700] On Sun, May 8, 2011 at 1:25 PM, Magnus Therning mag...@therning.org wrote: Are there any drawbacks to using the Apache license for Haskell packages? I don't think so. It looks to be almost identical to using BSD3, which is already quite popular for haskellers. This seems like a good write up of the apache license: http://www.oss-watch.ac.uk/resources/apache2.xml Jason Here is a more detailed analysis: http://www.ifosslr.org/ifosslr/article/view/42 -- Roman I. Cheplyaka :: http://ro-che.info/ Don't worry what people think, they don't do it very often. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] how to force hackage to use ghc 6.12.3
On Monday 09 May 2011 08:54:49, Michal Konečný wrote: I was hoping hackage will try also ghc 6.12.3 but it does not. Is there some way I can change the cabal file to help hackage to compile it with 6.12.3 and generate haddock? The package requires base = 4 so I cannot try base 4. base = 4 4.3 should do it ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] repa Shape help
On 09/05/2011, at 15:31 , bri...@aracnet.com bri...@aracnet.com wrote: main = do let x = A.fromList (AS.shapeOfList [2, 2]) ([1.0, 2.0, 3.0, 4.0]::[Double]) putStrLn $ show x test_repa.hs:10:13: Ambiguous type variable `sh' in the constraint: `Shape sh' arising from a use of `show' at test_repa.hs:10:13-18 Probable fix: add a type signature that fixes these type variable(s) Failed, modules loaded: none. After much staring at the type signatures I finally figured out that adding a type annotation to x of : :: Array DIM2 Double would fix the problem, but I'm not completely clear as to why. Because the GHC type system doesn't (yet) know that applying shapeOfList to a two element array should yield a DIM2. after all fromList is typed: (Shape sh, Elt a) = sh - [a] - Array sh a Since it knows [a] is [Double] and sh must be - well I'm not really clear on what sh is supposed to be. therein lies my problem. Although it does seem that sh can be darn near anything, which is probably why it was ambiguous. Shape is dimensionally of the array. The only valid choices for sh are DIM1, DIM2, DIM3 etc for 1 dimensional, 2 dimensional etc arrays. At one point I had tried something like (2 :. 2) and got a whole host of errors for that too, except that DIM2 is defined in exactly that way, so it's not at all obvious why that didn't work. Try (Z :. 2 :. 3). This is basically a list containing the column and row lengths. Similar to (3 : 2 : []), except that the list extends to the left instead of the right. The Z constructor is equivalent to []. Cheers, Ben. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Apache license, any drawbacks for Haskell packages?
On Mon, May 9, 2011 at 10:10, Max Rabkin max.rab...@gmail.com wrote: On Mon, May 9, 2011 at 10:59, Jason Dagit dag...@gmail.com wrote: On Sun, May 8, 2011 at 1:25 PM, Magnus Therning mag...@therning.org wrote: Are there any drawbacks to using the Apache license for Haskell packages? I don't think so. It looks to be almost identical to using BSD3, which is already quite popular for haskellers. I would consider this, in itself, to be a small but significant disadvantage. Anyone who uses Haskell is going to know (and probably be comfortable with) the BSD3 license. If I find Apache-licensed code, I now have to look that up, determine the differences between it and BSD3, find out whether it's compatible with the GPL and BSD3. Basically, the cost of introducing *any* new license to a software ecosystem is non-zero. Of course, a widespread license like Apache is better than making up your own. Yes, I agree with that, both points. The code is for a tool (not a library). In the past I'd just release it under GPL, but I thought I'd take a closer look at the Apache license, based on a discussion I had a few weeks ago. /M -- Magnus Therning OpenPGP: 0xAB4DFBA4 email: mag...@therning.org jabber: mag...@therning.org twitter: magthe http://therning.org/magnus ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] how to force hackage to use ghc 6.12.3
On Mon, May 09, 2011 at 11:38:47AM +0200, Daniel Fischer wrote: On Monday 09 May 2011 08:54:49, Michal Konečný wrote: I was hoping hackage will try also ghc 6.12.3 but it does not. Is there some way I can change the cabal file to help hackage to compile it with 6.12.3 and generate haddock? The package requires base = 4 so I cannot try base 4. base = 4 4.3 should do it That will stop users from building it with ghc 7.0, but I'm afraid the build client only uses the latest version, so these won't be fixed until ghc 7.2 is released. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A long day with HXT
Hi Henry, I have just spent many hours staring at code and losing some hair. My hope is to save you the same experience someday. Here was my goal: Take some XML, like photo url=somewhere align=left alt=/ and replace the align attribute with a class attribute, but only if the value of the align attribute was not null. This led to to followed (hugely condensed) attempts: you could try the following: module Align where import Text.XML.HXT.Core doc = concat $ [ collection , photo url='somewhere' align='left' alt=''/ , photo url='somewhere' align='' alt=''/ , /collection ] main = runX ( constA doc readFromString [] writeDocument [withIndent yes] modifyAlt writeDocument [withIndent yes] ) modifyAlt = processTopDownUntil (isPhotoWithNonEmptyAlign `guards` addClassAttr) isPhotoWithNonEmptyAlign = hasName photo hasAttrValue align (not .null) addClassAttr = addAttr class someclass removeAttr align Cheers, Uwe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Template Haskell reified type.
Language.Haskell.TH.Type contains, among others, two constructors: TupleT Int and ListT. I can safely construct types using them, but reification returns ConT GHC.Tuple.(,) and ConT GHC.Types.[] respectively. This is not fair asymmetry, I think. Also, it took purity from one of my functions while I debugged that problem. I had to make it into Q monad. ;) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Using Haskell to describe computer hardware.
http://thesz.mskhug.ru/svn/hhdl/ - main repository and http://thesz.mskhug.ru/svn/hhdl/examples/Simple.hs - three simple examples and http://thesz.mskhug.ru/svn/hhdl/MIPS-example/ - an attempt to describe MIPS-alike CPU using Haskell. Not yet done, it passes only simplest of tests (it fetches commands), but if you take a look at it you'll get an idea of what is going on. The goal is to create something along the lines of Bluespec, but as a DSeL in Haskell. Right now I concentrate on single-clock circuits, as they comprise most of hardware logic. I hacked together transformation of not-so-complex Haskell function definition into Haskell functions that operate on infinite streams. Of course, I tried my best to support calling other functions, conditional operators, pattern matching, etc, because that's what makes Haskell great and Bluespec has them too. Below is little explanation of three simple examples. First comes very simple function: $(transform [d| f1 :: (ToWires a, Num a) = (a,a) - a f1 (a,b) = a + b |]) After $(transform ...) you will have two functions: f1 and f1_S, the second one operates on streams. ToWires class in the context ensure that input and output values can be converted into arrays of bits when we'll get that part ready. The type of f1_S is: *Simple :t f1_S f1_S :: (ToWires a[a9GC], Num a[a9GC]) = (S a[a9GC], S a[a9GC]) - (S a[a9GC], S [String]) or put simply: *Simple :t f1_S f1_S :: (ToWires a, Num a) = (S a, S a) - (S a, S [String]) It accepts two streams and return two streams - value and logs. We could add messages into logs: $(transform [d| f2 :: (ToWires a, Num a) = (a,a) - a f2 (a,b) = s where s = a + b _display_a = a _display_b = b _display_s = s |]) f2 is just like f1, but when ran, it will produce logs about execution along the values. f2 used by runningSum, which compute a sum of values seen before current cycle: $(transform [d| runningSum :: (ToWires a, Num a) = a - a runningSum x = currentSum where nextSum = f2 (x,currentSum) currentSum = register 0 nextSum _display_currentSum = currentSum _display_x = x _display_nextSum = nextSum |]) runningSum uses latches. It latches nextSum to pass the value to the next cycle using register function. register accepts default value and a value to latch (stream of values to delay) . When the time will come for synthesizing circuits, our register's will become actual latches with reset and clk wires. This is how we test our runningSum_S with simple data: runningSumLogs :: IO () runningSumLogs = do mapM putStrLn $ map unlines $ take 5 $ toList_S $ snd $ runningSum_S (fromList_S [1::Int ..]) return () The output will be like the following: currentSum: 0 x: 1 nextSum: 1 nextSum_0 = Simple.f2 (x_1, currentSum_2): a: 1 b: 0 s: 1 currentSum: 1 x: 2 nextSum: 3 nextSum_0 = Simple.f2 (x_1, currentSum_2): a: 2 b: 1 s: 3 currentSum: 3 x: 3 nextSum: 6 nextSum_0 = Simple.f2 (x_1, currentSum_2): a: 3 b: 3 s: 6 Logs are nested and after label nextSum_0 = Simple.f2 (x_1, currentSum_2): we see logs from f2_S function. The code is in QUITE EXPERIMENTAL stage, but feel free to play and comment. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ANN: Newt - command-line template instantiation tool library
On Sun, May 8, 2011 at 10:38 PM, bri...@aracnet.com wrote: This is a useful tool ! I'm glad you think so too! I would like to suggest allowing customization of the syntax to indicate a tag, e.g. {# #} instead of (You just knew someone was going to say that, right ? :-) Indeed :) The tag syntax is controlled by two command-line flags: --prefix=... and --suffix=... It can be difficult to get the desired strings past both the shell and the regular expression compiler (although that last bit is changing... Josh Hoyt sent a patch that switches to basic string inspection, which should make this much simpler to use.) --Rogan I only mention this in the hopes that it still early enough for you to write the code in such a way to allow this even if you don't implement it right away. Brian ___ 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] ANNOUNCE: iterIO-0.1 - iteratee-based IO with pipe operators
From: dm-list-haskell-c...@scs.stanford.edu At Fri, 6 May 2011 10:10:26 -0300, Felipe Almeida Lessa wrote: So, in the enumerator vs. iterIO challenge, the only big differences I see are: a) iterIO has a different exception handling mechanism. b) iterIO can have pure iteratees that don't touch the monad. c) iterIO's iteratees can send control messages to ther enumerators. d) iterIO's enumerators are enumeratees, but enumerator's enumerators are simpler. e) enumerator has fewer dependencies. f) enumerator uses conventional nomenclature. g) enumerator is Haskell 98, while iterIO needs many extensions (e.g. MPTC and functional dependencies). Anything that I missed? The bottomline: the biggest advantage I see right now in favor of iterIO is c), I basically agree with this list, but think you are underestimating the value of a. I would rank a as the most important difference between the packages. (a also is the reason for d.) 'a' is important, but I think a lot of people underestimate the value of 'c', which is why a control system was implemented in 'iteratee'. I would argue that iteratee's control system is more powerful than you say. For example, the only reason iteratee can't implement tell is because it doesn't keep track of the position in the stream, it's relatively simple for an enumerator to return data to an iteratee using an IORef for example. And adding support to keep track of the stream position would be a pretty simple (and possibly desirable) change. But it's definitely not as sophisticated as IterIO, and probably won't become so unless I have need of those features. I like the MonadTrans implementation a lot. The vast majority of iteratees are pure, and GHC typically produces more efficient code for pure functions, so this is possibly a performance win. Although it makes something like the mutable-iter package very difficult to implement... John Lato ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Work on Collections Processing Arrows?
Has anyone developed a typeclass model for (Control.Monad.mapM) and related functions for arrows? I've a preliminary model, using Adam Megacz's Generalized Arrows, of the form: class (GArrowDrop a (**) u) = GArrowMap_ a (**) u c where mapA_ :: a d u - a (c d) u class (GArrow a (**) u c) = GArrowMap a (**) u c where mapA :: a d r - a (c d) (c r) class (GArrowMap a (**) u c) = GArrowJoin a (**) u c where join :: a d (c r) - a (c d) (c r) class (GArrow a (**) u) = GArrowUnion a (**) u c where union :: a ((c r) ** (c r)) (c r) class (GArrowMap a (**) u c, GArrow a (++) v) = GArrowPartition a (**) u (++) v c where partition :: a d (q ++ r) - a (c d) ((c q) ** (c r)) Motivations: regular arrows (including GArrows) expose simple products for behavior, but those have a static 'width' and don't seem suitable for processing large values. ArrowApply would give me a dynamic amount of processing, but seems excessively expressive. In my own case, 'c' might be representing an asynchronous or distributed, reactive collection, so the ability to restrict expressiveness is important for performance. I'm wondering if you know of any other work along the same lines. Thank you, Dave ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Type-class conditional behavior
On 08/05/2011 06:14 AM, Nicholas Tung wrote: Dear all, I'd like to write a function maybeShow :: a - Maybe String, which runs show if its argument is of class Show. This is surely an FAQ. Is the answer listed somewhere? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] parsing currency amounts with parsec
Hi everyone, I am relatively new to Haskell and Parsec, and I couldn't find any articles on parsing numbers in the following format: Positive: $115.33 Negative: ($1,323.42) I'm working on the parser for practical purposes (to convert a 3rd-party generated, most unhelpful format into one I can use), and I'd really appreciate any insight into a better way to do this, or if there are any built-in functions/established libraries that would be better suited to the task. My code below works, but doesn't seem terribly efficient. Thanks! Eric - {- parses positive and negative dollar amounts -} integer :: CharParser st Integer integer = PT.integer lexer float :: CharParser st Double float = PT.float lexer currencyAmount = try negAmount | posAmount negAmount = do char '(' char '$' a - currency char ')' return (negate a) posAmount = do char '$' a - currency return a currency = do parts - many floatOrSep let result = combine orderedParts where combine = sumWithFactor 1 orderedParts = reverse parts return result floatOrSep = try float | beforeSep beforeSep = do a - integer char ',' return (fromIntegral a :: Double) sumWithFactor n [] = 0 sumWithFactor n (x:xs) = n * x + next where next = sumWithFactor (n*1000) xs ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Type-class conditional behavior
Hi Ryan, On Sun, May 8, 2011 at 12:06 AM, Ryan Ingram ryani.s...@gmail.com wrote: However we know the behavior of these functions, and you can hack around it with a manual show instance that takes advantage of that knowledge: instance Show t = Show (AV t) where show (AVLeft a) = drop 5 $ show (Left a) That's a creative way to think about it, but unfortunately, the types don't quite work out: (AVLeft a) :: AV (Either ta tb) a :: AV ta Left a :: Either (AV ta) tc Since the argument of AVLeft is another AV. All this said, I agree that the presence of 'arr' in Arrow is a problem for many types of generalized computing. It overly constrains what can be an arrow, in my opinion. I think a better analysis of the primitives required for arrow notation to work would solve a lot of problems of this type. Yes, a graduate student here at UC Berkeley (Adam Megacz) is working on a project (Generalized Arrows) to alleviate this difficulty. I think the arrow notation not only unnecessarily prevents adding things like Show as typeclass constraints, but also makes it difficult to use an alternate Either / tuple type, like the AVLeft above, since you can't look inside the little functions it creates, like \x - (x, x), which is ga_copy in Adam's work. http://www.cs.berkeley.edu/~megacz/garrows/ cheers, Nicholas — https://ntung.com — CS and Mathematics major @ UC Berkeley ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Locking, unsafePerformIO and bolt-on thread safety.
A friend is making bindings to a C library that offers some fast math operations. The normal way to use the library is like this: int a = ...; int b = ...; int c = ...; int d = ...; int x= ...; int m, n; create_lookup_table(x); m= perform_math(a, b, x); n= perform_math(c, d, x); We see that the lookup table for x must be created before we can perform math in the field/ring/what-have-you defined by x. Once we have created the table, though, we're done. My friend would like to create a pure interface to this library. One thought was to write an interface to perform_math that checked if the table was created, created it if not, and did all this while locking an MVar so that no other instance could be called at the same time, trashing the table. Doing this behind unsafePerformIO would seem to be the ticket. We end up with an implementation like this: module FastMath where import Control.Concurrent import Foreign import Foreign.C foreign import ccall create_lookup_table :: CInt - IO () foreign import ccall perform_math :: CInt - CInt - CInt - IO CInt masterLock = unsafePeformIO (newMVar [CInt]) safe_perform_math a b x = do list - takeMVar masterLock toPut - if not (x `elem` list) then do create_lookup_table x return (x:list) elsereturn list result- perform_math a b x putMVar masterLock toPut return result performMath a b x = unsafePerformIO (safe_perform_math a b x) This does not compile but I think it gets the point across. Is this approach safe? The unsafePerformIO in conjunction with locking has me worried. -- Jason Dusek () 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] parsing currency amounts with parsec
On Mon, May 9, 2011 at 5:07 PM, Eric Rasmussen ericrasmus...@gmail.com wrote: Hi everyone, I am relatively new to Haskell and Parsec, and I couldn't find any articles on parsing numbers in the following format: Positive: $115.33 Negative: ($1,323.42) I'm working on the parser for practical purposes (to convert a 3rd-party generated, most unhelpful format into one I can use), and I'd really appreciate any insight into a better way to do this, or if there are any built-in functions/established libraries that would be better suited to the task. My code below works, but doesn't seem terribly efficient. Why do you think it inefficient? Is it slow? I don't have any substantial suggestions, but from a style perspective: * I would question the use of IEEE binary-floating-point number types for currency. Haskell ships with a fixed-point decimal library, but I don't know how fast it is: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-Fixed.html * You can re-use the 'positive' parser in the 'negative' one: negAmount = do char '(' a - posAmount char ')' return (negate a) * In the 'currencyAmount' declaration, I'm not sure that you need the 'try' before the 'negAmount', but I don't know what the rest of your grammar looks like. Thanks! Eric - {- parses positive and negative dollar amounts -} integer :: CharParser st Integer integer = PT.integer lexer float :: CharParser st Double float = PT.float lexer currencyAmount = try negAmount | posAmount negAmount = do char '(' char '$' a - currency char ')' return (negate a) posAmount = do char '$' a - currency return a currency = do parts - many floatOrSep let result = combine orderedParts where combine = sumWithFactor 1 orderedParts = reverse parts return result floatOrSep = try float | beforeSep beforeSep = do a - integer char ',' return (fromIntegral a :: Double) sumWithFactor n [] = 0 sumWithFactor n (x:xs) = n * x + next where next = sumWithFactor (n*1000) xs ___ 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] parsing currency amounts with parsec
On 5/9/11 10:04 PM, Antoine Latter wrote: On Mon, May 9, 2011 at 5:07 PM, Eric Rasmussenericrasmus...@gmail.com wrote: Hi everyone, I am relatively new to Haskell and Parsec, and I couldn't find any articles on parsing numbers in the following format: Positive: $115.33 Negative: ($1,323.42) I'm working on the parser for practical purposes (to convert a 3rd-party generated, most unhelpful format into one I can use), and I'd really appreciate any insight into a better way to do this, or if there are any built-in functions/established libraries that would be better suited to the task. My code below works, but doesn't seem terribly efficient. Why do you think it inefficient? Is it slow? I don't have any substantial suggestions, but from a style perspective: * I would question the use of IEEE binary-floating-point number types for currency. Haskell ships with a fixed-point decimal library, but I don't know how fast it is: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-Fixed.html There are also a few other options (that I can't seem to find links to at the moment), and some hints on how to do it yourself: http://augustss.blogspot.com/2007/04/overloading-haskell-numbers-part-3.html I'm not sure if your choice of parsing library is fixed or not, but you could probably speed things up significantly by using Attoparsec. In particular, Attoparsec's combinators for takeWhile, takeWhile1,scan,... return bytestrings, and you can then fold over the bytestring quite nicely. If your source is ASCII or anything ASCII compatible (Latin-1, Latin-9, UTF-8,...) then take a look at Data.Attoparsec.Char8.decimal[1][2]. Unless you need to verify that commas occur exactly every third digit, I'd suggest (a) dropping commas while scanning the string, or (b) implicitly dropping commas while folding over the string. If you do need to verify this, then your best option is (a), since you can maintain a state machine about how many digits seen since the last comma. Once you're using the Attoparsec strategy of folding over the raw byte buffers, then the only room for improvement is going to be making the code as straight-line as possible. Some untested example code: import qualified Data.Attoparsec as A import qualified Data.Attoparsec.Char8 as A8 import qualified Data.ByteString as B rawCurrency :: A.Parser (ByteString,ByteString) rawCurrency = do dollars - A.scan 0 step _ - A.char '.' -- Assuming it's required... cents - A.takeWhile1 isDigit_w8 -- Assuming no commas... return (dollars,cents) where step :: Int - Word8 - Maybe Int step 3 0x2C = Just 0 step s c | isDigit_w8 c = Just $! s+1 step _ _= Nothing -- Note: the order of comparisons is part of why it's fast. -- | A fast digit predicate. isDigit_w8 :: Word8 - Bool isDigit_w8 w = (w = 0x39 w = 0x30) {-# INLINE isDigit_w8 #-} -- With the dots filled in by whatever representation you use. currency :: A.Parser ... currency = do (dollars,cents) - rawCurrency let step a w = a * 10 + fromIntegral (w - 0x30) d = B.foldl' step 0 (B.filter (/= 0x2C) dollars) c = fromIntegral (B.foldl' step 0 cents) / (10 ^ length cents) return (... d ... c ...) amount :: A.Parser ... amount = pos | neg where pos = A8.char '$' * currency neg = do _ - A8.string ($ a - currency _ - A8.char ')' return (negate a) [1] And if you're using Attoparsec itself, you may want to take a look at Data.Attoparsec.Zepto as well. [2] If you're basing code on Attoparsec, you may want to look at some of my pending patches which improve performance on this (already extremely fast) code: https://bitbucket.org/winterkoninkje/attoparsec/changesets -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] parsing currency amounts with parsec
I'll check out Attoparsec, thanks! My first attempt may work for this particular task, but I'm warming up for a more intense parsing project and it sounds like Attoparsec with Bytestrings may work best. Also, just in case anyone reads this thread later and is looking for a quick Parsec solution, I discovered that the code I posted initially was a bit greedy in a bad way if the dollar amount was at the end of the line. I got rid of the original currency, floatOrSep, and beforeSep functions and replaced them with the code below (still verbose, but hopefully a better starting point for now). double = do i - integer return (fromIntegral i :: Double) currency = try float | largeAmount largeAmount = do first - double rest - many afterSep let parts = first : rest let result = combine orderedParts where combine = sumWithFactor 1 orderedParts = reverse parts return result afterSep = do char ',' try float | double On Mon, May 9, 2011 at 8:15 PM, wren ng thornton w...@freegeek.org wrote: On 5/9/11 10:04 PM, Antoine Latter wrote: On Mon, May 9, 2011 at 5:07 PM, Eric Rasmussenericrasmus...@gmail.com wrote: Hi everyone, I am relatively new to Haskell and Parsec, and I couldn't find any articles on parsing numbers in the following format: Positive: $115.33 Negative: ($1,323.42) I'm working on the parser for practical purposes (to convert a 3rd-party generated, most unhelpful format into one I can use), and I'd really appreciate any insight into a better way to do this, or if there are any built-in functions/established libraries that would be better suited to the task. My code below works, but doesn't seem terribly efficient. Why do you think it inefficient? Is it slow? I don't have any substantial suggestions, but from a style perspective: * I would question the use of IEEE binary-floating-point number types for currency. Haskell ships with a fixed-point decimal library, but I don't know how fast it is: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-Fixed.html There are also a few other options (that I can't seem to find links to at the moment), and some hints on how to do it yourself: http://augustss.blogspot.com/2007/04/overloading-haskell-numbers-part-3.html I'm not sure if your choice of parsing library is fixed or not, but you could probably speed things up significantly by using Attoparsec. In particular, Attoparsec's combinators for takeWhile, takeWhile1,scan,... return bytestrings, and you can then fold over the bytestring quite nicely. If your source is ASCII or anything ASCII compatible (Latin-1, Latin-9, UTF-8,...) then take a look at Data.Attoparsec.Char8.decimal[1][2]. Unless you need to verify that commas occur exactly every third digit, I'd suggest (a) dropping commas while scanning the string, or (b) implicitly dropping commas while folding over the string. If you do need to verify this, then your best option is (a), since you can maintain a state machine about how many digits seen since the last comma. Once you're using the Attoparsec strategy of folding over the raw byte buffers, then the only room for improvement is going to be making the code as straight-line as possible. Some untested example code: import qualified Data.Attoparsec as A import qualified Data.Attoparsec.Char8 as A8 import qualified Data.ByteString as B rawCurrency :: A.Parser (ByteString,ByteString) rawCurrency = do dollars - A.scan 0 step _ - A.char '.' -- Assuming it's required... cents - A.takeWhile1 isDigit_w8 -- Assuming no commas... return (dollars,cents) where step :: Int - Word8 - Maybe Int step 3 0x2C = Just 0 step s c | isDigit_w8 c = Just $! s+1 step _ _= Nothing -- Note: the order of comparisons is part of why it's fast. -- | A fast digit predicate. isDigit_w8 :: Word8 - Bool isDigit_w8 w = (w = 0x39 w = 0x30) {-# INLINE isDigit_w8 #-} -- With the dots filled in by whatever representation you use. currency :: A.Parser ... currency = do (dollars,cents) - rawCurrency let step a w = a * 10 + fromIntegral (w - 0x30) d = B.foldl' step 0 (B.filter (/= 0x2C) dollars) c = fromIntegral (B.foldl' step 0 cents) / (10 ^ length cents) return (... d ... c ...) amount :: A.Parser ... amount = pos | neg where pos = A8.char '$' * currency neg = do _ - A8.string ($ a - currency _ - A8.char ')' return (negate a) [1] And if you're using