Byt*_*ter 6 haskell state-monad monad-transformers
为了理解如何使用monad变换器,我编写了以下代码而没有一个.它逐行读取标准输入并显示每条反转线,直到遇到空行.它还使用行计算行数,State最后显示总数.
import Control.Monad.State
main = print =<< fmap (`evalState` 0) go where
go :: IO (State Int Int)
go = do
l <- getLine
if null l
then return get
else do
putStrLn (reverse l)
-- another possibility: fmap (modify (+1) >>) go
rest <- go
return $ do
modify (+1)
rest
Run Code Online (Sandbox Code Playgroud)
我想在每行之前添加当前行号.我能够做到StateT:
import Control.Monad.State
main = print =<< evalStateT go 0 where
go :: StateT Int IO Int
go = do
l <- lift getLine
if null l
then get
else do
n <- get
lift (putStrLn (show n ++ ' ' : reverse l))
modify (+1)
go
Run Code Online (Sandbox Code Playgroud)
我的问题是:如何在没有monad变换器的版本中做同样的事情?
Dan*_*ner 10
你遇到的问题是,手动展开StateT s IO a是s -> IO (s, a),不是IO (s -> (s, a))!一旦掌握了这些洞察力,就可以很容易地看到如何做到这一点:
go :: Int -> IO (Int, Int)
go s = do
l <- getLine
if null l
then return (s, s)
else do
putStrLn (show s ++ ' ' : reverse l)
go (s+1)
Run Code Online (Sandbox Code Playgroud)
您只需要在每一行上运行累积状态计算。这是 O(n\xc2\xb2) 时间,但由于您的第一个程序已经使用 O(n) 空间,所以这并不算太糟糕。当然,这种StateT方法几乎在各个方面都是优越的!如果你真的想“手动”完成而不付出效率代价,那么只需手动管理状态,而不是根本构建状态转换器。State使用而不是确实没有得到任何好处Int在第一个程序中
| 归档时间: |
|
| 查看次数: |
214 次 |
| 最近记录: |