[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