如何建模依赖于流中特定元素的计算?

时间:2014-08-11 15:15:56

标签: haskell conduit

我目前正在编写一个程序来分析从多个tar档案中收集的文件。我使用的是conduit,相关代码是here。这是一个示例计算:

unixVersion :: Require T.Text BSL.ByteString UnixVersion
unixVersion =   (parseRedhat <$> requireText "/etc/redhat-release")
            <|> (parseSuse   <$> requireText "/etc/SuSE-release")
            <|> ....

目标是每次越过相关的流事件时,所有这些计算都会“高级”(在前面的示例中,这将是与/etc/redhat-release/etc/SuSE-release对应的tar条目。)< / p>

使用这种功能的“完整”示例可能是:

tarStream "/path/to/tar.gz" =$ withRequirement [listcve] fst snd
                            =$ CL.concat
                            $$ CL.consume  

-- given the version of an OS and a list of installed packages, gives the CVEs
-- affecting this host.
listcve :: Require FilePath BSL.ByteString [CVE]
listcve = listCVEs <$> (cvelist <$> unixVersion)
                   <*> (T.lines <$> requireText "/soft/packages.lst")
    where
        listCVEs cvelist packages = ....
        cvelist v = case v of
                       REDHAT -> redhatCVEs
                       _      -> defaultCVEs

这个人为的例子只有一个计算,但我的最终程序将有大约30个,有几个“共享”计算(如unixVersion)。为了实现这一点,我决定我需要一种方法来知道流的给定元素是否容易被这些Require计算中的一个请求。这意味着我需要一个像:

这样的函数
getRequirements :: Require a b c -> S.Set a

不幸的是,这可能意味着Require a b最多只能是Applicative,永远不会是Monad

然后有withRequirement函数,其类型为:

withRequirement :: (Ord identifier, Eq identifier, Monad m)
                => [Require identifier content x] -- ^ The list of dependent computations
                -> (a -> identifier)              -- ^ Extracting the identifier
                -> (a -> m content)               -- ^ Extracting the content, possibly with effects
                -> Conduit a m x

这就像需求列表中的解释器一样。

无论如何,这是我的问题:

  • 如何对这些计算进行建模以实现共享?例如,unixVersion分析器被其他几个分析仪使用。在我目前的实现中,它们为每个实现重新计算。
  • 有没有办法让Monad接口,但不要尝试为每个流条目运行每个分析器?

0 个答案:

没有答案