Re: [Haskell-cafe] STM and random numbers

2007-01-13 Thread Tomasz Zielonka
On Sat, Jan 13, 2007 at 01:49:36PM +1000, Matthew Brecknell wrote:
  Rather than having a separate thread computing the random numbers
  using IO, why not just stick an StdGen in a TVar and write a function
  like:
  
  type RandomVar = TVar StdGen
  
  rnd :: RandomVar - STM a
  rnd var = do
   g - readTVar var
   let (r,g') = random g
   writeTVar var g'
   return r
 
 The user of this approach should be aware that it may lead to
 non-determinism. That is, the sequence of psuedo-random numbers
 extracted by any one thread will depend on those extracted by other
 threads, which may in turn depend on the scheduling of those threads.
 
 The TVar approach might also lead to excessive STM transaction
 abort-retry cycles, if multiple threads are retrieving many
 pseudo-random numbers via a single TVar.

As a workaround for these problems you can create a separate RandomVar
for each atomically block.

Best regards
Tomasz
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Are GADTs expressive? Simple proof-carrying code in Haskell98

2007-01-13 Thread oleg

Inspired by the recent post by Jim Apple, we demonstrate a datatype
`Terminates' that can hold only an assuredly terminating (strongly
normalizable) term in untyped lambda-calculus. Furthermore, the values
of the datatype `Terminates' contain all and only those untyped
lambda-calculus terms with that property. As in Jim Apple's solution,
to create the value `Terminates', the user submits the term in
question and the proof of its termination. The proof will be verified
-- and if it holds, the Terminates certificate will be created. As in
Jim Apple's solution, verification of the submitted proof has to be
done at run-time, to make sure the proof is not fake, that is, has no
undefined values. Our solution uses neither GADTs nor typeclasses; in
fact, it is in Haskell98. Also, the required proof from the user
couldn't be simpler.

Jim Apple wrote:
 To show how expressive GADTs are, the datatype Terminating can hold
 any term in the untyped lambda calculus that terminates, and none that
 don't. I don't think that an encoding of this is too surprising, but I
 thought it might be a good demonstration of the power that GADTs
 bring.
The shown GADT encoding seems to be of the kind that is convertible to
typeclasses in the straightforward way, see for example,
http://pobox.com/~oleg/ftp/Haskell/GADT-interpreter.hs 

Inn this particular example, GADT do not bring any
power. Incidentally, the typeclass encoding has an advantage: If the
submitted proof is invalid, the error will be reported at compile
time. There is not even a possibility of a run-time error. This is
because the typeclasses approach does only type-level computations and
does not look at values at all (which may as well be
undefined). Placing a value into a (rank-1) datatype forces the
typechecker to resolve any constraints associated with the value, or
report an error if constraints are not satisfiable.

However, it seems that the problem at hand admits a far simpler
solution -- in Haskell98. The solution is in spirit of lightweight
static capabilities. Here it is:

 module PCC (Terminates,  -- data constructor is not exported
 make_terminates, get_term) where

 import YourFavorite.Lambda_calc 

 data Terminates = Terminates{get_term::Term}

 make_terminates :: Term - Integer - Maybe Terminates
 make_terminates term limit = 
   case reduce_term_nsteps term limit of
 Left _ - Nothing
 Right normal_form - Just (Terminates term)


Because the data constructor is not exported, the only way to
construct a value `Terminates' from which a term can be extracted is
by invoking the function make_terminates. The function accepts a
lambda-term, and a proof of its termination. The proof takes the form
of the (upper bound of the) number of steps needed to normalize the
term. The function make_terminates checks the proof, by trying to
reduce the term that many steps. If the normal form is found in the
process, the term is normalizable and we create the
certificate. Otherwise, we conclude the termination proof does not
hold and we return Nothing. This proof checking is clearly decidable.

The module PCC constitutes the `trusted kernel' with respect to the
Terminates datatype. The function make_terminates must be rigorously
verified in order to deserve our trust. But the same should be said
for the GADT or any other solution: e.g., one can easily add a new
case alternative to the Normal datatype declaring Omega to be in the
normal form.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] strange performance of expression evaluators

2007-01-13 Thread Alexander Vodomerov
On Sat, Jan 13, 2007 at 11:44:38AM +1000, Matthew Brecknell wrote:

 So my advice here would be: always try the optimiser before you worry
 too much about strange performance!
Thanks for help!

I've done some more experiments. The following program defines simple
arithmetic expression with indexed variables. I've written four
different ways to evaluate them:
 - eval1 is simple monadic evaluator
 - eval2 is the obvious straight-forward implentation
 - compile1 is attempt to perform compilation
 - compile2 is refined compile1 with sub-expressions explicitely
 separated via let binding.

Test evaluates the same expression in 100 different environments.
The results are:
  - eval1 - 17.47 sec
  - eval2 - 3.71 sec
  - compile1 - 3.79 sec
  - compile2 - 3.74 sec

This figures are completely mysterious for me.
   1) I expected eval1 and eval2 to perform equally. In fact, eval1 is
   4.7 times slower for eval2.
   2) I expected compile{1,2} to perform much faster then eval{1,2}.
  However, the compilation attempt does not give any speed up at
  all.

Can anyone explain these results?

Program was compiled with ghc -O3 -fexcess-precision command.

For comparison, I wrote simple straight-forward implementation of
compile2 in C++. It runs approximately 1.04 sec (3.57 better than
Haskell).
 
import Data.Array.Unboxed
import Data.Array.Base
import Control.Monad.Reader
import Data.Int

foldl' f z [] =  z
foldl' f z (x:xs) =  (foldl' f $! f z x) xs

type Value = Int32
data Expr = Const !Value | Var !Int | Add !Expr !Expr | Sub !Expr !Expr | Mul 
!Expr !Expr
type Env = UArray Int Value

eval1 :: Expr - Reader Env Value
eval1 e =
case e of
  Const c - return c
  Var n - do { env - ask; return $ env ! n }
  Add e1 e2 - do
 v1 - eval1 e1
 v2 - eval1 e2
 return $ v1 + v2
  Sub e1 e2 - do
 v1 - eval1 e1
 v2 - eval1 e2
 return $ v1 - v2
  Mul e1 e2 - do
 v1 - eval1 e1
 v2 - eval1 e2
 return $ v1 * v2

eval2 :: Expr - Env - Value
eval2 e env =
case e of
  Const c - c
  Var n - env ! n
  Add e1 e2 - eval2 e1 env + eval2 e2 env
  Sub e1 e2 - eval2 e1 env - eval2 e2 env
  Mul e1 e2 - eval2 e1 env * eval2 e2 env

compile1 :: Expr - (Env - Value)
compile1 e =
case e of
  Const c - \env - c
  Var n - \env - env ! n
  Add e1 e2 - \env - (compile1 e1) env + (compile1 e2) env
  Sub e1 e2 - \env - (compile1 e1) env - (compile1 e2) env
  Mul e1 e2 - \env - (compile1 e1) env * (compile1 e2) env

compile2 :: Expr - (Env - Value)
compile2 e =
case e of
  Const c - \env - c
  Var n - \env - env ! n
  Add e1 e2 - let c1 = compile2 e1 in
   let c2 = compile2 e2 in
   \env - c1 env + c2 env
  Sub e1 e2 - let c1 = compile2 e1 in
   let c2 = compile2 e2 in
   \env - c1 env - c2 env
  Mul e1 e2 - let c1 = compile2 e1 in
   let c2 = compile2 e2 in
   \env - c1 env * c2 env

test1 :: Expr
test1 = Add (Mul (Add (Var 0) (Var 1)) (Add (Var 0) (Var 1))) (Mul (Sub (Var 0) 
(Var 1)) (Sub (Var 0) (Var 1)))

test :: Expr
test = Add (Mul test1 test1) (Add test1 test1)

do_test :: (Env - Value) - Value
do_test e =
foldl' (+) 0 (map (\n - e (array (0, 1) [(0, n), (1, n)])) [0..100])

main = do
  putStrLn testing empty expr
  let res0 = do_test (\env - 0)
  putStrLn $ result is  ++ show res0
  putStrLn testing compile 1
  let res1 = do_test (compile1 test)
  putStrLn $ result is  ++ show res1
  putStrLn testing compile 2
  let res2 = do_test (compile2 test)
  putStrLn $ result is  ++ show res2
  putStrLn testing eval 1
  let res3 = do_test (runReader (eval1 test))
  putStrLn $ result is  ++ show res3
  putStrLn testing eval 2
  let res4 = do_test (eval2 test)
  putStrLn $ result is  ++ show res4
  return ()

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Re: different performance of equivalent expression

2007-01-13 Thread apfelmus
 I've run into strange effect that I can not explain. I have simple
 expression that can be written by two equivalent ways. However one way
 give much performance gain over another. Here is an example:
 
 -- apply function many times (tail-recursive)
 many n f x = if n == 0 then x else many (n-1) f $! (f x)
 
 -- first adder function
 adder1 = let r = many 500 sin 1.0 in \x - x + r
 
 -- second adder function
 adder2 = \x - x + many 500 sin 1.0

 If you run program it think some seconds performing math, and them
 prints 4 results immediately. But with adder2 function, it perform
 calculation in every call, which can be seen visually.

 It seems that compiler is able to cache in some way long computation
 in first case, but not in second.

This is indeed the case and entirely reasonable. The effect is called
memoization, a key ingredient to lazy evaluation. To simplify the
explanation, let's take the examples

adder1 = let r = many 5000 (1+) 0 in \x - x + r
adder2 = \x - let s = many 5000 (1+) 0 in x + s

The evaluation of (adder1 3) proceeds as follows:

adder1 3
  = (let r = many 5000 (1+) 0 in \x - x + r) 3
  = let r = many 5000 (1+) 0 in 3 + r
  = let r = 5000 in 3 + r
  = 5003

Now, (r) will be updated with the result (5000) after it has been
calculated and subsequent access to (r) will retrieve the updated value
as in

adder1 4
  = (let r = 5000 in \x - x + r) 4
  = let r = 5000 in 4 + r
  = 5004

Every incarnation of (adder1) shares the same r. For (adder2), things
are different. Here, (s) will be updated as well, but different
incarnations of (adder2) do not share the same (s) because (s) is only
in scope after supplying some argument (x). Hence, every (adder2 3) and
(adder3 4) (re)calculates its own (s).

 I always thought that let a = b in x + a is just a syntactic sugar for x
 + b. Is it wrong?

This is correct but doesn't apply to the case above. The question here
is whether

let a = b in \x - x + a
  and
\x - let a = b in x + a

are equivalent. Considering the result, they are. But considering
running time and memory footprint, they are not. The first trades memory
for speed, the second trades speed for memory. In general, the compiler
is reluctant to switch between those two versions, i.e. it does not
perform much common subexpression elimination or let floating (see GHC
manual). The choice must be up to the programmer.


Regards,
apfelmus

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Re: strange performance of expression evaluators

2007-01-13 Thread apfelmus
 I've done some more experiments. The following program defines simple
 arithmetic expression with indexed variables. I've written four
 different ways to evaluate them:
  - eval1 is simple monadic evaluator
  - eval2 is the obvious straight-forward implentation
  - compile1 is attempt to perform compilation
  - compile2 is refined compile1 with sub-expressions explicitely
  separated via let binding.
 
 Test evaluates the same expression in 100 different environments.
 The results are:
   - eval1 - 17.47 sec
   - eval2 - 3.71 sec
   - compile1 - 3.79 sec
   - compile2 - 3.74 sec
 
 This figures are completely mysterious for me.
1) I expected eval1 and eval2 to perform equally. In fact, eval1 is
4.7 times slower for eval2.
2) I expected compile{1,2} to perform much faster then eval{1,2}.
   However, the compilation attempt does not give any speed up at
   all.

Your intention is that (compile2 test) should analyze the expression
tree of (test) only once when evaluating it for different environments.

I'm not sure whether the constructors (Add), (Mul) etc. get replaced
once and for all by (+) and (*) or whether this really matters, because
(eval2), (compile1) and (compile2) have the same running time. I think
that memoization (as explained in my previous post) only takes place for
values not of function type, i.e. partially evaluated functions aren't
memoized. It may also be that the compiler optimizes things for the
concrete expression (test) you gave in your code. So supplying the
expression interactively could show a difference between (eval2),
(compile1) and (compile2).

Ironically, (eval1) does compile as much as you intend (compile2) to
do. But it looks like the overhead imposed by appealing to
Control.Monad.Reader doesn't get inlined away completely.

Currently, you don't do much work per expression, it just gets
evaluated. To take advantage of memoization, you need to do more
expensive analysis on a per expression basis. For example, you might
want to precalculate stuff that doesn't depend on the environment:

   data ConstVar a = Const a | Var (Env - a)

   eval :: ConstVar a - Env - a
   eval (Const x) = const x
   eval (Var f)   = f

   -- addition, multiplication etc. do precalculation
   -- when the constituents are known beforehand
   instance Num a = ConstVar a where
   (Const x) + (Const y) = Const (x + y)
   x + y = Var (\e - eval x e + eval y e)
   ...

   data Expr a = Value a | Variable Name
   | Add (Expr a) (Expr a) | Mul (Expr a) (Expr a)

   compile :: Num a = Expr a - ConstVar a
   compile (Value c)= Const c
   compile (Variable v) = Var (\e - e ! v)
   compile (Add x y)= (compile x) + (compile y)
   compile (Mul x y)= (compile x) * (compile y)

   testexpr = (Mul (Value 1) (Value 2)) `Add` (Variable 1)
   test = eval . compile $ testexpr

Of course, this can be improved. For instance, it currently does not
know about the associative law like in

(Add (Value 1) (Add (Value 2) (Variable 1)))

Now, it is clear that analyzing the expression again and again every
time it needs to be evaluated (interpretation) is wasted work.


Regards,
apfelmus

PS:

 data Expr = Const !Value | Var !Int
   | Add !Expr !Expr | Sub !Expr !Expr | Mul !Expr !Expr

You'd better leave out the strictness annotations (!).

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


RE: [Haskell-cafe] Are GADTs expressive? Simple proof-carrying code inHaskell98

2007-01-13 Thread Meng Wang
Hi, Oleg.

It is nice to see how the eval function is encoded with type classes. I
always wonder whether the HOAS example from Xi's POPL 03 paper can be
programmed this way. In particular, it appears to me that the Fix clause
requires non-inductive derivation of the form

instance Eval (f e) a = Eval e a where
eval e@(Fix f) = eval (f e)

Any trick on getting this work? 

Meng


-Original Message-
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of [EMAIL PROTECTED]
Sent: 13 January 2007 09:20
To: haskell-cafe@haskell.org
Subject: [Haskell-cafe] Are GADTs expressive? Simple proof-carrying code
inHaskell98


Inspired by the recent post by Jim Apple, we demonstrate a datatype
`Terminates' that can hold only an assuredly terminating (strongly
normalizable) term in untyped lambda-calculus. Furthermore, the values
of the datatype `Terminates' contain all and only those untyped
lambda-calculus terms with that property. As in Jim Apple's solution,
to create the value `Terminates', the user submits the term in
question and the proof of its termination. The proof will be verified
-- and if it holds, the Terminates certificate will be created. As in
Jim Apple's solution, verification of the submitted proof has to be
done at run-time, to make sure the proof is not fake, that is, has no
undefined values. Our solution uses neither GADTs nor typeclasses; in
fact, it is in Haskell98. Also, the required proof from the user
couldn't be simpler.

Jim Apple wrote:
 To show how expressive GADTs are, the datatype Terminating can hold
 any term in the untyped lambda calculus that terminates, and none that
 don't. I don't think that an encoding of this is too surprising, but I
 thought it might be a good demonstration of the power that GADTs
 bring.
The shown GADT encoding seems to be of the kind that is convertible to
typeclasses in the straightforward way, see for example,
http://pobox.com/~oleg/ftp/Haskell/GADT-interpreter.hs 

Inn this particular example, GADT do not bring any
power. Incidentally, the typeclass encoding has an advantage: If the
submitted proof is invalid, the error will be reported at compile
time. There is not even a possibility of a run-time error. This is
because the typeclasses approach does only type-level computations and
does not look at values at all (which may as well be
undefined). Placing a value into a (rank-1) datatype forces the
typechecker to resolve any constraints associated with the value, or
report an error if constraints are not satisfiable.

However, it seems that the problem at hand admits a far simpler
solution -- in Haskell98. The solution is in spirit of lightweight
static capabilities. Here it is:

 module PCC (Terminates,  -- data constructor is not exported
 make_terminates, get_term) where

 import YourFavorite.Lambda_calc 

 data Terminates = Terminates{get_term::Term}

 make_terminates :: Term - Integer - Maybe Terminates
 make_terminates term limit = 
   case reduce_term_nsteps term limit of
 Left _ - Nothing
 Right normal_form - Just (Terminates term)


Because the data constructor is not exported, the only way to
construct a value `Terminates' from which a term can be extracted is
by invoking the function make_terminates. The function accepts a
lambda-term, and a proof of its termination. The proof takes the form
of the (upper bound of the) number of steps needed to normalize the
term. The function make_terminates checks the proof, by trying to
reduce the term that many steps. If the normal form is found in the
process, the term is normalizable and we create the
certificate. Otherwise, we conclude the termination proof does not
hold and we return Nothing. This proof checking is clearly decidable.

The module PCC constitutes the `trusted kernel' with respect to the
Terminates datatype. The function make_terminates must be rigorously
verified in order to deserve our trust. But the same should be said
for the GADT or any other solution: e.g., one can easily add a new
case alternative to the Normal datatype declaring Omega to be in the
normal form.
___
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] mapTuple

2007-01-13 Thread Grady Lemoine

I knew there must be a way in GHC to do that second example!

As for the third example, it might be a slick way to do some
super-hyper-refactoring, but I admit I can't think of anything it
would be actually necessary for offhand.

--Grady

On 1/12/07, Cale Gibbard [EMAIL PROTECTED] wrote:

On 12/01/07, Grady Lemoine [EMAIL PROTECTED] wrote:
 Is there anything in particular you're trying to accomplish?  It seems
 like this is the type of thing you'd accomplish with typeclasses if
 you had a less general problem than you've presented.  For example,

  mapShowTuple :: (Show a, Show b) = (a, b) - (String, String)
  mapShowTuple (x, y) = (show x, show y)

 That said, it would be nice do be able to do something a little more
 general, but still with a specific typeclass, like

  mapNumOpTuple :: (Num a, Num b) = (Num c = c - c) - (a, b) - (a, b)
  mapNumOpTuple f (x, y) = (f x, f y)

 (This unfortunately fails to typecheck; GHC chokes with Illegal
 polymorphic or qualified type.  On the other hand, I'm still pretty
 new to Haskell myself, so maybe someone else knows how to write this
 correctly without doing complex type hackery.)

It's close:

{-# OPTIONS_GHC -fglasgow-exts #-}

mapNumOpPair :: (Num a, Num b) = (forall c. Num c = c - c) - (a, b) - (a,b)
mapNumOpPair f (x,y) = (f x, f y)

 It would also be nice to be able to generalize over all typeclasses,
 e.g. (pseudo-code here)

 mapTypeclassOpTuple :: for all typeclasses C ((C a, C b) = (C c = c
 - c) - (a, b) - (a, b))

 but I don't even know how that would fit into Haskell's syntax.  I
 suspect it's an idea that's been discussed, and I just don't know the
 term for it.

That's an interesting idea, typeclass variables. It would require a
bit of a kind system for typeclasses, but that's not so hard. I
somehow doubt it would get used all *that* much though. Can anyone
think of a clever way to apply this?

 - Cale


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Are GADTs expressive? Simple proof-carrying code in Haskell98

2007-01-13 Thread Jim Apple

On 1/13/07, [EMAIL PROTECTED] [EMAIL PROTECTED] wrote:

The shown GADT encoding seems to be of the kind that is convertible to
typeclasses in the straightforward way, see for example,
http://pobox.com/~oleg/ftp/Haskell/GADT-interpreter.hs


See also Conor McBride's Faking It: Simulating Dependent Types in Haskell

   http://citeseer.ist.psu.edu/mcbride01faking.html

Also, GADTs are extensible in GHC HEAD, though type classes are still
necessary to write functions on them:

   http://haskell.org/haskellwiki/GHC/Indexed_types#Instance_declarations


Incidentally, the typeclass encoding has an advantage: If the
submitted proof is invalid, the error will be reported at compile
time.

[more snipped]

I don't quite understand what you're getting at here. Is it that with
the GADT approach, one could write

Terminating (Apply omega omega) (undefined) (undefined)

and the typechecker would not complain? That certainly is an issue,
but I think you're saying something deeper that I'm not getting.


However, it seems that the problem at hand admits a far simpler
solution -- in Haskell98. The solution is in spirit of lightweight
static capabilities. Here it is:

 module PCC (Terminates,  -- data constructor is not exported
 make_terminates, get_term) where

[snip]

The module PCC constitutes the `trusted kernel' with respect to the
Terminates datatype. The function make_terminates must be rigorously
verified in order to deserve our trust. But the same should be said
for the GADT or any other solution: e.g., one can easily add a new
case alternative to the Normal datatype declaring Omega to be in the
normal form.



That's true, but there is at least one disadvantage to the PCC module:
some functions manipulating terminating terms must be placed inside
the trusted core. This is not the case with GADTs. For instance, we
could write a term that takes a non-normalized (but terminating) term
and beta-reduces it once to return a new normalizing term. We can't do
this as a mere client of the PCC module without calling
make_terminates again.

Operations on types with hidden constructors sometimes have to be put
in the trusted core. This was a small cost for terminating terms in
the untyped lambda calculus, but it's a bigger cost for other
structures. This is sort of like writing nested types for balanced
trees vs. using Data.Set. Data.Set does guarantee that the tree is
balanced, but we can only believe this after looking at each function
in Data/Set.hs. Yes, the definition for balanced nested trees must be
written with the same care as the functions in Data.Set, but there are
a lot more functions in Data.Set

Jim
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Meaning abbreviations stat file GHC

2007-01-13 Thread Ron

Dear,

I made a profile[1] of a test program:
Where can I find documentation for the meaning of everything mentioned
below? Or alternatively, can anyone explain them?

Where can I see the effect of using the -xt option in this profile?

Ron

[1]
/Main +RTS -p -s -xt -hc
1,372,408,024 bytes allocated in the heap
121,255,600 bytes copied during GC (scavenged)
 6,584,692 bytes copied during GC (not scavenged)
 2,768,896 bytes maximum residency (68 sample(s))

  2649 collections in generation 0 (  1.11s)
68 collections in generation 1 (  0.49s)

 6 Mb total memory in use

 INIT  time0.00s  (  0.00s elapsed)
 MUT   time5.97s  (  6.63s elapsed)
 GCtime1.60s  (  1.88s elapsed)
 RPtime0.00s  (  0.00s elapsed)
 PROF  time0.19s  (  0.20s elapsed)
 EXIT  time0.00s  (  0.00s elapsed)
 Total time7.76s  (  8.71s elapsed)

 %GC time  20.6%  (21.5% elapsed)

 Alloc rate229,946,873 bytes per MUT second

 Productivity  76.9% of total user, 68.5% of total elapsed

Ron
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe