[Haskell-beginners] A better way?

Keith Sheppard keithshep at gmail.com
Sat Feb 21 18:52:35 EST 2009


Hello Patrick,

I renamed your function  maxTableColumnWidths to match up with my
naming. It seems to work except that it suffers from the same problem
as my 1st implementation when you feed it a table that has many rows:

*Table.IO>  maxTableColumnWidths (replicate 1000000 ["hello", "world"])
*** Exception: stack overflow

Thanks,
Keith

On Sat, Feb 21, 2009 at 5:54 PM, Patrick LeBoutillier
<patrick.leboutillier at gmail.com> wrote:
> Hi,
>
> I came up with this, which seems to work well if all your rows have
> the same number of fields:
>
> maxRowFieldWidths :: [[String]] -> [Int]
> maxRowFieldWidths rows = foldr rowMax zeros rows
>  where rowMax fields maxes = zipWith (\f m -> max (length f) m) fields maxes
>        zeros = 0 : zeros
>
> foldr is the key here, which allows you to "accumulate" the results of
> computations. In this case the accumulator is the list of all the
> maximums found so far. The initial value for the accumulator is an
> (infinite) list made up on only zeros. Haskell will generate only as
> much as it needs.
>
>
> Patrick
>
>
>
> On Sat, Feb 21, 2009 at 4:35 PM, Keith Sheppard <keithshep at gmail.com> wrote:
>> Hello,
>>
>> I'm new to haskell and still getting used to working with lazy
>> evaluation. I created a little function to calculate column widths for
>> a 2D list of strings (a table) by iterating through the list and
>> accumulating a max value for each column. My initial implementation
>> ran out memory for tables with many rows because of lazy evaluation
>> and here is how I dealt with it:
>>
>> {- |
>> for a table, calculate the max width in characters for each column
>> -}
>> maxTableColumnWidths :: [[String]] -> [Int]
>> maxTableColumnWidths [] = []
>> maxTableColumnWidths table =
>>    maxTableColumnWidthsInternal table []
>>
>> maxTableColumnWidthsInternal :: [[String]] -> [Int] -> [Int]
>> maxTableColumnWidthsInternal [] prevMaxValues = prevMaxValues
>> maxTableColumnWidthsInternal (row:tableTail) prevMaxValues
>>    | seqList prevMaxValues = undefined
>>    | otherwise = maxTableColumnWidthsInternal tableTail
>> (maxRowFieldWidths row prevMaxValues)
>>
>> -- this little function is for making the list strict... otherwise
>> -- we run out of memory
>> seqList [] = False
>> seqList (head:tail)
>>    | head `seq` False = undefined
>>    | otherwise = seqList tail
>>
>> maxRowFieldWidths :: [String] -> [Int] -> [Int]
>> maxRowFieldWidths row prevMaxValues =
>>    let colLengths = map length row
>>        lengthOfRow = length row
>>        lengthOfPrevMax = length prevMaxValues
>>        maxPrefixList = zipWith max colLengths prevMaxValues
>>    in
>>        if lengthOfRow == lengthOfPrevMax then
>>            maxPrefixList
>>        else if lengthOfRow > lengthOfPrevMax then
>>            maxPrefixList ++ (drop lengthOfPrevMax colLengths)
>>        else
>>            maxPrefixList ++ (drop lengthOfRow prevMaxValues)
>>
>>
>> This works but it isn't very pretty (maybe also inefficient?). Is
>> there a better way to deal with this kind of memory issue?
>>
>> Thanks!
>> Keith
>> _______________________________________________
>> Beginners mailing list
>> Beginners at haskell.org
>> http://www.haskell.org/mailman/listinfo/beginners
>>
>
>
>
> --
> =====================
> Patrick LeBoutillier
> Rosemère, Québec, Canada
>


More information about the Beginners mailing list