Multi groupby with foldl' and Map.insertWithKey

I'd say the cleanest way to go is to split your Info data structure into an intermediate key and a value part like so: type Key = String data Value = Value {count :: !Int, healthTopics :: ![String]} keyvalue :: Info -> (Key,Value) keyvalue (Info _ h k) = (k,Value 1 [h]) and give Value a Monoid instance: instance Monoid Value where mempty = Value 0 [] mappend (Value c s) (Value c' s') = Value (c+c') (s++s') (Or you could use (Sum Int) instead of Int and have type Value = (Sum Int,[String]). Then the Monoid instance is derived for you.) Now you can transform a list of Infos into a Map using a generic function: makeMap :: [Info] -> M.Map Key Value makeMap = M.fromListWith mappend . map keyvalue Semantically, it's pretty identical to ALeX Kazik's suggestion of using foldl' and alter. Internally, fromListWith uses a strict fold, so strictness should be the same as using foldl'. Olaf

On Wed, Dec 28, 2016 at 8:07 AM, Olaf Klinke
I'd say the cleanest way to go is to split your Info data structure into an intermediate key and a value part like so:
type Key = String data Value = Value {count :: !Int, healthTopics :: ![String]}
keyvalue :: Info -> (Key,Value) keyvalue (Info _ h k) = (k,Value 1 [h])
and give Value a Monoid instance:
instance Monoid Value where mempty = Value 0 [] mappend (Value c s) (Value c' s') = Value (c+c') (s++s')
(Or you could use (Sum Int) instead of Int and have type Value = (Sum Int,[String]). Then the Monoid instance is derived for you.)
A caution on this alternative: the first component of the tuple won't be strict enough and you'll leak space. I think the proposed solution is better. Note that you *don't* necessarily need the strictness annotation on healthTopics – this shifts around when the list append gets run but won't change space much. -Jan-Willem Maessen
Now you can transform a list of Infos into a Map using a generic function:
makeMap :: [Info] -> M.Map Key Value makeMap = M.fromListWith mappend . map keyvalue
Semantically, it's pretty identical to ALeX Kazik's suggestion of using foldl' and alter. Internally, fromListWith uses a strict fold, so strictness should be the same as using foldl'.
Olaf _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

Am 28.12.2016 um 19:40 schrieb Jan-Willem Maessen
: A caution on this alternative: the first component of the tuple won't be strict enough and you'll leak space. I think the proposed solution is better. Note that you *don't* necessarily need the strictness annotation on healthTopics – this shifts around when the list append gets run but won't change space much.
-Jan-Willem Maessen Thanks for clarifying this, Jan-Willem. So there ought to be stricter versions of the newtype wrappers in Data.Monoid. Even then, the tuple is not strict. Will that also leak space? I just thought the (Sum Int,[String]) type was a neat example of instance deriving.
Cheers, Olaf

On Wed, Dec 28, 2016 at 3:21 PM, Olaf Klinke
Am 28.12.2016 um 19:40 schrieb Jan-Willem Maessen
A caution on this alternative: the first component of the tuple won't be strict enough and you'll leak space. I think the proposed solution is better. Note that you *don't* necessarily need the strictness annotation on healthTopics – this shifts around when the list append gets run but won't change space much.
-Jan-Willem Maessen Thanks for clarifying this, Jan-Willem. So there ought to be stricter versions of the newtype wrappers in Data.Monoid. Even then, the tuple is not strict. Will that also leak space?
Yes, the fact that the tuple is strict means that Sum's strictness doesn't matter (and Sum is a newtype, so strictness doesn't really come into play).
I just thought the (Sum Int,[String]) type was a neat example of instance deriving.
Indeed! And if I were hacking up a one-shot script I'd probably do it that way.
Cheers, Olaf
participants (2)
-
Jan-Willem Maessen
-
Olaf Klinke