Using existential types

oleg at pobox.com oleg at pobox.com
Fri Oct 10 13:00:03 EDT 2003


Tim Docker wrote:

>  > data ColDesc rowv = forall a.
>  >      ColDesc (rowv -> a) ([a] -> a) (a -> String)
>  > 
>  > calculate :: [rowv] -> ColDesc rowv ->  ([String],String)
>  > calculate rs (ColDesc valf sumf fmtf) =
>  >      let vals = map valf rs in
>  >         (map fmtf vals, (fmtf.sumf)  vals)

> This code only does the (rowv -> a) evaluation once

Sorry I didn't know of that requirement. The desired sharing can easily
be introduced:

> data Results = Results { formatted:: [String], aggregated:: String }

> type ColDesc rowv = [rowv] -> Results

> calculate :: [rowv] -> ColDesc rowv ->  ([String],String)
> calculate rs transformer = (formatted res, aggregated res)
>   where res = transformer rs

> rows = ["I","wish","to","define","a","report"]

> mapp g f = g . (map f)

> cols = [
>     \rvs -> Results rvs "",
>     \rvs -> let vals = map length rvs
>             in Results (map show vals) (show$sum vals),
>     \rvs -> let vals = map (\s -> length s * length s) rvs
>             in Results (map show vals) (show$maximum vals)
>     ]

> values = [ calculate rows col | col <- cols ]

If we just need to format one value, we can write
> format_value v transformer = formatted $ transformer [v]

Due to laziness, the aggregate function will not be computed, unless
specifically requested.


More information about the Haskell-Cafe mailing list