how to write a loop in haskell way

Hi all: I'v been learning haskell for several months, and now I'm trying to write some "real word" program in haskell, like finding files under one directory or something My problem is that, I dont know the way of writing a loop in haskell. I searched google and found some code that translate c loop into haskell like this one:
I am new to haskell and would look to write a function equivalent to the following loop in C
int value = 500000; int part_stack[4]; int *part_ptr = part_stack; for (; value; value /= 10000) *part_ptr++ = value % 10000;
part_stack :: [Int] part_stack = [0,50]
Note that I've performed a memoization optimization--this makes the code both smaller, faster and easier to read! :P
Ignore David, he's pulling your leg. Here's the proper translation:
do alloca $ \value -> do poke value (500000::Int) allocaArray 4 $ \part_stack -> do alloca $ \part_ptr -> do poke part_ptr part_stack let loop = do val <- peek value if val == 0 then return () else do p <- peek part_ptr poke p (val `rem` 10000) poke part_ptr (p `plusPtr` 1) poke value (val `quot` 10000) loop loop
and I really think that's not a "haskell way", it's just translate c code into haskell code byte by byte My question is: how to translate above c code into haskell in "haskell way" Thanks and BR Ender

On Sun, 19 Dec 2010, ender wrote:
do alloca $ \value -> do poke value (500000::Int) allocaArray 4 $ \part_stack -> do alloca $ \part_ptr -> do poke part_ptr part_stack let loop = do val <- peek value if val == 0 then return () else do p <- peek part_ptr poke p (val `rem` 10000) poke part_ptr (p `plusPtr` 1) poke value (val `quot` 10000) loop loop
and I really think that's not a "haskell way", it's just translate c code into haskell code byte by byte My question is: how to translate above c code into haskell in "haskell way"
If the count of loop runs does not depend on results of the loop body, then 'mapM' and 'mapM_' applied to the list of increasing pointers are your friends. In your case, the loop aborts when 'val' becomes zero. I'm certainly thinking too complicated, but you might use MaybeT IO () (e.g. from transformers package) and abort 'mapM_' with 'mzero' when 'val' becomes zero. (MaybeT IO a) is like an IO monad with an early exit (somehow an exception) option.

2010/12/19 Henning Thielemann
On Sun, 19 Dec 2010, ender wrote:
do alloca $ \value -> do poke value (500000::Int) allocaArray 4 $ \part_stack -> do alloca $ \part_ptr -> do poke part_ptr part_stack let loop = do val <- peek value if val == 0 then return () else do p <- peek part_ptr poke p (val `rem` 10000) poke part_ptr (p `plusPtr` 1) poke value (val `quot` 10000) loop loop
and I really think that's not a "haskell way", it's just translate c code into haskell code byte by byte My question is: how to translate above c code into haskell in "haskell way"
If the count of loop runs does not depend on results of the loop body, then 'mapM' and 'mapM_' applied to the list of increasing pointers are your friends. In your case, the loop aborts when 'val' becomes zero. I'm certainly thinking too complicated, but you might use MaybeT IO () (e.g. from transformers package) and abort 'mapM_' with 'mzero' when 'val' becomes zero. (MaybeT IO a) is like an IO monad with an early exit (somehow an exception) option.
Hi Henning: Thanks for your quick reply. So recursive and monad is the proper way to simulate loop,right? Thanks and BR

Recursion replaces loops. If it needs to be monadic or not depends on what
you want to do.
On Sun, Dec 19, 2010 at 10:53 AM, ender
2010/12/19 Henning Thielemann
: On Sun, 19 Dec 2010, ender wrote:
do alloca $ \value -> do poke value (500000::Int) allocaArray 4 $ \part_stack -> do alloca $ \part_ptr -> do poke part_ptr part_stack let loop = do val <- peek value if val == 0 then return () else do p <- peek part_ptr poke p (val `rem` 10000) poke part_ptr (p `plusPtr` 1) poke value (val `quot` 10000) loop loop
and I really think that's not a "haskell way", it's just translate c code into haskell code byte by byte My question is: how to translate above c code into haskell in "haskell way"
If the count of loop runs does not depend on results of the loop body,
then
'mapM' and 'mapM_' applied to the list of increasing pointers are your friends. In your case, the loop aborts when 'val' becomes zero. I'm certainly thinking too complicated, but you might use MaybeT IO () (e.g. from transformers package) and abort 'mapM_' with 'mzero' when 'val' becomes zero. (MaybeT IO a) is like an IO monad with an early exit (somehow an exception) option.
Hi Henning: Thanks for your quick reply. So recursive and monad is the proper way to simulate loop,right?
Thanks and BR
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On 19 December 2010 21:53, ender
Thanks for your quick reply. So recursive and monad is the proper way to simulate loop,right?
Well, recursion (either explicitly or implicitly via map, fold, etc.) rather than iteration (i.e. a loop) is the usual approach in Haskell. -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com

On Sun, 19 Dec 2010, ender wrote:
Hi Henning: Thanks for your quick reply. So recursive and monad is the proper way to simulate loop,right?
I kept close to your suggestion, but avoiding monads, especially IO, is a good idea. If you do not need low-level memory access with peek and poke, better use lists or arrays (high level) or StorableVector (more efficient but not as flexible as array). http://www.haskell.org/haskellwiki/Avoiding_IO Avoiding explicit recursion is also a good thing - using too much (tail) recursive function calls ends up looking like code with lots of GOTOs. Better use higher order functions. http://www.haskell.org/haskellwiki/Haskell_programming_tips#Avoid_explicit_r...

On Sun, Dec 19, 2010 at 12:27 PM, ender
Hi all: I'v been learning haskell for several months, and now I'm trying to write some "real word" program in haskell, like finding files under one directory or something My problem is that, I dont know the way of writing a loop in haskell. I searched google and found some code that translate c loop into haskell like this one:
I am new to haskell and would look to write a function equivalent to the following loop in C
int value = 500000; int part_stack[4]; int *part_ptr = part_stack; for (; value; value /= 10000) *part_ptr++ = value % 10000;
part_stack :: [Int] part_stack = [0,50]
Note that I've performed a memoization optimization--this makes the code both smaller, faster and easier to read! :P
Ignore David, he's pulling your leg. Here's the proper translation:
do alloca $ \value -> do poke value (500000::Int) allocaArray 4 $ \part_stack -> do alloca $ \part_ptr -> do poke part_ptr part_stack let loop = do val <- peek value if val == 0 then return () else do p <- peek part_ptr poke p (val `rem` 10000) poke part_ptr (p `plusPtr` 1) poke value (val `quot` 10000) loop loop
and I really think that's not a "haskell way", it's just translate c code into haskell code byte by byte My question is: how to translate above c code into haskell in "haskell way"
Hi, Usually, loops are translated in recursion or higher order functions (maps, folds, scans). To generate a list from a number, use functions like iterate or repeat. To end the iterate, use a function from the takeWhile family. My translation of the above would be (no type signatures because I'm lazy right now): valueTrim x = div x 10000 valueGet x = mod x 100000 f x = map valueGet $ takeWhile (/= 0) $ iterate valueTrim x (call with f 500000) Reading the last line, you have a very concise description: trim x until it becomes 0 and apply valueGet to each of the results. -- Mihai

On 19 December 2010 21:27, ender
Hi all: I'v been learning haskell for several months, and now I'm trying to write some "real word" program in haskell, like finding files under one directory or something My problem is that, I dont know the way of writing a loop in haskell. I searched google and found some code that translate c loop into haskell like this one:
I am new to haskell and would look to write a function equivalent to the following loop in C
int value = 500000; int part_stack[4]; int *part_ptr = part_stack; for (; value; value /= 10000) *part_ptr++ = value % 10000;
part_stack :: [Int] part_stack = [0,50]
Note that I've performed a memoization optimization--this makes the code both smaller, faster and easier to read! :P
Ignore David, he's pulling your leg. Here's the proper translation:
do alloca $ \value -> do poke value (500000::Int) allocaArray 4 $ \part_stack -> do alloca $ \part_ptr -> do poke part_ptr part_stack let loop = do val <- peek value if val == 0 then return () else do p <- peek part_ptr poke p (val `rem` 10000) poke part_ptr (p `plusPtr` 1) poke value (val `quot` 10000) loop loop
and I really think that's not a "haskell way", it's just translate c code into haskell code byte by byte My question is: how to translate above c code into haskell in "haskell way"
Short answer: you don't. Longer answer: have a read through http://book.realworldhaskell.org/read/io-case-study-a-library-for-searching-... -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com

2010/12/19 Ivan Lazar Miljenovic
On 19 December 2010 21:27, ender
wrote: Hi all: I'v been learning haskell for several months, and now I'm trying to write some "real word" program in haskell, like finding files under one directory or something My problem is that, I dont know the way of writing a loop in haskell. I searched google and found some code that translate c loop into haskell like this one:
I am new to haskell and would look to write a function equivalent to the following loop in C
int value = 500000; int part_stack[4]; int *part_ptr = part_stack; for (; value; value /= 10000) *part_ptr++ = value % 10000;
part_stack :: [Int] part_stack = [0,50]
Note that I've performed a memoization optimization--this makes the code both smaller, faster and easier to read! :P
Ignore David, he's pulling your leg. Here's the proper translation:
do alloca $ \value -> do poke value (500000::Int) allocaArray 4 $ \part_stack -> do alloca $ \part_ptr -> do poke part_ptr part_stack let loop = do val <- peek value if val == 0 then return () else do p <- peek part_ptr poke p (val `rem` 10000) poke part_ptr (p `plusPtr` 1) poke value (val `quot` 10000) loop loop
and I really think that's not a "haskell way", it's just translate c code into haskell code byte by byte My question is: how to translate above c code into haskell in "haskell way"
Short answer: you don't.
Longer answer: have a read through http://book.realworldhaskell.org/read/io-case-study-a-library-for-searching-...
-- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com
Great! That's exactly what I want, thanks a lot
participants (5)
-
ender
-
Henning Thielemann
-
Ivan Lazar Miljenovic
-
Lennart Augustsson
-
Mihai Maruseac