jos*_*uan 3 haskell monad-transformers
让State'我的程序状态包含一些数据.
type State' m a = StateT Int m a
Run Code Online (Sandbox Code Playgroud)
我会在一些计算中使用它.
例子:
-- genData, return some string (using Int value and State')
genData :: Int -> State' String
genData n = ...
-- genDatas, return multiple strings
genDatas :: Int -> State' [String]
genDatas n = mapM genData [1..n]
-- printLog, write log message (enumerating lines)
printLog :: String -> State' IO ()
printLog msg = do
n <- get
let n' = n + 1
put n'
liftIO $ putStrLn $ "Message #" ++ (show n') ++ ": " ++ msg
Run Code Online (Sandbox Code Playgroud)
我认为这不是正确的做法:
-- If I need a "in context function" returning a Int value...
--
-- addExtra, return current Int in state plus x
addExtra :: Int -> State' Identity Int
addExtra x = get >>= return.(+x)
Run Code Online (Sandbox Code Playgroud)
要addExtra在一些monad上下文中使用我的函数,我会这样做:
doComplex :: State' IO ()
doComplex = do
printLog "Starting process..."
-- It's ugly!
s <- get
Identity (w, s') <- return $ runStateT (addExtra 5) s
put s' -- save state
printLog $ "computed value: " ++ (show w)
Run Code Online (Sandbox Code Playgroud)
以State'不同的方式分享我的monad 的正确方法是什么?(正如IO a所做)
谢谢!
(我已经阅读了一些教程和一些源代码,但我无法理解)
由于您的addExtra函数实际上并没有对底层monad执行任何操作,因此您只需更改类型签名以使其与monad无关:
addExtra :: Monad m => Int -> State' m Int
addExtra x = get >>= return . (+x)
Run Code Online (Sandbox Code Playgroud)
现在你可以写这个
doComplex :: State' IO ()
doComplex = do
printLog "Starting process..."
w <- addExtra 5
printLog $ "Computed value: " ++ show w
Run Code Online (Sandbox Code Playgroud)
哪个更漂亮,就像你的旧代码一样:
*Main> runStateT doComplex 0
Message #1: Starting process...
Message #2: Computed value: 6
((),2)
Run Code Online (Sandbox Code Playgroud)
我可能想要重写addExtra为以下之一.首先,要么使用表示法
addExtra x = do s <- get
return (s + x)
Run Code Online (Sandbox Code Playgroud)
或使用liftM,因为我们并没有真正使用我们有monad的事实
addExtra x = liftM (+x) get
Run Code Online (Sandbox Code Playgroud)
甚至使用gets(感谢Daniel Wagner在评论中)
addExtra x = gets (+x)
Run Code Online (Sandbox Code Playgroud)
当然,到目前为止,您可能不需要额外的功能.你也可以写
doComplex = do printLog "Starting process..."
w <- gets (+5)
printLog $ "Computed value: " ++ show w
Run Code Online (Sandbox Code Playgroud)
同样,我可能会重写printLog.如果你发现自己get处于状态,对它做某些事情,然后put把它拿回去,你可能只想使用它modify.
printLog msg = do modify (+1)
n <- get
liftIO . putStrLn $ "Message #" ++ show n ++ ": " ++ msg
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
107 次 |
| 最近记录: |