如何使用Monad.Writer进行跟踪?
问题描述:
我的代码如下所示:如何使用Monad.Writer进行跟踪?
我想在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
答
你只需要的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
办法之一使用'x mapM(\ l - > tokenize l“”)行并且以单子方式重写'tokenize'。我对此并不满意,因为我们失去了'concatMap'的流媒体性能。我想知道是否可以使monadic版本以某种方式保存流媒体,知道我们在这里使用作家monad ... – chi
@chi我没有想到性能影响。将'concatMapM'定义为折叠有帮助吗? – user2297560
@ user2297560在处理通用monad时,我不认为有效的'concatMapM'可以存在。在作家的具体情况下......我不知道。 – chi