Re: [Haskell-cafe] Please help me spot where space leak occur.
On Fri, Jul 22, 2011 at 1:54 AM, Olexander Kozlov wrote: > Jason, thank you for your help. The hint for using -s option is very > valuable. > It is good to see people answering questions about Haskell here on > haskell-cafe. stackoverflow is another good place to ask. > This is really matter. I hope I will be helpfull some day too :) > As for the question I didn't mention in my psot that Fn can be of arbitrary > size. You could extend my solution pretty easily to work for arbitrary size. > Now I have another question which I'm concerned with. I used foldl' (strict) > in my implementation > instead of just foldl (lazy). Does it mean that libraries are to be in two > implementations one strict > and another one lazy? Because there no way to affect strictness/lazyness of > function without modifying > its implementation. I' going to ask this question as a separate thread. It doesn't come up that much. It comes up here with your foldl, with Chans, modifyIORef, modifySTRef, and a few things like that. But most of the time you want a lazy version until you spot a space leak. Most of the time the library creator notices and makes a strict version as needed. One of the nice things about Haskell is that you get a choice between lazy and strict, and lazy by default is nice in many ways. Space leaks like this are not usually show stoppers for experienced Haskell folks. Good luck! Jason ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Please help me spot where space leak occur.
Jason, thank you for your help. The hint for using -s option is very valuable. It is good to see people answering questions about Haskell here on haskell-cafe. This is really matter. I hope I will be helpfull some day too :) As for the question I didn't mention in my psot that Fn can be of arbitrary size. I choosed 3 for simplicity. And with your solution I cannot match agains list of arbitrary size. But I have found the cause of memory consumption. To find it I started to unfold test function and found that the recursive call to compose is not strict. Here is what I did with base implementation: fna = [(1, 2), (2, 3), (3, 1)] fni = [(1, 1), (2, 2), (3, 3)] fldl compose fni (repl 5 fna) fldl compose fni (fna : repl 4 fna) fldl compose (compose fni fna) (repl 4 fna) fldl compose (compose fni fna) (fna : repl 3 fna) fldl compose (compose (compose fni fna) fna) (repl 3 fna) fldl compose (compose (compose fni fna) fna) (fna : repl 2 fna) fldl compose (compose (compose (compose fni fna) fna) fna) (repl 2 fna) fldl compose (compose (compose (compose fni fna) fna) fna) (fna : repl 1 fna) fldl compose (compose (compose (compose (compose fni fna) fna) fna) fna) (repl 1 fna) fldl compose (compose (compose (compose (compose fni fna) fna) fna) fna) (fna : repl 0 fna) fldl compose (compose (compose (compose (compose (compose fni fna) fna) fna) fna) fna) (repl 0 fna) fldl compose (compose (compose (compose (compose (compose fni fna) fna) fna) fna) fna) [] compose (compose (compose (compose (compose ((1, 1) : (2, 2) : (3, 3) : []) fna) fna) fna) fna) fna compose (compose (compose (compose ((1, lkup 1 fna) : compose ((2, 2) : (3, 3) : []) fna) fna) fna) fna) fna compose (compose (compose ((1, lkup (lkup 1 fna) fna) : compose (compose ((2, 2) : (3, 3) : []) fna) fna) fna) fna) fna compose (compose ((1, lkup (lkup (lkup 1 fna) fna) fna) : compose (compose (compose ((2, 2) : (3, 3) : []) fna) fna) fna) fna) fna compose ((1, lkup (lkup (lkup (lkup 1 fna) fna) fna) fna) : compose (compose (compose (compose ((2, 2) : (3, 3) : []) fna) fna) fna) fna) fna (1, lkup (lkup (lkup (lkup (lkup 1 fna) fna) fna) fna) fna) : compose (compose (compose (compose (compose ((2, 2) : (3, 3) : []) fna) fna) fna) fna) fna (1, lkup (lkup (lkup (lkup 2 fna) fna) fna) fna) : compose (compose (compose (compose (compose ((2, 2) : (3, 3) : []) fna) fna) fna) fna) fna (1, lkup (lkup (lkup 3 fna) fna) fna) : compose (compose (compose (compose (compose ((2, 2) : (3, 3) : []) fna) fna) fna) fna) fna (1, lkup (lkup 1 fna) fna) : compose (compose (compose (compose (compose ((2, 2) : (3, 3) : []) fna) fna) fna) fna) fna (1, lkup 2 fna) : compose (compose (compose (compose (compose ((2, 2) : (3, 3) : []) fna) fna) fna) fna) fna (1, 3) : compose (compose (compose (compose (compose ((2, 2) : (3, 3) : []) fna) fna) fna) fna) fna (1, 3) : (2, lkup (lkup (lkup (lkup (lkup 2 fna) fna) fna) fna) fna) : compose (compose (compose (compose (compose ((3, 3) : []) fna) fna) fna) fna) fna (1, 3) : (2, lkup (lkup (lkup (lkup 3 fna) fna) fna) fna) : compose (compose (compose (compose (compose ((3, 3) : []) fna) fna) fna) fna) fna (1, 3) : (2, lkup (lkup (lkup 1 fna) fna) fna) : compose (compose (compose (compose (compose ((3, 3) : []) fna) fna) fna) fna) fna (1, 3) : (2, lkup (lkup 2 fna) fna) : compose (compose (compose (compose (compose ((3, 3) : []) fna) fna) fna) fna) fna (1, 3) : (2, lkup 3 fna) : compose (compose (compose (compose (compose ((3, 3) : []) fna) fna) fna) fna) fna (1, 3) : (2, 1) : compose (compose (compose (compose (compose ((3, 3) : []) fna) fna) fna) fna) fna (1, 3) : (2, 1) : (3, lkup (lkup (lkup (lkup (lkup 3 fna) fna) fna) fna) fna) : compose (compose (compose (compose (compose [] fna) fna) fna) fna) fna (1, 3) : (2, 1) : (3, lkup (lkup (lkup (lkup 1 fna) fna) fna) fna) : compose (compose (compose (compose (compose [] fna) fna) fna) fna) fna (1, 3) : (2, 1) : (3, lkup (lkup (lkup 2 fna) fna) fna) : compose (compose (compose (compose (compose [] fna) fna) fna) fna) fna (1, 3) : (2, 1) : (3, lkup (lkup 3 fna) fna) : compose (compose (compose (compose (compose [] fna) fna) fna) fna) fna (1, 3) : (2, 1) : (3, lkup 1 fna) : compose (compose (compose (compose (compose [] fna) fna) fna) fna) fna (1, 3) : (2, 1) : (3, 2) : compose (compose (compose (compose (compose [] fna) fna) fna) fna) fna (1, 3) : (2, 1) : (3, 2) : [] The first thing I noticed is that fldl has to be strict to avoid n thunks for compose evaluation. The next thing is that compose itself has to be strict with both lkup and recursive calls strict too. If I left recursive call non-strict (that is where my problem was) I will have n thunks for recursive composition evaluation. If I left call to lkup non-strict I will have n thunks for mapped value evaluation for each member of Fn. n is the amount functions I whant to compose with. I my example this is 1,000,000 functions. Now I have another question which I'm concerned with. I used foldl' (strict) in my implementation instead of
Re: [Haskell-cafe] Please help me spot where space leak occur.
On Thu, Jul 21, 2011 at 1:22 AM, Olexander Kozlov wrote: > Greetings Haskell community, > I stuck with a space leak problem in simple task. I have a function > described with a list of pairs: > type Fn a b = [(a, b)] > mapping values from a to b. And I have a composition operation which accepts > two functions and returns > theirs composition: > compose :: Eq b => Fn a b -> Fn b c -> Fn a c > Finding composition of 1,000,000 functions takes about 240M with the > following implementation: > type Fn a b = [(a, b)] > lkup :: Eq a => a -> Fn a b -> b > lkup x ((a, b) : abs) = if x /= a then lkup x abs else b > compose :: Eq b => Fn a b -> Fn b c -> Fn a c > compose ((a, b) : abs) bcs = (a, lkup b bcs) : compose abs bcs > compose [] _ = [] > fldl :: (a -> b -> a) -> a -> [b] -> a > fldl f z (x:xs) = fldl f (f z x) xs > fldl _ z [] = z > fna = [(1, 2), (2, 3), (3, 1)] > fni = [(1, 1), (2, 2), (3, 3)] > test = fldl compose fni (replicate 100 fna) > main = print test > I build with: > ghc --make -prof -auto-all -caf-all -fforce-recomp -rtsopts Test.hs > Profile results: > Test.exe +RTS -K50M -p -RTS > total time = 0.34 secs (17 ticks @ 20 ms) > total alloc = 240,003,820 bytes (excludes profiling overheads) > COST CENTRE MODULE %time %alloc > compose Main 58.8 80.0 > lkup Main 35.3 0.0 > test Main 5.9 11.7 > fldl Main 0.0 8.3 > After reading 'High-Performance Haskell' by Johan Tibell I tried to made my > compose function strict: > compose :: Eq b => Fn a b -> Fn b c -> Fn a c > compose ((a, b) : abs) bcs = let c = lkup b bcs in c `seq` (a, c) : compose > abs bcs > compose [] _ = [] > and memory consuption reduced down to 180M. Good achievement but still too > much! > Profile results: > Test.exe +RTS -K50M -p -RTS > total time = 0.24 secs (12 ticks @ 20 ms) > total alloc = 180,003,820 bytes (excludes profiling overheads) > COST CENTRE MODULE %time %alloc > compose Main 83.3 73.3 > lkup Main 8.3 0.0 > fldl Main 8.3 11.1 > test Main 0.0 15.6 > I tried to make fldl strict as well: > fldl :: (a -> b -> a) -> a -> [b] -> a > fldl f z (x:xs) = let z' = f z x in z' `seq` fldl f z' xs > fldl _ z [] = z > and end up with 160M of total allocations. > Profile results: > Test.exe +RTS -K32M -p -RTS > total time = 0.30 secs (15 ticks @ 20 ms) > total alloc = 160,003,820 bytes (excludes profiling overheads) > COST CENTRE MODULE %time %alloc > compose Main 46.7 82.5 > lkup Main 40.0 0.0 > test Main 6.7 17.5 > fldl Main 6.7 0.0 > Please help me spot where space leak occur, I see no other places for space > leaks. I'll appreciate any help. The space leak is because your fldl is not as strict as is needed. This version of the program needs about 1 meg on my computer: {-# LANGUAGE BangPatterns #-} type Fn a b = [(a, b)] lkup :: Eq a => a -> Fn a b -> b lkup x ((a, b) : abs) = if x /= a then lkup x abs else b compose :: Eq b => Fn a b -> Fn b c -> Fn a c compose ((a, b) : abs) bcs = (a, lkup b bcs) : compose abs bcs compose [] _ = [] -- fldl :: (a -> b -> a) -> a -> [b] -> a fldl f z (x:xs) = let z'@[(!z1,!z2),(!z3,!z4),(!z5,!z6)] = f z x in z' `seq` fldl f z' xs fldl _ z [] = z fna = [(1, 2), (2, 3), (3, 1)] fni = [(1, 1), (2, 2), (3, 3)] test = fldl compose fni (replicate 100 fna) main = print test $ Test +RTS -K50M -p -s -RTS [(1,2),(2,3),(3,1)] 351,125,156 bytes allocated in the heap 108,576 bytes copied during GC 26,888 bytes maximum residency (1 sample(s)) 18,168 bytes maximum slop 1 MB total memory in use (0 MB lost due to fragmentation) Generation 0: 669 collections, 0 parallel, 0.00s, 0.00s elapsed Generation 1: 1 collections, 0 parallel, 0.00s, 0.00s elapsed INIT time0.00s ( 0.01s elapsed) MUT time0.50s ( 0.50s elapsed) GCtime0.00s ( 0.00s elapsed) RPtime0.00s ( 0.00s elapsed) PROF time0.00s ( 0.00s elapsed) EXIT time0.00s ( 0.00s elapsed) Total time
[Haskell-cafe] Please help me spot where space leak occur.
Greetings Haskell community, I stuck with a space leak problem in simple task. I have a function described with a list of pairs: type Fn a b = [(a, b)] mapping values from a to b. And I have a composition operation which accepts two functions and returns theirs composition: compose :: Eq b => Fn a b -> Fn b c -> Fn a c Finding composition of 1,000,000 functions takes about 240M with the following implementation: type Fn a b = [(a, b)] lkup :: Eq a => a -> Fn a b -> b lkup x ((a, b) : abs) = if x /= a then lkup x abs else b compose :: Eq b => Fn a b -> Fn b c -> Fn a c compose ((a, b) : abs) bcs = (a, lkup b bcs) : compose abs bcs compose [] _ = [] fldl :: (a -> b -> a) -> a -> [b] -> a fldl f z (x:xs) = fldl f (f z x) xs fldl _ z [] = z fna = [(1, 2), (2, 3), (3, 1)] fni = [(1, 1), (2, 2), (3, 3)] test = fldl compose fni (replicate 100 fna) main = print test I build with: ghc --make -prof -auto-all -caf-all -fforce-recomp -rtsopts Test.hs Profile results: Test.exe +RTS -K50M -p -RTS total time =0.34 secs (17 ticks @ 20 ms) total alloc = 240,003,820 bytes (excludes profiling overheads) COST CENTREMODULE %time %alloc composeMain 58.8 80.0 lkup Main 35.30.0 test Main 5.9 11.7 fldl Main 0.08.3 After reading 'High-Performance Haskell' by Johan Tibell I tried to made my compose function strict: compose :: Eq b => Fn a b -> Fn b c -> Fn a c compose ((a, b) : abs) bcs = let c = lkup b bcs in c `seq` (a, c) : compose abs bcs compose [] _ = [] and memory consuption reduced down to 180M. Good achievement but still too much! Profile results: Test.exe +RTS -K50M -p -RTS total time =0.24 secs (12 ticks @ 20 ms) total alloc = 180,003,820 bytes (excludes profiling overheads) COST CENTREMODULE %time %alloc composeMain 83.3 73.3 lkup Main 8.30.0 fldl Main 8.3 11.1 test Main 0.0 15.6 I tried to make fldl strict as well: fldl :: (a -> b -> a) -> a -> [b] -> a fldl f z (x:xs) = let z' = f z x in z' `seq` fldl f z' xs fldl _ z [] = z and end up with 160M of total allocations. Profile results: Test.exe +RTS -K32M -p -RTS total time =0.30 secs (15 ticks @ 20 ms) total alloc = 160,003,820 bytes (excludes profiling overheads) COST CENTREMODULE %time %alloc composeMain 46.7 82.5 lkup Main 40.00.0 test Main 6.7 17.5 fldl Main 6.70.0 Please help me spot where space leak occur, I see no other places for space leaks. I'll appreciate any help. (I intentionally wrote my own implementations of lookup and foldl to have direct control on them.) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Please help me debug my arrow
On 18/01/10 20:33, Paul Johnson wrote: I'm going nuts looking at this. Can anyone see what I'm doing wrong? I found the problem eventually. Its a scoping problem with "rt1" in the (.) function when composeSP gets called recursively. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Please help me debug my arrow
Hi, I'm trying to write an arrow for a real-time stream processor. I'm basing it on the SP type in Hughes paper on Generalising Monads to Arrows (http://www.cs.chalmers.se/~rjmh/Papers/arrows.pdf) section 6. I've extended this with a notion of time by making each step a function of time. But I can't get the compose operator to work. The arrow itself is defined in http://haskell.pastebin.com/m49944f64 with the (.) function highlighted. Some simple tests are in http://haskell.pastebin.com/m6d90f27 with the problematic call highlighted. When run it produces an infinite list of puts, which causes the SimulateRTSP interpreter function to diverge. But I've run the expansions by hand, and they seem to work (see the test case file at the bottom). I'm going nuts looking at this. Can anyone see what I'm doing wrong? Thanks, Paul. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: please help me to find errors from my first app
thanks. I know how to do it. I should treat it as a stream. -- Thanks & Regards Changying Li ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] please help me to find errors from my first app
On 2008 August 08 Friday, Changying Li wrote: > I want to write a reverse proxy like perlbal to practive haskell. Now I > just write a very simple script to forward any request to > www.google.com. > > but it dosn't work. I run command ' runhaskell Proxy.hs' and 'wget > http://localhost:8080/'. but wget just wait forever and runhaskkell can > get request. when I break wget, the 'runhaskell' can print response > returned from www.google.com. The problem is with > request <- hGetContents hRequest which blocks until wget closes the connection. Using lazy bytestrings just defers the problem slightly. Your processRequest blocks when the 'request' string is used. For some insight into how this can be avoided, see hGetBufNonBlocking. I'm not familiar enough with the Haskell libraries to point you to the ideal solution. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] please help me to find errors from my first app
Hi. I want to write a reverse proxy like perlbal to practive haskell. Now I just write a very simple script to forward any request to www.google.com. but it dosn't work. I run command ' runhaskell Proxy.hs' and 'wget http://localhost:8080/'. but wget just wait forever and runhaskkell can get request. when I break wget, the 'runhaskell' can print response returned from www.google.com. why? module Main where import System.Posix.Process import Network import Prelude hiding (putStr) import System.IO hiding (hGetContents, putStr) import Control.Concurrent import System.Posix.Signals import Data.ByteString.Lazy.Char8 (hGetContents, hPut, putStr,hGet,cons) listenPort = PortNumber 8080 connectToHost = "208.67.219.230" connectToPort = PortNumber 80 main :: IO () main = do hSetBuffering stdout NoBuffering socket <- listenOn listenPort let doLoop = do (hdl, _, _) <- accept socket forkIO $ processRequest hdl doLoop doLoop processRequest :: Handle -> IO () processRequest hRequest = do installHandler sigPIPE Ignore Nothing; hSetBuffering hRequest NoBuffering hSetBuffering stdout NoBuffering request <- hGetContents hRequest putStr $ '>' `cons` (' ' `cons` request) hResponse <- connectTo connectToHost connectToPort hSetBuffering hResponse NoBuffering hPut hResponse request response <- hGetContents hResponse putStr $ '<' `cons` (' ' `cons` response) hPut hRequest response hClose hRequest hClose hResponse -- Thanks & Regards Changying Li ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell scripting system (please help me simplify the design)
On 27/10/05, Joel Reymont <[EMAIL PROTECTED]> wrote: > On Oct 27, 2005, at 4:59 PM, Robert Dockins wrote: [snip] > > As a side note, I see you are doing a bunch of operations on lists > > of properties. If performance is an issue, you might want to > > consider using Data.Map or similar. If your properties lists can > > get big, mergeprops looks like a potential problem ( O( n*(n+m) ) > > each time it's called ). > > What would I use as the key for each map entry? If I knew this then I > could use a map :-). As it stands, each property is a solid chunk and > I can't even extract the name of the attribute it was created with. I > don't think Map lets me index on Strings, does it? [snip] > Joel > You can use any type in Ord as an index for a Map -- see fromList in the Data.Map documentation. Strings are actually quite an effective type of key, as they don't usually even need to be fully evaluated to be compared. - Cale ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell scripting system (please help me simplify the design)
Something else just occurred to me... How would I represent "no command" using the Unstuff monad? I'm returning Maybe Command right now, would this change? On Oct 27, 2005, at 4:59 PM, Robert Dockins wrote: You could consider creating a monad for the "unstuff" part of the operation that would hide dealing with the FastString, the tupling and the case analysis on Maybe. Your code might then look like: class (Eq a) => Packet a where unstuff :: Unstuff a stuff :: a -> P.FastString size :: a -> Int instance Packet BaseTableState where unstuff = unstuffprops baseTableStateProps >>= return . BaseTableState sutff (BaseTableState a) = stuffprops a size (BaseTableState a) = sizeprops a where Unstuff is the type constructor for your monad. -- http://wagerlabs.com/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell scripting system (please help me simplify the design)
Robert, On Oct 27, 2005, at 4:59 PM, Robert Dockins wrote: You could consider creating a monad for the "unstuff" part of the operation that would hide dealing with the FastString, the tupling and the case analysis on Maybe. Could you elaborate on this a bit please? How would I write and use such a monad? If you end up doing a lot of instances like this, the monad could well be a win; it also gives you the opportunity to add error reporting during the parse if you want. This is exactly the problem I'm facing now. Parsing is failing and I need to take apart my pure code just for testing. How would you code this monad? As a side note, I see you are doing a bunch of operations on lists of properties. If performance is an issue, you might want to consider using Data.Map or similar. If your properties lists can get big, mergeprops looks like a potential problem ( O( n*(n+m) ) each time it's called ). What would I use as the key for each map entry? If I knew this then I could use a map :-). As it stands, each property is a solid chunk and I can't even extract the name of the attribute it was created with. I don't think Map lets me index on Strings, does it? Since I end up modifying properties a lot I think I sould use monads but I need to read up to get a clear picture. Joel -- http://wagerlabs.com/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell scripting system (please help me simplify the design)
On Oct 27, 2005, at 11:01 AM, Joel Reymont wrote:Folks,With lots of help from #haskell and haskell-cafe I came up with the following setup. It's working fine but requires quite a bit of boilerplate code. Could you please help me simplify it?I apologize for the very long message and will describe any parts that are unclear. Please ask away. This is my first Haskell code, written over the course of 3 weeks (1 week to learn Haskell) so I'm bound to get some things wrong or unoptimal. Still, I'm quite amazed that I have been able to get this to work and to work correctly in such a short time span.Welcome to Haskell!The system is basically a scripting engine to test a poker server that lets you write simple scripts. I went out of my way to enable QA techs to use as little Haskell as possible, thus I'm treating all poker commands/packets as a list of properties.What I found is that I'm writing a lot of boiler-plate code to handle the convertion of property values into "storables". I think this dovetails into the recent GADT discussion. I wonder if my design and interaction between Packet, Convertible, Prop and Attr can be simplified.[snip]My concern is mostly with a lot of similar boilerplate code required for casting, specially in very alike cases like the following:data Pot = Pot [Prop] deriving (Eq, Show, Typeable)data BaseTableState = BaseTableState [Prop] deriving (Eq, Show, Typeable)instance Packet Pot where unstuff xs = case props of Just props -> (Just $ Pot props, xs') Nothing -> (Nothing, xs) where (props, xs') = unstuffprops xs potProps <<< this is the only difference stuff (Pot a) = stuffprops a size (Pot a) = sizeprops ainstance Convertible [Prop] Pot where convert_AB a = Pot $ mergeprops a potProps convert_BA (Pot b) = binstance Packet BaseTableState where unstuff xs = case props of Just props -> (Just $ BaseTableState props, xs') Nothing -> (Nothing, xs) where (props, xs') = unstuffprops xs baseTableStateProps stuff (BaseTableState a) = stuffprops a size (BaseTableState a) = sizeprops ainstance Convertible [Prop] BaseTableState where convert_AB a = BaseTableState $ mergeprops a baseTableStateProps convert_BA (BaseTableState b) = bNotice that the differences are only in the list of properties required for conversion. I'm wondering if this can be simplified somehow.You could consider creating a monad for the "unstuff" part of the operation that would hide dealing with the FastString, the tupling and the case analysis on Maybe.Your code might then look like:class (Eq a) => Packet a where unstuff :: Unstuff a stuff :: a -> P.FastString size :: a -> Intinstance Packet BaseTableState where unstuff = unstuffprops baseTableStateProps >>= return . BaseTableState sutff (BaseTableState a) = stuffprops a size (BaseTableState a) = sizeprops a where Unstuff is the type constructor for your monad.If you end up doing a lot of instances like this, the monad could well be a win; it also gives you the opportunity to add error reporting during the parse if you want.As a side note, I see you are doing a bunch of operations on lists of properties. If performance is an issue, you might want to consider using Data.Map or similar. If your properties lists can get big, mergeprops looks like a potential problem ( O( n*(n+m) ) each time it's called ).___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Haskell scripting system (please help me simplify the design)
Folks, With lots of help from #haskell and haskell-cafe I came up with the following setup. It's working fine but requires quite a bit of boilerplate code. Could you please help me simplify it? I apologize for the very long message and will describe any parts that are unclear. Please ask away. This is my first Haskell code, written over the course of 3 weeks (1 week to learn Haskell) so I'm bound to get some things wrong or unoptimal. Still, I'm quite amazed that I have been able to get this to work and to work correctly in such a short time span. The system is basically a scripting engine to test a poker server that lets you write simple scripts. I went out of my way to enable QA techs to use as little Haskell as possible, thus I'm treating all poker commands/packets as a list of properties. What I found is that I'm writing a lot of boiler-plate code to handle the convertion of property values into "storables". I think this dovetails into the recent GADT discussion. I wonder if my design and interaction between Packet, Convertible, Prop and Attr can be simplified. These are a couple of sample scripts (incomplete): --- module Test where import Script import Handshake as H script env = do setDebugLevel 100 dotimes 1 $ launch $ H.script [] waitForChildren --- module Handshake where import Script script env = -- connect to server do world <- connect env "192.168.0.197" 15667 -- setup callbacks world <- add world [ [ onCmd := CmdHandshake Server, call := onServerHandshake ], [ onCmd := CmdConnectGame Server, call := onConnectGame ], [ onCmd := CmdServerInfo Server, call := onServerInfo ], [ onCmd := CmdLogon Server, call := onLogon ], [ onCmd := CmdGameInfo Server, call := onGameInfo ], [ onCmd := CmdMoney Server, call := onMoney ] ] -- start handshake send world $ make (CmdHandshake Invalid) [] run world onServerHandshake cmd world = do send world $ make (CmdConnectGame Client) [ localIP := "10.0.0.2", affiliateID := [28] ] return world onServerInfo cmd world = do send world $ make (CmdLogon Client) [ name := "foo", password := "bar", affiliateID := [28] ] -- retrieve table id tables' <- get tables cmd debug 99 $ "Tables: " ++ show tables' tableID' <- get tableID $ head tables' debug 99 $ "TableID: " ++ show tableID' debug 99 $ "World: " ++ show world -- save it for later use world <- set (tableID := tableID') world -- return updated info return world onGameInfo cmd world = do debug 99 "Got game!" stop world --- I'm describing binary packets using properties (from WxHaskell) with the added twist that when you say attr := value you can specify what value will be converted to for storage. This is how I would use the system... This describes the properties for the admin message and wait list init commands. I would use the properties to serialize the commmands. cmdProps (CmdAdminMessage Server) = [ title := "", message := "", postAction := 0 ] cmdProps (CmdSrvWaitListInit Server) = [ waitListTables := [] ] I also have a "dictionary" that describes the attributes such as title, message, postAction, etc. I'm allowing deeply nested lists of properties. title :: Attr String WString = makeAttr "title" message :: Attr String WString = makeAttr "message" postAction :: Attr Word8 Word8 = makeAttr "postAction" waitListTables :: Attr [TableID] (FixedList Word8 (LE TableID)) = makeAttr "waitListTables" Attr String WString means that a String is accepted on the right-hand side and the string will be converted into a wide string for storage. Same thing with a list of table ids that is converted into a list of little-endian table ids (word32s) prefixed by a Word8 length for storage. The conversion/casting is done with code like this: class Convertible a b where convert_AB :: a -> b convert_BA :: b -> a instance Convertible [Word8] FastString where convert_AB a = packWords a convert_BA b = unpackWords b instance Convertible Bool Bool where convert_AB
Please help me
From: David Jonas Savimbi Johannesburg, South Africa Email: [EMAIL PROTECTED] June 3rd, 2003. Dear Sir, It is my humble pleasure to write you this letter irrespective of the fact that you do not know me. However, I got your name through your country business directory here in my search for a reliable and trustworthy person that can assist me confidently. My name is Mr.John Jonas Savimbi. I am the son of Late Dr. Jonas Savimbi from Angola. I am 29 years old and I have got two younger sisters of same blood. Our mother died almost a year ago. We are all fighting for political asylum in South Africa. We cannot find a home in Angola anymore because of the war that our late father fought with the government of Angola until he died in that war. The government of Angola is now mad at us because our late father also wanted to be president and caused the people to fight the war for him because he was the president of UNITA political movement of Angola. So now we are in South Africa and we are suffering too much because we don't have money and the government of South Africa will not give jobs to asylum seekers. I am much concerned about my younger sisters who are finding it very difficult to manage in the situation. But I know that we should not suffer this way. I know that I must not let my younger sisters get into trouble because of money. So after consideration I am hereby begging for your assistance to help me to recover the sum of USD $29 Million which is my inheritance from my late mother. My late mother had taken this money with her to Spain in a diplomatic metal box marked (Precious Stones). Subsequently she lodged the metal box (As precious Stones) with a Securities and Valuables Protection company in Spain. I am supposed to be the beneficiary in the event of her death. However, all effort I made to go Spain to claim was refused by the Spainish embassy. And this was while it was still possible for me to travel. Now I cannot travel anywhere anymore. So in the situation that we are facing now, I must find somebody who can go to the Spain on my behalf. I understand that I will have to transfer my beneficiary rights unto you. I am willing to do so in the hope that you are a God fearing person who will not abandon us after you have the money. So from the bottom of my heart I am giving you 20% of the all the money. Once we have enough to sustain us sufficiently, you may be come our fund manager and invest the rest wisely for us. If you will be kind to assist us, please inform me urgently. Kind regards to you and your family. Sincerely, David Jonas savimbi ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Please help me
From: David Jonas Savimbi Johannesburg, South Africa Email: [EMAIL PROTECTED] June 3rd, 2003. Dear Sir, It is my humble pleasure to write you this letter irrespective of the fact that you do not know me. However, I got your name through your country business directory here in my search for a reliable and trustworthy person that can assist me confidently. My name is Mr.John Jonas Savimbi. I am the son of Late Dr. Jonas Savimbi from Angola. I am 29 years old and I have got two younger sisters of same blood. Our mother died almost a year ago. We are all fighting for political asylum in South Africa. We cannot find a home in Angola anymore because of the war that our late father fought with the government of Angola until he died in that war. The government of Angola is now mad at us because our late father also wanted to be president and caused the people to fight the war for him because he was the president of UNITA political movement of Angola. So now we are in South Africa and we are suffering too much because we don't have money and the government of South Africa will not give jobs to asylum seekers. I am much concerned about my younger sisters who are finding it very difficult to manage in the situation. But I know that we should not suffer this way. I know that I must not let my younger sisters get into trouble because of money. So after consideration I am hereby begging for your assistance to help me to recover the sum of USD $29 Million which is my inheritance from my late mother. My late mother had taken this money with her to Spain in a diplomatic metal box marked (Precious Stones). Subsequently she lodged the metal box (As precious Stones) with a Securities and Valuables Protection company in Spain. I am supposed to be the beneficiary in the event of her death. However, all effort I made to go Spain to claim was refused by the Spainish embassy. And this was while it was still possible for me to travel. Now I cannot travel anywhere anymore. So in the situation that we are facing now, I must find somebody who can go to the Spain on my behalf. I understand that I will have to transfer my beneficiary rights unto you. I am willing to do so in the hope that you are a God fearing person who will not abandon us after you have the money. So from the bottom of my heart I am giving you 20% of the all the money. Once we have enough to sustain us sufficiently, you may be come our fund manager and invest the rest wisely for us. If you will be kind to assist us, please inform me urgently. Kind regards to you and your family. Sincerely, David Jonas savimbi ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: please help me
On Sun, 7 Apr 2002, Eric wrote: |> Hi there, I am a beginner a haskell,and I have some |> difficulty in dealing with an assignment that is to |> translate a string representation of a list of |> appointments into a list of appointments. For example: [requirements snipped] |> How can I finish the requirement make use of library |> functions such as words, unwords, lines and break. Hey Leo, Well, I'm just learning haskell too, but I decided to give this a shot. I think I solved the main problem, but I did hit a few snags of my own so I can't be sure. Here goes: Basically, I defined "appointment" as a single type... But I couldn't figure out how to print that type. So I can't really test what I've done, other than I know it compiles. :) Can someone show me how to fill in "show" down here? ) > module Main where > > data Appt = Appt (Bool, Int, Int, String) > instance Show Appt where >show x = "???" I then used liness and words to break the multi-line string into a list of lists of words: > strToApps :: String -> [Appt] > strToApps x = map lineToApp (lines x) > lineToApp x = wordsToApp (words x) Since the starting "!" was optional, the structure of the list could go in two directions here: > wordsToApp :: [String] -> Appt > wordsToApp ws | head ws == "!" = mkAppt True (tail ws) > | otherwise = mkAppt False (ws) Now it's just a matter of parsing the rest of the line. For simplicity's sake, I took the liberty of assuming you always used the same number of digits for the hours, so I didn't have to search for the "-": > mkAppt :: Bool -> [String] -> Appt > mkAppt isImp (w:ws) = Appt (isImp, start, done, note) > where (hs, hd) = splitAt 3 w -- assumes zero-padded (eg 01-03) > start = atoi hs > done = atoi hd > note = foldr1 concat ws > concat a b = a ++ " " ++ b That "atoi" function came from working through the exercises in Rex Pages online book ( http://www.cs.ou.edu/cs1323h/textbook/haskell.shtml ) > horner str = foldr1 op (reverse str) > where op d s = d + (10 * s) > atoi str = horner [digitToInt d | d <- str] Then I defined a main function: > -- I wonder what a refec is. :) > main = do print $ strToApps "! 10-11 lecture\n12-13 lunch at the refec :(" ... And that's it! I think it would work if I could figure out how to print Appt objects (or whatever you call them in haskell). Meanwhile, I get this because of the way I defined show: Main> main [???,???] Cheers, - Michal http://www.sabren.net/ [EMAIL PROTECTED] Give your ideas the perfect home: http://www.cornerhost.com/ cvs - weblogs - php - linux shell - perl/python/cgi - java ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
please help me
Hi there, I am a beginner a haskell,and I have some difficulty in dealing with an assignment that is to translate a string representation of a list of appointments into a list of appointments. For example: strToApps "! 10-11 lecture 12-13 lunch at the refec :(" Would yield: [((10,11),"lecture",True), ((12,13),"lunch at the refec :(",False)] "!" is used to determine that appointment is important or not I have done some work,those are: > type Date = (Day,Month,Year) -- e.g. (1,1,2000) = 1/1/2000 > type Year = Int > type Month= Int > type Day = Int > type Hour = Int > type Minute = Int > type Time = Hour-- only times on the hour for now > type Appointment = (Duration, Note, Important) > type Duration = (Time,Time) -- e.g. (13,14) = 1-2pm, forall (s,f) in Duration: s < f > type Note = String > type Important = Bool > strToApps :: String -> [Appointment] > strToApps s = How can I finish the requirement make use of library functions such as words, unwords, lines and break. I am eager to receive your help, thank you very much. Best Wishes Leo === ÐÂÀËÃâ·Ñµç×ÓÓÊÏä (http://mail.sina.com.cn) ÐÂÀË·ÖÀàÐÅÏ¢£º¶þÊÖÊг¡×ßÒ»×ߣ¬¸Ã³öÊÖʱ¾Í³öÊÖ£¡ (http://classad.sina.com.cn/2shou/) ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: Please help me
Faizan, A clue is to use list comprehensions (which are very like ZF set notation) First think how you would define a cartesian product in set notation X x Y x Z = {(x,y,z) | ...} and then think how this is written in list comprehension notation Chris > -Original Message- > From: FAIZAN RAZA [mailto:[EMAIL PROTECTED]] > Sent: 08 February 2001 13:49 > To: [EMAIL PROTECTED] > Subject: Please help me > > > Hello > > > Please help me to solve this questions > > > Question > > Cartesian Product of three sets, written as X x Y x Z is > defined as the set > of all ordered triples such that the first element is a > member of X, the > second is member of Y, and the thrid member of set Z. write a Haskell > function cartesianProduct which when given three lists (to > represent three > sets) of integers returns a list of lists of ordered triples. > > For examples, cartesianProduct [1,3][2,4][5,6] returns > [[1,2,5],[1,2,6],[1,4,5],[1,4,6],[3,2,5],[3,2,6],[3,4,5],[3,4,6]] > > > > Please send me reply as soon as possible > > Ok > > I wish you all the best of luck > > > > ___ > Haskell-Cafe mailing list > [EMAIL PROTECTED] > http://www.haskell.org/mailman/listinfo/haskell-cafe > ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Please help me
At 2001-02-08 02:04, Ashley Yakeley wrote: >That's easy. Just define 'product' as a function that finds the cartesian >product of any number of lists, and then once you've done that you can >apply it to make the special case of three items like this: > >cartesianProduct a b c = product [a,b,c] > >At least, that's how I would do it. eesh, 'product' is something else in the Prelude. Better call it 'cartprod' or something. -- Ashley Yakeley, Seattle WA ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Please help me
At 2001-02-08 13:49, FAIZAN RAZA wrote: >write a Haskell >function cartesianProduct which when given three lists (to represent three >sets) of integers returns a list of lists of ordered triples. That's easy. Just define 'product' as a function that finds the cartesian product of any number of lists, and then once you've done that you can apply it to make the special case of three items like this: cartesianProduct a b c = product [a,b,c] At least, that's how I would do it. -- Ashley Yakeley, Seattle WA ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Please help me
Hello Please help me to solve this questions Question Cartesian Product of three sets, written as X x Y x Z is defined as the set of all ordered triples such that the first element is a member of X, the second is member of Y, and the thrid member of set Z. write a Haskell function cartesianProduct which when given three lists (to represent three sets) of integers returns a list of lists of ordered triples. For examples, cartesianProduct [1,3][2,4][5,6] returns [[1,2,5],[1,2,6],[1,4,5],[1,4,6],[3,2,5],[3,2,6],[3,4,5],[3,4,6]] Please send me reply as soon as possible Ok I wish you all the best of luck ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe