Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何嵌套单子_Haskell_Monads - Fatal编程技术网

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'

我在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'
        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