Here is a type I'm using to record stats.
data UserzFormationViews
= UserzFormationViews
{ formationsViewed :: [(FormationId, UTCTime)]
, ...
}
Basically, the data is a monoid. Actually, it's even less restrictive than that, because the monoidal append on this piece of data is commutative (i.e. embarrassingly parallel). It's incredibly convenient to be able to just throw a pile of these together and tabulate the stats with a familiar mconcat
.
At other times, it's useful to get all the user's views, in a form like this:
class RetrieveViews a where
getViews :: a -> [(UserId,FormationId,UTCTime)]
This obviously messes with the monoidal definition of UserzFormationViews. The initial object (i.e. mempty
) would need a dummy value for the UserId. In more primitive languages, you'd just leave that as NULL, which is a dirty hack. And we don't like those kinds of dirty hacks in Haskell. What do we do instead?
instance RetrieveViews (UserId, UserzFormationViews) where
...
vs = getViews (zeUserzId,zeUserzViews)
So wrong and so awesome at the same time. :)
No comments:
Post a Comment