如何使用 Monad.Writer 进行跟踪?

Posted

技术标签:

【中文标题】如何使用 Monad.Writer 进行跟踪?【英文标题】:How to use Monad.Writer for tracing? 【发布时间】:2016-10-02 17:07:32 【问题描述】:

我的代码如下所示:

我想在 tokenize 函数中使用 tell 来写入同一个 Writer Monad。这可能吗?

tokenize :: T.Text -> T.Text -> [Token]
tokenize t token
   | T.null t = addToken token []
   | h == ' ' = addToken token (tokenize r "")
   | h == '"' = let (t', r') = consumeString r
                in addToken t' (tokenize r' "")
   | otherwise = tokenize r (T.snoc token h)
   where h = T.head t
         r = T.tail t

parse :: [T.Text] -> W.Writer String [Token]
parse lines = do
    let x = concatMap (\l -> tokenize l "") lines
    W.tell "hello"
    return x

main :: IO ()
main = do
    content <- readContent
    let lines = toTextList content
    let (res, log) = W.runWriter $ parse lines
    forM_ res $ \x ->
        print x
    print log

【问题讨论】:

一个选项可以是使用x &lt;- concat &lt;$&gt; mapM (\l -&gt; tokenize l "") lines 并以一元方式重写tokenize。我对此不太满意,因为我们失去了concatMap 的出色流媒体性能。我想知道是否可以以某种方式制作 monadic 版本来保留流,知道我们在这里使用 writer monad... @chi 我没有想到性能影响。将concatMapM 定义为折叠是否有帮助? @user2297560 我不认为高效的concatMapM 在处理通用单子时可以存在。在作家的具体情况下......我不知道。 【参考方案1】:

您只需要将tokenize 的结果提升到Writer

tokenize :: T.Text -> T.Text -> W.Writer [Token]
tokenize t token
   | T.null t = return $ addToken token []
   | h == ' ' = return $ addToken token (tokenize r "")
   | h == '"' = let (t', r') = consumeString r
                in return $ addToken t' (tokenize r' "")
   | otherwise = return $ tokenize r (T.snoc token h)
   where h = T.head t
         r = T.tail t

然后parse 必须更改以处理来自tokenize 的一元结果:

parse :: [T.Text] -> W.Writer String [Token]
parse lines = do
    x <- concat <$> mapM (\l -> tokenize l "") lines
    W.tell "hello"
    return x

【讨论】:

以上是关于如何使用 Monad.Writer 进行跟踪?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用映射文件对 Android 堆栈跟踪进行去混淆处理

如何使用视频对物体进行运动跟踪? [关闭]

如何存储位置数据以使用核心数据进行跟踪?

如何使用代码进行 java 对象分配跟踪

使用 System.Net.HttpClient 进行上传时如何跟踪进度? [复制]

如何使用wps宏进行大批量物流跟踪