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

Haskell 如何对依赖于流中特定元素的计算建模?,haskell,conduit,Haskell,Conduit,我目前正在编写一个程序,分析从多个tar档案中收集的文件。我使用的是导管,相关代码为。下面是一个示例计算: unixVersion :: Require T.Text BSL.ByteString UnixVersion unixVersion = (parseRedhat <$> requireText "/etc/redhat-release") <|> (parseSuse <$> requireText "/etc/Su

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

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

不幸的是,这可能意味着requireab最多只能是一个应用程序,永远不会是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 analyzer被其他几个分析仪使用。在我当前的实现中,它会为它们中的每一个重新计算。 有没有一种方法可以让Monad接口实现这个功能,而不必为每个流条目运行每个分析器?
现在还不太清楚需要什么。它是解析器吗?或者它应该代表某种有状态的计算,就像你说的推进它们一样?还有,你具体想分享什么?在什么人之间?我试图查看github页面,但没有多大帮助。它认为您可能希望将这些事情分开:有一个应用程序解析器,它也知道它需要的元素集,然后有一个解释器,它在事件流上运行这样一个解析器。还要注意,链接到github会使问题变得不自含——当您将另一个更改推送到repo时,链接将不再反映与答案对应的状态。链接到一个特定的提交会更好,但是项目/帐户仍然可以被删除/重命名,所以最好提取一段小的代码并直接放到问题中。我试着按照你的建议。Require不是解析器,它只是一个表示计算的树状数据类型。然后按照您的建议,由类似解释器的函数对其进行评估。它还可以被另一个返回所需标识符列表的函数遍历。
-- 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
getRequirements :: Require a b c -> S.Set a
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