如何在Haskell中打印状态单子的结果?

如何在Haskell中打印状态单子的结果?,haskell,monads,Haskell,Monads,是否可以在Haskell中打印状态单子的结果 我试图理解状态单子,在我一直遵循的一本书中,提供了下面创建状态单子的代码,但我很难理解这个主题,因为我无法直观地查看过程,即看到最终结果 newtype State s a = State { runState :: s -> (a,s)} instance Monad (State s) where return x = State $ \s -> (x,s) (State h) >>= f = S

是否可以在Haskell中打印状态单子的结果

我试图理解状态单子,在我一直遵循的一本书中,提供了下面创建状态单子的代码,但我很难理解这个主题,因为我无法直观地查看过程,即看到最终结果

newtype State s a = State { runState :: s -> (a,s)}

instance Monad (State s) where  
    return x = State $ \s -> (x,s)  
    (State h) >>= f = State $ \s -> let (a, newState) = h s  
                                        (State g) = f a  
                                    in  g newState

通常不可能以有意义的方式打印函数。如果函数的域很小,则可以从包中导入以获得一个Show实例,该实例打印语义上与函数等价的查找表。导入该模块后,您只需将派生显示添加到newtype声明中,即可在较小的状态空间上打印状态操作。

如果这正是您想要的结果,并且您只是在调试:

import Debug.Trace
import Control.Monad.Trans.State

action :: State [Int] ()
action = do
  put [0]
  modify (1:)
  modify (2:)
  get >>= traceShowM
  modify (3:)
  modify (4:)
  get >>= traceShowM

您提供的代码定义了状态的类型。它还说状态s是一个monad,也就是说,状态s的类型符合monad类型类/接口。这意味着您可以将一个状态的计算绑定到另一个状态,只要每个状态的类型相同

因此,你的情况类似于一个人,他定义了地图的类型,也编写了代码,说地图符合这样或那样的接口,但他没有任何地图,也没有用地图运行任何计算。那就没什么可打印的了

我认为您希望看到评估或执行状态操作的结果,但是您还没有定义任何实际的状态操作,也没有对它们调用runState、evalState或execState。不要忘记,您还需要提供一个初始状态来运行计算


所以,我们可以先让s和a成为一些特殊的类型。例如,让我们成为Int,让a成为Int。现在你可以编写一些fn,例如f::Int->Int,Int和g::Int->Int,Int。可能一个函数递减状态,返回新的状态和值,另一个函数递增状态,返回新的状态和值。然后,您可以通过将f包装到状态构造函数中,使其成为状态Int。您可以使用>>=将任意多个状态操作链接在一起。最后,您可以使用runState来获取结果值和结果状态,只要您还提供初始状态,例如0

“如何打印状态单子”与“如何打印状态单子的结果”是一个完全不同的问题,至少如果我将前者理解为打印状态操作,将后者理解为打印执行一次状态操作的结果。你是什么意思?@leftaroundabout result抱歉。谢谢,但我得到的错误不在put、modify、modify、get、modify、modify、get的范围内?这是使用库提供的函数,可通过导入Control.Monad.Trans.State访问。谢谢,我得到一个不明确的出现“State”的错误,它可以引用“Main.State”,还是“Control.Monad.Trans.State.State”@GurkenglasState已经在transformers包中定义,如果要使用包的版本,您必须注释掉您的版本。或者,您可以在运行操作函数时重新实现get和putI get错误显示状态[Int]?@liminalishit非常感谢您的回答,这真的很有帮助!我做了一个函数f来增加状态。我有点不确定如何做链条部分对不起,你能给我举个例子吗。谢谢你让f=\x->x+1,x+1,让g=状态f>>>=状态f。这表示将状态增加两次的状态操作。运行状态g 0应返回2,2。等价地,如果h=\x->返回x+1、x+1和j=stateth>>=stateth,则runstateth0返回2,2。这可能会让你感觉到状态单子是如何工作的。但是,从mtl或transformers这样的包中使用get put和modify构建状态操作通常是使用状态monad的方式,它与命令式语言中可能使用的命令式风格非常相似。