[Haskell-cafe] how to write a loop in haskell way

Mihai Maruseac mihai.maruseac at gmail.com
Sun Dec 19 11:45:19 CET 2010


On Sun, Dec 19, 2010 at 12:27 PM, ender <crazyender at gmail.com> 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"

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



More information about the Haskell-Cafe mailing list