【问题标题】:A Stricter Control.Monad.Trans.Writer.Strict更严格的 Control.Monad.Trans.Writer.Strict
【发布时间】:2014-11-03 03:22:30
【问题描述】:

所以我们有:

import Control.Monad.Writer.Strict

type M a = Writer (Map Key Val) a

对于一些KeyVal

只要我们不查看收集的输出,一切正常:

report comp = do
  let (a,w) = runWriter comp
  putStrLn a

但是,如果我们要检查 w,就会出现堆栈溢出。

 report comp = do
   let (a,w) = runWriter comp
   guard (not $ null w) $ do -- forcing w causes a stack overflow
     reportOutputs w
   putStrLn a

我认为原因是因为(>>=) for Writer is defined as

m >>= k  = WriterT $ do
    (a, w)  <- runWriterT m
    (b, w') <- runWriterT (k a)
    return (b, w `mappend` w')

如果我有一个大的Writer a 计算,它会建立一个很长的mappends 序列:w &lt;&gt; (w' &lt;&gt; (w'' &lt;&gt; ...)),在这种情况下,这是一个Map.union,它在地图的脊椎中是严格的。因此,如果我建立了大量的联合,则必须在我强制 Map 溢出堆栈时立即评估整个事情。

我们想要的是尽早执行联合。我们想要一个更严格的 Strict.Writer:

m >>= k = WriterT $ do
    (a, w) <- runWriterT m
    (b, w') <- runWriterT (k a)
    let w'' = w `mappend` w'
    w'' `seq` return (b, w'')

所以我的问题是:这是否存在于某些“标准”库中?如果没有,为什么不呢?

【问题讨论】:

  • 这在Space leak in Pipes with RWST 中已经遇到过,但是我没有关于“标准库”问题的答案。 “为什么不”可能太自以为是了。
  • 好吧,“为什么不”主要是期待诸如“它不在图书馆中,因为当你把它变得过于严格时你违反了单子法则”或一些类似的技术原因。不像“因为[意见]”。

标签: haskell lazy-evaluation monad-transformers strictness


【解决方案1】:

您的问题的直接答案是:不,没有提供此功能的标准库。此外,您提出的版本仍然会泄漏。我知道的唯一不泄漏的版本是使用严格的StateT 模拟WriterT。我写了一个非常详细的e-mail about this to the Haskell libraries mailing list,比较了几种实现的严格性和性能。长话短说:将WriterT 实现为严格的StateT 不仅可以消除空间泄漏,还可以生成非常高效的代码。

这是有效的实现:

newtype WriterT w m a = WriterT { unWriterT :: w -> m (a, w) }

instance (Monad m, Monoid w) => Monad (WriterT w m) where
    return a = WriterT $ \w -> return (a, w)
    m >>= f  = WriterT $ \w -> do
        (a, w') <- unWriterT m w
        unWriterT (f a) w'

runWriterT :: (Monoid w) => WriterT w m a -> m (a, w)
runWriterT m = unWriterT m mempty

tell :: (Monad m, Monoid w) => w -> WriterT w m ()
tell w = WriterT $ \w' ->
    let wt = w `mappend` w'
     in wt `seq` return ((), w `mappend` w')

我希望看到它在某个时候添加到 transformers,但有一些小问题需要解决(例如,模块名称应该是什么)。

【讨论】:

  • 现在可以作为库使用吗?
  • @user3237465 有writer-cps-mtl(或writer-cps-full,如果您需要一些额外的lensmmorph 实例)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-20
  • 2013-11-17
  • 2011-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多