Re: [Haskell-cafe] Function application layout

2011-05-26 Thread Neil Brown

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

2011-05-17 Thread Neil Brown

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?

2011-04-14 Thread Neil Brown

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

2011-03-31 Thread Neil Brown

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

2011-02-09 Thread Neil Brown

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

2011-01-29 Thread Neil Brown

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

2011-01-12 Thread Neil Brown

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

2011-01-12 Thread Neil Brown

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

2010-11-15 Thread Neil Brown

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

2010-11-10 Thread Neil Brown

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

2010-11-10 Thread Neil Brown

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

2010-11-09 Thread Neil Brown

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

2010-11-09 Thread Neil Brown
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

2010-10-22 Thread Neil Brown

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

2010-10-22 Thread Neil Brown

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

2010-10-06 Thread Neil Brown

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

2010-10-05 Thread Neil Brown

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

2010-09-30 Thread Neil Brown

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

2010-09-22 Thread Neil Brown

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

2010-09-15 Thread Neil Brown

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

2010-09-14 Thread Neil Brown

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

2010-09-14 Thread Neil Brown

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

2010-09-08 Thread Neil Brown

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

2010-09-07 Thread Neil Brown

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?

2010-09-06 Thread Neil Brown

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

2010-09-03 Thread Neil Brown

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

2010-09-02 Thread Neil Brown

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 * - *

2010-08-19 Thread Neil Brown

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

2010-08-18 Thread Neil Brown

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

2010-08-10 Thread Neil Brown

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

2010-08-03 Thread Neil Brown

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

2010-07-26 Thread Neil Brown

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

2010-07-08 Thread Neil Brown

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

2010-07-01 Thread Neil Brown

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

2010-07-01 Thread Neil Brown

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

2010-07-01 Thread Neil Brown

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

2010-07-01 Thread Neil Brown

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.

2010-06-28 Thread Neil Brown

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?

2010-06-23 Thread Neil Brown

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

2010-06-21 Thread Neil Brown

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

2010-06-14 Thread Neil Brown

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

2010-05-25 Thread Neil Brown

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 ?

2010-05-06 Thread Neil Brown

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?

2010-04-26 Thread Neil Brown

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

2010-04-26 Thread Neil Brown

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

2010-04-26 Thread Neil Brown

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

2010-04-21 Thread Neil Brown

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

2010-04-15 Thread Neil Brown

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 ?

2010-04-09 Thread Neil Brown

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

2010-04-07 Thread Neil Brown

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

2010-03-28 Thread Neil Brown

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

2010-03-27 Thread Neil Brown

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

2010-03-05 Thread Neil Brown

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

2010-03-04 Thread Neil Brown

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

2010-03-04 Thread Neil Brown

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

2010-03-04 Thread Neil Brown

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?

2010-02-25 Thread Neil Brown

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

2010-02-18 Thread Neil Brown

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

2010-02-17 Thread Neil Brown

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

2010-02-17 Thread Neil Brown

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

2010-02-16 Thread Neil Brown

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

2010-02-10 Thread Neil Brown
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

2010-02-04 Thread Neil Brown

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

2010-02-03 Thread Neil Brown

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

2010-01-28 Thread Neil Brown

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

2010-01-26 Thread Neil Brown

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?

2010-01-23 Thread Neil Brown

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)

2010-01-22 Thread Neil Brown

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

2010-01-11 Thread Neil Brown

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

2010-01-05 Thread Neil Brown

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?

2009-12-24 Thread Neil Brown

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 ?

2009-12-04 Thread Neil Brown

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 ...

2009-12-04 Thread Neil Brown

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]

2009-12-03 Thread Neil Brown

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?

2009-12-03 Thread Neil Brown

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 ?

2009-12-03 Thread Neil Brown

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

2009-11-25 Thread Neil Brown
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

2009-11-25 Thread Neil Brown

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

2009-11-25 Thread Neil Brown

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

2009-11-19 Thread Neil Brown

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?

2009-11-17 Thread Neil Brown

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

2009-11-16 Thread Neil Brown

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

2009-11-16 Thread Neil Brown

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

2009-11-15 Thread Neil Brown

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 ?

2009-11-12 Thread Neil Brown

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

2009-11-12 Thread Neil Brown

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?

2009-11-09 Thread Neil Brown

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?

2009-11-09 Thread Neil Brown

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

2009-11-08 Thread Neil Brown

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

2009-11-07 Thread Neil Brown

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?

2009-11-03 Thread Neil Brown

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?

2009-10-12 Thread Neil Brown

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

2009-10-11 Thread Neil Brown

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

2009-10-05 Thread Neil Brown

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

2009-09-11 Thread Neil Brown

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

2009-08-17 Thread Neil Brown

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

2009-07-17 Thread Neil Brown

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

2009-06-22 Thread Neil Brown

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?

2009-06-18 Thread Neil Brown

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

2009-06-18 Thread Neil Brown
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


  1   2   >