Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.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 MonadState陷入无限递归循环中_Haskell_Monads_Monad Transformers - Fatal编程技术网

Haskell MonadState陷入无限递归循环中

Haskell MonadState陷入无限递归循环中,haskell,monads,monad-transformers,Haskell,Monads,Monad Transformers,[编辑3] 我终于解决了这个问题:我为MonadState实例添加了put方法: instance MonadState CPUState VM where get = VM get put s = do liftIO $ putStrLn $ "Modifying state" liftIO $ putStrLn.show $ (ip s) state (\_ -> ((),s)) 只要

[编辑3]

我终于解决了这个问题:我为MonadState实例添加了put方法:

instance MonadState CPUState VM where
    get = VM get
    put s = do
              liftIO $ putStrLn $ "Modifying state"
              liftIO $ putStrLn.show $ (ip s)
              state (\_ -> ((),s))
只要状态需要更新,无限循环就会启动:

let s' = (cpuState { ip = (ip cpuState) + 1 })
put s'
我真的不知道为什么。。。请大家澄清一下为什么它一直递归调用put方法

[编辑2]

现在我知道它为什么挂了,这都是因为这一行:

modify $ \s -> (cpuState { globalMemory = newGlobalMemory, ip = currentIP + 1 })
在我制作新类型之前,它工作得很好。。。如何在MonadState实例上实现相同的方法

[编辑1]

谢谢你,池!实际上我也做了类似的事情:

newtype VM a = VM{
    unwrapVM :: RWST [Quadruple] [String] (CPUState) IO a
} deriving (Functor, Applicative, Monad, MonadIO,
             MonadRWS [Quadruple] [String] CPUState)

instance MonadReader [Quadruple] VM where
    ask = VM ask

instance MonadWriter [String] VM where
    tell = VM . tell

instance MonadState CPUState VM where
    get = VM get
这是编译的,但是当我评估RWST时,它只是无限期地挂在那里

事实上,我试着用你的方式来做,但我得到了以下编译错误(即使使用了GeneraledNewTypeDeriving):

[原始问题]

给定包装RWST的新类型:

newtype VM a = VM{
    unwrapVM :: RWST [Quadruple] [String] (CPUState) IO a
} deriving (Functor, Applicative, Monad, MonadIO)
为什么不可能做这样的事情

startVM :: [Quadruple] -> Memory -> Memory -> IO ()
startVM quads globalMemory localMemory = 
    do 
      (a,w) <- evalRWST (unwrapVM $ runVM) quads (setInitialCPUState globalMemory localMemory) 
      mapM_ (putStrLn) $ w 

runVM :: VM ()
runVM = do
          quadruples <-  ask     . . . .    [1] 
          cpuState <-  get       . . . .    [2]
          return ()
startVM::[fourple]->内存->内存->IO()
startVM四边形全局内存本地内存=
做

(a,w)您需要显式地请求继承所需的实例

newtype VM a = VM{
    unwrapVM :: RWST [Quadruple] [String] (CPUState) IO a
} deriving (Functor, Applicative, Monad, MonadIO, MonadState, MonadReader)
                                               -- ^^^^^^^^^^^^^^^^^^^^^^^
为此,您可能需要扩展名
GeneralisedNewtypeDeriving

您需要明确地继承这些实例,否则您可以定义自己的实例

instance MonadState VM where ...
instance MonadReader VM where ...

事实上,将现有类型
T
包装在
newtype W
下,只为
W
提供一个不同于
T

的实例,这是非常常见的。无限循环是由于put中的me调用状态造成的。我刚把它改成:

instance MonadState CPUState VM where
    get = VM get
    put s = VM . put $ s 
对于任何想要隐藏嵌套monad转换器的人来说,这是一种方法:

newtype VM a = VM{
    unwrapVM :: RWST [Quadruple] [String] (CPUState) IO a
} deriving (Functor, Applicative, Monad, MonadIO,MonadRWS [Quadruple] [String] CPUState)

instance MonadReader [Quadruple] VM where
    ask = VM ask

instance MonadWriter [String] VM where
    tell = VM . tell

instance MonadState CPUState VM where
    get = VM get
    put s = VM . put $ s 

谢谢你,齐!请看一看我更新的问题:-)对未来问题的建议:(1)请不要对原始问题进行根本性的修改,或者添加单独的问题,特别是如果有人已经回答了(否定正确答案并不好)。如果您还有其他问题,最好在回答问题时留下评论,要求澄清较小的问题,或者发布新问题,要求澄清较大的问题。(2) 如果你在一个问题上添加了额外的信息,不要按时间倒序,因为这会使问题很难阅读。下次我会更有意识的。谢谢你,杜普洛德诺担心:)可能需要一段时间来适应这个地方的习俗,但这一切都是为了更好(即,文章作为阅读材料将具有持久的价值)。
newtype VM a = VM{
    unwrapVM :: RWST [Quadruple] [String] (CPUState) IO a
} deriving (Functor, Applicative, Monad, MonadIO,MonadRWS [Quadruple] [String] CPUState)

instance MonadReader [Quadruple] VM where
    ask = VM ask

instance MonadWriter [String] VM where
    tell = VM . tell

instance MonadState CPUState VM where
    get = VM get
    put s = VM . put $ s