【发布时间】:2012-05-18 22:50:45
【问题描述】:
很抱歉,这个问题描述太抽象了:这是为了我的工作,出于商业机密的原因,我不能给出现实世界的问题,只是一个抽象。
我有一个应用程序接收包含键值对的消息。键来自一组定义的关键字,每个关键字都有固定的数据类型。因此,如果“Foo”是整数,“Bar”是日期,您可能会收到如下消息:
Foo: 234
Bar: 24 September 2011
消息中可能包含任何键的子集。键的数量相当大(几十个)。但现在让我们坚持使用 Foo 和 Bar。
显然有这样的记录对应的消息:
data MyRecord {
foo :: Maybe Integer
bar :: Maybe UTCTime
-- ... and so on for several dozen fields.
}
记录使用“Maybe”类型,因为该字段可能尚未收到。
我还有许多需要从当前值(如果存在)计算的派生值。比如我想拥有
baz :: MyRecord -> Maybe String
baz r = do -- Maybe monad
f <- foo r
b <- bar r
return $ show f ++ " " ++ show b
其中一些功能很慢,所以我不想不必要地重复它们。我可以为每条新消息重新计算 baz 并以原始结构记录它,但如果一条消息保持 foo 和 bar 字段不变,那么这就是浪费 CPU 时间。相反,我可以在每次需要时重新计算 baz,但如果基础参数自上次以来没有改变,那又会浪费 CPU 时间。
我想要的是某种智能记忆或基于推送的重新计算,只有在参数发生变化时才会重新计算 baz。我可以通过注意到 baz 仅依赖于 foo 和 bar 来手动检测这一点,因此只根据更改这些值的消息重新计算它,但对于容易出错的复杂函数。
另一个问题是其中一些函数可能有多种策略。例如,您可能有一个可以使用 'mplus' 从 Foo 或 Bar 计算的值。
有人知道现有的解决方案吗?如果没有,我应该怎么做?
【问题讨论】:
-
一个明显的观点——你能接受由“已知”内在数据索引的 Map 中的派生数据,而不是在记录中嵌入这两种类型的数据吗?如果您可以像这样管理数据,那么考虑何时和如何重新计算会容易得多。
-
这将强制所有派生数据为同一类型,这可能意味着将其粉碎成一个字符串。它是一个后备位置,但不是我想要的。 OTOH 也许有一些涉及“forall”的解决方案可以解决这个问题。
标签: haskell