Haskell 如何嵌套单子
我在Haskell中有以下代码:Haskell 如何嵌套单子,haskell,monads,Haskell,Monads,我在Haskell中有以下代码: import Control.Monad.Trans.State simpleState = state (\x -> (x, x + 1)) runUntil :: (s -> Bool) -> State s a -> State s a runUntil f s = do s' <- get -- Here I want to print value of s' to console if f s'
import Control.Monad.Trans.State
simpleState = state (\x -> (x, x + 1))
runUntil :: (s -> Bool) -> State s a -> State s a
runUntil f s = do
s' <- get
-- Here I want to print value of s' to console
if f s'
then s >> runUntil f s
else s
main :: IO ()
main = do
let (x,s) = runState (runUntil (< 10) simpleState) 0
putStrLn $ "State = " ++ (show s) ++ " Result = " ++ (show x)
import Control.Monad.Trans.State
simpleState=状态(\x->(x,x+1))
运行直到::(s->Bool)->状态sa->状态sa
运行直到f s=do
运行到
其他
main::IO()
main=do
设(x,s)=运行状态(runUntil(<10)simpleState)0
putStrLn$“State=“++(show s)++”Result=“++(show x)
我想在每次RunTill迭代时打印状态值。如果我不能在
runtil
函数中打印它,我可以在哪里执行此操作?欢迎来到Monad Transformers的奇妙世界。有一个很好的名为MTL的库,它提供了大多数monad的“monad transformer”等价物。按照惯例,它们以大写字母T结尾,因此StateT
是我们想要的。Monad变压器有其通常的操作和一个以上的操作,lift
,对于一个类似这样的StateT
lift :: Monad m => m a -> StateT s m a
现在在IO
上有一个特殊的变压器类,叫做MonadIO
。为了使用它,我们会做一些类似的事情。它类似于一个普通的旧monad转换器,但具有类型签名
liftIO :: (MonadIO m, Monad m) => IO a -> m a
import Control.Monad.State
import Control.Monad.Trans
simpleState :: StateT Integer IO ()
simpleState = modify (+1)
runUntil :: Show s => (s -> Bool) -> StateT s IO a -> StateT s IO s
runUntil pred newState = do
curr <- get
if pred curr
then liftIO (print curr) >> newState >> runUntil pred newState
else return curr
请注意,现在我们使用bind(在我看来,我们的打印可能只是为了调试目的 如果我是正确的,您可以使用Debug.trace从任何位置(甚至在IO函数之外)打印到终端 只需导入Debug并连接到像这样的任何其他值
trace (show s') $
if f s'
then s >> runUntil f s
else s
(注意,trace的签名是String->a->a,因此需要$后跟另一个表达式。)
同样,这只适用于开发代码,应该从生产代码中删除(它完全打破了“无副作用”的概念)
trace (show s') $
if f s'
then s >> runUntil f s
else s