Re: [Haskell-cafe] Function application layout
On 25/05/11 10:00, Jonas Almström Duregård wrote: As an equivalent to: f (x a) (y b) (z c) Of course my intention is that the new keyword should initiate layout syntax so we can write this: f applied to x a y b z c Here's a (tongue-in-cheek) trick that allows for layout close to what you wanted (spoiler: but not close enough!). We start by switching to parameterised monads (which allow you to change the type of the monad as you go down the do-block; look carefully at the second and third parameters in the monad class): {-# LANGUAGE RebindableSyntax #-} import Control.Applicative import Prelude ((++), (.), Num(..), Eq(..), ($), id, Int, Char, String, Float, ?, const, Show(..), Fractional(..)) class Monad m where (=) :: m a b y - (y - m b c z) - m a c z return :: b - m a a b () :: Monad m = m a b y - m b c z - m a c z () m n = m = const n Then we define a type for wrapping pure functions in this monad: data Fun a b c = Fun (a - b) c instance Monad Fun where (=) (Fun f x) m = let Fun g y = m x in Fun (g . f) y return x = Fun id x Then we add a helper for unwrapping it: ($$) :: a - Fun a b c - b ($$) f (Fun g _) = g f And a function for supplying an argument: r :: a - Fun (a - b) b a r x = Fun ($ x) x And so what does let us do? Well, here's how it's used: foo :: Int - Char - String - Float - String foo a b c d = show (a, b, c, d) eg :: String eg = foo $$ do r$ 2 + 1 r$ 'c' r$ hello ++ goodbye r$ 3.0 foo is the function we want to apply, and eg shows how to apply it in do-notation with an argument on each line. I couldn't manage to remove the r$ at the beginning of each line, which rather ruins the whole scheme :-( On the plus side, there's no brackets, it's only two extra characters per line, and you can have whatever you like after the r$. For those who are interested, you can also use the same trick for writing Applicatives in a do notation. Continuing the same module, we can add an analogue for each of the types and functions for Applicative: data App f a b c = App (f a - f b) c instance Applicative f = Monad (App f) where (=) (App f x) m = let App g y = m x in App (g . f) y return x = App id x ($$) :: Applicative f = f a - App f a b c - f b ($$) f (App g _) = g f s :: Applicative f = f a - App f (a - b) b (f a) s x = App (* x) x Then we can use this on things which are Applicative but not Monad, e.g. egA :: [String] egA = getZipList $ pure foo $$ do s$ ZipList [3, 6, 7] s$ ZipList hello s$ ZipList [more, strings] s$ ZipList [1.0, 1.5, 2.0] And that's enough silly playing around :-) Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Inconsistent window updates with SDL library
On 17/05/11 01:42, Michael Serra wrote: eventLoop w cs = do drawCells w cs e - waitEventBlocking checkEvent e where checkEvent (KeyUp (Keysym SDLK_ESCAPE _ _)) = return () checkEvent (KeyUp (Keysym SDLK_n _ _)) = eventLoop w $ nextgen cs checkEvent _= eventLoop w cs Your code is a bit strange. It redraws the window every time there is a window event (whether its an unrelated key-down or a relevant event). So whenever there's some window events, your window rapidly redraws (and in a different set of random colours). I'm not sure this is the intended behaviour? I didn't find any point at which the program didn't advance and redraw when I released 'n' -- but I'm not sure if that was exactly the problem you're having. Can you clarify exactly what the problem is? Is that you're not seeing the keypresses being processed, or is it that you expect more redrawing than there is, etc? Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Type Classes in Haskell - how can I make GHC make a choice of types, when the type chosen doesn't matter?
On 14/04/11 13:00, Chris Dew wrote: class Stream a b c d where (-) :: a - (b - c) - d instance Stream (IO d) d (IO c) (IO c) where f - g = f= g instance Stream d d (IO c) (IO c) where f - g = g f instance Stream d d c c where x - y = y $ x I notice that in all your instances, the last two types are the same. So do you need the final type parameter? Could you not make it: class Stream a b c where (-) :: a - (b - c) - c I quickly tried this, and it fixes the errors you were getting. If that doesn't hold for all instances you have in mind, then you may want to use functional dependencies or type families to specify a relationship between the types. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] BlockedIndefinitelyOnMVar exception
On 31/03/11 11:03, Gregory Collins wrote: I'm guessing the trigger condition for BlockedIndefinitelyOnMVar is blocked and mvar refcount == 1 It's not simply a reference count (the thread that's blocked forever can hold multiple references to the MVar and it's still blocked indefinitely). Here's how I understand it. Blocked threads are not counted as roots during the GC. Therefore for a blocked thread to survive a round of GC without being collected, something reachable from a root has to point to the thread. The only thing that points to a thread blocked on an MVar (same idea for TVars, too) is the MVar itself. Therefore, something that's reachable from a GC root (a running thread is a root, I think) must point to the MVar to allow the thread to survive the GC. If a thread would be garbage collected, it is instead woken up with a BlockedIndefinitelyOnMVar exception. I think if you put an MVar into a StablePtr, that may prevent threads waiting on it from being woken up with that exception. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Possible bug in Control.Concurrent
On 09/02/11 15:34, Krzysztof Skrzętnicki wrote: Hello Cafe, Here is a simple program that yields strange results: module Main where import Control.Concurrent import Control.Concurrent.Chan import Control.Monad main = do c - newChan writeChan c 1 forkIO $ forever $ do i - readChan c print (forkio,i) isEmptyChan c = print Now, this is strange thing: we put single element into the channel. We take it out. What your program does is put a single element into the channel, and then *repeatedly* try to take one out (notice the forever you have in there!). Judging by the results, the program deadlocks, which seems like a reasonable outcome to me. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] 3GB allocation, 75% CPU usage from a callback function
Hi, First of all, don't be fooled by the alloc statistic. That is not 3GB memory residency, that's 3GB allocation, which was interspersed with lots of garbage collections, in the same way that measuring how many times malloc was called in a C program doesn't necessarily indicate memory residency. Using +RTS -s, it looks like your program uses around 10MB at any one time. As for the speed, your program is doing a lot of conversions that aren't necessary. CFloat has the Num and Floating instances necessary to use sin, so you're better off making everything a CFloat, rather than converting to and from Float. I took your program and ironed it out a bit (you were also using an extra readIORef as part of the modifyIORef that you didn't need), and used Criterion to test the speed. Here's the program in its entirety (you'll need to cabal install criterion): === import Data.IORef import Foreign.C.Types import Criterion.Main newSinWave :: Int - Float - IO (CFloat - IO CFloat) newSinWave sampleRate freq = do ioref - newIORef (0::Integer) let multiplier = 2 * pi * freq / (fromIntegral sampleRate) return (\ _ - {-# SCC sinWave #-} do t - readIORef ioref modifyIORef ioref (+1) return $ fromRational $ toRational $ sin (fromIntegral t * multiplier)) newSinWave' :: Int - Float - IO (CFloat - IO CFloat) newSinWave' sampleRate freq = do ioref - newIORef 0 let multiplier = 2 * pi * (realToFrac freq) / (fromIntegral sampleRate) return (\ _ - {-# SCC sinWave' #-} do t - readIORef ioref writeIORef ioref (t+1) return $ sin (t * multiplier)) runLots :: (a - IO a) - a - IO a runLots f = go 1 where go 0 !x = return x go n !x = f x = go (n - 1) main :: IO () main = do f - newSinWave 44100 100 g - newSinWave' 44100 100 defaultMain [bench old $ runLots f 0, bench new $ runLots g 0] === And here's the output from Criterion on my machine, compiled with -XBangPatterns -O1 -rtsopts: === benchmarking old collecting 100 samples, 1 iterations each, in estimated 10.54111 s bootstrapping with 10 resamples mean: 116.4734 ms, lb 116.2565 ms, ub 117.1492 ms, ci 0.950 std dev: 1.794715 ms, lb 626.6683 us, ub 3.992824 ms, ci 0.950 found 5 outliers among 100 samples (5.0%) 1 (1.0%) low severe 3 (3.0%) high mild 1 (1.0%) high severe variance introduced by outliers: 0.993% variance is unaffected by outliers benchmarking new collecting 100 samples, 2 iterations each, in estimated 1.417208 s bootstrapping with 10 resamples mean: 10.33277 ms, lb 10.15559 ms, ub 10.50883 ms, ci 0.950 std dev: 904.9297 us, lb 845.3293 us, ub 973.6881 us, ci 0.950 variance introduced by outliers: 1.000% variance is unaffected by outliers === So unless I've done something wrong in the methodology (always possible), that's made it ten times faster. And here's the output from +RTS -s: === 6,458,290,512 bytes allocated in the heap 10,855,744 bytes copied during GC 5,522,696 bytes maximum residency (5 sample(s)) 3,194,696 bytes maximum slop 13 MB total memory in use (0 MB lost due to fragmentation) === Hope that helps, Neil. On 29/01/2011 16:29, Edward Amsden wrote: I recently got the jack package from hackage working again. For those unfamiliar, jack is a callback-based audio server. Writing a client entails importing the C library or its bindings (the Sound.JACK module in my case), creating a client and some ports (using provided library functions), and then registering callbacks for audio processing. I've written a simple program that outputs a sine wave through JACK. The server's sample rate is 44100, which means that this function must be called 44100 times/second (it is buffered, so generally that would be in chunks of 64, 128, or 256). It is an IO function, which gives the only opportunity to keep track of time: (Note that the function produced by newSinWave is the one actually registered as a callback: newSinWave :: Int - Float - IO (CFloat - IO CFloat) newSinWave sampleRate freq = do ioref- newIORef (0::Integer) let multiplier = 2 * pi * freq / (fromIntegral sampleRate) return (\_ - {-# SCC sinWave #-} do t- readIORef ioref modifyIORef ioref (+1) return $ fromRational $ toRational $ sin (fromIntegral t * multiplier)) I profiled this since when my program registered with the jack server and started taking callbacks, it was using about 75% cpu (in contrast, the echo program included with the jack package uses less than 2%). The following two lines are of concern to me: total alloc = 3,040,397,164 bytes (excludes profiling overheads) My program uses 3GB of virtual memory over a 15 second
Re: [Haskell-cafe] MonadRandom-computation that does not terminate
On 11/01/11 23:19, Tim Baumgartner wrote: Hi, I'm having difficulties with this function I wrote: iterateR :: (MonadRandom m) = (a - m a) - a - m [a] iterateR g s = do s' - g s return (s:) `ap` iterateR g s' I'm running the computation with evalRandIO and surprisingly the first call of main in ghci succeeds, but the second does not terminate. Reproducible. Any clues what I'm doing wrong here? If we unfold ap we get: iterateR g s = do s' - g s f - return (s:) x - iterateR g s' return (f x) What happens here depends on exactly how the monad is defined, but for many monads that will form an infinite loop that prevents a value being returned. In the case of RandT from MonadRandom, it is not possible to execute the action after the iterateR call finishes without knowing the final state from the call, which requires evaluating the infinite loop of monadic actions. Does that help? Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Misleading MVar documentation
On 12/01/11 15:53, Edward Z. Yang wrote: These are interesting, opposed perspectives, and I suspect what would be good is to treat both situations. I think perhaps what would be good to put in the introduction is the conceptual model of MVars: that is, take and put are the fundamental operations, and everything else is composed of them. With additional constraints on who is writing and reading MVars, you can assume more safety properties, but you have to ensure that those are indeed held (or you should use STM instead.) I'll try another writeup. Does anyone know where the original papers for MVars might be? I think the original paper is Concurrent Haskell, available here: http://www.haskell.org/ghc/docs/papers/concurrent-haskell.ps.gz and here: http://research.microsoft.com/en-us/um/people/simonpj/papers/concurrent-haskell.ps.gz Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] [ANNOUNCE] Parallel Haskell project underway
On 15/11/10 15:23, Dmitry Astapov wrote: == Dragonfly == http://www.dragonfly.co.nz/ Participants: Finlay Thompson, Edward Abraham Cloudy Bayes: Hierarchical Bayesian modeling in Haskell The Cloudy Bayes project aims to develop a fast Bayesian model fitter that takes advantage of modern multiprocessor machines. It will support model descriptions in the BUGS model description language (WinBUGS, OpenBUGS, and JAGS). It will be implemented as an embedded domain specific language (EDSL) within Haskell. A wide range of model hierarchical Bayesian model structures will be possible, including many of the models used in medical, ecological, and biological sciences. This is slightly OT, but having used WinBUGS a little, I am very pleased to see this listed as a project. WinBUGS is a commendable piece of work, but is really showing its age these days. Between its really horrible error messages if anything goes wrong, awkward scripting/job-running interface (slightly eased by R2WinBUGS), and of course lack of support for multicore, I think this is a case where parallel Haskell could provide a lot of benefits over the existing software. Also, can you tell us which (if any) of these projects will be released as open-source? Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Typeable state map
Hi, You have a problem with your function getPhi. It has type: getPhi :: forall a e m. (MutableMatrix a e m, Typeable a, Typeable e, Floating e, Ord e) = VarStateT m () where MutableMatrix is: class (PrimMonad m) = MutableMatrix a e m | a - e m where No matter how you call getPhi, you can't specify the 'a' and 'e' types -- they don't appear in the real part of the type signature, and the fundep on the MutableMatrix class is not sufficient to determine 'a' or 'e' from 'm'. This means that there is no way for the compiler to pick a type for 'a' or 'e' when getPhi is called, and there is no way to make the 'a' and 'e' for getPhi be the same as the 'a' and 'e' for compute. getPhi needs to know what type it is attempting to cast the dynamic state into and at the moment you can't tell it. The solutions that I can think of are either to pass dummy parameters of type 'a' and 'e' to allow you to specify the type, or to add a fundep like m - a e (but I don't think that one holds?). Thanks, Neil. On 10/11/10 13:10, Vladimir Matveev wrote: Hi, I want to use something like (Control.Monad.StateT (Data.Map.Map String Dynamic) m). So I wrote VarStateT datatype and corresponding classes (Control/Monad/VarState.hs in [1]). Then I tried to use it in my program (Math/Eigenvalues.hs in [1]). But compiler refused to compile it with many type errors. I thought that it would be sufficient to use ScopedTypeVariables and write all type annotations. It helped slightly, many messages were gone, but now compiler throws an error I don't know how to solve. ghc --make -o out/eigenvalues -outputdir build Main.hs [3 of 4] Compiling Math.Eigenvalues ( Math/Eigenvalues.hs, build/Math/Eigenvalues.o ) Math/Eigenvalues.hs:14:30: Could not deduce (MutableMatrix a e m) from the context (MutableMatrix a2 e2 m, Typeable a2, Typeable e2, Floating e2, Ord e2) arising from a use of `getPhi' at Math/Eigenvalues.hs:14:30-35 Possible fix: add (MutableMatrix a e m) to the context of the type signature for `compute' In the second argument of `()', namely `getPhi' In the first argument of `()', namely `maxElem a getPhi' In the first argument of `()', namely `maxElem a getPhi buildB' Math/Eigenvalues.hs:14:40: Could not deduce (MutableMatrix a1 e1 m) from the context (MutableMatrix a2 e2 m, Typeable a2, Typeable e2, Floating e2, Ord e2) arising from a use of `buildB' at Math/Eigenvalues.hs:14:40-45 Possible fix: add (MutableMatrix a1 e1 m) to the context of the type signature for `compute' In the second argument of `()', namely `buildB' In the first argument of `()', namely `maxElem a getPhi buildB' In the first argument of `(=)', namely `maxElem a getPhi buildB buildA' How to sort this out? [1] http://dl.dropbox.com/u/1415321/prog/eigenvalues.tar.gz ___ 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] Type Directed Name Resolution
On 10/11/10 12:36, Yves Parès wrote: I think this idea is a stairway to duck typing. I exagerate, of course, but here is my point: It shouldn't be difficult to make a class: class HasName a where name :: a - String For accessing parts of data structures that have the same type, I agree that a type-class is best. However, this doesn't cover the situation where the type of the field is different across types, e.g. data SomeXmlDerivedThingy = C { name :: Maybe String } data Person = P { name :: String } Then you'd need a fundep on your class, which begins to get ugly: class HasName a b | a - b where name :: a - b It also doesn't work when the two instances of name come from totally separate libraries that don't know anything about each other (e.g. one's an xml library, the other is a database library). Then you have to add such a class in your own code to resolve the conflict. But having read the wiki page, it seems TDNR doesn't work in where I would particularly want it (e.g. record updating), so I'm not sure it's that worthwhile. As an aside, the rule on the wiki page says Unlike normal unqualified variable occurrences, it is legal for there to be many f's in scope. To resolve which one is intended, find the type of a, and the type of all of the in-scope f's. If there is exactly one f whose type matches that of a, that resolve the occurrence of f. Otherwise the program is in error. I wonder if special syntax is actually needed for this. How much of the language would be broken by adopting the general rule: If the only definitions of f are at the top-level or imported, find the type of 'a' and the type of all the in-scope 'f' s. If there is exactly one match then use it, otherwise it's an error.? Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: change in overlapping instance behavior between GHC 6.12 and GHC 7 causes compilation failure
On 09/11/10 11:53, Neil Brown wrote: XMLGenerator.lhs:64:16: Overlapping instances for EmbedAsChild (IdentityT IO) (XMLGenT m (XML m)) arising from a use of `asChild' at XMLGenerator.lhs:64:16-22 Matching instances: instance [overlap ok] (XML m ~ x, XMLGen m) = EmbedAsChild m x -- Defined at XMLGenerator.lhs:37:11-52 instance [overlap ok] (EmbedAsChild m c) = EmbedAsChild m (XMLGenT m c) -- Defined at XMLGenerator.lhs:31:11-60 I think I should expand slightly more on this bit, especially since I chopped off the useful line The choice depends on the instantiation of `m'. The problem is that depending on the choice of m in the instance (the EmbedAsChild (IdentityT IO) (XMLGenT m (XML m)) part), you may or may not match the second overlapping instance. If you choose m=IdentityT IO then it matches the second instance, if you choose anything else then it won't, so GHC can't tell at this point which instance to choose. Which makes them not just overlapping, but also leaves no clear choice (which is why it prompts you to use IncoherentInstances). When you typed the genElement foo part explicitly and gave a type to the monad m, that fixed the ambiguity. So I think it's not even that you needed incoherent instances, you have an unresolvable ambiguity if the type of m is left to be inferred. So I still think the question is why the old instance with the ~ worked fine. (Does this help, or am I telling you what you've already worked out for yourself?) Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: change in overlapping instance behavior between GHC 6.12 and GHC 7 causes compilation failure
I'm not sure whether to reply to the list(s) or the ticket; maybe if you think my comments are valid they can be copied to the ticket. From looking, it seems to me that you do have overlapping instances, and I wonder if it's actually a 6.12 bug for accepting the code, not a 7 bug for rejecting it. I took your XMLGenerator.lhs file from the ticket and loaded it in GHC 6.12; it loaded fine. Then I looked through and squinted at this instance: instance (EmbedAsChild m c, m1 ~ m) = EmbedAsChild m (XMLGenT m1 c) That looked to me like a long-winded way of saying: instance (EmbedAsChild m c) = EmbedAsChild m (XMLGenT m c) Unless I'm missing something? So I made that change, then loaded it again. Suddenly I have overlapping instances in 6.12: XMLGenerator.lhs:64:16: Overlapping instances for EmbedAsChild (IdentityT IO) (XMLGenT m (XML m)) arising from a use of `asChild' at XMLGenerator.lhs:64:16-22 Matching instances: instance [overlap ok] (XML m ~ x, XMLGen m) = EmbedAsChild m x -- Defined at XMLGenerator.lhs:37:11-52 instance [overlap ok] (EmbedAsChild m c) = EmbedAsChild m (XMLGenT m c) -- Defined at XMLGenerator.lhs:31:11-60 It seems to me that the two instances can overlap; consider if I define an instance for XMLGen: data WhateverM instance XMLGen WhateverM where type XML WhateverM = XMLGenT WhateverM () At that point your instances would overlap if I want an instance for EmbedAsChild WhateverM (XMLGenT WhateverM ()). My understanding of the way type-classes are checked is that since that instance could exist somewhere in a different module, we must reject the two instances for EmbedAsChild. (Or rather: ignoring the head of the instance declarations, the instances can overlap.) But I may be wrong! So my guess is you've always had overlapping instances (assuming this code is representative of your original), and my hypothesis is that the use of ~ in one of the instances was somehow stopping GHC 6.12 from spotting this. Thoughts (and corrections!) welcome. Thanks, Neil. On 08/11/10 23:30, Jeremy Shaw wrote: Hello, I have narrowed this down further to a single file. And created a trac bug for it: http://hackage.haskell.org/trac/ghc/ticket/4485 This is (the only thing?) holding up HSP and happstack moving to GHC 7. - jeremy On Tue, Nov 2, 2010 at 5:36 PM, Jeremy Shawjer...@n-heptane.com wrote: Hello, I have a module, XMLGenerator, which has some overlapping instances. I have a second module, Test, which imports that module and also adds some more overlapping instances. Both modules contain {-# LANGUAGE OverlappingInstances #-} at the top. Under some old version of 6.13 (and probably 6.12), if I put both modules in the same directory and try to load Test.hs, it gets the error: Test.hs:16:15: Overlapping instances for EmbedAsChild (M IO) (XMLGenT m (XML m)) arising from a use of `asChild' at Test.hs:16:15-21 Matching instances: instance (m1 ~ m, EmbedAsChild m c) = EmbedAsChild m (XMLGenT m1 c) -- Defined at XMLGenerator.hs:16:10-68 instance (XML m ~ x, XMLGen m) = EmbedAsChild m x -- Defined at XMLGenerator.hs:19:10-51 In the first argument of `($)', namely `asChild' In the expression: asChild $ (genElement foo) In the definition of `asChild': asChild b = asChild $ (genElement foo) If I put the XMLGenerator module in a separate package, dummy-hsx, and the Test modules links against it, I still get the error. *but* if I add: Extensions: OverlappingInstances to the dummy-hsx.cabal file, then Test.hs compiles just fine! So, for starters, I do not understand why that happens. Under GHC 7.0rc1, modifying the .cabal file has no effect. Instead I always get the error: Test.hs:16:15: Overlapping instances for EmbedAsChild (M IO) (XMLGenT m (XML m)) arising from a use of `asChild' Matching instances: instance [overlap ok] (m1 ~ m, EmbedAsChild m c) = EmbedAsChild m (XMLGenT m1 c) -- Defined in XMLGenerator (The choice depends on the instantiation of `m' To pick the first instance above, use -XIncoherentInstances when compiling the other instance declarations) Adding the IncoherentInstances flag does make it compile -- but I have never enabled that flag and not regretted it. What changed between GHC 6.12 and GHC 7.0? Is there a some solution besides using IncoherentInstances in every module that imports XMLGenerator? I have attached XMLGenerator.hs, Test.hs, and dummy-hsx.cabal. thanks! - jeremy ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org
Re: [Haskell-cafe] Convert Either to Tree - Occurs check
On 22/10/10 09:23, André Batista Martins wrote: Tks for the answer, the data structure of Either is: data Either a b = Left a | Right bderiving (Eq, Ord, Read, Show) one example of what i want convert is: Left(Right(Left(Left( Hi, The problem here is that the type of Left () is: Either () a The type of Left (Left ()) is: Either (Either () a) b The type of Right (Left (Left ())) is: Either c (Either (Either () a) b) and finally, the type of Left (Right (Left (Left ( is: Either (Either c (Either (Either () a) b)) d That is, each level in the tree must have a different type. For this reason, you can't sensibly use Either for tree types of varying depth (a type-class would help, but I doubt it's what you want). A sensible type for a tree is the one you gave in your original post, TreeE. So why do you want to encode the tree with Either (not really possible) and then convert to your TreeE type? Why not just start out with the values in your tree type? Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] tried to use the example given in the source of network.browser
Hi, On 22/10/10 14:58, Michael Litchard wrote: main = do rsp- Network.Browser.browse $ do setAllowRedirects True -- handle HTTP redirects request $ getRequest http://google.com/; fmap (take 100) (getResponseBody rsp) but I got this errortest.lhs:10:39: Couldn't match expected type `Network.Stream.Result (Response [a])' against inferred type `(Network.URI.URI, Response String)' In the first argument of `getResponseBody', namely `rsp' In the second argument of `fmap', namely `(getResponseBody rsp)' In the expression: fmap (take 100) (getResponseBody rsp) how did I get this error? I'm perplexed as this came right from the source. To be specific, it came from the documentation of the library... which turns out not to match the source. It seems you instead want: main = do (_, rsp) - Network.Browser.browse $ do setAllowRedirects True -- handle HTTP redirects request $ getRequest http://google.com/; print (take 100 $ rspBody rsp) I've changed the last bit to print the first 100 lines of the result rather than return them, as I imagine that is what you want if you're using it as a main function. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Lazy evaluation from Why Functional programming matters
On 06/10/10 11:00, C K Kashyap wrote: My ultimate aim it to write an EDSL for x86 - as in, describe a micro-kernel in haskell, compiling and running which would generate C code ( not sure if it's even possible - but I am really hopeful). Have you seen Potential (http://intoverflow.wordpress.com/2010/05/21/announcing-potential-x86-64-assembler-as-a-haskell-edsl/)? Quote: The language’s goal is to provide a solid foundation for the development of a useful (multi-tasked, multi-processor, etc) microkernel Which sounds like it's exactly what you want. Also, see Harpy (http://uebb.cs.tu-berlin.de/harpy/). Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Lambda-case / lambda-if
On 05/10/10 07:52, Nicolas Wu wrote: I'd prefer to see something like \ 1 - f | 2 - g but I'm sure something could be worked out. While I think the case of is a good idea, multiple clauses in lambdas seems more canonical to me. Alternatively, we could abandon lambdas and just use lambda-case. All expressions like \1 - f become case of 1 - f Multi-argument functions are a bit more verbose, as we effectively go back to single argument functions with manual currying: \x (C y) - z becomes: case of {x - case of {C y - z}} There is the small matter of losing backwards compatibility, of course. But on the plus side, this would reduce the number of constructions in the language by one. (I think the strictness semantics, etc match up for this transformation?). ;-) Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] EDSL for Makefile
On 30/09/10 09:41, C K Kashyap wrote: Hi All, I was thinking about doing an EDSL for Makefile (as an exercise) I put down my line of thought here - http://hpaste.org/40233/haskell_makefile_edsl I'd appreciate some feedback on the approach. Also, I wanted some idea on how(in the current approach) I could make the target name and the dependency available to the action writer - as shown below. r1 = Rule { target = file1, dependsOn = [file2], action = do execute (gcc -c ++ dependencyList ++ -o ++ target) } Neil Mitchell gave a talk at AngloHaskell 2009 on doing a better make in Haskell. I've found the abstract on the wiki: http://www.haskell.org/haskellwiki/AngloHaskell/2009 but, alas, no slides to be found. My memory was that he had implemented the system successfully for internal use at a company and it had worked out quite well. Perhaps you can contact him about the slides. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ANNOUNCE: http-enumerator 0.0.0
On 22/09/10 11:22, C K Kashyap wrote: Hey Michael, I'd like to announce the first release of http-enumerator[1], an HTTP client package with support for HTTPS connections. This release is very experimental; bug reports and API feedback are very welcome. This sounds nice (I'll certainly try it out). A non-technical question - why have you named it http-enumerator? If I've understood it right, this is kinda equivalent of curl/wget (for http/https) right? From the original announcement: using the enumerator package to allow efficient parsing of response bodies -- I'm guessing that explains it :-) Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] try, seq, and IO
On 15/09/10 10:13, Jeroen van Maanen wrote: The past year I have been working on a port of my machine learning project named LExAu from Java to Haskell. I'm still very glad I took the jump, because the complexity curve appears to be log shaped rather than exp shaped. In one year I almost got to the functionality that had taken me five years to produce in Java (of course it helped a lot that I had a working prototype this time). There is one thing that still bothers me though: when I write seq or $! it doesn't seem to have any effect! Currently I am trying to add some exception handling to help me debug the system, but the code that I managed to produce depends on the logging statement to produce the desired result. :-( It looks like this, and only works when I uncomment the line '-- logger Check sum: [...]', otherwise the exception is caught by the try around the body of the thread that this code runs in: do logger Received update [showString label, logs update] result- try $! do maybeUpdatedModel- return $ f update startModel theCheckSum- return $ liftM checkSum maybeUpdatedModel -- logger Check sum [showString label, shows theCheckSum] return $! seq theCheckSum maybeUpdatedModel maybeNextModel- case result of Right theMaybeNextModel - return theMaybeNextModel Left exception - do let exc :: SomeException exc = exception logger Exception [showString label, shows exception] return Nothing logger Maybe next model [showString label, logs maybeNextModel] For more context see: http://lexau.svn.sourceforge.net/viewvc/lexau/branches/totem/src/LExAu/Pipeline/Concurrent.hs?revision=326view=markup after line 241. Can someone explain why a few showStrings a shows and a putStrLn are more effective in forcing the check sum to be computed (which necessarily evaluates the complete updated model and reveals the lurking exception) than the seq on the line just below the logging statement? I just looked at your code for a second time and I think I know. Here's my guess: It's all about the types, and weak head normal form. The theCheckSum item has type Maybe a, and you are looking for an exception in the a part that's wrapped by Maybe (I presume: the Just/Nothing is determined by the function f, not checkSum). When you use seq or $!, you only evaluated to weak head normal form, For something of type Maybe a, that's only the Just/Nothing part. Forcing that aspect to be evaluated only requires some evaluation of the function f, and the checkSum function doesn't need to be applied, even if it is a Just value. However, your shows function digs deeper and evaluates the whole thing, so hence it will trigger the error where seq and $! won't. So, if I'm right, you need to change your function to make sure to evaluate the checksum itself. The deepseq package on Hackage may help here (use the deepseq function in place of seq: http://hackage.haskell.org/packages/archive/deepseq/1.1.0.0/doc/html/Control-DeepSeq.html). I'm a little suspicious of the code as a whole though: why does checkSum throw an exception rather than returning a Maybe value? Or is it an exception somehow outside of your control? Another thing: x - return $ blah in a do block is bad style, and can always be replaced with: let x = blah Note that there is no in needed with let statements in do blocks (that confused me when first learning Haskell). Hope that helps, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Question on concurrency
On 14/09/10 07:45, Arnaud Bailly wrote: What surprised me is that I would expect the behaviour of the two functions to be different: - in doRunMvnInIO, I would expect stdout's content to be printed before stderr, ie. the 2 threads are ordered because I call takeMVar in between calls to forkIO - in doRunMvnInIO', this is not true and both theads run concurrently. but actually there does not seem to be a difference: printing is still interleaved in both functions, AFAICT. Hi, I've tried your code (substituting a program that spits out different streams of numbers on stdout and stderr for maven), and I see the behaviour you had expected: the first version does print all of stdout before stderr, whereas the second version shows interleaving of the two streams. Are you certain that you are seeing interleaving in the first version? Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Full strict functor by abusing Haskell exceptions
On 13/09/10 17:25, Maciej Piechotka wrote: import Control.Exception import Foreign import Prelude hiding (catch) data StrictMonad a = StrictMonad a deriving Show instance Monad StrictMonad where return x = unsafePerformIO $ do (return $! x) `catch` \(SomeException _) - return x return $! StrictMonad x StrictMonad v= f = f v It seems to be valid IMHO Functor and Monad (I haven't prove it) as long as functions terminates. I'm not sure if I'm allowed to use unsafePerformIO in my counter-example, but you used it so why not ;-) The first monad law says: return a = k = k a let k = const (StrictMonad ()) a = unsafePerformIO launchMissiles In k a no missiles will be launched, in return a = k, they will be launched. You can construct a similar example against m = return = m. Although, if you changed your definition of bind to: StrictMonad v = f = return v = f = return Then as long as return x = return = return x (which it does for you) then you automatically satisfy the first two monad laws! Which is an interesting way of solving the problem -- haven't checked the third law though. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] ANNOUNCE: game-probability-1.1
Hi, I've just released version 1.1 of my game-probability library. It's intended to be an easy way to investigate the probability of various dice rolls and card draws (the latter is the new addition for the 1.1 release), using a Haskell library/EDSL. It has various examples in the documentation, plus a few blog posts on its design (all links below). Hackage: http://hackage.haskell.org/package/game-probability Docs (while waiting for Hackage to generate): http://twistedsquare.com/game-probability-1.1/ Blog posts: http://chplib.wordpress.com/2010/08/13/nice-dice-in-haskell/ http://chplib.wordpress.com/2010/08/23/sharp-cards-in-haskell-drawing-cards/ http://chplib.wordpress.com/2010/09/08/sharp-cards-in-haskell-the-odds/ As a quick taster, below are some examples of using the library. Showing the probabilities of a dice roll prints out a bar chart -- here is the sum of two six-sided dice: show (2 * d6) 2 : # 3 : ## 4 : ### 5 : 6 : # 7 : ## 8 : # 9 : 10: ### 11: ## 12: # Querying probabilities of the outcomes of dice rolls: chancePred (= 16) (3*d6) 5 % 108 The chance of drawing different numbers of Copper cards in a starting hand of 5 drawn from 7 Copper and 3 Estate (this is from the card game Dominion): chanceMap (makeCards $ replicate 7 Copper ++ replicate 3 Estate) (drawCount (== Copper) 5) fromList [(2,1 % 12),(3,5 % 12),(4,5 % 12),(5,1 % 12)] Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Restricted type classes
On 07/09/10 05:24, wren ng thornton wrote: that other class would (most likely) be a subclass of pointed functors. In any case, it does mean there's something of a mismatch between singleton vs return/pure/point/unit. Not quite sure what you mean by a mis-match Of course, I'd expect singleton to obey the pointed law as well, so Just that they're not the same thing. For example, ZipList supports pure but it has no meaningful instance of singleton since every ZipList is infinite. I don't believe that every ZipList is infinite (if this should be the case, the constructor shouldn't be exposed!), just that ZipLists created by pure are infinite -- that's the obvious definition to meet the Applicative laws. You can quite happily use: (+) $ ZipList [1,2,3] * ZipList [4,5] == ZipList [5,7] So ZipList does have a meaningful definition of singleton (singleton x = ZipList [x]; I'm sure there are other pointed functors that don't have a good definition for singleton), and a meaningful definition of pure, but they're not the same definition. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] overloaded list literals?
On 06/09/10 11:23, Johannes Waldmann wrote: We have overloaded numerical literals (Num.fromInteger) and we can overload string literals (IsString.fromString), so how about using list syntax ( [], : ) for anything list-like (e.g., Data.Sequence)? I would have thought you have two obvious choices for the type-class (things like folding are irrelevant to overloading list literals): class IsList f where fromList :: [a] - f a or: class IsList f where cons :: a - f a - f a empty :: f a I'd go for the first, as I'd imagine you are only overloading the [a,b,c] form, not the a:b:c:[] form, and the first reflects this better. Both of these could be used to convert a list literal into a list-like type (e.g. Sequence). But neither of them would be useful for sets or maps, because the classes lack an Ord constraint on the type a -- maybe this makes overloaded list literals fairly limited in utility. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Unnecessarily strict implementations
On 03/09/10 11:11, Henning Thielemann wrote: Ivan Lazar Miljenovic schrieb: On 3 September 2010 04:57, Arie Peterson ar...@xs4all.nl wrote: On Thu, 2 Sep 2010 19:30:17 +0200, Daniel Fischer daniel.is.fisc...@web.de wrote: Why would one consider using Ord for Map an abuse? A kludge, for performance reasons, but an abuse? Because it forces one to declare Ord instances for types which have no natural ordering. It is useful to *not* have such instances, in order to catch programming errors. What precisely do you mean by natural ordering? E.g. I wanted to have a Set of Gaussian (complex) integers, but I did not want to define an Ord instance for them, because writing a (b :: Gaussian) is a bug with high probability. Isn't this what newtype is good for? Instead of declaring Ord Gaussian to get Set Gaussian and risking the bug you describe, create newtype GaussianInSet = G Gaussian, declare Ord GaussianInSet and use Set GaussianInSet. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Unnecessarily strict implementations
On 02/09/10 17:10, Stephen Sinclair wrote: On Thu, Sep 2, 2010 at 3:25 AM, Jan Christiansen j...@informatik.uni-kiel.de wrote: I prefer False= _|_ = True Sorry to go a bit off topic, but I find it funny that I never really noticed you could perform less-than or greater-than comparisons on Bool values. What's the semantic reasoning behind allowing relative comparisons on booleans? In what context would you use it? It seems to me a throwback to C's somewhat arbitrary assumption that False=0 and True=1. Comparison on Bool itself is probably not particularly useful. But it is often useful if the Bool is part of a larger data structure. For example, I might want to have Set (String, Bool); without the Ord instance on Bool I couldn't do this. Similarly, you couldn't derive Ord on your data types that have Bool in them without the Ord Bool instance. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Having a connection between kind * and kind * - *
On 19/08/10 14:26, Ivan Lazar Miljenovic wrote: , | -- | Indicates what kind of value may be stored within a type. Once | -- superclass constraints are available, the @v@ parameter will | -- become an associated type. | class Stores c v | c - v | | data family Constraints :: (* - *) - * - * | | class (Stores (c v) v) = Suitable c v where | constraints :: Constraints c v ` This works. However, what doesn't work is when I try to use these classes to re-define Functor: , | class (Stores c v) = Mappable c v where | rigidMap :: (v - v) - c - c | | class (Mappable (c v) v) = Functor c where | fmap :: (Suitable c a, Suitable c b) = (a - b) - c a - c b ` I'm no typing expert... but how do you expect the type-checker to be able to infer a type for 'v' here? Even with the fundep from Stores, 'c v' should determine 'v', but what value is the type-checker going to pick for 'v'? It's not mentioned again anywhere else, and it is needed in order to pick the Mappable instance. What would you do with the Mappable instance anyway? You can only use it if type 'a' is the same as type 'b' (and then I think *this* is type you'd want for 'v'), and I don't see that any of your other constraints or machinery can help you to identify when this is the case. Hope that helps your thinking, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Heavy lift-ing
On 17/08/10 17:13, Tilo Wiklund wrote: On 24/07/2010, aditya siramaditya.si...@gmail.com wrote: Perhaps I'm being unclear again. All I was trying to say was that: liftM2 (-) [0,1] [2,3] /= liftM2 (-) [2,3] [0,1] -deech I'm sorry if I'm bumping an old thread, but why should liftM2 f be commutative when f isn't? (I hope I'm not responding incorrectly) I think the point that was being made is that: liftM2 (flip f) /= flip (liftM2 f) This is because the former (well: liftM2 (flip f) a b) effectively does: do {x - a; y - b; return (f y x)} Whereas the latter (flip (liftM2 f) a b) effectively does: do {y - b; x - a; return (f y x)} That is, the order of the arguments to liftM2 matters because they are executed in that order. So lifting the flipped function has a different effect to flipping the lifted function. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] zip-archive performance/memmory usage
On 10/08/10 00:29, Pieter Laeremans wrote: Hello, I'm trying some haskell scripting. I'm writing a script to print some information from a zip archive. The zip-archive library does look nice but the performance of zip-archive/lazy bytestring doesn't seem to scale. Executing : eRelativePath $ head $ zEntries archive on an archive of around 12 MB with around 20 files yields Stack space overflow: current size 8388608 bytes. The script in question can be found at : http://github.com/plaeremans/HaskellSnipplets/blob/master/ZipList.hs I'm using the latest version of haskell platform. Are these libaries not production ready, or am I doing something terribly wrong ? I downloaded your program and compiled it (GHC 6.12.1, zip-archive 0.1.1.6, bytestring 0.9.1.5). I ran it on the JVM src.zip (20MB, ~8000 files) and it sat there for a minute (67s), taking 2.2% memory according to top, then completed successfully. Same behaviour with -O2. Which compares very badly in time to the instant return when I ran unzip -l on the same file, but I didn't see any memory problems. Presumably your archive is valid and works with unzip and other tools? Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ANNOUNCE: approximate-equality 1.0 -- Newtype wrappers for approximate equality
On 03/08/10 05:32, Gregory Crosswhite wrote: I am pleased to announce the release of the package approximate-equality, which provides newtype wrappers that allow one to effectively override the equality operator of a value so that it is/approximate/ rather than/exact/. The wrappers use type annotations to specify the tolerance; the 'Digits' type constructor has been provided for specifying the tolerance using type-level natural numbers. Instances for all of the classes in the numerical hierarchy have been provided for the wrappers, so the wrapped values can mostly be used in the same way as the original values. (In fact, most of the time one doesn't even have to wrap the starting values, since expressions such as (1+sqrt 2/3) are automatically wrapped thanks to the 'fromIntegral' method of the 'Num' typeclass.) The motivation behind this package is that there are times when working with floating point numbers that one would like the equality operator to check for approximate equality rather than exact equality. For example, in one of my own projects I have a walker that spits out a list of coordinate values that I keep track of, and since floating point arithmetic is inexact it will often arrive at the same point from two different paths and thus obtain slightly different values for the coordinates of that point. I could have just written a function to do approximate matching of the point and be done with it, but then I can't leverage pre-built data structures such as Data.Set and Data.Map which use (==) for determining whether a key is a member. This package is compatible with Haskell 2010, as it only uses the EmptyDataDecls extension, and the only package dependency is type-level-natural-numbers which itself is Haskell 2010. Any feedback from the community is, of course, very welcome. I like the look of this. Eq and Ord instances that use epsilon values look like they will be handy. I have a design question/suggestion. You have: class AbsoluteTolerance absolute_tolerance where absoluteToleranceOf :: Fractional value = AbsolutelyApproximateValue absolute_tolerance value - value Why do you need this class (and the other two)? It looks like you can just define: absoluteToleranceOf :: (NaturalNumber n, Fractional value) = AbsolutelyApproximateValue (Digits n) value - value absoluteToleranceOf = toleranceFromDigits . getAbsoluteTolerance So you can get the same function without needing to add a type-class. Or is it that you envisage other tolerance specifications besides Digit? If so, I wonder if this flexibility complicates your API unnecessarily. If you removed those type-classes and just stuck with Digits, the size of your API documentation would halve, and make the docs a lot more readable. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Actors and message-passing a la Erlang
On 25/07/10 21:55, Yves Parès wrote: Hello ! I've been studying Erlang and Scala, and I was wondering if someone has already implemented an actors and message passing framework for concurrent and distributed programs in Haskell. Hi, Take a look at the concurrency section on Hackage: http://hackage.haskell.org/packages/archive/pkg-list.html#cat:concurrency The actor library and eprocess library mention Erlang, but it seems like no other libraries attempting to replicate Erlang's concurrency model have made it on to Hackage. I wonder if part of the reason for this is that Erlang uses untyped (or should that be dynamically typed?) communication, which doesn't set as easily with Haskell's static typing. (Looking at the Haskell concurrency libraries on that list suggests that Haskell concurrency tends to focus either on transactions or on typed channels as a concurrency mechanism instead.) Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] use of modules to save typing
On 08/07/10 09:08, Michael Mossey wrote: data PlayState = PlayState { playState_cursor :: Int , playState_verts :: [Loc] , playState_len :: Int , playState_doc :: MusDoc } Notice how often the characters playState_ get typed. This would be a great situation for Emacs abbreviations. When you define an abbreviation in Emacs, such as defining xps to expand to PlayState, emacs will watch for the characters xps. It will then replace xps with PlayState when you type a non-alphanumeric character following xps. So if I type xps. the moment I hit . it changes to PlayState. But I would have a hard time using this feature with playState_ because it is always followed by an alphanumeric character. What about auto-completion? With that set of definitions, typing plexpand-key should give you playState_ (it expands to the longest unambigious expansion), and adding cexpand-key should give you playState_cursor. So you get the full thing for about five keystrokes, without any worrying about alphanumeric vs non-alphanumeric. I have completion bound to tab in emacs (a la tab completion in the shell): (global-set-key (kbd TAB) 'dabbrev-expand) and am pretty happy with this for Haskell coding. dabbrev-expand does not perform any Haskell-specific context-sensitive completion -- it just picks words out of open buffers, but I've found this to work to my satisfaction. One additional nice thing is that after a completed word, if you press space then expand-key again, it inserts the most common next word after your previous completion based on open buffers. Since in Haskell function calls and types are separated by spaces, this allows you to quickly complete common phrases from your Haskell code. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: chart broken under 6.12 according to criterion
On 01/07/10 10:19, Tom Doris wrote: According to the criterion.cabal file shipped with the latest (0.5.0.1) version of criterion, the Chart package is broken under GHC 6.12: flag Chart description: enable use of the Chart package -- Broken under GHC 6.12 so far Does anyone know the status of this problem? It's been a little frustrating getting Criterion up and running - it didn't work at all under 6.10 due to a compiler bug (The impossible happened error on uvector install) and now it works under 6.12 but without the nice charts that are so useful. Appreciate any insight or workarounds for this, thanks Hi, cabal install criterion -fChart --reinstall builds fine for me on GHC 6.12.1, and I can draw the KDE graphs succesfully for the criterion examples. I think that comment in the cabal file is probably related to Chart's dependency on gtk2hs. gtk2hs used to be broken on GHC 6.12, but these days it works -- and is on Hackage, too. Give that cabal command a go and see if it works for you. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] functional dependencies question
On 01/07/10 12:37, Patrick Browne wrote: Why do some cases such as 1) fail to run even if they are the only instantiation. -- 1) Compiles but does not run instance LocatedAt Int String where spatialLocation(1)=home That instance is fine. I presume the problem is that you are trying to run this function using spatialLocation 1 as the function call. The problem with that is that the 1 part has type Num a = a, i.e. it can be any Num type. Even though you only have one instance, that's not used to constrain the type for 1. The call spatialLocation (1::Int) works correctly. Looking at your other examples, all the ones that don't work have a numeric type for the parameter, so I suspect it is the same issue throughout. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] functional dependencies question
On 01/07/10 13:11, Patrick Browne wrote: Neil, Does the following sum up the situation? The class Num has subclasses containing various numeric types and the literal 1 is a value for one or more of those types. Hence the Haskell compiler says the instance 1) is OK. But at run time, without the quantified (1:Int), the 1 could of more than one type, which causes a problem. I think you have the rough gist, but a few clarifications are necessary. I've added some angle brackets to show the differences: The class Num has instances for various numeric types and the literal 1 is a shorthand for fromIntegral 1 which can be instantiated to any of those types. At compile time, without the qualified (1::Int), the 1 could be instatianted to any type, and so the compiler cannot determine which instance is required, because it doesn't know an exact type for the literal 1. All this is at compile-time, not run-time. The problem comes down to needing to know a specific type in order to pick a type-class instance -- the functional dependencies are actually irrelevant to this aspect. Let's say I have this simpler class: class Big a where isBig :: a - Bool instance Big Int where isBig x = (x 100) -- big for an Int instance Big Integer where isBig x = (x 1) -- big for an Integer If you ask isBig , the compiler needs to know which instance to use. The literal can be an Int or an Integer, so the instance is ambigious, and that will cause the error. So the compiler needs some clarification to choose an instance. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: chart broken under 6.12 according to criterion
On 02/07/2010 00:03, wren ng thornton wrote: OS= OSX 10.5.8 GHC = 6.12.1 Cabal-Install = 0.8.2 Cabal = 1.8.0.2 $ cabal install criterion -fChart --reinstall Resolving dependencies... ... Configuring cairo-0.11.0... setup: gtk2hsC2hs is required but it could not be found. I had this same problem installing gtk2hs originally. As some helpful posters on reddit pointed out at the time (http://www.reddit.com/r/haskell/comments/c7uh3/gtk2hs_now_on_hackage/) you need: cabal install gtk2hs-buildtools alex happy before instlaling gtk2hs, and also to make sure that the location where cabal puts its binaries is in your $PATH. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] MonadCatchIO and bracket.
On 28/06/2010 20:02, Carl Howells wrote: While working this weekend on the Snap web framework, I ran into a problem. Snap implements MonadCatchIO, so I thought I could just use bracket to handle resource acquisition/release in a safe manner. Imagine my surprise when bracket simply failed to run the release action sometimes. I quickly determined the times when it doesn't run are when Snap's monadic short-circuiting is used. I dug into the source of bracket (in the transformers branch, though the mtl branch has the same behavior in these cases, with slightly different code), and the reason why quickly became obvious: See also this recent thread on haskell-cafe: http://www.haskell.org/pipermail/haskell-cafe/2010-June/079198.html which concluded that the ContT instance in MonadCatchIO is broken. I think as you say, the instances of that library are flawed when dealing with monads that can alter the control flow. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Control.Alternative --- some and many?
On 23/06/10 06:54, Christopher Done wrote: I'm not sure how Alternative differs from MonadPlus, other than being defined for Applicative rather than Monad. They have the same laws (identity and associativity). Importantly, MonadPlus must satisfy some laws for (=) and (), whereas Alternative must only satisfy laws for the new (|) operator. There are plenty of monads that do not satisfy the laws for MonadPlus (particularly the difficult mzero-being-right-zero law), but do satisfy the laws when defining their (|) implementation. So they are different because MonadPlus overlaps with Monad, whereas Alternative does not (and thus, in my view, is much cleaner and more useful). Some and many are probably motivated by their usefulness in parsers. Hence optional, etc. I'm sure there are plenty of other uses for it. I wrote a little about some and many in Alternative in this blog post: http://chplib.wordpress.com/2010/05/05/choose-anything-adding-an-alternative-instance/ (scroll down to the Alternative heading). I think they are mainly useful with a left-biased choice operator. On 23 June 2010 05:22, Gregory Crosswhitegcr...@phys.washington.edu wrote: Hey everyone, Could someone explain to me (or point me to a reference explaining) the purpose of the some and many methods of the Alternative class? Also, there is a link posted in the documentation for Control.Applicative to a paper which describes the motivation behind the Applicative class; is there similarly a paper explaining the motivation behind the Alternative class? (The problem with Googling for Alternative is that this word is used a whole lot of the time, and very rarely does it refer to the Alernative class. :-) ) Cheers, Greg ___ 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 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] MonadCatchIO-transformers and ContT
Hi, Here's my guess. Take a look at this version, and try running it: === {-# LANGUAGE PackageImports #-} import qualified MonadCatchIO-transformers Control.Monad.CatchIO as C import Control.Monad.IO.Class import Control.Monad.Trans.Cont bracket_' :: C.MonadCatchIO m = m a -- ^ computation to run first (\acquire resource\) - m b -- ^ computation to run last when successful (\release resource\) - m b -- ^ computation to run last when an exception occurs - m c -- ^ computation to run in-between - m c -- returns the value from the in-between computation bracket_' before after afterEx thing = C.block $ do _ - before r - C.unblock thing `C.onException` afterEx _ - after return r f :: ContT (Either String String) IO String f = do bracket_' (say acquired) (say released-successful) (say released-exception) (say executed) say Hello! () - error error return success where say = liftIO . putStrLn main :: IO () main = flip runContT (return . Right) f = print === I get: acquired executed released-successful Hello! released-exception Tmp.hs: error So the exception handler is running after the code that follows the whole bracket_' call -- and after the bracket_' call has completed succesfully! Here's my speculation, based on glancing at the libraries involved: I believe the reason for this may be the MonadCatchIO instance for ContT: === instance MonadCatchIO m = MonadCatchIO (ContT r m) where m `catch` f = ContT $ \c - runContT m c `catch` \e - runContT (f e) c === To my eye, that code takes the continuation to run after the block, c (which in your case involves the after-action from bracket_, and then the error), and runs that inside the catch block. This causes a successful completion of bracket_ (first release), followed by the error, which triggers the catch block which then runs the final actions (second release) and rethrows the error. Does that sound possible to anyone else? Thanks, Neil. On 21/06/10 09:39, Michael Snoyman wrote: Hi cafe, I ran into a segfault while working on some database code. I eventually traced it back to a double-finalizing of a statement (read: freeing memory twice), which ultimately led back to switching my code to use the ContT monad transformer. I was able to isolate this down to a minimal test case (catch.hs); when run, it prints the line released twice. In an attempt to understand what's going on, I rewrote the code to avoid the libraries entirely (catch-simplified.hs); it didn't give me any insight into the problem, but maybe it will help someone else. If someone sees an obvious mistake I'm making in my usage of the bracket_ function, please let me know. Otherwise, I'd really like to get a fix for this so I can use this library. Thanks, Michael ___ 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] learning advanced haskell
On 14/06/10 06:42, Aran Donohue wrote: Hi Cafe, I've been doing Haskell for a few months, and I've written some mid-sized programs and many small ones. I've read lots of documentation and many papers, but I'm having difficulty making the jump into some of the advanced concepts I've read about. How do people build intuitions for things like RankNTypes and arrows? (Is the answer Get a PhD in type theory?) Normally I learn by coding up little exercise programs, but for these I don't have good intuitions about the kinds of toy problems I ought to try to solve that would lead me to understand these tools better. For systems like Template Haskell and SYB, I have difficulty judging when I should use Haskell's simpler built-in semantic abstractions like functions and typeclasses and when I should look to these other mechanisms. I'd second Ivan's suggestion to learn-by-need. For SYB and Template Haskell, and probably for most other fancy abstractions, you can get on happily without them in most cases. When you start to think there must be a better way! while coding, that's when you should start looking for advanced features. For example, if you find yourself writing the Nth boilerplate function that pattern-matches all cases in your ADT just to apply a function in its sub-types, that's when you'll want some form of generic programming like SYB. And by that point you'll understand one of the problems that generic programming solves, which is halfway towards understanding the techniques themselves. Hope that helps, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] TDD in Haskell
On 25/05/10 12:36, Ionut G. Stan wrote: Hi, I'm doing TDD in pretty much all of the languages that I know, and I want to introduce it early in my Haskell learning process. I wonder though, if there's some established process regarding TDD, not unit testing. I've heard of QuickCheck and HUnit, but I've also read that QuickCheck is used mostly for testing pure code, while HUnit for impure code? I tend to use HUnit more than QuickCheck (even for pure code), but that may be a reflection of the projects I've worked on. Reasons why I have used HUnit: - Writing an Arbitrary instance for a data type wasn't worth the effort. When writing a nanopass compiler, it seemed like too much effort to write an Arbitrary instance to produce a valid fragment of AST for that particular pass (given that each pass would probably need a different instance). Problems with the instance include: * If I allowed every instance to generate the full variety of AST elements, the chances of generating an AST fragment that tested the pass in question would be vanishingly small, which would require customising the instance (or adding generation conditions) in fiddly ways for each pass to make sure I got good coverage. * For most passes, the AST must obey many pre-conditions, such as all variables being declared before use, all expressions type-checking, passing various safety/sanity checks and so on. All these (and different sets of them) would need to be considered for each Arbitrary instance, which adds a lot of effort to the instance generation, when I can easily craft a few targeted pieces of input myself. - With some functions I can provide an exhaustive check of all inputs, for which QuickCheck is ill-suited. This would suit SmallCheck and LazySmallCheck, but often it's just easier to write something like: assertTrue $ and [checkResult x (f x) | x - allInputs] than to use the other frameworks. - For QuickCheck 1, testing of things like IO actions was very difficult (I think unsafePerformIO was needed?) but QuickCheck 2 is much better in that regard once you've gone the hang of it. More generally, I often think it is less effort to test the corner/edge cases carefully with HUnit than it is to express the properties of the function (and the properties are almost always noticeably longer than the function being tested) and construct an Arbitrary instance that produces valid input. Perhaps I just haven't worked on the right projects for QuickCheck or haven't got into the property-based testing mindset, though. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] mixing map and mapM ?
Bill Atkins wrote: Almost - liftM modificationTime has type Status - IO EpochTime. Like other IO functions (getLine, putStrLn), it returns an IO action but accepts a pure value (the modification time) Also, I like this style: import Control.Applicative (($)) blah = do times - mapM (PF.modificationTime $ PF.getFileStatus) filenames ... The $ operator evaluates to fmap so it's a cleaner way to apply a pure function to an IO value. That won't type-check (unless I've missed some crafty trick with the types?!); you have two functions you want to compose, but the $ operator (i.e. fmap) applies a function on the left to a functor-value on the right. You would instead need: times - mapM ((PF.modificationTime $) . PF.getFileStatus) filenames At which point I prefer Ivan's liftM version rather than the above section (or worse: using ($) prefix). The original request is a relatively common thing to want to do, so I was slightly surprised that hoogling for: (b - c) - (a - f b) - a - f c didn't turn up any relevant results. This function is a lot like (=) but with a pure rather than side-effecting function on the left-hand side. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What do _you_ want to see in FGL?
Hi, Primarily I want to see in FGL: documentation, documentation and more documentation. The library has lots of undocumented functions (especially the queries, e.g. http://hackage.haskell.org/packages/archive/fgl/5.4.2.2/doc/html/Data-Graph-Inductive-Query-DFS.html has no documentation at all), and the only reference is the original paper. I've seen several people who didn't read the paper (or didn't read the right bits) get confused by the inductive way the graph is constructed, when they try to de-construct it. I would also like to see the library reduced in size/scope if possible; there's a lot of modules in FGL, but all I've ever used are D.G.I.Graph, D.G.I.Tree, D.G.I.Graphviz and D.G.I.Query.DFS. I consider this to probably be the most common usage of the library by others too (if you throw in D.G.I.Query.BFS). So by the sounds of it, if you split Graphviz and Query off to separate libraries, I probably only use the core module. Ivan Lazar Miljenovic wrote: Here are some ideas that I have regarding FGL: * Better fundamental data structures: one of the things that has always annoyed me about FGL is how much it uses tuples; I propose re-defining the Context type to be a record-based data structure. Also, usage of Sets, Maps, etc. where applicable. I think this is worth doing, even if it does break code. If you're doing Context, you may as well do LNode and LEdge too. * Data.Graph.Inductive.Monad: does anyone actually use this? No, now that I look at it, it's not what I would expect. It seems to be a lot of operations that could be constructed by sticking liftM before the normal operations. For example: nodesM :: GraphM m gr = m (gr a b) - m [Node] I would have thought the useful operations for graphs and monads would have been something more like: nodesM :: GraphM m gr = gr (m a) (m b) - m [Node] On that node, I would like to see some instances for the graph types: particularly Functor, Foldable and Traversable, for both (Gr a) and (Flip Gr b) -- where Flip is http://hackage.haskell.org/packages/archive/TypeCompose/latest/doc/html/Control-Compose.html#t:Flip or http://hackage.haskell.org/packages/archive/category-extras/latest/doc/html/Control-Functor-Combinators-Flip.html If you put FGL in a repository somewhere, I might be able to find some time to write those instances and perhaps contribute a bit of documentation (no promises, though!). Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] and [] = True; or [] = False
Bjorn Buckwalter wrote: Dear all, Does it make good sense that 'and []' returns 'True' and 'or []' returns 'False'? It's certainly what I would expect it to do, based on several ways of thinking. 1: If we define the function using explicit recursion: and (x:xs) = x and xs Therefore and [] has to be True. Similar logic for or. 2: My instinct is to consider and = all (== True), while or = any (== True). It's even clearer to me that all [] = True and any [] = False (similiar to Miguel's post). Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] The Poor Man's PVP-Checking Tool
Hi, The issue of a tool to help with checking packages against the Package Versioning Policy (PVP: http://www.haskell.org/haskellwiki/Package_versioning_policy) has come up several times on this list, and it seems to be a generally wanted tool. One of the things desired in such a tool is the ability to check what has been added/changed/removed in the latest version of a package, to help see what kind of version bump is needed according to the PVP. This could also be used to check if past releases have obeyed the PVP. A proper way to build this tool is to parse the types of everything involved (functions, data types, and instances), and check them for being the same (given that the type parameters may have been renamed, or a definition substituted for a synonym and so on). I have instead hacked together a tool in an hour or so that roughly does the job. It uses Perl, which I haven't written for a long time, because that was quickest -- if this bothers you, pretend its a crazy Haskell EDSL or something :-). I've attached the Perl script. It combines the command-line tools diff and sort with a tiny bit of manual processing along with the Haskell tool cabal-install, and brings them to bear on the output of haddock --hoogle, which already nicely spits out the types of all functions, data types and instances in your library. It looks for differences in the output between two package versions, and tells you what version bump it thinks you need. It errs on the conservative side, I believe -- it should never miss a bump when it's needed, but you may sometimes get a false alarm if you've made a harmless change. As an example, let's take the recent stm release. You run the Perl script with the name and version of both package versions (if you omit the version, it should use the latest): n...@beast ~: perl cmp.perl stm-2.1.2.0 stm-2.1.1.2 Warning: The documentation for the following packages are not installed. No links will be generated to these packages: ffi-1.0, rts-1.0 Warning: The documentation for the following packages are not installed. No links will be generated to these packages: ffi-1.0, rts-1.0 25a26 Control.Concurrent.STM.TVar:readTVarIO :: TVar a - IO a 39c40 @version 2.1.1.2 --- @version 2.1.2.0 Given previous version number A.B.C.D: It seems you have added something. You must increase C (or A or B) For those who can read diff, you get the diff. At the bottom, the tool works out the required bump; here something was added so C must be increased, and we can see that the package did just that. Let's take another example from my latest development version of my CHP library; here I run the command with one argument (chp, which means the latest version on Hackage): n...@banshee ~/work/chp: perl cmp.perl chp Warning: The documentation for the following packages are not installed. No links will be generated to these packages: rts-1.0 Control/Concurrent/CHP/Alt.hs:116:9: Warning: orphan instance: instance Alternative CHP Warning: The documentation for the following packages are not installed. No links will be generated to these packages: rts-1.0 6a7 Control.Concurrent.CHP.Alt:instance Alternative CHP 82d82 Control.Concurrent.CHP.Channels.Creation:class ChannelTuple t 88,92d87 Control.Concurrent.CHP.Channels.Creation:instance (Channel r w) = ChannelTuple (Chan r w a, Chan r w a) Control.Concurrent.CHP.Channels.Creation:instance (Channel r w) = ChannelTuple (Chan r w a, Chan r w a, Chan r w a) Control.Concurrent.CHP.Channels.Creation:instance (Channel r w) = ChannelTuple (Chan r w a, Chan r w a, Chan r w a, Chan r w a) Control.Concurrent.CHP.Channels.Creation:instance (Channel r w) = ChannelTuple (Chan r w a, Chan r w a, Chan r w a, Chan r w a, Chan r w a) Control.Concurrent.CHP.Channels.Creation:instance (Channel r w) = ChannelTuple (Chan r w a, Chan r w a, Chan r w a, Chan r w a, Chan r w a, Chan r w a) 102d96 Control.Concurrent.CHP.Channels.Creation:newChannels :: (ChannelTuple t, MonadCHP m) = m t 149c143 Control.Concurrent.CHP.Monad:class (MonadIO m) = MonadCHP m --- Control.Concurrent.CHP.Monad:class (Monad m) = MonadCHP m 155a150 Control.Concurrent.CHP.Monad:foreverP :: CHP a - CHP b 156a152 Control.Concurrent.CHP.Monad:liftIO_CHP :: IO a - CHP a 160a157 Control.Concurrent.CHP.Monad:process :: String - a - a 164a162 Control.Concurrent.CHP.Monad:subProcess :: String - a - a 169c167 Control.Concurrent.CHP.Parallel:data (Monad m, MonadCHP m) = ForkingT m a --- Control.Concurrent.CHP.Parallel:data ForkingT m a 173d170 Control.Concurrent.CHP.Parallel:instance (MonadIO m) = MonadIO (ForkingT m) 175c172 Control.Concurrent.CHP.Parallel:instance MonadTrans ForkingT --- Control.Concurrent.CHP.Parallel:liftForking :: (Monad m) = m a - ForkingT m a 239c236 @version 2.1.0.1 --- @version 2.2.0 Given previous version number A.B.C.D: It seems you have added, removed or changed some instances. You must
Re: [Haskell-cafe] ANN: forkable-monad 0.1
Hi, This is quite a neat generalisation of forkIO, and something I've wanted in the past. My comment would be about the MonadIO m requirement for ForkableMonad. I understand that conceptually it's a nice thing to have. But practically, I don't think it's necessary, and could be a little restrictive -- I could imagine potentially having a newtype-wrapped monad that doesn't have a MonadIO instance, but does have a ForkableMonad instance. I tried removing the MonadIO constraint, and it works as long as you add a Monad constraint either to the class or to the ReaderT and StateT instances. That depends if you can imagine an instance of ForkableMonad that wasn't a Monad (an applicative perhaps)... probably not, especially given the name. In short: I recommend changing MonadIO m to Monad m on the class. I came up with this instance for ContT: instance (ForkableMonad m) = ForkableMonad (ContT r m) where forkIO act = lift $ forkIO (runContT act (const $ return undefined)) I don't know if that's useful and/or correct, though. Thanks, Neil. David Anderson wrote: Dear Haskellers, I'm happy, and only slightly intimidated, to announce the initial release of forkable-monad. The short version is that forkable-monad exports a replacement forkIO that lets you do this: type MyMonad = ReaderT Config (StateT Ctx IO) startThread :: MyMonad ThreadId startThread = forkIO threadMain threadMain :: MyMonad () threadMain = forever $ liftIO $ putStrLn Painless monad stack forking! Note the lack of monad stack deconstruction and reconstruction to transport it over to the new thread. You'll find the details in the Haddock documentation for the module. forkable-monad is available: * On hackage: http://hackage.haskell.org/package/forkable-monad * Via cabal: cabal install forkable-monad * Source and issue tracker: http://code.google.com/p/forkable-monad/ Feedback is of course welcome. As this is my first published Haskell code and Hackage upload, I expect there will be quite a bit! - Dave ___ 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] GHC, odd concurrency space leak
Jason Dagit wrote: On Wed, Apr 14, 2010 at 3:13 PM, Daniel Fischer daniel.is.fisc...@web.de mailto:daniel.is.fisc...@web.de wrote: Am Mittwoch 14 April 2010 23:49:43 schrieb Jason Dagit: It will be interesting to hear what fixes this! forever' m = do _ - m forever' m When I define that version of forever, the space leak goes away. Not with optimisations. Thanks for pointing that out. I forgot to say so in my email. Here are two reduced versions of the original program: snip I find non-termination with a much simpler program than yours (GHC 6.12.1): \begin{code}{-# OPTIONS -O1 #-} import Control.Concurrent import Control.Monad (forever) main = do putStrLn Main thread starting forkIO $ do putStrLn Started thread forever $ return () putStrLn Delaying threadDelay (1 * 100) putStrLn Delayed \end{code} If I compile that with ghc --make -threaded and run it, with -O1 or -O2, it burns CPU and never terminates. With -O0 it terminates. So looks like some optimisation is causing the problem. I might guess it's something to do with the RTS and threadDelay that's causing the problem. Delayed is never printed on my system, so it seems like (even when run with +RTS -N2) the original thread is not ever being rescheduled; perhaps the timeout queue isn't checked properly when a thread is burning up the CPU like that, and optimisations are on? Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the consensus about -fwarn-unused-do-bind ?
Ivan Lazar Miljenovic wrote: As of 6.12.1, the new -fwarn-unused-do-bind warning is activated with -Wall. This is based off a bug report by Neil Mitchell: http://hackage.haskell.org/trac/ghc/ticket/3263 . However, does it make sense for this to be turned on with -Wall? For starters, why should this warning apply only to do blocks and not to explicit usage of , etc.? That is, the following code (as specified in the above bug report) generates an error: do doesFileExist foo return 1 yet this doesn't: doesFileExist foo return 1 The comments in that bug report actually mention My patch does not warn on uses of , only in do-notation, where the situation is more clear cut. I take to be an explicit sign that the user wants to ignore the result of the first action, whereas in do-notation it may be an accident. So I think it was the right decision. When I first compiled my CHP library with it, I was surprised to find that I had very few instances: 6 warnings in ~3000 lines of heavily-monadic code. And one or two of those I probably shouldn't be ignoring the return. The way I see it, I have 4 options: 1. Do as the error suggests and preface usage of these parser combinators with _ -. 2. Use some function of type (Monad m) = m a - m () instead of doing _ -. 3. Duplicate the parser combinators in question so that I have one version that returns a value and another that does the main parser and then returns (); then use this second combinator in do blocks where I don't care about the returned value. 4. Put -fno-warn-unused-do-bind in the .cabal file. The first two options don't appeal to me as being excessive usage of boilerplate; the third involves too much code duplication. However, I am loath to just go and disable a warning globally. I'd be tempted by number two, but I it's more typing to write ignore $ than _ -, so maybe 1 is the best option after all. I've frequently encountered the annoyance of monadic return values -- but to satisfy type signatures rather than avoid this warning. For example, I have a CHP parallel operator: (||) :: CHP a - CHP b - CHP (a,b) and a function writeChannel :: Chanout a - a - CHP (). But if you try to write a function like: writeBoth :: a - (Chanout a, Chanout a) - CHP () writeBoth x (outA, outB) = writeChannel outA x || writeChannel outB x You get a type error (expected: CHP (), but got: CHP ((), ()) -- both return types contain no information anyway!). You either have to append return () (or similarly use do-notation), or do as I did and make another form of the operator that discards the output (and there I can't use the add-another-underscore convention!). It's annoying that you end up with lots of operations in libraries duplicated with an underscore variant, or different operators. Sometimes it can make an important semantic difference (e.g. mapM requires Traversable but mapM_ only requires Foldable), but often it's just a matter of no, I don't care about the return value from this (e.g. forkIO). I sometimes wonder if there could be some syntactic sugar that might help, but it does feel like overkill just for this purpose. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Haskell.org re-design
Thomas Schilling wrote: Here's a matching Wiki style: http://i.imgur.com/XkuzH.png I like your designs (I liked the blue and orange version, but all the colour schemes seem fine). For the wiki design, it would be good to re-think and cull those links at the top of the page. For example, I don't think that random page needs to be in the top bar. With several other links it's not clear to me what they do. Perhaps it's just me, but wiki community and special pages doesn't suggest what they do or why I would want to click them, and related changes also puzzles me as to what it might be. The recent changes and page history links seem redundant. The Haskell wiki has some useful content but the pages are cluttered with these links. Simply removing a few of these links (while we're redesigning the site anyway) would enhance the pages' usability. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] chp-plus doesn't install
Neil Brown wrote: Colin Paul Adams wrote: I'm getting these errors (ghc 6.10.4 on Linux x86_64): Building chp-plus-1.1.0... [1 of 9] Compiling Control.Concurrent.CHP.Test ( Control/Concurrent/CHP/Test.hs, dist/build/Control/Concurrent/CHP/Test.o ) [2 of 9] Compiling Control.Concurrent.CHP.Console ( Control/Concurrent/CHP/Console.hs, dist/build/Control/Concurrent/CHP/Console.o ) [3 of 9] Compiling Control.Concurrent.CHP.Connect ( Control/Concurrent/CHP/Connect.hs, dist/build/Control/Concurrent/CHP/Connect.o ) Control/Concurrent/CHP/Connect.hs:146:67: Couldn't match expected type `ChanOpts a' against inferred type `ConnectableParam (Chanout a)' In the first argument of `oneToOneChannel'', namely `o' In the second argument of `($)', namely `oneToOneChannel' o' In the first argument of `(=)', namely `((writer reader) $ oneToOneChannel' o)' There's no conflict between the two instances, though. I wonder if making ConnectableParam depend on l and r would fix it. I'll look further into this when I get onto a 6.10.4 machine. That did indeed turn out to be the fix. That will teach me to release a package without remembering to test it on GHC 6.10 first. I've uploaded chp-plus 1.2.0 to Hackage, which should fix this issue (among other changes). So: cabal update cabal install chp-plus Should work now. Let me know if you have any other troubles. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] chp-plus doesn't install
Colin Paul Adams wrote: I'm getting these errors (ghc 6.10.4 on Linux x86_64): Building chp-plus-1.1.0... [1 of 9] Compiling Control.Concurrent.CHP.Test ( Control/Concurrent/CHP/Test.hs, dist/build/Control/Concurrent/CHP/Test.o ) [2 of 9] Compiling Control.Concurrent.CHP.Console ( Control/Concurrent/CHP/Console.hs, dist/build/Control/Concurrent/CHP/Console.o ) [3 of 9] Compiling Control.Concurrent.CHP.Connect ( Control/Concurrent/CHP/Connect.hs, dist/build/Control/Concurrent/CHP/Connect.o ) Control/Concurrent/CHP/Connect.hs:146:67: Couldn't match expected type `ChanOpts a' against inferred type `ConnectableParam (Chanout a)' In the first argument of `oneToOneChannel'', namely `o' In the second argument of `($)', namely `oneToOneChannel' o' In the first argument of `(=)', namely `((writer reader) $ oneToOneChannel' o)' I don't immediately have a GHC 6.10.4 machine to hand, but that is an odd error. Here is the code in question: instance ConnectableExtra (Chanout a) (Chanin a) where type ConnectableParam (Chanout a) = ChanOpts a connectExtra o = (=) ((writer reader) $ oneToOneChannel' o) (based on the class: class ConnectableExtra l r where type ConnectableParam l connectExtra :: ConnectableParam l - ((l, r) - CHP ()) - CHP () ) So I don't see why there is a type mismatch; ConnectableParam (Chanout a) is ChanOpts a. I don't know if it's somehow confused by the recently added similar instance: instance ConnectableExtra (Chanout a) (Shared Chanin a) where type ConnectableParam (Chanout a) = ChanOpts a connectExtra o = (=) ((writer reader) $ oneToAnyChannel' o) There's no conflict between the two instances, though. I wonder if making ConnectableParam depend on l and r would fix it. I'll look further into this when I get onto a 6.10.4 machine. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Benchmarking and Garbage Collection
Simon Marlow wrote: import Control.Concurrent import Control.Concurrent.CML import Control.Monad main :: IO () main = do let numChoices = 2 cs - replicateM numChoices channel mapM_ forkIO [replicateM_ (10 `div` numChoices) $ sync $ transmit c () | c - cs] replicateM_ 10 $ sync $ choose [receive c (const True) | c - cs] Good grief. Can I get a copy of this program? It might be something simple that we can fix. Just having lots of threads shouldn't be a performance problem per se, we have benchmarks that create millions of threads without any problems. That's all the code you need, along with the cml package from Hackage. Put the above few lines into GoodGrief.hs (the reply has munged the indentation slightly), and do: cabal install cml ghc --make -threaded GoodGrief.hs ./GoodGrief +RTS -s That got me the listed results on GHC 6.12.1 (I did use -threaded but not -N as I was on a single-core machine; I believe the same problem occurs without -threaded). The problem is in the CML library that the above code uses. Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Benchmarking and Garbage Collection
Hi, I'm looking at benchmarking several different concurrency libraries against each other. The benchmarks involve things like repeatedly sending values between two threads. I'm likely to use Criterion for the task. However, one thing I've found is that the libraries have noticeably different behaviour in terms of the amount of garbage created. Criterion has an option to perform GC between each benchmark, but I think that the benchmark is only fair if it takes into account the GC time for each system; it doesn't seem right for two systems to be counted as equal if the times to get the results are the same, but then one has to spend twice as long as the other in GC afterwards. Here's some options I've considered: * I could make a small change to Criterion to include the time for performing GC in each benchmark run, but I worry that running the GC so often is also misrepresentative (might 100 small GCs take a lot longer than one large GC of the same data?) -- it may also add a lot of overhead to quick benchmarks, but I can avoid that problem. * Alternatively, I could run the GC once at the end of all the runs, then apportion the cost equally to each of the benchmark times (so if 100 benchmarks require 0.7s of GC, add 0.007s to each time) -- but if GC is triggered somewhere in the middle of the runs, that upsets the strategy a little. * I guess a further alternative is to make each benchmark a whole program (and decently long), then just time the whole thing, rather than using Criterion. Has anyone run into these issues before, and can anyone offer an opinion on what the best option is? Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Benchmarking and Garbage Collection
Jesper Louis Andersen wrote: On Thu, Mar 4, 2010 at 7:16 PM, Neil Brown nc...@kent.ac.uk wrote: However, one thing I've found is that the libraries have noticeably different behaviour in terms of the amount of garbage created. In fact, CML relies on the garbage collector for some implementation constructions. John H. Reppys Concurrent Programming in ML is worth a read if you haven't. My guess is that the Haskell implementation of CML is bloody expensive. It is based on the paper http://www.cs.umd.edu/~avik/projects/cmllch/ where Chaudhuri first constructs an abstract machine for CML and then binds this to the Haskell MVar and forkIO constructions. CML is indeed the library that has the most markedly different behaviour. In Haskell, the CML package manages to produce timings like this for fairly simple benchmarks: INIT time0.00s ( 0.00s elapsed) MUT time2.47s ( 2.49s elapsed) GCtime 59.43s ( 60.56s elapsed) EXIT time0.00s ( 0.01s elapsed) Total time 61.68s ( 63.07s elapsed) %GC time 96.3% (96.0% elapsed) Alloc rate784,401,525 bytes per MUT second Productivity 3.7% of total user, 3.6% of total elapsed I knew from reading the code that CML's implementation would do something like this, although I do wonder if it triggers some pathological case in the GC. The problem is that when I benchmark the program, it seems to finish it decent time; then spends 60 seconds doing GC before finally terminating! So I need some way of timing that will reflect this; I wonder if just timing the entire run-time (and making the benchmarks long enough to not be swallowed by program start-up times, etc) is the best thing to do. A secondary issue is whether I should even include CML at all considering the timings! Thanks, Neil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Benchmarking and Garbage Collection
Jesper Louis Andersen wrote: On Thu, Mar 4, 2010 at 8:35 PM, Neil Brown nc...@kent.ac.uk wrote: CML is indeed the library that has the most markedly different behaviour. In Haskell, the CML package manages to produce timings like this for fairly simple benchmarks: %GC time 96.3% (96.0% elapsed) I knew from reading the code that CML's implementation would do something like this, although I do wonder if it triggers some pathological case in the GC. That result is peculiar. What are you doing to the library, and what do you expect happens? Since I have some code invested on top of CML, I'd like to gain a little insight if possible. In trying to simplify my code, the added time has moved from GC time to EXIT time (and increased!). This shift isn't too surprising -- I believe the time is really spent trying to kill lots of threads. Here's my very simple benchmark; the main thread repeatedly chooses between receiving from two threads that are sending to it: import Control.Concurrent import Control.Concurrent.CML import Control.Monad main :: IO () main = do let numChoices = 2 cs - replicateM numChoices channel mapM_ forkIO [replicateM_ (10 `div` numChoices) $ sync $ transmit c () | c - cs] replicateM_ 10 $ sync $ choose [receive c (const True) | c - cs] Compiling with -threaded, and running with +RTS -s, I get: INIT time0.00s ( 0.00s elapsed) MUT time2.68s ( 3.56s elapsed) GCtime1.84s ( 1.90s elapsed) EXIT time 89.30s ( 90.71s elapsed) Total time 93.82s ( 96.15s elapsed) I think the issue with the CML library is that it spawns a lot of threads (search the source for forkIO: http://hackage.haskell.org/packages/archive/cml/0.1.3/doc/html/src/Control-Concurrent-CML.html). Presumably the Haskell RTS isn't optimised for this approach (maybe the ML RTS was, from what you said?), and at the end of the program it spends a lot of time reaping the threads. The problem isn't nearly as bad if you don't use choose, though: import Control.Concurrent import Control.Concurrent.CML import Control.Monad main :: IO () main = do c - channel forkIO $ replicateM_ 10 $ sync $ transmit c () replicateM_ 10 $ sync $ receive c (const True) I get: INIT time0.00s ( 0.00s elapsed) MUT time1.92s ( 2.65s elapsed) GCtime0.92s ( 0.93s elapsed) EXIT time0.00s ( 0.02s elapsed) Total time2.65s ( 3.59s elapsed) %GC time 34.6% (25.8% elapsed) Hope that helps, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Proper round-trip HughesPJ/Parsec for Doubles?
Andy Gimblett wrote: 1. break the line after do (to avoid a layout change when change name or arguments of float' or rename the variable e) I'm not convinced by this; perhaps while editing the code it's useful, but those changes don't happen very often, and when they do, any half-decent editor ought to be able to handle making the change consistently. I do sometimes drop the do to the next line, but usually in order to keep things within 80 columns. I think this is somewhat a matter of personal taste though. More on this at the end... I think the implication is that the layout change you mention will cause a version control commit to look like the whole function changed, whereas if you didn't have to alter the indent, it would be clear that the only lines that changed are the one introducing the extra parameter, and any subsequent lines that need to be changed to use the parameter. BTW, to add another option, I like this style: float' t = do ... Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] CURL and threads
Hi, Your code forks off N threads to do HTTP response checking, then waits for the reply (invokeThreads). Each thread (runHTTPThread) calls curlGetResponse and *immediately* sends the answer back down the channel to invokeThreads (checkAuthResponse) -- then waits for half a second before terminating. As soon as the original process (invokeThreads) has all N responses, it forks off N threads again. So if your code manages to process the N requests such that it can do them all in, say, 0.05 seconds, you'll have about ten times as many threads in your system as you intended (because they all hang around for 0.5 seconds after completing their work). I suspect what you intended to do was put that threadDelay call *before* sending back the response, which would prevent this leaking of threads. Some quick style suggestions: your recursion pattern in dumpChannel is easily replaced with replicateM, and your infinite recursion in invokeThreads could easily become the function forever. Never recurse directly if a combinator can remove the need :-) Your code could easily be accomplished in CHP (http://hackage.haskell.org/package/chp). runParMapM would solve your exact problem easily; you could replace your code with: module NTLMTest where import Control.Monad.Trans (liftIO) import Control.Applicative (($)) import System.IO import Network.Curl import Control.Concurrent.CHP type ResponseState = Either Bool String isResponseOk :: String - CurlResponse - ResponseState isResponseOk username response = case respCurlCode response of CurlOK - Left True _ - Right $ username ++ = ++ respStatusLine response ++ :: ++ (show . respStatus $ response) -- Note: I re-ordered the parameters to this function checkAuthResponse :: String - String - String - IO ResponseState checkAuthResponse url user passwd = isResponseOk user $ curlGetResponse_ url [CurlHttpAuth [HttpAuthAny], CurlUserPwd $ user ++ : ++ passwd] url = http://localhost:8082/; credentials = map (\i - (user ++ show i,123456)) [1..21] main = runCHP_ $ runParMapM (liftIO . uncurry (checkAuthResponse url)) credentials = mapM (liftIO . either (const $ return ()) putStrLn) That above version will get all the responses in parallel and print them out once they are all done, and is quite short. This isn't what your original code did though -- that read the responses from a channel and printed them as they arrived. The below version is probably the closest CHP version to your original code: module NTLMTest where import Control.Monad (replicateM_, (=)) import Control.Monad.Trans (liftIO) import Control.Applicative (($)) import System.IO import Network.Curl import Control.Concurrent.CHP type ResponseState = Either Bool String isResponseOk :: String - CurlResponse - ResponseState isResponseOk username response = case respCurlCode response of CurlOK - Left True _ - Right $ username ++ = ++ respStatusLine response ++ :: ++ (show . respStatus $ response) -- Note: I re-ordered the parameters to this function checkAuthResponse :: String - String - String - IO ResponseState checkAuthResponse url user passwd = isResponseOk user $ curlGetResponse_ url [CurlHttpAuth [HttpAuthAny], CurlUserPwd $ user ++ : ++ passwd] url = http://localhost:8082/; credentials = map (\i - (user ++ show i,123456)) [1..21] main = runCHP_ $ do chan - anyToOneChannel runParallel_ $ dumpChannel (reader chan) : map (claim (writer chan) . writeValue = liftIO . uncurry (checkAuthResponse url)) credentials where dumpChannel :: Chanin ResponseState - CHP () dumpChannel c = replicateM_ (length credentials) (readChannel c = liftIO . either (const $ return ()) putStrLn) This version runs the dumpChannel procedure in parallel with a thread for each credential that writes the result to a shared channel (claiming it as it does so). Neither of my versions checks the credentials repeatedly like yours does, but you can easily add that in. If you're not a point-free fan (I find it irresistible these days), I can break those solutions down a bit into more functions. Hope that helps, Neil. Eugeny N Dzhurinsky wrote: On Wed, Feb 17, 2010 at 07:34:07PM +0200, Eugene Dzhurinsky wrote: Hopefully, someone could help me in overcoming my ignorance :) I realized that I can share the same Chan instance over all invocations in main, and wrap internal function into withCurlDo to ensure only one IO action gets executed with this library. Finally I've come with the following code, which however still has some memory leaks. May be someone will get an idea what's wrong below? = module NTLMTest where import System.IO import Network.Curl import
Re: [Haskell-cafe] RFC: concurrent-extra
Roel van Dijk wrote: 2010/2/16 Neil Brown nc...@kent.ac.uk: I had a look at the code for Event (both versions) and Lock (but not the others just yet) and it seemed fine. If you do lots of calls to waitTimeout before a set you will accumulate old locks in the list, but that won't cause any error that I can see, so it would only be a problem in pathological cases. I think I can fix the garbage locks on waitTimeout by tupling each lock with the ThreadId of the thread that created it. When a timeout occurs I can then simply remove the unnecessary lock from the list. The extra overhead would be the construction of a tuple and acquiring a ThreadId each time you wait for an event. You don't need to do use ThreadId: MVar has an Eq instance, so you could make your Lock type derive an Eq instance, and then you can just compare the Locks to remove it after the timeout occurs (e.g. using delete to take it out of the list; it should be quite near the head of the list anyway). In fact, you may as well make most of your types derive an Eq instance where possible, as this can be useful sometimes. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Pointfree composition for higher arity
Sean Leather wrote: I find myself often writing this pattern: someFun x y z = ... fun y z = runFun $ someFun someDefault y z or, alternatively: fun y = runFun . someFun someDefault y I very often write this too (wanting function composition, but with a two-argument function on the right hand side). The trick I picked up from somewhere is to do: fun = (runFun .) . someFun someDefault I'm not too keen on that, as it seems clumsy. I often end up writing the operator that you describe, but have never settled on a consistent name (since the obvious one to me, (..), is taken). Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] RFC: concurrent-extra
Hi, I had a look at the code for Event (both versions) and Lock (but not the others just yet) and it seemed fine. If you do lots of calls to waitTimeout before a set you will accumulate old locks in the list, but that won't cause any error that I can see, so it would only be a problem in pathological cases. I'm not sure there is a good way to test MVar algorithms. One way to do it (which the Concurrent Haskell Debugger did online, IIRC: http://www.informatik.uni-kiel.de/~fhu/chd/) is to reimplement IO to explore different interleavings of the various MVar calls to look for deadlocks. If you're testing STM, generally you can look to capture invariants of your transactions and check that they hold after each transaction (e.g. that if the state is Set, there shouldn't be any locks waiting with an event). Thanks, Neil. Roel van Dijk wrote: Hello, We wrote a small library (1) which offers a few extra synchronization primitives. These primitives are found in the standard libraries of languages like Java and Python, but not in Haskell. Before releasing concurrent-extra on hackage, we would like some comments on its name, design, implementation, documentation (2) and general usefulness. All primitives are implemented with MVars and IORefs, except for Control.Concurrent.STM.Event. There is a small test suite which tests some properties: cabal configure -ftest cabal build cabal test The test suite still needs to be expanded a great deal. We found that testing concurrent algorithms is really hard. Now we test things like this shouldn't deadlock by checking if it doesn't take too long. But that doesn't feel very formal. Is there a more principled approach to testing concurrent algorithms in Haskell? After writing our version of a read-write lock we noticed the package rwlock (3) on hackage. But there is a difference: rwlock is implemented with STM while our version is implemented entirely with MVars. Regards, Roel Bas van Dijk 1 - http://code.haskell.org/~roelvandijk/code/concurrent-extra/ 2 - http://code.haskell.org/~roelvandijk/code/concurrent-extra/doc/html/concurrent-extra/index.html 3 - http://hackage.haskell.org/package/rwlock ___ 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] Using Cabal during development
Don't you simply need to do what the error message says, and add (*in the Executable section*, at the end of the file): build-depends: SFML ? Limestraël wrote: I think I must be dumb or something. I did my SFML.cabal exactly the way the packager of vty-ui did vty-ui.cabal, and I still have got the error when building: hs_src/SFML/Direct/Graphics.hs:51:7: Could not find module `SFML.Direct.Types.Enums': It is a member of the hidden package `SFML-1.5'. Perhaps you need to add `SFML' to the build-depends in your .cabal file. it is a hidden module in the package `SFML-1.5' Use -v to see a list of the files searched for. My cabal file is http://old.nabble.com/file/p27522604/SFML.cabal here . Il you get to know why it doesn't work, please tell me, because I'm lost... I have a hs_src directory, which contains an SFML directory (the lib) and a demo.hs file. (the simple main) It's the way vty-ui package is done. Jonathan Daugherty-4 wrote: Then how does the 'Executable' section of your .cabal look like? That's what I can't get working. Executable vty-ui-demo Hs-Source-Dirs: src Main-is: Demo.hs Build-Depends: mtl = 1.1 1.2 The Main-is refers to src/Demo.hs. This example is from: http://hackage.haskell.org/packages/archive/vty-ui/0.2/vty-ui.cabal The package description link on any Hackage package page will link to the release's cabal file, so you can see how other folks have written their Executable sections. Hope that helps, -- Jonathan Daugherty ___ 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
[Haskell-cafe] ANN: progression-0.1
Hi all, I've just uploaded the first release of Progression to Hackage. Progression is a small library that pulls together several other libraries and utilities (particularly Criterion) to support the optimisation of Haskell programs. To use it, you wrap up your benchmarks in a program that passes them to Progression. When you run this program, Progression records the benchmarks, and offers to draw you a graph comparing these latest times to a selection (specified by you) of previously recorded times. What you get is a graph that allows you to see if your changes have made enough difference over your benchmarks for you to keep the change (or whether it has made most of them worse, and you need to roll back!). Progression doesn't include any benchmarking logic; it delegates all that to the Criterion library, and plots the resulting mean (with confidence intervals). More details and an example graph are available in a blog post: http://chplib.wordpress.com/2010/02/04/progression-supporting-optimisation-in-haskell/ Feedback is welcome, either here or in the comments on the blog post. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GHC/base API documentation has been generated incorrectly
Hi, I noticed this on another package recently. Turned out it's already been reported as a haddock bug (http://trac.haskell.org/haddock/ticket/128) and fixed. I guess this will be sorted when the fixed version of haddock is used to re-generate the docs. Thanks, Neil. John Millikin wrote: Looking at (for example) the docs for 'bracket'[1], the parameter documentation has been shifted up by one. The source code[2] looks correct, so perhaps Haddock is parsing it incorrectly? Docs for other functions, such as 'showSigned'[3], exhibit the same error. [1] http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Exception.html#v%3Abracket [2] http://www.haskell.org/ghc/docs/latest/html/libraries/base/src/Control-Exception-Base.html#bracket [3] http://www.haskell.org/ghc/docs/latest/html/libraries/base/Numeric.html#v%3AshowSigned ___ 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] scheduling an alarm
Brian Denheyer wrote: On Tue, 26 Jan 2010 22:41:44 -0800 Thomas DuBuisson thomas.dubuis...@gmail.com wrote: doEvent f usDelay = forkIO $ threadDelay usDelay doEvent f usDelay f Are you sure that's right ? It seems to be a memory-gobbling infinite loop... Why would I think that ? I think that because the following code: import Control.Concurrent f = putStrLn foo doEvent f usDelay = do forkIO $ threadDelay usDelay doEvent f usDelay f _really_ _does_ start to consume all of the memory on my system, that's why. I don't know why, but that's what it does on my system. It's not obvious to me that it should do that. So maybe ghci is not doing TCO. The code you have presented at the bottom is an infinite loop that I would expect to consume all the memory on your system. That code spins at 100% busy, forking off threadDelay calls without ever stopping, and will never perform f. Ouch -- infinite loop, and likely hugely memory-consuming (in fact, I'm not sure how the last poster didn't find that it consumed a lot of memory...). However, that code is slightly different to the original (that I have left in up the top) which had a crucial do missing (although you can infer it from the indentation). The original code should be: doEvent f usDelay = forkIO $ do threadDelay usDelay doEvent f usDelay f That is, the latter two lines should be inside the forkIO block, not after it. This code will wait for the given delay, then fork a new thread, then perform f. As long as f takes less time to complete than usDelay, this code should not eat memory and is quite reasonable. I hope that clears up the confusion. Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] foldl in terms of foldr
Xingzhi Pan wrote: On Tue, Jan 26, 2010 at 11:24 PM, Eduard Sergeev eduard.serg...@gmail.com wrote: Xingzhi Pan wrote: The first argument to foldr is of type (a - b - a), which takes 2 arguments. But 'step' here is defined as a function taking 3 arguments. What am I missing here? You can think of step as a function of two arguments which returns a function with one argument (although in reality, as any curried function, 'step' is _one_ argument function anyway): step :: b - (a - c) - (b - c) e.g. 'step' could have been defined as such: step x g = \a - g (f a x) to save on lambda 'a' was moved to argument list. Right. But then step is of the type b - (a - c) - (b - c). But as the first argument to foldr, does it agree with (a - b - a), which was what I saw when I type :t foldr in ghci? step is of type b - (a - a) - (a - a), which does agree with (a - b - b), the first argument to foldr (what you posted, both times, a - b - a, is the type of the first argument of *foldl* not foldr). The code is building up a function (type: a - a) from the list items, which it then applies to the initial value given to foldl. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] could we get a Data instance for Data.Text.Text?
Jeremy Shaw wrote: Hello, Would it be possible to get a Data instance for Data.Text.Text? This would allow us to create a Serialize instance of Text for use with happstack -- which would be extremely useful. Last time this came up, I had a look at providing a Data instance for Text, and I got as far as needing a Data instance for ByteString#, accompanied by an error I don't fully understand, but I think is telling me that things involving magic hashes are magic: Data/Text/Array.hs:104:35: Couldn't match kind `#' against `*' When matching the kinds of `ByteArray# :: #' and `d :: *' Expected type: d Inferred type: ByteArray# In the first argument of `z', namely `Array' The problem with a Data instance for Text is that it is using this ByteArray# type, which can't easily interact with the Data type-class because it's a special type. I would suggest providing a Data instance for ByteArray#, but I don't think that's possible either. As far as I can understand it all, your Data instance is probably the closest you are going to get to having a decent Data instance without something else (GHC/SYB) changing significantly. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Existential Types (I guess)
Ozgur Akgun wrote: data NumHolder = forall a. Num a = NumHolder a instance Show NumHolder where show (NumHolder n) = show n liftNum :: (Num a) = (a - a) - NumHolder - NumHolder liftNum f (NumHolder c) = NumHolder (f c) The problem here is that you declare that liftNum will work for any single type a, decided (effectively) by the caller of the function. But if the caller chooses Int for a, and your NumHolder has a Float inside it, that isn't going to work. You need to take a function that will work for any Num type a: liftNum :: (forall a. Num a = a - a) - NumHolder - NumHolder liftNum f (NumHolder c) = NumHolder (f c) This uses Rank2Types, but that's necessary for what you want. By moving the forall from being implicit at the start of the signature to inside the brackets, you declare that this is a function that works for all types a (that are a member of type-class Num). This should compile and work as you wanted. Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] ANN: chp-2.0.0, chp-plus-1.0.0
Hi, I've just released version 2.0.0 of the Communicating Haskell Processes (CHP) message-passing concurrency library onto Hackage. The main change from 1.x is that I have split the functionality into two libraries: the core functionality remains in the chp package (now version 2.0.0), while some of the additional capabilities have been moved out to the new chp-plus package (version 1.0.0). This should help in the long run by keeping the packages from becoming too large, and by allowing me to trim the dependencies of the core chp package. I've written more about the changes here, for those who it will affect: http://chplib.wordpress.com/2010/01/11/splitting-chp/ This will require small changes to your build system if you're using CHP and you upgrade to the new versions. The new versions should also fix build troubles with GHC 6.12 -- let me know if you have any troubles installing under 6.10 or 6.12. Hackage links: http://hackage.haskell.org/package/chp-2.0.0 http://hackage.haskell.org/package/chp-plus-1.0.0 Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] [Very long] (CHP?) Compressing, MD5 and big files
Hi, Sorry for the slightly delayed reply -- I didn't have time to look through all your code and understand it until just now. Your code has one (no doubt frustratingly!) small problem, which is in the deadlocking pipeline3: Maciej Piechotka wrote: pipeline3 :: CHP () pipeline3 = enrolling $ do file - oneToManyChannel' $ chanLabel File fileGZ - oneToOneChannel' $ chanLabel File GZ data_ - oneToManyChannel' $ chanLabel Data compressed - oneToManyChannel' $ chanLabel Data Compressed md5 - oneToOneChannel' $ chanLabel MD5 md5Compressed - oneToOneChannel' $ chanLabel MD5 Compressed fileGZ' - Enroll (reader file) fileData - Enroll (reader file) dataMD5 - Enroll (reader data_) dataCompress - Enroll (reader data_) compressedFile - Enroll (reader compressed) compressedMD5 - Enroll (reader compressed) liftCHP $ runParallel_ [getFiles (writer file), (forever $ readChannel fileGZ' = writeChannel (writer fileGZ) . (++.gz)) `onPoisonRethrow` (poison fileGZ' poison (writer fileGZ)), readFromFile fileData (writer data_), calculateMD5 dataMD5 (writer md5), compressCHP dataCompress (writer compressed), writeToFile (reader fileGZ) compressedFile, calculateMD5 compressedMD5 (writer md5Compressed), forever $ readChannel dataMD5 = liftIO . print readChannel compressedMD5 = liftIO . print] Problems: (CHP) Thread terminated with: thread blocked indefinitely in an STM transaction _b3, _b4, File GZ.test1.gz Where you have readChannel dataMD5 and readChannel compressedMD5 in the last few lines, you actually meant to have readChannel (reader md5) and readChannel (reader md5Compressed). Your mistake meant that the former two channels were being used more times in parallel than you had enrolled and that the latter two channels were being written to but not read from. Either of these mistakes could cause deadlock, so hence why you were getting a strange deadlock. Unfortunately, the type system didn't save you this time, because the channel types happened to be the same. It took me a while to find it, too! On a side note, it would be good to have a static check for these mistakes (using a channel in parallel unsafely, and only using one end of a channel), but the only way I found to use Haskell's type-system for this is a rather nasty type-indexed monad. I guess if you use newChannelRW and name both the results, you would get an unused variable warning if you didn't use either end of the channel. This would fix one issue, but not the other. Hope that helps, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Does the TMVar and TChan really obey STM rules?
Andrey Sisoyev wrote: Hi everyone, isEmptyTMVar :: TMVar a - STM Bool Source Check whether a given TMVar is empty. Notice that the boolean value returned is just a snapshot of the state of the TMVar. By the time you get to react on its result, the TMVar may have been filled (or emptied) - so be extremely careful when using this operation. Use tryTakeTMVar instead if possible. When I read this in the haddock to Control.Concurrent.STM.TMVar, I started to suspect that the behavior of TMVar and TChan might be worse than I imagined. That warning seems a little paranoid to me. The state of the TMVar must persist to the end of the transaction (from the point of view of the process executing a transaction), so isEmptyTMVar seems fine as long as you act on it in the same transaction. What would be bad would be something like: do b - atomically $ isEmptyTMVar tv if b Where you act on the value in a later transaction. (Unless I've missed something?) Few questions on TMVar and TChan: (1) If 2 threads are sleeping-waiting for the output of TChan, and it gets filled, do they both wakeup, or just one? (2) Similar question about reading/writing TMVar. (3) If a thread is sleeping-waiting for the output of TChan, but transaction wants to restart due to the change in any of touched TVar, then does the thread wakeup and restart the transaction? (4) Similar question about TMVar. Also, if there is some paper on this, please, give me a link on it. I believe, 1 and 2: both wake up and retry the transaction, but only the process that completes the transaction first will succeed, the other will end up going back to sleep. 3 and 4: yes. I think the rule is simply, if you call retry, you'll wait until any TVar you've read from so far changes, then you'll wake up and redo the transaction. To see how that affects TMVar and TChan, read their source code to see what they are actually doing with TVars and retry. Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GHC magic optimization ?
Emmanuel CHANTREAU wrote: I will take an example: f x y= x+y The program ask the user to enter two numbers and print the sum. If the user enter 1 2 f 1 2=3 is stored and a gargage collector is used to remove this dandling expression later ? If the user enter again 1 2, ghc search in dandling results to try to find the result without computing it again ? Hi, I think what you're asking is how Haskell knows at run-time for which expressions it can re-use the results. The answer is: it doesn't, it works it out at compile-time. So if you have: f x y = x + y And at some point in your program you call f 1 2, and later on from a totally separate function you call f 1 2, the function will be evaluated twice (assuming 1 and 2 weren't known constants at compile-time). But let's say you have: g x y = f x y * f x y Now the compiler (i.e. at compile-time) can do some magic. It can spot the common expression and know the result of f x y must be the same both times, so it can convert to: g x y = let z = f x y in z * z Now, the Haskell run-time will evaluate f x y once, store the result in z, and use it twice. That's how it can use commonalities in your code and avoid multiple evaluations of the same function call, which I *think* was your question. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] You are in a twisty maze of concurrency libraries, all different ...
Patrick Caldon wrote: I'm looking for the right concurrency library/semantics for what should be a reasonably simple problem. I have a little simulator: runWorldSim :: MTGen - SimState - IO SimState it takes about a second to run on a PC. It's functional except it whacks the rng, which needs IO. I run 5-10 of these jobs, and then use: mergeWorld :: [SimState] - SimState to pick the best features of the runs and build another possible world (state). Then I use this new world to run another 5-10 jobs and so on. I run this through ~2 iterations. It's an obvious place for parallelism. I'm looking for a concurrency library with something like: forkSequence :: Int - [IO a] - IO [a] which I could call with something like this: forkSequence 4 (take 10 (repeat (runWorldSim g ss))) this would construct 4 threads, then dispatch the 10 jobs onto the threads, and pack up the results into a list I could run through my merger. Why particularly do you want to run the 10 jobs on 4 threads? Haskell's run-time is quite good at spreading out the lightweight threads onto all your cores, so the easiest thing to do is run the 10 jobs on 10 (light-weight) threads and let the run-time sort out the rest. So if what you want is a function: runPar :: [IO a] - IO [a] you can easily construct this. Shameless plug: my CHP library effectively has this function already, runParallel :: [CHP a] - CHP [a] (CHP being a slight layer on top of IO). But you can do it just as easily with, say, STM. Here is a version where order doesn't matter (apologies for the point-free style): import Control.Concurrent import Control.Concurrent.STM import Control.Monad modifyTVar :: TVar a - (a - a) - STM () modifyTVar tv f = readTVar tv = writeTVar tv . f runPar :: [IO a] - IO [a] runPar ps = do resVar - newTVarIO [] mapM_ (forkIO . (= atomically . modifyTVar resVar . (:))) ps atomically $ do res - readTVar resVar when (length res length ps) retry return res If order does matter, you can zip the results with an index, and sort by the index afterwards. If efficiency matters, you can perform other tweaks. But the principle is quite straightforward. Or you can refactor your code to take the IO dependency out of your random number generation, and run the sets of pure code in parallel using the parallel library. If all you are using IO for is random numbers, that's probably the nicest approach. Thanks, Neil. P.S. take 10 . repeat is the same as replicate 10 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Fwd: Re: [Haskell-cafe] Implicit newtype unwrapping]
Sjoerd Visscher wrote: In the case of Dual [1] `mappend` Dual [2] there's no need to do any unwrapping. There is if you say: l :: [Int] l = Dual [1] `mappend` Dual [2] The way I think this could work is that when the type checker detects a type error, it will first try to resolve it by newtype unwrapping (or wrapping even). So if I have: l :: Dual [Int] l = [1] `mappend` [2] It will wrap after the mappend, rather than before? But: l :: Dual [Int] l = Dual [1] `mappend` [2] Would wrap the RHS in Dual? Does this version unwrap the LHS: l :: [Int] l = Dual [1] `mappend` [2] And finally, what about: l :: [Int] l = Dual [1] `mappend` Endo [2] Automatic wrapping and unwrapping, like automatic coercions, look like an opportunity for surprising behaviour. OTOH, perhaps some sort of deriving mechanism would be good. To revisit someone's previous suggestion, perhaps you could allow functions in the deriving clause, so that if you have: f :: Foo - Foo - Foo newtype MyFoo = MyFoo {getFoo :: Foo} deriving (f as g) will generate: g :: MyFoo - MyFoo - MyFoo g x y = Foo (f (getFoo x) (getFoo y)) I think it's not something worth adding (too subtle), but I thought I'd throw it in as a possibility. Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Are there standard idioms for lazy, pure error handling?
wren ng thornton wrote: Nicolas Pouillard wrote: Excerpts from Heinrich Apfelmus's message of Tue Dec 01 11:29:24 +0100 2009: For mnemonic value, we could call it a train: data Train a b = Wagon a (Train a b) | Loco b I rather like it too. The mnemonic version sounds a lot nicer than ListEnd, though I'd probably call the constructors Cabin and Caboose. I suspect the Train name runs into cultural differences. Cabin and Caboose are not names I know in relation to trains, and even Wagon and Loco don't immediately convey to me which one is which. I think a more obvious Cons/Terminator naming scheme is best. Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Optimization with Strings ?
Emmanuel CHANTREAU wrote: Le Thu, 3 Dec 2009 13:20:31 +0100, David Virebayre dav.vire+hask...@gmail.com a écrit : It doesn't work this way : Strings are just lists of Chars. Comparison is made recursively, Char by Char. You can have a look at the source to make sure : instance (Eq a) = Eq [a] where [] == [] = True (x:xs) == (y:ys) = x == y xs == ys _xs== _ys= False Hello Thank you David and Bulat for your answers. I don't see the proof you see. Because GHC could store two sames objects juste once and by the definition of == on lists it could deduce that forall x; List x = x==x. GHC have all informations to do this optimization job, because haskell functions definitions are mathematics definitions. Besides any other reasons, Haskell has the error function, and infinite lists. Consider: p :: String p = error Haha! q :: String q = repeat 'a' pEqualsP :: Bool pEqualsP = p == p qEqualsQ :: Bool qEqualsQ = q == q By your rule, pEqualsP and qEqualsQ should be True. In fact, the correct answer is that pEqualsP should produce an error and qEqualsQ should never terminate. Since Strings can contain such errors and infinite lists, you can't know for certain that an object equals itself without checking its entire length, which is what the original definition for equals did anyway. There may be strict data structures for which your optimisation might be applicable, though. Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Possible FGL bug
It looks like a bug to me. Can you show an exact list of nodes and edges that is causing mkGraph to fail? Or is that what you have displayed, and I can't parse it properly? Thanks, Neil. Ivan Lazar Miljenovic wrote: When developing my QuickCheck-2 test-suite for graphviz, I wrote the following Arbitrary instance for FGL graphs (which needs FlexibleInstances): , | instance (Graph g, Arbitrary n, Arbitrary e, Show n, Show e) = Arbitrary (g n e) where | arbitrary = do ns - liftM nub arbitrary | let nGen = elements ns | lns - mapM makeLNode ns | trace (Nodes: ++ show lns) (return ()) | les - listOf $ makeLEdge nGen | trace (Edges: ++ show les) (return ()) | return $ mkGraph lns les | where | makeLNode n = liftM ((,) n) arbitrary | makeLEdge nGen = liftM3 (,,) nGen nGen arbitrary | | shrink gr = map (flip delNode gr) (nodes gr) ` However, when I try to run this, I occasionally get irrefutable pattern match failures as follows: , | *Data.GraphViz.Testing.Instances.FGL Data.Graph.Inductive.Tree sample (arbitrary :: Gen (Gr Int Char)) | | | 0:0-[] | | 0:-2-[] | 1:0-[('\a',0)] | 2:0-[] | | -4:-3-[('U',-3),('#',1)] | -3:3-[] | 1:-1-[('}',-3)] | | -8:8-[] | -3:2-[] | -1:-5-[('\US',-3),('',0)] | 0:5-[('F',-1),('p',4)] | 4:-1-[] | | -2:8-[('\177',-2),('(',-2),('d',-2),('4',-2),('D',-2),('\US',-2),('d',-2),('u',-2)] | | -16:11-[] | -2:-2-[] | 0:11-[('@',1)] | 1:13-[('u',11)] | 9:-11-[('\231',11)] | 11:12-[('\226',1)] | 16:15-[] | | -10:2-[] | -4:8-[] | 1:30-[] | 26:26-[('',1),('K',-4)] | 31:-21-[] | | -35:51-[('@',-29)] | -29:21-[('\132',-11)] | -11:-31-[('j',61)] | -4:40-[('a',-29)] | 0:6-[('z',-35),('9',28),('\170',-11),('\SUB',28)] | 23:8-[('P',-29),('(',61),('\\',28)] | 28:60-[] | 61:44-[('q',61)] | *** Exception: Data/Graph/Inductive/Graph.hs:250:26-59: Irrefutable pattern failed for pattern (Data.Maybe.Just (pr, _, la, su), g') ` The actual error comes from the definition of insEdge: , | -- | Insert a 'LEdge' into the 'Graph'. | insEdge :: DynGraph gr = LEdge b - gr a b - gr a b | insEdge (v,w,l) g = (pr,v,la,(l,w):su) g' | where (Just (pr,_,la,su),g') = match v g ` with the Graph instance for Tree-based graphs using this for its mkGraph method: , | mkGraph vs es = (insEdges' . insNodes vs) empty | where | insEdges' g = foldl' (flip insEdge) g es ` So, is this really a bug in FGL, or am I using mkGraph wrong? On another note, why doesn't the PatriciaTree graph type have a Show instance? :( ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Possible FGL bug
David Menendez wrote: From what I can tell, insEdge inserts an edge between two nodes which are already in the graph. The code is calling insEdge on arbitrarily-labeled nodes, which may not exist in the graph. That's what I thought initially, but in fact what it is doing is exactly what you suggest: Instead of picking arbitrary node labels, try selecting arbitrary elements from the list of node labels. That nGen = elements ns line assigns into nGen a random generator that will pick from ns, the list of nodes. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Scrap your boilerplate traversals
Hi, You want gmapT (or gmapM for the monadic version). If you look at the source to the everywhere function, you'll see that everywhere is defined in terms of gmapT: everywhere f = f . gmapT (everywhere f) Thanks, Neil. rodrigo.bonifacio wrote: Hi all, Is there a non-recursive traversal defined in Data.Generics' modules? I mean, the everywhere traversal first applies a function f to the subterms, and then applies f to the result. I am wondering if do exists a traversal that applies f only to the subterms. Thanks in advance, Rodrigo. ___ 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] (possibly) a list comprehensions question
Ozgur Akgun wrote: Anyway, just forget the fact that these funstions do not do a check on the length of the input list for a moment. My question is, how can I generalize this function to accept a list of lists of arbitrary length, and produce the required result. Hi, The concise solution is the list monad, as already posted. If that confuses you, here is a version using list comprehensions (well, mostly): allPossibilities :: [[a]] - [[a]] allPossibilities [] = [[]] allPossibilities (l:ls) = [ x : xs | x - l, xs - allPossibilities ls] The second line prefixes all possibilities from the later lists with every element from the the first list. Note that the base-case is crucial; if it is the empty list [], that xs - allPossibilities ls will not find any elements, and thus the list comprehension becomes the empty list, and the whole thing falls apart. Thus the base case must be the list containing the empty list, so that you have one possibility arising at the end upon which to prefix the items. Hope that makes sense... Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Status of TypeDirectedNameResolution proposal?
Simon Peyton-Jones wrote: | What's the status of the TDNR proposal [1]? It's stalled. As far as I know, there's been very little discussion about it. It's not a trivial thing to implement, and it treads on delicate territory (how . is treated). Having skimmed the page, it seems like the re-use of . is one of the major difficulties of the proposal. Would it be possible to use -? It has been used for accessing members in C and C++, so it is not too unusual a choice. It is already special in Haskell so it wouldn't break anyone's code -- but do its other uses (case statements and lambdas) mean that it would cause problems in the grammar if re-used for TDNR? Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Strange parallel behaviour with Ubuntu Karmic / GHC 6.10.4
Michael Lesniak wrote: Hello, I've written a smaller example which reproduces the unusual behaviour. Should I open a GHC-Ticket, too? Hi, I get these results: $ time ./Temp +RTS -N1 -RTS 16 real0m16.010s user0m10.869s sys0m5.144s $ time ./Temp +RTS -N2 -RTS 16 real0m12.794s user0m13.341s sys0m7.136s Looking at top, the second version used ~160% CPU time (i.e. it was using both cores fairly well). So I don't think I get the same bad behaviour as you. Those sys times look high by the way -- I guess it's all the calls to getTime? I wonder if that number might be causing the problem; can you replicate it with lower sys times? Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Strange parallel behaviour with Ubuntu Karmic / GHC 6.10.4
Michael Lesniak wrote: Hello, getTime? I wonder if that number might be causing the problem; can you replicate it with lower sys times? That was it! Thanks Neil! When I'm using some number crunching without getTime it works (with more or less the expected speedup and usage of two cores) on my Ubuntu 9.10, too. Out of curiosity, the question is still open: Why does the old example (using getTime) work so much better on an older version of Ubuntu/RedHat and not on the new ones? Your kernels were: Setup: Machine A: Quadcore, Ubuntu 9.04, Kernel 2.6.28-13 SMP Machine B: AMD Opteron 875, 8 cores, 2.6.18-164 SMP- (some redhat) Machine C: Dual-Core, Ubuntu 9.10, Kernel 2.6.31-14 SMP Looking at the implementation of getTime ThreadCPUTime in the clock package, it calls clock_gettime(CLOCK_THREAD_CPUTIME_ID,..). According to this page (http://www.h-online.com/open/news/item/Kernel-Log-What-s-new-in-2-6-29-Part-8-Faster-start-up-and-other-behind-the-scenes-changes-740591.html), the changes in 2.6.29 (changes which only your Ubuntu 9.10 machine has) included a patch (http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=c742b31c03f37c5c499178f09f57381aa6c70131) which altered the implementation of that function. Perhaps on some multi-processor machines the new implementation effectively serialises the code? I know there used to be issues of whether some of the timers were synchronised across processors/cores (to stop them appearing to go backwards), so maybe something with the timers and their synchronisations effectively stops your program running in parallel. If it helps, my machine is: Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz according to /proc/cpuinfo. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Strange parallel behaviour with Ubuntu Karmic / GHC 6.10.4
Michael Lesniak wrote: Hello, I'm currently developing some applications with explicit threading using forkIO and have strange behaviour on my freshly installed Ubuntu Karmic 9.10 (Kernel 2.6.31-14 SMP). Setup: Machine A: Quadcore, Ubuntu 9.04, Kernel 2.6.28-13 SMP Machine B: AMD Opteron 875, 8 cores, 2.6.18-164 SMP- (some redhat) Machine C: Dual-Core, Ubuntu 9.10, Kernel 2.6.31-14 SMP Compiler on all machines: ghc 6.10.4 (downloaded from GHCs official website) Hi, I have a dual-core Ubuntu 9.10 machine (running whatever GHC comes with the distro -- 6.10.x), so if you put your test code somewhere that I can get at, I can run it and see if I get the same effect. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What does the `forall` mean ?
Eugene Kirpichov wrote: 2009/11/12 Andrew Coppin andrewcop...@btinternet.com: Even I am still not 100% sure how placing forall in different positions does different things. But usually it's not something I need to worry about. :-) To me it does not look like it does different things: everywhere it denotes universal polymorphism. What do you mean? I might be missing something. I think what he means is that this: foo :: forall a b. (a - a) - b - b uses ScopedTypeVariables, and introduces the type-name a to be available in the where clause of myid. Whereas something like this: foo2 :: (forall a. a - a) - b - b uses Rank2Types (I think?) to describe a function parameter that works for all types a. So although the general concept is the same, they use different Haskell extensions, and one is a significant extension to the type system while the other (ScopedTypeVariables) is just some more descriptive convenience. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Cabal upload issue
Jeremy O'Donoghue wrote: Hi all, I'm in the process of trying update the revisions of wx (part of wxHaskell) on hackage. I'm getting an error I find slightly surprising: ... Library if flag(splitBase) build-depends: base = 3, wxcore = 0.12.1.1, stm Change this last line to base = 3 5 to get rid of the warning. I think the idea is that if base becomes version 5, it will likely break your code, so you should specify ahead of time that this library isn't currently designed to work with a version of base beyond 4. That way when someone installs your package in the future and you haven't tested with base 5, cabal will know to use base 4 for your library. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Observer pattern in Haskell?
Andy Gimblett wrote: Hi all, I've been doing some GUI programming recently, using wx. To help manage dependencies between state and UI elements, I looked for a Haskell version of the Observer design pattern, and I found an implementation written by Bastiaan Heeren of ou.nl [1]. Now, before I make a hackage release: 1. Does anyone have any comments, on either version? There is no way to remove an observer, which is something I'd expect to have available. I realise this would require assigning a key to each observer (and thus perhaps storing them in an associative map) or some way to filter them, but I think if you can only ever add observers, it will get awkward. 2. In particular, is the MVar version sensible? I'm aiming for mutual exclusion between threads. I _think_ I've got it, but I'm perhaps not familiar enough with the semantics of MVar to be certain. Advice appreciated. If it _is_ sensible, then is there any reason not to just use this, and discard the IORef version? It looks fine (and thread-safe) to me, but I'd agree that you may as well just use the MVar version and leave out the IORef version. The current implementation is synchronous, in that any observer functions are called immediately and synchronously (and in the same thread as the change of subject value). I'm pondering extending the package with an asynchronous version where the update just trips a flag, and the observer function picks this up later - possibly in another thread. The idea there is to help in cases where certain operations have to be in a particular thread. But this will mean a change to the typeclass too, I guess - or the addition of another one for observers themselves. Again, any thoughts? I was a bit surprised at first that the observers were called synchronously. Asynchronous is what I'd expect, and it's also harder to code the asynchronous handlers wrongly. One blocking call (such as putMVar) in a synchronous handler can screw up your whole program by delaying the subsequent observers (and at that stage, the order in which the observers were added begins to matter). But my idea of how asynchronous would be implemented seems different to yours, judging by your description. Why not just augment this function in the synchronous version: notifyObservers :: Subject sub val = sub - IO () notifyObservers subject = do value - getValue subject observers - getObservers subject mapM_ ($ value) observers to become: notifyObserversAsync :: Subject sub val = sub - IO () notifyObserversAsync subject = do value - getValue subject observers - getObservers subject mapM_ (forkIO . ($ value)) observers This is what I was expecting to happen -- all the observer actions are spawned off into their own thread to run whatever code they want (either communicating back to an existing thread, or performing some long in-depth action). Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Observer pattern in Haskell?
Andy Gimblett wrote: was a bit surprised at first that the observers were called synchronously. Asynchronous is what I'd expect, and it's also harder to code the asynchronous handlers wrongly. One blocking call (such as putMVar) in a synchronous handler can screw up your whole program by delaying the subsequent observers (and at that stage, the order in which the observers were added begins to matter). True, but the observers shouldn't be able to access the MVars directly, I think? They should only be able to use the exposed interface, which won't let that happen? Just to clarify -- I meant access to another MVar. Basically, if I do this: do v - newMVar addObserver sub (putMVar v) If when the observers are run, the MVar v (that I've allocated) is non-empty, my code will block until it is empty, which will also block all the subsequent observers from being run (and block the code that called setValue) until the MVar is cleared by another thread. So my one poorly-written observer could deadlock (or cause stutter in) the system, whereas in the forkIO version, this observer would be fine -- it would block in its own new thread. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Names for properties of operators
Hi, Thanks for the replies so far. If it helps, after I sent my post, I spotted a couple of arithmetic examples: Neil Brown wrote: 2: (a % b) % c = (a % c) % b Division (on rationals) obeys this property (a / b) / c = (a / c) / b -- which is actually equal to a / (b * c), but that doesn't matter for my property. 4: (a % b) ~ c = (a ~ c) % b Division and multiplication on rationals obey this property: (a / b) * c = (a * c) / b. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Names for properties of operators
Hi, We have names for properties of operators/functions. For example, if this holds: a % b = b % a for some operator %, we say that % is commutative. Similarly, if this holds: (a % b) % c = a % (b % c) we say that % is associative. Is there a name for this property, which I'm numbering 1, (where (%) :: a - b - b; i.e. the operator is potentially, but not necessarily, asymmetrically typed): 1: a % (b % c) = b % (a % c) For example, `Set.insert` obeys 1 for any values of a, b and c. (Any operator that is both associative and commutative automatically satisfies this property, but this property can be satisfied without the operator being either of those.) Given this property, we could prove useful follow-on results, such as: foldr (%) x ys = foldr (%) x (reverse ys) foldr (%) x ys = foldl (flip (%)) x ys The property 1 effectively states that the far-right hand element in a chain of such operators is special, but the ordering of everything to the left of it doesn't matter. One could conceive of a mirror property (where (%) :: a - b - a): 2: (a % b) % c = (a % c) % b If (%) obeys 1, flip (%) obeys 2 (and vice versa). I think these properties are useful -- I'd like to know if they have names already to describe them by. A similar property of two relations (where ((%), (~)) :: (a - b - b, c - b - b) ) would be: 3: a % (b ~ c) = b ~ (a % c) with mirror version (and adjusted types): 4: (a % b) ~ c = (a ~ c) % b Do these have a name? As an example, `Set.insert` and `Set.union` obey property 3 for all values of a, b and c. There are also symmetrically-typed examples of these operators, but the Set operations are easy and familiar. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Are all arrows functors?
Hi, I was thinking about some of my code today, and I realised that where I have an arrow in my code, A b c, the type (A b) is also a functor. The definition is (see http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Arrow.html): fmap = (^) -- Or, in long form: fmap f x = arr f x Out of curiosity, and since this is a typical haskell-cafe question, does this definition of fmap hold for all arrows? And is there a wiki page somewhere that has a table of all of these Haskell type-classes (Functor, Monad, Category, Arrow, Applicative and so on), and says that if you are an instance of class A you must have some corresponding instance of B? (e.g. all Monads are Functors and Applicatives) I'm fairly certain my arrow isn't a Monad or Applicative, although of course it must be a Category, given the type-class dependency, but it would be nice when using one of these things to see what other instances you should automatically supply. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] is proof by testing possible?
Dan Piponi wrote: On Mon, Oct 12, 2009 at 10:42 AM, muad muad.dib.sp...@gmail.com wrote: Is it possible to prove correctness of a functions by testing it? consider a function of signature swap :: (a,b) - (b,a) We don't need to test it at all, it can only do one thing, swap its arguments. (Assuming it terminates.) swap = undefined Terminates and does not swap its arguments :-) What do free theorems say about this, exactly -- do they just implicitly exclude this possibility? Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ANN: text 0.5, a major revision of the Unicode text library
Bryan O'Sullivan wrote: On Fri, Oct 9, 2009 at 8:33 AM, Jeremy Shaw jer...@n-heptane.com mailto:jer...@n-heptane.com wrote: What are the chances of seeing a, instance Data Text, some day? I might as well follow up here, since I've sent Jeremy a couple of messages on this subject. I think maybe someone else will have to take a crack at a Data instance for Text, because the documentation for Data.Data is not written in English. In its syntax and structure, it closely hews to what we think of as English, but it is the kind of documentation that can only be understood by someone who already knows what it is going to say. This is an exemplar of my experience with the cottage industry of generic programming in Haskell: I'd really quite like to use the stuff, but for goodness's sake, o beloved researchers, please aim your expository papers at non-specialists once in a while. An endless chain of papers of the form my technique, which you won't understand, is better than this other technique, which you haven't read about and won't anyway understand, in subtle ways that you won't understand does not feel to me like progress. Data is probably the most complex bit of Haskell I've seen, and pretty much needs a full paper to have an idea of what's going on, so I'm not sure it's a typical piece of Haskell (nor even a typical bit of generic programming) to pick on. I had a crack at a simple proper Data instance, and got as far as needing a Data instance for ByteString#, accompanied by an error I don't fully understand, but I think is telling me that things involving magic hashes are magic: Data/Text/Array.hs:104:35: Couldn't match kind `#' against `*' When matching the kinds of `ByteArray# :: #' and `d :: *' Expected type: d Inferred type: ByteArray# In the first argument of `z', namely `Array' What is the Data instance required for here, exactly? Is it generic transformations, or for generic serialisation (or some other need)? It may be possible to fake the Data instance to cover the needed aspects. I'm not in favour of the boxing/unboxing that Jeremy suggested, because Text doesn't really contain a String, but I'm also not sure that a real Data instance (exposing all the innards) is that great either. By the way: text-0.5 doesn't build for me on my GHC 6.8.2 system with base-3, mainly because you are assuming the class-based exception mechanism from base-4 in the Data.Text.Encoding.Error module, without using the extensible-exceptions package. I'm happy to knock up some patches that fixes it, if you still want to support that configuration? Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] apply function arguments in a list
Michael Mossey wrote: If I have a list containing the arguments I want to give to a function, is there a general way to supply those arguments in a compact syntax? In other words, I could have args = [1,2,3] f x y z = ... I would write t = f (args!!0) (args!!1) (args!!2) but there may be a neater, more general syntax. In general, the problem is that you can't guarantee ahead of time that the list will have three elements, so however you write it, you'll turn a compile-time error (wrong number of args to function) into a run-time error (!! says index is invalid). The neatest way is probably: t [x,y,z] = f x y z Which will give a slightly better error if the list is the wrong size. If your function takes many arguments of the same type, perhaps you could generalise it to take a list of arbitrary size, and do away with requiring three arguments? Alternatively, use tuples if you want an easy way to carry the arguments around together: args = (1, 2, 3) f x y z = ... uncurry3 f (x,y,z) = f x y z t = uncurry3 f (uncurry already exists, I think uncurry3 is one you have to add yourself). Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Control.Exception base-3/base-4 woes
Hi, In my CHP library I need to do some exception catching. I want the library to work on GHC 6.8 (with base-3 -- this is the current version in Ubuntu Hardy and Jaunty, for example) and GHC 6.10 (which comes with base-4). But base-3 and base-4 need different code for exception catching (whether it's importing Control.OldException or giving a type to the catch method). Here's what I currently do -- my Haskell file contains this: #if __GLASGOW_HASKELL__ = 609 import qualified Control.OldException as C #else import qualified Control.Exception as C #endif My cabal file contains this (it used to say just base,... but Hackage complained at me the other day when I tried to upload that): Build-Depends: base = 3 5, ... This works on two machines: one is 6.8+base-3, the other is 6.10+base-3base-4, where cabal seems to use base-4. However, I have had a bug report (now replicated) which stems from a different 6.10+base-3base-4 machine where cabal picks base-3 instead. The real problem is that the #if is based on GHC version, but really it should be based on which base-* library is being used. I know the code works with base-3 (use Control.Exception) and base-4 (use Control.OldException) but I can't get the build process right to alter the code based on which base-* library is being used. Can anyone tell me how to fix this? I don't think that changing to always use Control.Exception would fix this, because I need to give a different type for catch in base-3 to base-4, so there's still the incompatibility to be dealt with. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Got problems with classes
Hi, One reason (there may be more) is as follows: Grigory Sarnitskiy wrote: class Configuration c where getParticleI :: (Particle p) = c - Int - p This type signature declares that for any type c that has a Configuration instance (and an Int), you can give me back something that is of *any type* p, provided I have a Particle instance for p. So if I was to declare: instance Particle Int Then I should be able to do: x :: Int x = getParticleI someConfigurationItem 6 But... type Collection p = UArray (Int,Int) Double instance Configuration (Collection p) where getParticleI config i = (1,1,1) :: ParticleC What you are doing in your instance, however, is always returning a ParticleC, which is a specific type rather than any type that belongs to Particle. There are several ways to solve this. A few examples: 1. Make getParticleI specifically return a ParticleC, rather than the type p. 2. Add a makeParticle function to the particle type-class. If you had: class Particle p where makeParticle :: (Double, Double, Double) - p Then you could rewrite that last line as: getParticleI config i = makeParticle (1, 1, 1) And then the return would be of any type p that has a Particle instance. 3. Parameterise the collection over the particle, e.g. class Configuration c where getParticleI :: Particle p = c p - Int - p But currently Collection is not actually parameterised using the p parameter (the UArray has Double, not Particle), so I can't properly adjust your example for that. Hope that helps, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Line drawing algorithm
CK Kashyap wrote: Hi All, I am working on a diagraming utility in Haskell. I started with line drawing. I am doing the basic stuff using the y = mx + c formula to draw a line between (x1,y1) and (x2,y2) Hi, Are you doing this to learn Haskell, learn about drawing lines, or to just get it implemented? If either of the latter two, when drawing a straight line you shouldn't need to do floating point operations such as this: newY = y1 + round (slope * (fromIntegral (newX - x1))) Bresenham's algorithm (or similar variants) allows you to draw a line without needing floating point. A Haskell implementation is here: http://rosettacode.org/wiki/Bresenham%27s_line_algorithm#Haskell Although it may not be too understandable! Wikipedia has an explanation of the general algorithm: http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm As to how to cope with the dy dx case in your code given the dx dy case, you could just swap the x and y coords at the start, then swap back the x and y coords of all the output points afterwards. Odd, but effective :-) Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] coding standard question
Jules Bean wrote: I've been using GHC for years and my honest opinion is that the warnings very rarely flag an actual maintainability problem in the code I write, and very frequently annoying highlight something I knew I was doing, and did quite deliberately - most often inexhaustive patterns or shadowing. I would agree to a certain extent about the warnings. Name shadowing is not really a problem, and it's often hard to avoid shadowing names that already exist in an imported module (why shouldn't I have a variable named lines?). It's also usually the case that when I write inexhaustive pattern matches, it's because I know that the function (in a where clause) cannot be called with the missing pattern. Type defaulting and monomorphism bits may be useful to some, but I only usually fix them to get rid of the warning, not because they cause a problem. The ones I find useful are unused imports (handy for tidying up the import list), overlapping patterns, missing fields, warnings about tabs and a few others. Of course, you can easily customise which warnings are on and which are off, so we can all have different preferences. It would be nice to be able to set some warnings to be errors though, while leaving others as warnings, or turned off (don't think GHC can do this?). Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] how to #include files within parsec ... without unsafePerformIO?
Leonard Siebeneicher wrote: Dear reader, I wonder whether there is a 'general' working solution to include files within a parsec parser. Without the need of unsafePerformIO. At least in parsec 2, I don't think so. Our solution was to read in the main file, tokenise it (using Alex), preprocess it (using some regex-like pattern matching on the token stream) in the IO monad and include the new files then (also tokenising and preprocessing them). Then after preprocessing we feed the entire resulting token stream to Parsec. Whether a two-phase approach (preprocess then parse) works depends on whether your include syntax is simple enough that you can spot the includes without parsing. Thanks, Neil. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Confusion on the third monad law when using lambda abstractions
Clicking on the source code link reveals that enum2 is used in the where clause. It's not important to the transformation that Jake was performing. In essence, = is the monadic version of . (function composition) and as explained, it can be used to do some pointfree-like programming in the presence of monads. It's also handy in the arguments to things like mapM. E.g. f = mapM (\x - foo x = bar) becomes: f = mapM (bar = foo) Neil. Colin Adams wrote: What is enum2 doing in all of this - it appears to be ignored. 2009/6/18 Jake McArthur jake.mcart...@gmail.com: Jake McArthur wrote: Generally, you can transform anything of the form: baz x1 = a = b = ... = z x1 into: baz = a = b = ... = z I was just looking through the source for the recently announced Hyena library and decided to give a more concrete example from a real-world project. Consider this function from the project's Data.Enumerator module[1]: compose enum1 enum2 f initSeed = enum1 f1 (Right initSeed) = k where f1 (Right seed) bs = ... k (Right seed) = ... First, I would flip the `(=)` into a `(=)` (and I will ignore the `where` portion of the function from now on): compose enum1 enum2 f initSeed = k = enum1 f1 (Right initSeed) Next, transform the `(=)` into a `(=)`: compose enum1 enum2 f initSeed = k = enum1 f1 $ Right initSeed We can move the `($)` to the right by using `(.)`: compose enum1 enum2 f initSeed = k = enum1 f1 . Right $ initSeed Finally, we can drop the `initSeed` from both sides: compose enum1 enum2 f = k = enum1 f1 . Right I didn't test that my transformation preserved the semantics of the function or even that the type is still the same, but even if it's wrong it should give you the idea. - Jake [1] http://github.com/tibbe/hyena/blob/9655e9e6473af1e069d22d3ee75537ad3b88a732/Data/Enumerator.hs#L117 ___ 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 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe