如何在 Haskell 中打印 State Monad 的结果?

How to print the result of a State Monad in Haskell?

是否可以在 Haskell 中打印状态 monad 的结果?

我正在尝试理解状态 monad,在我一直关注的一本书中提供了以下用于创建状态 monad 的代码,但我在这个主题上苦苦挣扎,因为我无法直观地查看过程,即看到最终结果。

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

通常不可能以有意义的方式打印函数。如果函数的域很小,您可以导入 Data.Universe.Instances.Show from the universe-reverse-instances 包以获得一个 Show 实例,该实例打印在语义上等同于该函数的查找 table。导入该模块后,您可以简单地将 deriving Show 添加到 newtype 声明中,以便能够在较小的状态空间上打印 State 操作。

如果这只是你想要的结果,如果你只是调试:

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

您提供的代码定义了 State s a 种类 。而且它还说 State s 是一个 monad——也就是说,那种东西 State s 是符合 Monad typeclass/interface 的。这意味着您可以将一个 State s 计算绑定到另一个(只要每个 s 的类型相同)。

所以你的情况类似于某人已经定义了 Map 是什么东西,并且还写了代码说 Map 符合这样那样的接口,但谁没有任何地图,还没有 运行 使用它们进行任何计算。那就没什么可打印了。

我认为您想查看评估或执行状态操作的结果,但您尚未定义任何实际状态操作,也没有调用 runState(或 evalStateexecState) 在他们身上。不要忘记您还需要为 运行 计算提供初始状态。

所以也许可以从让 sa 成为某些特定类型开始。例如。设 sInt 并设 aInt。现在你可以去写一些 fns,例如f :: Int -> (Int, Int),以及 g :: Int -> (Int, Int)。也许一个函数递减状态,返回新的状态和值,而另一个函数递增状态,返回新的状态和值。然后你可以通过将 f 包装在 State 构造函数中来从 f 中创建一个 State Int Int 。您可以使用 >>= 将任意数量的状态操作链接在一起。最后,您可以对此使用 runState 来获取结果值和结果状态,只要您还提供初始状态(例如 0)即可。