Re: [Haskell-cafe] Newbie vs. laziness

2007-03-21 Thread Udo Stenzel
Alex Queiroz wrote:
> 
> I don't quite get how ($!) works. I have this function:
> 
>   ids <- liftM (map fromSql . concat ) $! quickQuery con query []

There's a difference between an IO action and the result of said action,
and similarly there's a difference between making sure an action is
evaluated and making sure the result of executing the action is
evalulated.  You did the former.

If you really wanted to evaluate the result to WHNF (only) before
finishing dbCreateIndices, this would work:

>   ids <- liftM (map fromSql . concat ) $ quickQuery con query []
>   ids `seq` return $ IntMap.fromList $ zip ids [0..]

But you probably need to evaluate the complete list, so you need more:

>   ids <- liftM (map fromSql . concat ) $ quickQuery con query []
>   foldr seq () ids `seq` return $ IntMap.fromList $ zip ids [0..]

Of course, if you insist on using ($!), that's also possible:

>   ids <- liftM (map fromSql . concat ) $ quickQuery con query []
>   return $ IntMap.fromList $ flip zip [0..] $! foldr seq ids ids


HTH.

-Udo.


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


Re: [Haskell-cafe] Newbie vs. laziness

2007-03-20 Thread Alex Queiroz

Hallo,

On 3/20/07, Jules Bean <[EMAIL PROTECTED]> wrote:


Personally I'd inclined to suggest use of the strict FetchRow which the
library provides than struggle with explicit uses of seq to fight an
over-lazy IO action.



Sounds like a good suggestion. Thanks very much for the help!

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


Re: [Haskell-cafe] Newbie vs. laziness

2007-03-20 Thread Jules Bean

Alex Queiroz wrote:


However that's a bit clumsy. What kind of error are you seeing when you
say 'it crashes'?



I must fetch all rows of the result, otherwise the database will
be in an inconsistent state and all subsequent queries crash the
application. Fetching all rows automatically finishes the previous
statement, so I must evaluate the spine of the list.


Odd. That sounds like a suprising library design to me. What's the point 
in returning a lazy list if you then leave everything in an inconsistent 
state until the list is fully evaluated? In that circumstance I'd rather 
have a strict list.


I was intrigued and went and read the library documentation. It says

"...Please note that the careless use of this function can lead to some 
unpleasant behavior...But then, similar caveats apply with hGetContents..."


I don't know if I agree; these caveats seem definably worse than those 
which apply with hGetContents, if they can in fact cause crashes. The 
worse problem with hGetContents is that if someone else writes to that 
file while you're reading, you can see a mixture of old and new data. 
This seems to be far worse: you can't even make two queries unless you 
guarantee you finish the first completely first.


Personally I'd inclined to suggest use of the strict FetchRow which the 
library provides than struggle with explicit uses of seq to fight an 
over-lazy IO action.



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


Re: [Haskell-cafe] Newbie vs. laziness

2007-03-20 Thread Jeff Polakow
Hello,

> dbCreateIndices con dtn dof = do
>let dummy = newDbItem
>let query = "SELECT id FROM " ++ (dtn dummy) ++ " ORDER BY " ++ (dof 
dummy)
>ids <- liftM (map fromSql . concat ) $! quickQuery con query []
>return $ IntMap.fromList $ zip ids [0..]
> 
> quickQuery returns a lazy list of results, and I expected ($!) to make
> it strict. But my program crashes if I use it this way. But, if I add
> a print to the function:
> 
When using lazy DB connections in HDBC (I'm assuming you're using HDBC 
since quickQuery is the pre-packaged lazy query call in HDBC), you have to 
be careful about forcing all the data your'e expecting from a query on a 
connection before using the same connection for something else. As the 
previous poster mentioned, $! will only evaluate the list to weak head 
normal form. Printing out the list will indeed force everything in the 
list to be evaluated. 

There is an extended discussion of this same issue (in the context of lazy 
file io) in this thread from haskell-cafe: 
http://www.haskell.org/pipermail/haskell-cafe/2007-March/023498.html

-Jeff


---

This e-mail may contain confidential and/or privileged information. If you 
are not the intended recipient (or have received this e-mail in error) 
please notify the sender immediately and destroy this e-mail. Any 
unauthorized copying, disclosure or distribution of the material in this 
e-mail is strictly forbidden.___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Newbie vs. laziness

2007-03-20 Thread Alex Queiroz

Hallo,

On 3/20/07, Jules Bean <[EMAIL PROTECTED]> wrote:


What $! does is force its arguments into WHNF before applying the
function. WHNF means, roughly, either a lambda or a constructor at the
top-level.



I think I got it now.



However that's a bit clumsy. What kind of error are you seeing when you
say 'it crashes'?



I must fetch all rows of the result, otherwise the database will
be in an inconsistent state and all subsequent queries crash the
application. Fetching all rows automatically finishes the previous
statement, so I must evaluate the spine of the list.

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


Re: [Haskell-cafe] Newbie vs. laziness

2007-03-20 Thread Jules Bean

Alex Queiroz wrote:

quickQuery returns a lazy list of results, and I expected ($!) to make
it strict. But my program crashes if I use it this way. But, if I add
a print to the function:


'Making things strict' isn't that simple.

What $! does is force its arguments into WHNF before applying the 
function. WHNF means, roughly, either a lambda or a constructor at the 
top-level.


In terms of your list (ids) you are forcing it to either (:) or [] at 
the top level (the two list constructors). So you force the 'top layer' 
of the list; you check if it's empty or not.


If you want to force the whole spine of the list (that's the shape but 
not the values) then (length ids) `seq` return () would do that.


However that's a bit clumsy. What kind of error are you seeing when you 
say 'it crashes'?


It looks to me like your program creates a lazily generated list in the 
DB monad which looks superficially like a sensible thing to do.


Jules

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


[Haskell-cafe] Newbie vs. laziness

2007-03-20 Thread Alex Queiroz

Hallo list,

I don't quite get how ($!) works. I have this function:

dbCreateIndices con dtn dof = do
  let dummy = newDbItem
  let query = "SELECT id FROM " ++ (dtn dummy) ++ " ORDER BY " ++ (dof dummy)
  ids <- liftM (map fromSql . concat ) $! quickQuery con query []
  return $ IntMap.fromList $ zip ids [0..]

quickQuery returns a lazy list of results, and I expected ($!) to make
it strict. But my program crashes if I use it this way. But, if I add
a print to the function:

dbCreateIndices con dtn dof = do
  let dummy = newDbItem
  let query = "SELECT id FROM " ++ (dtn dummy) ++ " ORDER BY " ++ (dof dummy)
  ids <- liftM (map fromSql . concat ) $! quickQuery con query []
  print ids
  return $ IntMap.fromList $ zip ids [0..]

print makes the ids list strict and all is well. How is the correct
way to use ($!) ?

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