gpt4 book ai didi

haskell - 沿着不同的 "return type"函数定义和使用 StateT 的正确方法

转载 作者:行者123 更新时间:2023-12-02 10:48:09 26 4
gpt4 key购买 nike

State'成为我的程序状态和一些数据。

type State' m a = StateT Int m a

我会在一些计算中使用它。

示例:

-- 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

我认为这不是正确的方法:

-- 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)

要在某些 monad 上下文中使用我的 addExtra 函数,我这样做:

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)

沿着不同的函数共享我的 State' monad 的正确方法是什么? (正如IO a正在做的那样)

谢谢!

(我读过一些教程和一些源代码,但看不懂)

最佳答案

回答您的问题

由于您的 addExtra 函数实际上并未对底层 monad 执行任何操作,因此您只需更改类型签名即可使其与 monad 无关:

addExtra :: Monad m => Int -> State' m Int
addExtra x = get >>= return . (+x)

现在你可以写这个

doComplex :: State' IO ()
doComplex = do
printLog "Starting process..."

w <- addExtra 5

printLog $ "Computed value: " ++ show w

这更漂亮,并且工作起来就像您的旧代码:

*Main> runStateT doComplex 0
Message #1: Starting process...
Message #2: Computed value: 6
((),2)

旁白

我可能会想将 addExtra 重写为以下内容之一。首先,要么使用 do 表示法

addExtra x = do s <- get
return (s + x)

或者使用liftM,因为我们并没有真正使用我们有一个 monad 的事实

addExtra x = liftM (+x) get

甚至可以使用gets (感谢评论中的 Daniel Wagner)

addExtra x = gets (+x)

当然,此时您可能不需要附加功能。你也可以直接写

doComplex = do printLog "Starting process..."
w <- gets (+5)
printLog $ "Computed value: " ++ show w

同样,我可能会重写printLog。如果您发现自己获取状态,对其执行某些操作,然后将其恢复,您可能只想使用修改

printLog msg = do modify (+1)
n <- get
liftIO . putStrLn $ "Message #" ++ show n ++ ": " ++ msg

关于haskell - 沿着不同的 "return type"函数定义和使用 StateT 的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13156732/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com