簡體   English   中英

使用Operational Monad實現的編寫器無法正常工作

[英]Writer implemented with Operational Monad does not work lazily

我使用Operational Monad方法編寫了具有Writer功能的monad。 然后,我注意到它並不懶惰。

在下面的代碼中,有一個rogueWriter執行無限多的語句,每個語句都寫入一個字符串。 該程序不會終止,僅需要無限輸出的某些字符。

經過分析后,我注意到流氓作家實際上非常友好(哈哈),因為當我從runMyWriter rogueWriter更改為runWriter rogueWriter ,一切進展順利。

問題:

  1. 如何最好地解釋這種行為?
  2. 我應該如何更改代碼才能使其正常工作?
  3. 哪些monad變壓器SomeMonadT出現相同的問題
    SomeMonadT Writer w WriterT w SomeMonad (也許有一些例子?)

編輯:是否有可能我要在這里反轉無限字符串? Sjoerd Visscher的解決方案與我的解決方案之間的顯着區別是

w `mappend` ws  resp.  ws `mappend` w

碼:

{-# LANGUAGE GADTs, FlexibleContexts, TypeSynonymInstances,
                    FlexibleInstances, MultiParamTypeClasses #-}

module Writer where

import Control.Monad.Identity
import Control.Monad.Operational
import Control.Monad.Writer
import Data.Monoid

data MyWriterI w a where
    Tell :: w -> MyWriterI w ()

type MyWriterT w = ProgramT (MyWriterI w)

type MyWriter w = (MyWriterT w) Identity

runMyWriterT :: (Monad m, Monoid w) => MyWriterT w m a -> m (a, w)
runMyWriterT prog = run prog mempty
  where
    run prog ws = viewT prog >>= flip eval ws
    eval (Return a)       ws = return (a, ws)
    eval (Tell w :>>= is) ws = run (is ()) (ws `mappend` w)

runMyWriter :: (Monoid w) => MyWriter w a -> (a, w)
runMyWriter prog = runIdentity (runMyWriterT prog)

instance (Monad m, Monoid w) => MonadWriter w (MyWriterT w m) where
    tell   = singleton . Tell
    listen = undefined
    pass   = undefined

-- Demonstration of the problem:

rogueWriter :: MonadWriter String m => m ()
rogueWriter = mapM_ (tell . show) [1..]

main = let (_, infiniteOutput) = runMyWriter rogueWriter
       in putStrLn (take 20 infiniteOutput)

我不知道為什么您的程序會失敗,但這就是我的寫法:

runMyWriterT prog = run prog
  where
    run prog = viewT prog >>= eval
    eval (Return a)       = return (a, mempty)
    eval (Tell w :>>= is) = do
      ~(r, ws) <- run (is ())
      return (r, w `mappend` ws)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM